1use hibitset::BitSet;
2use std::{
3 collections::{BinaryHeap, HashMap, HashSet, VecDeque},
4 convert::TryInto,
5 fmt::Debug,
6 hash::Hash,
7};
8
9pub fn topological_sort<InIndex, OutIndex, F, OrderIndicator, FOrd, Set>(
13 index_set: Set, predecessor_edges: F, order_indicator: FOrd,
14) -> Vec<OutIndex>
15where
16 InIndex: Copy + Hash + Eq + PartialEq + Ord + TryInto<OutIndex>,
17 <InIndex as TryInto<OutIndex>>::Error: Debug,
18 F: Fn(InIndex) -> Vec<InIndex>,
19 OrderIndicator: Ord,
20 FOrd: Fn(InIndex) -> OrderIndicator,
21 Set: SetLike<InIndex> + Default + Clone + IntoIterator<Item = InIndex>,
22{
23 let mut num_next_edges = HashMap::new();
24
25 for me in index_set.clone() {
26 num_next_edges.entry(me).or_insert(0);
27 for prev in predecessor_edges(me) {
28 if index_set.contains(&prev) {
29 *num_next_edges.entry(prev).or_insert(0) += 1;
30 }
31 }
32 }
33
34 let mut candidates = BinaryHeap::new();
35 let mut reversed_indices = Vec::new();
36
37 for me in index_set.clone() {
38 if num_next_edges[&me] == 0 {
39 candidates.push((order_indicator(me), me));
40 }
41 }
42 while let Some((_, me)) = candidates.pop() {
43 reversed_indices.push(me.try_into().expect("index in range"));
44
45 for prev in predecessor_edges(me) {
46 if index_set.contains(&prev) {
47 num_next_edges.entry(prev).and_modify(|e| *e -= 1);
48 if num_next_edges[&prev] == 0 {
49 candidates.push((order_indicator(prev), prev));
50 }
51 }
52 }
53 }
54 reversed_indices.reverse();
55 reversed_indices
56}
57
58pub fn get_future<'a, InIndex, OutIndex, F, FStop, Set, Iter>(
62 index_set: Iter, successor_edges: F, stop_condition: FStop,
63) -> Set
64where
65 InIndex: 'a + Copy + TryInto<OutIndex>,
66 <InIndex as TryInto<OutIndex>>::Error: Debug,
67 OutIndex: 'a + Copy + Hash + Eq + PartialEq + Ord,
68 F: Fn(InIndex) -> Vec<InIndex>,
69 FStop: Fn(InIndex) -> bool,
70 Set: SetLike<OutIndex> + Default,
71 Iter: IntoIterator<Item = InIndex>,
72{
73 let mut queue = VecDeque::new();
74 let mut visited = Set::default();
75 for i in index_set {
76 visited.insert(i.try_into().expect("index in range"));
77 queue.push_back(i);
78 }
79 while let Some(x) = queue.pop_front() {
80 for succ in successor_edges(x) {
81 if stop_condition(succ) {
82 continue;
83 }
84 let out_index = succ.try_into().expect("index in range");
85 if !visited.contains(&out_index) {
86 queue.push_back(succ);
87 visited.insert(out_index);
88 }
89 }
90 }
91 visited
92}
93
94pub trait Graph {
95 type NodeIndex: 'static + Copy + Hash + Eq + PartialEq + Ord;
96}
97
98pub trait DAG: Graph {
100 fn predecessor_edges(
101 &self, node_index: Self::NodeIndex,
102 ) -> Vec<Self::NodeIndex>;
103
104 fn topological_sort_with_order_indicator<OrderIndicator, FOrd, Set>(
105 &self, index_set: Set, order_indicator: FOrd,
106 ) -> Vec<Self::NodeIndex>
107 where
108 OrderIndicator: Ord,
109 FOrd: Fn(Self::NodeIndex) -> OrderIndicator,
110 Set: SetLike<Self::NodeIndex>
111 + Default
112 + Clone
113 + IntoIterator<Item = Self::NodeIndex>,
114 {
115 topological_sort(
116 index_set,
117 |i| self.predecessor_edges(i),
118 order_indicator,
119 )
120 }
121
122 fn topological_sort<Set>(&self, index_set: Set) -> Vec<Self::NodeIndex>
123 where Set: SetLike<Self::NodeIndex>
124 + Default
125 + Clone
126 + IntoIterator<Item = Self::NodeIndex> {
127 self.topological_sort_with_order_indicator(index_set, |_| true)
130 }
131}
132
133pub trait RichDAG: DAG {
134 fn successor_edges(
135 &self, node_index: Self::NodeIndex,
136 ) -> Vec<Self::NodeIndex>;
137
138 fn get_future_with_stop_condition<FStop, Set, Iter>(
139 &self, index_set: Iter, stop_condition: FStop,
140 ) -> Set
141 where
142 FStop: Fn(Self::NodeIndex) -> bool,
143 Set: SetLike<Self::NodeIndex> + Default,
144 Iter: IntoIterator<Item = Self::NodeIndex>,
145 {
146 get_future(index_set, |i| self.successor_edges(i), stop_condition)
147 }
148
149 fn get_future<Set, Iter>(&self, index_set: Iter) -> Set
150 where
151 Set: SetLike<Self::NodeIndex> + Default,
152 Iter: IntoIterator<Item = Self::NodeIndex>,
153 {
154 self.get_future_with_stop_condition(index_set, |_| false)
155 }
156}
157
158pub trait TreeGraph: Graph {
159 fn parent(&self, node_index: Self::NodeIndex) -> Option<Self::NodeIndex>;
160 fn referees(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex>;
161}
162
163pub trait RichTreeGraph: TreeGraph {
164 fn children(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex>;
165 fn referrers(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex>;
166}
167
168impl<T: TreeGraph> DAG for T {
169 fn predecessor_edges(
170 &self, node_index: Self::NodeIndex,
171 ) -> Vec<Self::NodeIndex> {
172 let mut predecessor_edges = self.referees(node_index);
173 if let Some(p) = self.parent(node_index) {
174 predecessor_edges.push(p);
175 }
176 predecessor_edges
177 }
178}
179
180impl<T: RichTreeGraph + DAG> RichDAG for T {
181 fn successor_edges(
182 &self, node_index: Self::NodeIndex,
183 ) -> Vec<Self::NodeIndex> {
184 let mut successor_edges = self.children(node_index);
185 successor_edges.append(&mut self.referrers(node_index));
186 successor_edges
187 }
188}
189
190pub trait SetLike<T> {
191 fn insert(&mut self, i: T) -> bool;
192 fn contains(&self, i: &T) -> bool;
193}
194
195impl<T: Eq + Hash> SetLike<T> for HashSet<T> {
196 fn insert(&mut self, i: T) -> bool { self.insert(i) }
197
198 fn contains(&self, i: &T) -> bool { self.contains(i) }
199}
200
201impl SetLike<u32> for BitSet {
202 fn insert(&mut self, i: u32) -> bool { self.add(i) }
203
204 fn contains(&self, i: &u32) -> bool { self.contains(*i) }
205}