1use std::collections::{BinaryHeap, HashSet, VecDeque};
7
8use crate::base::{DiGraph, EdgeWeight, Graph, Node};
9use crate::error::{GraphError, Result};
10
11#[allow(dead_code)]
27pub fn breadth_first_search<N, E, Ix>(graph: &Graph<N, E, Ix>, source: &N) -> Result<Vec<N>>
28where
29 N: Node + std::fmt::Debug,
30 E: EdgeWeight,
31 Ix: petgraph::graph::IndexType,
32{
33 if !graph.has_node(source) {
34 return Err(GraphError::InvalidGraph(format!(
35 "Source node {source:?} not found"
36 )));
37 }
38
39 let mut visited = HashSet::new();
40 let mut queue = VecDeque::new();
41 let mut result = Vec::new();
42
43 let start_idx = graph
45 .inner()
46 .node_indices()
47 .find(|&idx| graph.inner()[idx] == *source)
48 .unwrap();
49
50 queue.push_back(start_idx);
51 visited.insert(start_idx);
52
53 while let Some(current_idx) = queue.pop_front() {
54 result.push(graph.inner()[current_idx].clone());
55
56 for neighbor_idx in graph.inner().neighbors(current_idx) {
58 if !visited.contains(&neighbor_idx) {
59 visited.insert(neighbor_idx);
60 queue.push_back(neighbor_idx);
61 }
62 }
63 }
64
65 Ok(result)
66}
67
68#[allow(dead_code)]
84pub fn breadth_first_search_digraph<N, E, Ix>(
85 graph: &DiGraph<N, E, Ix>,
86 source: &N,
87) -> Result<Vec<N>>
88where
89 N: Node + std::fmt::Debug,
90 E: EdgeWeight,
91 Ix: petgraph::graph::IndexType,
92{
93 if !graph.has_node(source) {
94 return Err(GraphError::InvalidGraph(format!(
95 "Source node {source:?} not found"
96 )));
97 }
98
99 let mut visited = HashSet::new();
100 let mut queue = VecDeque::new();
101 let mut result = Vec::new();
102
103 let start_idx = graph
105 .inner()
106 .node_indices()
107 .find(|&idx| graph.inner()[idx] == *source)
108 .unwrap();
109
110 queue.push_back(start_idx);
111 visited.insert(start_idx);
112
113 while let Some(current_idx) = queue.pop_front() {
114 result.push(graph.inner()[current_idx].clone());
115
116 for neighbor_idx in graph
118 .inner()
119 .neighbors_directed(current_idx, petgraph::Direction::Outgoing)
120 {
121 if !visited.contains(&neighbor_idx) {
122 visited.insert(neighbor_idx);
123 queue.push_back(neighbor_idx);
124 }
125 }
126 }
127
128 Ok(result)
129}
130
131#[allow(dead_code)]
148pub fn depth_first_search<N, E, Ix>(graph: &Graph<N, E, Ix>, source: &N) -> Result<Vec<N>>
149where
150 N: Node + std::fmt::Debug,
151 E: EdgeWeight,
152 Ix: petgraph::graph::IndexType,
153{
154 if !graph.has_node(source) {
155 return Err(GraphError::InvalidGraph(format!(
156 "Source node {source:?} not found"
157 )));
158 }
159
160 let mut visited = HashSet::new();
161 let mut stack = Vec::new();
162 let mut result = Vec::new();
163
164 let start_idx = graph
166 .inner()
167 .node_indices()
168 .find(|&idx| graph.inner()[idx] == *source)
169 .unwrap();
170
171 stack.push(start_idx);
172
173 while let Some(current_idx) = stack.pop() {
174 if !visited.contains(¤t_idx) {
175 visited.insert(current_idx);
176 result.push(graph.inner()[current_idx].clone());
177
178 let mut neighbors: Vec<_> = graph.inner().neighbors(current_idx).collect();
180 neighbors.reverse();
181 for neighbor_idx in neighbors {
182 if !visited.contains(&neighbor_idx) {
183 stack.push(neighbor_idx);
184 }
185 }
186 }
187 }
188
189 Ok(result)
190}
191
192#[allow(dead_code)]
201pub fn depth_first_search_digraph<N, E, Ix>(graph: &DiGraph<N, E, Ix>, source: &N) -> Result<Vec<N>>
202where
203 N: Node + std::fmt::Debug,
204 E: EdgeWeight,
205 Ix: petgraph::graph::IndexType,
206{
207 if !graph.has_node(source) {
208 return Err(GraphError::InvalidGraph(format!(
209 "Source node {source:?} not found"
210 )));
211 }
212
213 let mut visited = HashSet::new();
214 let mut stack = Vec::new();
215 let mut result = Vec::new();
216
217 let start_idx = graph
219 .inner()
220 .node_indices()
221 .find(|&idx| graph.inner()[idx] == *source)
222 .unwrap();
223
224 stack.push(start_idx);
225
226 while let Some(current_idx) = stack.pop() {
227 if !visited.contains(¤t_idx) {
228 visited.insert(current_idx);
229 result.push(graph.inner()[current_idx].clone());
230
231 let mut neighbors: Vec<_> = graph
233 .inner()
234 .neighbors_directed(current_idx, petgraph::Direction::Outgoing)
235 .collect();
236 neighbors.reverse();
237 for neighbor_idx in neighbors {
238 if !visited.contains(&neighbor_idx) {
239 stack.push(neighbor_idx);
240 }
241 }
242 }
243 }
244
245 Ok(result)
246}
247
248#[derive(Clone)]
250struct PriorityState<N: Node + std::fmt::Debug, P: PartialOrd> {
251 node: N,
252 priority: P,
253}
254
255impl<N: Node + std::fmt::Debug, P: PartialOrd> PartialEq for PriorityState<N, P> {
256 fn eq(&self, other: &Self) -> bool {
257 self.node == other.node
258 }
259}
260
261impl<N: Node + std::fmt::Debug, P: PartialOrd> Eq for PriorityState<N, P> {}
262
263impl<N: Node + std::fmt::Debug, P: PartialOrd> PartialOrd for PriorityState<N, P> {
264 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
265 Some(self.cmp(other))
266 }
267}
268
269impl<N: Node + std::fmt::Debug, P: PartialOrd> Ord for PriorityState<N, P> {
270 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
271 other
273 .priority
274 .partial_cmp(&self.priority)
275 .unwrap_or(std::cmp::Ordering::Equal)
276 }
277}
278
279#[allow(dead_code)]
294pub fn priority_first_search<N, E, Ix, P, F>(
295 graph: &Graph<N, E, Ix>,
296 source: &N,
297 priority_fn: F,
298) -> Result<Vec<N>>
299where
300 N: Node + std::fmt::Debug + Clone,
301 E: EdgeWeight,
302 Ix: petgraph::graph::IndexType,
303 P: PartialOrd + Clone + Copy,
304 F: Fn(&N) -> P,
305{
306 if !graph.has_node(source) {
307 return Err(GraphError::InvalidGraph(format!(
308 "Source node {source:?} not found"
309 )));
310 }
311
312 let mut visited = HashSet::new();
313 let mut priority_queue = BinaryHeap::new();
314 let mut result = Vec::new();
315
316 let _start_idx = graph
318 .inner()
319 .node_indices()
320 .find(|&idx| graph.inner()[idx] == *source)
321 .unwrap();
322
323 priority_queue.push(PriorityState {
324 node: source.clone(),
325 priority: priority_fn(source),
326 });
327
328 while let Some(current_state) = priority_queue.pop() {
329 let current_node = ¤t_state.node;
330
331 if visited.contains(current_node) {
332 continue;
333 }
334
335 visited.insert(current_node.clone());
336 result.push(current_node.clone());
337
338 let current_idx = graph
340 .inner()
341 .node_indices()
342 .find(|&idx| graph.inner()[idx] == *current_node)
343 .unwrap();
344
345 for neighbor_idx in graph.inner().neighbors(current_idx) {
347 let neighbor_node = &graph.inner()[neighbor_idx];
348 if !visited.contains(neighbor_node) {
349 priority_queue.push(PriorityState {
350 node: neighbor_node.clone(),
351 priority: priority_fn(neighbor_node),
352 });
353 }
354 }
355 }
356
357 Ok(result)
358}
359
360#[allow(dead_code)]
370pub fn priority_first_search_digraph<N, E, Ix, P, F>(
371 graph: &DiGraph<N, E, Ix>,
372 source: &N,
373 priority_fn: F,
374) -> Result<Vec<N>>
375where
376 N: Node + std::fmt::Debug + Clone,
377 E: EdgeWeight,
378 Ix: petgraph::graph::IndexType,
379 P: PartialOrd + Clone + Copy,
380 F: Fn(&N) -> P,
381{
382 if !graph.has_node(source) {
383 return Err(GraphError::InvalidGraph(format!(
384 "Source node {source:?} not found"
385 )));
386 }
387
388 let mut visited = HashSet::new();
389 let mut priority_queue = BinaryHeap::new();
390 let mut result = Vec::new();
391
392 priority_queue.push(PriorityState {
393 node: source.clone(),
394 priority: priority_fn(source),
395 });
396
397 while let Some(current_state) = priority_queue.pop() {
398 let current_node = ¤t_state.node;
399
400 if visited.contains(current_node) {
401 continue;
402 }
403
404 visited.insert(current_node.clone());
405 result.push(current_node.clone());
406
407 let current_idx = graph
409 .inner()
410 .node_indices()
411 .find(|&idx| graph.inner()[idx] == *current_node)
412 .unwrap();
413
414 for neighbor_idx in graph
416 .inner()
417 .neighbors_directed(current_idx, petgraph::Direction::Outgoing)
418 {
419 let neighbor_node = &graph.inner()[neighbor_idx];
420 if !visited.contains(neighbor_node) {
421 priority_queue.push(PriorityState {
422 node: neighbor_node.clone(),
423 priority: priority_fn(neighbor_node),
424 });
425 }
426 }
427 }
428
429 Ok(result)
430}
431
432#[allow(dead_code)]
446pub fn bidirectional_search<N, E, Ix>(
447 graph: &Graph<N, E, Ix>,
448 source: &N,
449 goal: &N,
450) -> Result<Option<Vec<N>>>
451where
452 N: Node + std::fmt::Debug + Clone + std::hash::Hash + Eq,
453 E: EdgeWeight,
454 Ix: petgraph::graph::IndexType,
455{
456 if !graph.has_node(source) || !graph.has_node(goal) {
457 return Err(GraphError::InvalidGraph(
458 "Source or goal node not found".to_string(),
459 ));
460 }
461
462 if source == goal {
463 return Ok(Some(vec![source.clone()]));
464 }
465
466 let start_idx = graph
468 .inner()
469 .node_indices()
470 .find(|&idx| graph.inner()[idx] == *source)
471 .unwrap();
472 let goal_idx = graph
473 .inner()
474 .node_indices()
475 .find(|&idx| graph.inner()[idx] == *goal)
476 .unwrap();
477
478 let mut forward_queue = VecDeque::new();
479 let mut backward_queue = VecDeque::new();
480 let mut forward_visited = HashSet::new();
481 let mut backward_visited = HashSet::new();
482 let mut forward_parent: std::collections::HashMap<
483 petgraph::graph::NodeIndex<Ix>,
484 petgraph::graph::NodeIndex<Ix>,
485 > = std::collections::HashMap::new();
486 let mut backward_parent: std::collections::HashMap<
487 petgraph::graph::NodeIndex<Ix>,
488 petgraph::graph::NodeIndex<Ix>,
489 > = std::collections::HashMap::new();
490
491 forward_queue.push_back(start_idx);
492 backward_queue.push_back(goal_idx);
493 forward_visited.insert(start_idx);
494 backward_visited.insert(goal_idx);
495
496 while !forward_queue.is_empty() || !backward_queue.is_empty() {
497 if !forward_queue.is_empty() {
499 let current = forward_queue.pop_front().unwrap();
500
501 if backward_visited.contains(¤t) {
503 return Ok(Some(reconstruct_bidirectional_path(
504 graph,
505 start_idx,
506 goal_idx,
507 current,
508 &forward_parent,
509 &backward_parent,
510 )));
511 }
512
513 for neighbor in graph.inner().neighbors(current) {
514 if !forward_visited.contains(&neighbor) {
515 forward_visited.insert(neighbor);
516 forward_parent.insert(neighbor, current);
517 forward_queue.push_back(neighbor);
518 }
519 }
520 }
521
522 if !backward_queue.is_empty() {
524 let current = backward_queue.pop_front().unwrap();
525
526 if forward_visited.contains(¤t) {
528 return Ok(Some(reconstruct_bidirectional_path(
529 graph,
530 start_idx,
531 goal_idx,
532 current,
533 &forward_parent,
534 &backward_parent,
535 )));
536 }
537
538 for neighbor in graph.inner().neighbors(current) {
539 if !backward_visited.contains(&neighbor) {
540 backward_visited.insert(neighbor);
541 backward_parent.insert(neighbor, current);
542 backward_queue.push_back(neighbor);
543 }
544 }
545 }
546 }
547
548 Ok(None)
549}
550
551#[allow(dead_code)]
553pub fn bidirectional_search_digraph<N, E, Ix>(
554 graph: &DiGraph<N, E, Ix>,
555 source: &N,
556 goal: &N,
557) -> Result<Option<Vec<N>>>
558where
559 N: Node + std::fmt::Debug + Clone + std::hash::Hash + Eq,
560 E: EdgeWeight,
561 Ix: petgraph::graph::IndexType,
562{
563 if !graph.has_node(source) || !graph.has_node(goal) {
564 return Err(GraphError::InvalidGraph(
565 "Source or goal node not found".to_string(),
566 ));
567 }
568
569 if source == goal {
570 return Ok(Some(vec![source.clone()]));
571 }
572
573 let start_idx = graph
575 .inner()
576 .node_indices()
577 .find(|&idx| graph.inner()[idx] == *source)
578 .unwrap();
579 let goal_idx = graph
580 .inner()
581 .node_indices()
582 .find(|&idx| graph.inner()[idx] == *goal)
583 .unwrap();
584
585 let mut forward_queue = VecDeque::new();
586 let mut backward_queue = VecDeque::new();
587 let mut forward_visited = HashSet::new();
588 let mut backward_visited = HashSet::new();
589 let mut forward_parent: std::collections::HashMap<
590 petgraph::graph::NodeIndex<Ix>,
591 petgraph::graph::NodeIndex<Ix>,
592 > = std::collections::HashMap::new();
593 let mut backward_parent: std::collections::HashMap<
594 petgraph::graph::NodeIndex<Ix>,
595 petgraph::graph::NodeIndex<Ix>,
596 > = std::collections::HashMap::new();
597
598 forward_queue.push_back(start_idx);
599 backward_queue.push_back(goal_idx);
600 forward_visited.insert(start_idx);
601 backward_visited.insert(goal_idx);
602
603 while !forward_queue.is_empty() || !backward_queue.is_empty() {
604 if !forward_queue.is_empty() {
606 let current = forward_queue.pop_front().unwrap();
607
608 if backward_visited.contains(¤t) {
610 return Ok(Some(reconstruct_bidirectional_path_digraph(
611 graph,
612 start_idx,
613 goal_idx,
614 current,
615 &forward_parent,
616 &backward_parent,
617 )));
618 }
619
620 for neighbor in graph
621 .inner()
622 .neighbors_directed(current, petgraph::Direction::Outgoing)
623 {
624 if !forward_visited.contains(&neighbor) {
625 forward_visited.insert(neighbor);
626 forward_parent.insert(neighbor, current);
627 forward_queue.push_back(neighbor);
628 }
629 }
630 }
631
632 if !backward_queue.is_empty() {
634 let current = backward_queue.pop_front().unwrap();
635
636 if forward_visited.contains(¤t) {
638 return Ok(Some(reconstruct_bidirectional_path_digraph(
639 graph,
640 start_idx,
641 goal_idx,
642 current,
643 &forward_parent,
644 &backward_parent,
645 )));
646 }
647
648 for neighbor in graph
649 .inner()
650 .neighbors_directed(current, petgraph::Direction::Incoming)
651 {
652 if !backward_visited.contains(&neighbor) {
653 backward_visited.insert(neighbor);
654 backward_parent.insert(neighbor, current);
655 backward_queue.push_back(neighbor);
656 }
657 }
658 }
659 }
660
661 Ok(None)
662}
663
664#[allow(dead_code)]
666fn reconstruct_bidirectional_path<N, E, Ix>(
667 graph: &Graph<N, E, Ix>,
668 start_idx: petgraph::graph::NodeIndex<Ix>,
669 goal_idx: petgraph::graph::NodeIndex<Ix>,
670 meeting_point: petgraph::graph::NodeIndex<Ix>,
671 forward_parent: &std::collections::HashMap<
672 petgraph::graph::NodeIndex<Ix>,
673 petgraph::graph::NodeIndex<Ix>,
674 >,
675 backward_parent: &std::collections::HashMap<
676 petgraph::graph::NodeIndex<Ix>,
677 petgraph::graph::NodeIndex<Ix>,
678 >,
679) -> Vec<N>
680where
681 N: Node + std::fmt::Debug + Clone,
682 E: EdgeWeight,
683 Ix: petgraph::graph::IndexType,
684{
685 let mut forward_path = Vec::new();
686 let mut current = meeting_point;
687
688 while current != start_idx {
690 forward_path.push(graph.inner()[current].clone());
691 current = forward_parent[¤t];
692 }
693 forward_path.push(graph.inner()[start_idx].clone());
694 forward_path.reverse();
695
696 let mut backward_path = Vec::new();
698 current = meeting_point;
699 while current != goal_idx {
700 if let Some(&parent) = backward_parent.get(¤t) {
701 current = parent;
702 backward_path.push(graph.inner()[current].clone());
703 } else {
704 break;
705 }
706 }
707
708 let mut full_path = forward_path;
710 full_path.extend(backward_path);
711 full_path
712}
713
714#[allow(dead_code)]
716fn reconstruct_bidirectional_path_digraph<N, E, Ix>(
717 graph: &DiGraph<N, E, Ix>,
718 start_idx: petgraph::graph::NodeIndex<Ix>,
719 goal_idx: petgraph::graph::NodeIndex<Ix>,
720 meeting_point: petgraph::graph::NodeIndex<Ix>,
721 forward_parent: &std::collections::HashMap<
722 petgraph::graph::NodeIndex<Ix>,
723 petgraph::graph::NodeIndex<Ix>,
724 >,
725 backward_parent: &std::collections::HashMap<
726 petgraph::graph::NodeIndex<Ix>,
727 petgraph::graph::NodeIndex<Ix>,
728 >,
729) -> Vec<N>
730where
731 N: Node + std::fmt::Debug + Clone,
732 E: EdgeWeight,
733 Ix: petgraph::graph::IndexType,
734{
735 let mut forward_path = Vec::new();
736 let mut current = meeting_point;
737
738 while current != start_idx {
740 forward_path.push(graph.inner()[current].clone());
741 current = forward_parent[¤t];
742 }
743 forward_path.push(graph.inner()[start_idx].clone());
744 forward_path.reverse();
745
746 let mut backward_path = Vec::new();
748 current = meeting_point;
749 while current != goal_idx {
750 if let Some(&parent) = backward_parent.get(¤t) {
751 current = parent;
752 backward_path.push(graph.inner()[current].clone());
753 } else {
754 break;
755 }
756 }
757
758 let mut full_path = forward_path;
760 full_path.extend(backward_path);
761 full_path
762}
763
764#[cfg(test)]
765mod tests {
766 use super::*;
767
768 #[test]
769 fn test_breadth_first_search() {
770 let mut graph: Graph<i32, f64> = Graph::new();
771
772 graph.add_edge(1, 2, 1.0).unwrap();
776 graph.add_edge(2, 3, 1.0).unwrap();
777 graph.add_edge(2, 4, 1.0).unwrap();
778
779 let result = breadth_first_search(&graph, &1).unwrap();
780
781 assert_eq!(result[0], 1);
783 assert_eq!(result[1], 2);
784 assert!(result.contains(&3));
786 assert!(result.contains(&4));
787 assert_eq!(result.len(), 4);
788 }
789
790 #[test]
791 fn test_breadth_first_search_digraph() {
792 let mut graph: DiGraph<i32, f64> = DiGraph::new();
793
794 graph.add_edge(1, 2, 1.0).unwrap();
799 graph.add_edge(2, 3, 1.0).unwrap();
800 graph.add_edge(2, 4, 1.0).unwrap();
801
802 let result = breadth_first_search_digraph(&graph, &1).unwrap();
803
804 assert_eq!(result[0], 1);
805 assert_eq!(result[1], 2);
806 assert!(result.contains(&3));
807 assert!(result.contains(&4));
808 assert_eq!(result.len(), 4);
809 }
810
811 #[test]
812 fn test_depth_first_search() {
813 let mut graph: Graph<i32, f64> = Graph::new();
814
815 graph.add_edge(1, 2, 1.0).unwrap();
817 graph.add_edge(1, 3, 1.0).unwrap();
818 graph.add_edge(2, 4, 1.0).unwrap();
819
820 let result = depth_first_search(&graph, &1).unwrap();
821
822 assert_eq!(result[0], 1);
824 assert_eq!(result.len(), 4);
825 assert!(result.contains(&2));
826 assert!(result.contains(&3));
827 assert!(result.contains(&4));
828 }
829
830 #[test]
831 fn test_depth_first_search_digraph() {
832 let mut graph: DiGraph<i32, f64> = DiGraph::new();
833
834 graph.add_edge(1, 2, 1.0).unwrap();
836 graph.add_edge(1, 3, 1.0).unwrap();
837 graph.add_edge(2, 4, 1.0).unwrap();
838
839 let result = depth_first_search_digraph(&graph, &1).unwrap();
840
841 assert_eq!(result[0], 1);
842 assert_eq!(result.len(), 4);
843 assert!(result.contains(&2));
844 assert!(result.contains(&3));
845 assert!(result.contains(&4));
846 }
847
848 #[test]
849 fn test_bidirectional_search() {
850 let mut graph: Graph<i32, f64> = Graph::new();
851
852 graph.add_edge(1, 2, 1.0).unwrap();
854 graph.add_edge(2, 3, 1.0).unwrap();
855 graph.add_edge(3, 4, 1.0).unwrap();
856 graph.add_edge(4, 5, 1.0).unwrap();
857
858 let path = bidirectional_search(&graph, &1, &5).unwrap().unwrap();
860 assert_eq!(path[0], 1);
861 assert_eq!(path[path.len() - 1], 5);
862 assert!(path.len() <= 5);
863
864 let same_path = bidirectional_search(&graph, &3, &3).unwrap().unwrap();
866 assert_eq!(same_path, vec![3]);
867
868 let mut disconnected: Graph<i32, f64> = Graph::new();
870 disconnected.add_node(1);
871 disconnected.add_node(2);
872 let no_path = bidirectional_search(&disconnected, &1, &2).unwrap();
873 assert_eq!(no_path, None);
874 }
875
876 #[test]
877 fn test_bidirectional_search_digraph() {
878 let mut graph: DiGraph<i32, f64> = DiGraph::new();
879
880 graph.add_edge(1, 2, 1.0).unwrap();
882 graph.add_edge(2, 3, 1.0).unwrap();
883 graph.add_edge(3, 4, 1.0).unwrap();
884 graph.add_edge(4, 5, 1.0).unwrap();
885
886 let path = bidirectional_search_digraph(&graph, &1, &5)
888 .unwrap()
889 .unwrap();
890 assert_eq!(path[0], 1);
891 assert_eq!(path[path.len() - 1], 5);
892
893 let no_path = bidirectional_search_digraph(&graph, &5, &1).unwrap();
895 assert_eq!(no_path, None);
896 }
897
898 #[test]
899 fn test_priority_first_search() {
900 let mut graph: Graph<i32, f64> = Graph::new();
901
902 graph.add_edge(1, 2, 1.0).unwrap();
906 graph.add_edge(2, 3, 1.0).unwrap();
907 graph.add_edge(2, 4, 1.0).unwrap();
908
909 let result = priority_first_search(&graph, &1, |node| *node).unwrap();
911
912 assert_eq!(result[0], 1);
914 assert_eq!(result[1], 2);
915 assert!(result.contains(&3));
916 assert!(result.contains(&4));
917 assert_eq!(result.len(), 4);
918
919 let result_reverse = priority_first_search(&graph, &1, |node| -node).unwrap();
921 assert_eq!(result_reverse[0], 1);
922 assert_eq!(result_reverse[1], 2);
924 assert!(
926 result_reverse.iter().position(|&x| x == 4)
927 < result_reverse.iter().position(|&x| x == 3)
928 );
929 }
930
931 #[test]
932 fn test_priority_first_search_digraph() {
933 let mut graph: DiGraph<i32, f64> = DiGraph::new();
934
935 graph.add_edge(1, 2, 1.0).unwrap();
940 graph.add_edge(2, 3, 1.0).unwrap();
941 graph.add_edge(2, 4, 1.0).unwrap();
942
943 let result = priority_first_search_digraph(&graph, &1, |node| *node).unwrap();
945
946 assert_eq!(result[0], 1);
947 assert_eq!(result[1], 2);
948 assert!(result.contains(&3));
949 assert!(result.contains(&4));
950 assert_eq!(result.len(), 4);
951
952 let result_constant = priority_first_search_digraph(&graph, &1, |_| 1).unwrap();
954 assert_eq!(result_constant[0], 1);
955 assert_eq!(result_constant[1], 2);
956 assert_eq!(result_constant.len(), 4);
957 }
958}