prepona/algo/shortest_path/
dijkstra.rs1use magnitude::Magnitude;
2use num_traits::{Unsigned, Zero};
3use std::collections::HashMap;
4use std::{any::Any, collections::HashSet};
5
6use crate::provide::{Edges, Graph, Vertices};
7use crate::{
8 graph::{subgraph::ShortestPathSubgraph, Edge, EdgeDir},
9 prelude::Neighbors,
10};
11
12pub struct Dijkstra<W> {
64 visited: Vec<bool>,
65 dist: Vec<Magnitude<W>>,
66 prev: Vec<Magnitude<usize>>,
67}
68
69impl<W: Copy + Ord + Zero + Any + Unsigned> Dijkstra<W> {
70 pub fn init<E, Ty, G>(graph: &G) -> Self
72 where
73 E: Edge<W>,
74 Ty: EdgeDir,
75 G: Edges<W, E> + Vertices + Graph<W, E, Ty>,
76 {
77 let vertex_count = graph.vertex_count();
78
79 Dijkstra {
80 visited: vec![false; vertex_count],
81 dist: vec![Magnitude::PosInfinite; vertex_count],
82 prev: vec![Magnitude::PosInfinite; vertex_count],
83 }
84 }
85
86 fn next_id(&self) -> Option<usize> {
87 self.dist
88 .iter()
89 .enumerate()
90 .filter(|(virt_id, dist)| dist.is_finite() && self.visited[*virt_id] == false)
91 .min_by(|(_, dist1), (_, dist2)| dist1.cmp(dist2))
92 .and_then(|(v_id, _)| Some(v_id))
93 }
94
95 pub fn execute<E, Ty, G>(
105 mut self,
106 graph: &G,
107 src_id: usize,
108 ) -> ShortestPathSubgraph<W, E, Ty, G>
109 where
110 E: Edge<W>,
111 Ty: EdgeDir,
112 G: Edges<W, E> + Neighbors + Vertices + Graph<W, E, Ty>,
113 {
114 let mut edges = vec![];
115
116 let id_map = graph.continuos_id_map();
117
118 let src_virt_id = id_map.virt_id_of(src_id);
119
120 self.dist[src_virt_id] = W::zero().into();
121
122 while let Some(virt_id) = self.next_id() {
123 self.visited[virt_id] = true;
124
125 let real_id = id_map.real_id_of(virt_id);
126
127 for (n_id, edge) in graph.edges_from_unchecked(real_id) {
128 let n_virt_id = id_map.virt_id_of(n_id);
129
130 let alt = self.dist[virt_id] + *edge.get_weight();
131 if alt < self.dist[n_virt_id] {
132 self.dist[n_virt_id] = alt;
133 self.prev[n_virt_id] = virt_id.into();
134
135 edges.retain(|(_, dst_id, _)| *dst_id != n_id); edges.push((real_id, n_id, edge.get_id())); }
138 }
139 }
140
141 let mut distance_map = HashMap::new();
142 for virt_id in 0..graph.vertex_count() {
143 let real_id = id_map.real_id_of(virt_id);
144 distance_map.insert(real_id, self.dist[virt_id]);
145 }
146
147 let vertices = edges
148 .iter()
149 .flat_map(|(src_id, dst_id, _)| vec![*src_id, *dst_id])
150 .chain(std::iter::once(src_id))
151 .collect::<HashSet<usize>>();
152
153 ShortestPathSubgraph::init(graph, edges, vertices, distance_map)
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160 use crate::graph::MatGraph;
161 use crate::storage::{DiMat, Mat};
162
163 #[test]
164 fn one_vertex_undirected_graph() {
165 let mut graph = MatGraph::init(Mat::<usize>::init());
170 let a = graph.add_vertex();
171
172 let sp_subgraph = Dijkstra::init(&graph).execute(&graph, a);
173
174 assert_eq!(sp_subgraph.distance_to(a).unwrap(), 0.into());
177 assert_eq!(sp_subgraph.vertex_count(), 1);
178 assert_eq!(sp_subgraph.vertices()[0], a);
179 assert_eq!(sp_subgraph.edges_count(), 0);
180 }
181
182 #[test]
183 fn one_vertex_directed_graph() {
184 let mut graph = MatGraph::init(DiMat::<usize>::init());
189 let a = graph.add_vertex();
190
191 let sp_subgraph = Dijkstra::init(&graph).execute(&graph, a);
192
193 assert_eq!(sp_subgraph.distance_to(a).unwrap(), 0.into());
194 assert_eq!(sp_subgraph.vertex_count(), 1); assert_eq!(sp_subgraph.vertices()[0], a);
196 assert_eq!(sp_subgraph.edges_count(), 0);
197 }
198
199 #[test]
200 fn trivial_undirected_graph() {
201 let mut graph = MatGraph::init(Mat::<usize>::init());
210 let a = graph.add_vertex();
211 let b = graph.add_vertex();
212 let c = graph.add_vertex();
213 let d = graph.add_vertex();
214 let e = graph.add_vertex();
215
216 graph.add_edge_unchecked(a, b, 6.into());
217 let ad = graph.add_edge_unchecked(a, d, 1.into());
218 let bd = graph.add_edge_unchecked(b, d, 2.into());
219 graph.add_edge_unchecked(b, c, 5.into());
220 graph.add_edge_unchecked(b, e, 2.into());
221 let ce = graph.add_edge_unchecked(c, e, 5.into());
222 let de = graph.add_edge_unchecked(d, e, 1.into());
223
224 let sp_subgraph = Dijkstra::init(&graph).execute(&graph, a);
226
227 assert_eq!(sp_subgraph.vertex_count(), 5);
229 assert_eq!(sp_subgraph.edges_count(), 4);
230 assert!(vec![a, b, c, d, e]
231 .iter()
232 .all(|vertex_id| sp_subgraph.vertices().contains(vertex_id)));
233 assert!(vec![ad, bd, ce, de]
234 .into_iter()
235 .all(|edge_id| sp_subgraph.edge(edge_id).is_ok()));
236 assert_eq!(sp_subgraph.distance_to(a).unwrap(), 0.into());
237 assert_eq!(sp_subgraph.distance_to(b).unwrap(), 3.into());
238 assert_eq!(sp_subgraph.distance_to(c).unwrap(), 7.into());
239 assert_eq!(sp_subgraph.distance_to(d).unwrap(), 1.into());
240 assert_eq!(sp_subgraph.distance_to(e).unwrap(), 2.into());
241 }
242
243 #[test]
244 fn trivial_directed_graph() {
245 let mut graph = MatGraph::init(DiMat::<usize>::init());
255 let a = graph.add_vertex(); let b = graph.add_vertex(); let c = graph.add_vertex(); let d = graph.add_vertex(); let e = graph.add_vertex(); graph.add_edge_unchecked(a, b, 6.into());
262 let ad = graph.add_edge_unchecked(a, d, 1.into());
263 graph.add_edge_unchecked(b, d, 2.into());
264 graph.add_edge_unchecked(b, e, 2.into());
265 let cb = graph.add_edge_unchecked(c, b, 1.into());
266 let ec = graph.add_edge_unchecked(e, c, 1.into());
267 let de = graph.add_edge_unchecked(d, e, 1.into());
268
269 let sp_subgraph = Dijkstra::init(&graph).execute(&graph, a);
271
272 assert_eq!(sp_subgraph.vertex_count(), 5);
274 assert_eq!(sp_subgraph.edges_count(), 4);
275 assert!(vec![a, b, c, d, e]
276 .iter()
277 .all(|vertex_id| sp_subgraph.vertices().contains(vertex_id)));
278 assert!(vec![ad, cb, ec, de]
279 .into_iter()
280 .all(|edge_id| sp_subgraph.edge(edge_id).is_ok()));
281 assert_eq!(sp_subgraph.distance_to(a).unwrap(), 0.into());
282 assert_eq!(sp_subgraph.distance_to(b).unwrap(), 4.into());
283 assert_eq!(sp_subgraph.distance_to(c).unwrap(), 3.into());
284 assert_eq!(sp_subgraph.distance_to(d).unwrap(), 1.into());
285 assert_eq!(sp_subgraph.distance_to(e).unwrap(), 2.into());
286 }
287}