MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / run

Function run

nodedb/src/engine/graph/algo/sssp.rs:26–92  ·  view source on GitHub ↗

Run SSSP (Dijkstra) from a source node on the CSR index. Returns `(node_id, distance)` for all reachable nodes. Unreachable nodes get `f64::INFINITY`. Returns an error if the source node doesn't exist.

(csr: &CsrIndex, params: &AlgoParams)

Source from the content-addressed store, hash-verified

24/// Returns `(node_id, distance)` for all reachable nodes. Unreachable nodes
25/// get `f64::INFINITY`. Returns an error if the source node doesn't exist.
26pub fn run(csr: &CsrIndex, params: &AlgoParams) -> Result<AlgoResultBatch, crate::Error> {
27 let n = csr.node_count();
28 if n == 0 {
29 return Ok(AlgoResultBatch::new(GraphAlgorithm::Sssp));
30 }
31
32 let source = params
33 .source_node
34 .as_deref()
35 .ok_or_else(|| crate::Error::BadRequest {
36 detail: "SSSP requires source_node parameter".into(),
37 })?;
38
39 let source_id = csr
40 .node_id_raw(source)
41 .ok_or_else(|| crate::Error::BadRequest {
42 detail: format!("source node '{source}' not found in graph"),
43 })?;
44
45 // Dijkstra requires non-negative edge weights. Pre-scan for negatives
46 // to fail fast with a clear error rather than silently producing wrong results.
47 if csr.has_weights() {
48 for node in 0..n {
49 for (_lid, _dst, w) in csr.iter_out_edges_weighted_raw(node as u32) {
50 if w < 0.0 {
51 return Err(crate::Error::BadRequest {
52 detail: format!(
53 "SSSP (Dijkstra) requires non-negative edge weights, found {w} on edge from '{}'",
54 csr.node_name_raw(node as u32)
55 ),
56 });
57 }
58 }
59 }
60 }
61
62 let mut dist = vec![f64::INFINITY; n];
63 dist[source_id as usize] = 0.0;
64
65 // Min-heap: (Reverse(distance), node_id).
66 // Reverse wraps f64 for min-heap behavior with Rust's max-heap BinaryHeap.
67 let mut heap: BinaryHeap<Reverse<(OrdF64, u32)>> = BinaryHeap::new();
68 heap.push(Reverse((OrdF64(0.0), source_id)));
69
70 while let Some(Reverse((OrdF64(d), u))) = heap.pop() {
71 // Skip stale entries (lazy deletion).
72 if d > dist[u as usize] {
73 continue;
74 }
75
76 // Relax outbound edges.
77 for (_lid, v, weight) in csr.iter_out_edges_weighted_raw(u) {
78 let new_dist = d + weight;
79 if new_dist < dist[v as usize] {
80 dist[v as usize] = new_dist;
81 heap.push(Reverse((OrdF64(new_dist), v)));
82 }
83 }

Callers 10

sssp_shortest_via_relayFunction · 0.70
sssp_unreachable_nodeFunction · 0.70
sssp_missing_sourceFunction · 0.70
sssp_no_source_paramFunction · 0.70
sssp_single_nodeFunction · 0.70
sssp_to_record_batchFunction · 0.70
sssp_diamond_graphFunction · 0.70

Calls 10

OrdF64Class · 0.85
push_node_f64Method · 0.80
to_stringMethod · 0.80
node_countMethod · 0.45
node_id_rawMethod · 0.45
has_weightsMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45
node_name_rawMethod · 0.45

Tested by 10

sssp_shortest_via_relayFunction · 0.56
sssp_unreachable_nodeFunction · 0.56
sssp_missing_sourceFunction · 0.56
sssp_no_source_paramFunction · 0.56
sssp_single_nodeFunction · 0.56
sssp_to_record_batchFunction · 0.56
sssp_diamond_graphFunction · 0.56