1use std::borrow::Borrow;
2use std::collections::{BTreeMap, BTreeSet, VecDeque};
3use std::fmt;
4
5pub struct Graph<N: Clone, E: Clone> {
6 nodes: im_rc::OrdMap<N, im_rc::OrdMap<N, E>>,
7}
8
9impl<N: Eq + Ord + Clone, E: Default + Clone> Graph<N, E> {
10 pub fn new() -> Graph<N, E> {
11 Graph {
12 nodes: im_rc::OrdMap::new(),
13 }
14 }
15
16 pub fn add(&mut self, node: N) {
17 self.nodes.entry(node).or_insert_with(im_rc::OrdMap::new);
18 }
19
20 pub fn link(&mut self, node: N, child: N) -> &mut E {
21 self.nodes
22 .entry(node)
23 .or_insert_with(im_rc::OrdMap::new)
24 .entry(child)
25 .or_default()
26 }
27
28 pub fn reversed(&self) -> Graph<N, E> {
30 let mut ret = Graph::new();
31
32 for n in self.iter() {
33 ret.add(n.clone());
34 for (m, e) in self.edges(n) {
35 *ret.link(m.clone(), n.clone()) = e.clone();
36 }
37 }
38
39 ret
40 }
41
42 pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool
43 where
44 N: Borrow<Q>,
45 Q: Ord + Eq,
46 {
47 self.nodes.contains_key(k)
48 }
49
50 pub fn edge(&self, from: &N, to: &N) -> Option<&E> {
51 self.nodes.get(from)?.get(to)
52 }
53
54 pub fn edges(&self, from: &N) -> impl Iterator<Item = (&N, &E)> {
55 self.nodes.get(from).into_iter().flat_map(|x| x.iter())
56 }
57
58 pub fn sort(&self) -> Vec<N> {
60 let mut ret = Vec::new();
61 let mut marks = BTreeSet::new();
62
63 for node in self.nodes.keys() {
64 self.sort_inner_visit(node, &mut ret, &mut marks);
65 }
66
67 ret
68 }
69
70 fn sort_inner_visit(&self, node: &N, dst: &mut Vec<N>, marks: &mut BTreeSet<N>) {
71 if !marks.insert(node.clone()) {
72 return;
73 }
74
75 for child in self.nodes[node].keys() {
76 self.sort_inner_visit(child, dst, marks);
77 }
78
79 dst.push(node.clone());
80 }
81
82 pub fn iter(&self) -> impl Iterator<Item = &N> {
83 self.nodes.keys()
84 }
85
86 pub fn len(&self) -> usize {
87 self.nodes.len()
88 }
89
90 pub fn is_path_from_to<'a>(&'a self, from: &'a N, to: &'a N) -> bool {
92 let mut stack = vec![from];
93 let mut seen = BTreeSet::new();
94 seen.insert(from);
95 while let Some(iter) = stack.pop().and_then(|p| self.nodes.get(p)) {
96 for p in iter.keys() {
97 if p == to {
98 return true;
99 }
100 if seen.insert(p) {
101 stack.push(p);
102 }
103 }
104 }
105 false
106 }
107
108 pub fn path_to_bottom<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
117 self.path_to(pkg, |s, p| s.edges(p))
118 }
119
120 pub fn path_to_top<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
129 self.path_to(pkg, |s, pk| {
130 s.nodes
134 .iter()
135 .filter_map(|(p, adjacent)| adjacent.get(pk).map(|e| (p, e)))
136 })
137 }
138}
139
140impl<'s, N: Eq + Ord + Clone + 's, E: Default + Clone + 's> Graph<N, E> {
141 fn path_to<'a, F, I>(&'s self, pkg: &'a N, fn_edge: F) -> Vec<(&'a N, Option<&'a E>)>
142 where
143 I: Iterator<Item = (&'a N, &'a E)>,
144 F: Fn(&'s Self, &'a N) -> I,
145 'a: 's,
146 {
147 let mut back_link = BTreeMap::new();
148 let mut queue = VecDeque::from([pkg]);
149 let mut last = pkg;
150
151 while let Some(p) = queue.pop_front() {
152 last = p;
153 let mut out_edges = true;
154 for (child, edge) in fn_edge(&self, p) {
155 out_edges = false;
156 back_link.entry(child).or_insert_with(|| {
157 queue.push_back(child);
158 (p, edge)
159 });
160 }
161 if out_edges {
162 break;
163 }
164 }
165
166 let mut result = Vec::new();
167 let mut next = last;
168 while let Some((p, e)) = back_link.remove(&next) {
169 result.push((next, Some(e)));
170 next = p;
171 }
172 if result.iter().all(|(n, _)| n != &next) {
173 result.push((next, None));
174 }
175 result.reverse();
176 #[cfg(debug_assertions)]
177 {
178 for x in result.windows(2) {
179 let [(n2, _), (n1, Some(e12))] = x else {
180 unreachable!()
181 };
182 assert!(std::ptr::eq(
183 self.edge(n1, n2).or(self.edge(n2, n1)).unwrap(),
184 *e12
185 ));
186 }
187 let last = result.last().unwrap().0;
188 let set: Vec<_> = result.iter().map(|(k, _)| k).collect();
189 if !fn_edge(&self, last)
190 .filter(|(e, _)| !set.contains(&e))
191 .next()
192 .is_none()
193 {
194 self.print_for_test();
195 unreachable!("The last element in the path should not have outgoing edges");
196 }
197 }
198 result
199 }
200}
201
202#[test]
203fn path_to_case() {
204 let mut new = Graph::new();
205 new.link(0, 3);
206 new.link(1, 0);
207 new.link(2, 0);
208 new.link(2, 1);
209 assert_eq!(
210 new.path_to_bottom(&2),
211 vec![(&2, None), (&0, Some(&())), (&3, Some(&()))]
212 );
213}
214
215#[test]
216fn path_to_self() {
217 let mut new: Graph<i32, ()> = Graph::new();
219 new.link(0, 0);
220 assert_eq!(new.path_to_bottom(&0), vec![(&0, Some(&()))]);
221}
222
223#[test]
224fn reverse() {
225 let mut new: Graph<i32, ()> = Graph::new();
226 new.link(0, 1);
227 new.link(0, 2);
228
229 let mut expected: Graph<i32, ()> = Graph::new();
230 expected.add(0);
231 expected.link(1, 0);
232 expected.link(2, 0);
233 assert_eq!(new.reversed(), expected);
234}
235
236impl<N: Eq + Ord + Clone, E: Default + Clone> Default for Graph<N, E> {
237 fn default() -> Graph<N, E> {
238 Graph::new()
239 }
240}
241
242impl<N: fmt::Display + Eq + Ord + Clone, E: Clone> fmt::Debug for Graph<N, E> {
243 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
244 writeln!(fmt, "Graph {{")?;
245
246 for (n, e) in &self.nodes {
247 writeln!(fmt, " - {}", n)?;
248
249 for n in e.keys() {
250 writeln!(fmt, " - {}", n)?;
251 }
252 }
253
254 write!(fmt, "}}")?;
255
256 Ok(())
257 }
258}
259
260impl<N: Eq + Ord + Clone, E: Clone> Graph<N, E> {
261 #[cfg(debug_assertions)]
267 #[allow(clippy::print_stderr)]
268 fn print_for_test(&self) {
269 let names = self
271 .nodes
272 .keys()
273 .chain(self.nodes.values().flat_map(|vs| vs.keys()))
274 .collect::<BTreeSet<_>>()
275 .into_iter()
276 .collect::<Vec<_>>();
277 let mut new = Graph::new();
278 for n1 in self.nodes.keys() {
279 let name1 = names.binary_search(&n1).unwrap();
280 new.add(name1);
281 for n2 in self.nodes[n1].keys() {
282 let name2 = names.binary_search(&n2).unwrap();
283 *new.link(name1, name2) = ();
284 }
285 }
286 eprintln!("Graph for tests = {new:#?}");
287 }
288}
289
290impl<N: Eq + Ord + Clone, E: Eq + Clone> PartialEq for Graph<N, E> {
291 fn eq(&self, other: &Graph<N, E>) -> bool {
292 self.nodes.eq(&other.nodes)
293 }
294}
295impl<N: Eq + Ord + Clone, E: Eq + Clone> Eq for Graph<N, E> {}
296
297impl<N: Eq + Ord + Clone, E: Clone> Clone for Graph<N, E> {
298 fn clone(&self) -> Graph<N, E> {
299 Graph {
300 nodes: self.nodes.clone(),
301 }
302 }
303}