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

Method graph_shortest_path

nodedb-client/src/traits/core/trait_def.rs:336–398  ·  view source on GitHub ↗

Find the shortest path between two nodes. Returns the path as a list of node IDs (`from` first, `to` last), or `None` if no path exists within `max_depth` hops. Default: forward breadth-first search built on `graph_traverse`. Each frontier expansion calls `graph_traverse(node, 1, edge_filter)` to discover outgoing neighbors. Inherits the underlying impl's edge direction semantics. Implementation

(
        &self,
        collection: &str,
        from: &NodeId,
        to: &NodeId,
        max_depth: u8,
        edge_filter: Option<&EdgeFilter>,
    )

Source from the content-addressed store, hash-verified

334 /// performance — round-tripping per-hop is O(path_length) wire
335 /// hops.
336 async fn graph_shortest_path(
337 &self,
338 collection: &str,
339 from: &NodeId,
340 to: &NodeId,
341 max_depth: u8,
342 edge_filter: Option<&EdgeFilter>,
343 ) -> NodeDbResult<Option<Vec<NodeId>>> {
344 if from == to {
345 return Ok(Some(vec![from.clone()]));
346 }
347 if max_depth == 0 {
348 return Ok(None);
349 }
350
351 // Map of `node -> parent` used to reconstruct the path once the
352 // target is reached. The source has no parent entry.
353 let mut parent: std::collections::HashMap<NodeId, NodeId> =
354 std::collections::HashMap::new();
355 let mut frontier: Vec<NodeId> = vec![from.clone()];
356
357 for _ in 0..max_depth {
358 let mut next_frontier: Vec<NodeId> = Vec::new();
359 for node in &frontier {
360 let sg = self
361 .graph_traverse(collection, node, 1, edge_filter)
362 .await?;
363 for edge in &sg.edges {
364 // Only follow edges originating from the current
365 // node — `graph_traverse` may include adjacent
366 // edges that don't extend the BFS frontier.
367 if &edge.from != node {
368 continue;
369 }
370 let dst = &edge.to;
371 if dst == from || parent.contains_key(dst) {
372 continue;
373 }
374 parent.insert(dst.clone(), node.clone());
375 if dst == to {
376 let mut path = vec![to.clone()];
377 let mut cur = to.clone();
378 while &cur != from {
379 let p = parent
380 .get(&cur)
381 .expect("BFS reached `to` so all ancestors are tracked")
382 .clone();
383 path.push(p.clone());
384 cur = p;
385 }
386 path.reverse();
387 return Ok(Some(path));
388 }
389 next_frontier.push(dst.clone());
390 }
391 }
392 if next_frontier.is_empty() {
393 return Ok(None);

Callers

nothing calls this directly

Implementers 3

dispatch.rsnodedb-client/src/remote/client/dispat
trait_def.rsnodedb-client/src/traits/core/trait_de
dispatch.rsnodedb-client/src/native/client/dispat

Calls 7

graph_traverseMethod · 0.45
insertMethod · 0.45
cloneMethod · 0.45
expectMethod · 0.45
getMethod · 0.45
pushMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected