Documentation
¶
Overview ¶
Example 01_basic — build a weighted directed transport network, freeze it to an immutable CSR snapshot, and run a single-source Dijkstra shortest-paths query with route reconstruction.
This is the minimal end-to-end GoGraph routing flow, scaled to a size where the search work is observable: a seeded generator lays down a realistic road-style network, the mutable adjlist.AdjList builder ingests it, csr.BuildFromAdjList freezes it into an immutable snapshot, and search.Dijkstra computes shortest paths from a single source over the whole graph. The parent chain of the result is resolved back to node coordinates through the graph.Mapper to print a concrete multi-hop route.
Model ¶
The network is a directed random geometric graph (RGG). N junctions are placed at seeded integer coordinates in a [0, span) x [0, span) square. Two junctions within Euclidean radius are joined by a road in BOTH directions; the road's weight is the integer-rounded straight-line distance between them (always >= 1). The radius is tuned above the RGG connectivity threshold (r ~ span*sqrt(ln N / (pi*N))) so the giant component spans the whole graph, and an id-ordered backbone (junction i <-> i+1, carrying its true geometric weight) is laid down as a synthetic connectivity guarantee so that EVERY junction is reachable from the source for any seed and scale. The backbone roads are long and the local roads are short, so Dijkstra almost always routes through the short local roads — the backbone only guarantees reachability, it does not dominate the shortest paths.
Because every road's weight is at most the radius, a route between two distant junctions must traverse many short hops: the shortest paths are genuinely multi-hop, which is what makes this a meaningful Dijkstra exercise rather than a one-edge lookup.
Determinism ¶
The data shape is reproducible for a fixed -seed: junction placement is drawn from a seeded math/rand, the adjacency is emitted in a fixed order (ascending source, then ascending destination), and edge weights are computed with integer-only arithmetic — ceil(sqrt(dx*dx + dy*dy)) — so the weights, the reachable-junction count, and the shortest distances to fixed target junctions are bit-identical across machines, OS and architecture. (math.Hypot/math.Sqrt are deliberately avoided in the weight path: their last-bit result can differ between amd64 and arm64 because of FMA fusion, which could flip an integer weight and so a pinned fact.) Lines prefixed with "# " carry volatile telemetry (durations, throughput, live heap) that varies per run and per machine.
Scale ¶
Run with no flags, the example builds a small deterministic default (a few thousand junctions) that the regression test pins and that stays well under the short-test budget. Every dimension is a flag, so the same binary scales up to where the search cost becomes interesting:
go run ./examples/01_basic # small deterministic default go run ./examples/01_basic -nodes 1000000 -seed 7 # observable-scale run