Skip to content

Commit 125809a

Browse files
committed
Adding code for finding k shortest paths in a graph. This implements Yen's algorithm to find the k paths in time O(kn^3).
1 parent fcb24f9 commit 125809a

6 files changed

Lines changed: 551 additions & 3 deletions

File tree

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/editor.xml

Lines changed: 483 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/rustworkx-ranjana-fork.iml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustworkx-core/src/shortest_path/simple_shortest_paths.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ where
419419
// their costs are pushed on to the heap. The best path from the heap at the end of the iteration
420420
// is added to listA.
421421
let mut listB: BinaryHeap<MinScored<K, Vec<NodeIndex>>> = BinaryHeap::new();
422+
let mut paths_in_listB: HashSet<Vec<NodeIndex>> = HashSet::new();
422423

423424
for i in 1usize..max_paths {
424425
// listA contains the i shortest paths, while listB contains candidate paths.
@@ -470,10 +471,14 @@ where
470471
if shortest_root_target_path.len() > 0 {
471472
// create new_path by appending current_path till divergence point and the shortest path after that.
472473
let mut new_path = current_path[0..j].to_owned();
473-
println!("new_path {:?}", new_path);
474+
//println!("new_path {:?}", new_path);
474475
new_path.extend_from_slice(&shortest_root_target_path);
475-
println!("Adding path of cost {:?} to listB", root_cost + path_cost);
476-
listB.push(MinScored(root_cost + path_cost, new_path));
476+
//println!("Adding path of cost {:?} to listB", root_cost + path_cost);
477+
// Add the path to listB if it does not already exist.
478+
if !paths_in_listB.contains(&new_path) {
479+
listB.push(MinScored(root_cost + path_cost, new_path.clone()));
480+
paths_in_listB.insert(new_path);
481+
}
477482
}
478483

479484
// add current edge cost to the root cost
@@ -642,6 +647,7 @@ mod tests {
642647
//use crate::get_shortest_paths;
643648
use petgraph::{Graph, Undirected};
644649
use petgraph::graph::NodeIndex;
650+
use rand::Rng;
645651
//use crate::shortest_path::get_shortest_paths;
646652
use crate::shortest_path::simple_shortest_paths::{dijkstra_k_shortest_paths, get_smallest_k_paths_yen};
647653
//use petgraph_evcxr::draw_graph;
@@ -718,6 +724,29 @@ mod tests {
718724

719725

720726

727+
}
728+
729+
#[test]
730+
fn test_k_shortest_random_graph() {
731+
let mut g = Graph::new_undirected();
732+
let nodes: Vec<NodeIndex> = (0..5000).map(|_| g.add_node(())).collect();
733+
let mut rng: rand::prelude::ThreadRng = rand::thread_rng();
734+
for _ in 0..62291 { // Adjust the number of edges as desired
735+
let a = rng.gen_range(0..nodes.len());
736+
let b = rng.gen_range(0..nodes.len());
737+
let weight = rng.gen_range(1..100); // Random weight between 1 and 100
738+
if a != b { // Prevent self-loops
739+
g.add_edge(nodes[a], nodes[b], weight as f32); }
740+
}
741+
println!("GRaph created");
742+
let source = nodes[1];
743+
let target = nodes[4000];
744+
let shortest_path_get :usize = 5;
745+
//println!(“{:?}“, g);
746+
for p in get_smallest_k_paths_yen( &mut g,source,target,10) {
747+
println!("New Path {:#?} ",p);
748+
}
749+
721750
}
722751

723752

0 commit comments

Comments
 (0)