dependent_sort/dependent_sort/
mod.rs1use crate::TopologicalError;
2use std::{
3 cmp::Ordering,
4 collections::{BTreeMap, HashMap, VecDeque},
5 fmt::{Debug, Display},
6 hash::Hash,
7 ops::AddAssign,
8};
9
10mod arithmetic;
11mod display;
12#[allow(dead_code)]
16#[derive(Debug)]
17pub struct DependentSort<'i, T, G> {
18 tasks: Vec<Task<'i, T, G>>,
20 allow_circular: bool,
23}
24
25#[derive(Debug)]
27pub struct Task<'i, T, G> {
28 pub id: &'i T,
30 pub group: Option<&'i G>,
32 pub dependent_tasks: Vec<&'i T>,
34}
35
36#[derive(Debug)]
38pub struct Group<'i, T, G> {
39 pub id: Option<&'i G>,
41 pub tasks: Vec<&'i T>,
43}
44
45#[derive(Debug)]
46struct FinalizeDependencies<'i, T, G> {
47 task_map: Vec<&'i T>,
49 group_map: Vec<&'i G>,
51 virtualized_groups: Vec<isize>,
53 virtualized_dependent_tasks: Vec<Vec<usize>>,
54}
55
56impl<'i, T, G> Task<'i, T, G> {
57 pub fn new(id: &'i T) -> Self {
59 Self { id, group: None, dependent_tasks: vec![] }
60 }
61 pub fn new_with_dependent(id: &'i T, dependent_tasks: Vec<&'i T>) -> Self {
63 Self { id, group: None, dependent_tasks }
64 }
65 pub fn with_group(self, group: &'i G) -> Self {
67 Self { group: Some(group), ..self }
68 }
69}
70
71impl<'i, T, G> DependentSort<'i, T, G>
72where
73 T: PartialEq,
74 G: PartialEq,
75{
76 fn finalize(&self) -> Result<FinalizeDependencies<'i, T, G>, TopologicalError<'i, T, G>> {
77 let mut sorter = FinalizeDependencies::default();
78 for task in &self.tasks {
79 sorter.task_map.push(task.id);
80 if let Some(group) = task.group {
81 if !sorter.group_map.contains(&group) {
82 sorter.group_map.push(group);
83 }
84 }
85 }
86 for task in &self.tasks {
87 sorter.virtualize(task)?;
88 }
89 Ok(sorter)
90 }
91 pub fn sort(&mut self) -> Result<Vec<Task<'i, T, G>>, TopologicalError<'i, T, G>> {
93 let sorter = self.finalize()?;
94 let sorted = double_topological_sort(
95 sorter.virtualized_groups.clone(),
96 sorter.virtualized_groups.len(),
97 sorter.virtualized_dependent_tasks.clone(),
98 );
99 Ok(sorted.into_iter().map(|i| self.tasks[i as usize].clone()).collect())
100 }
101 pub fn sort_grouped(&mut self) -> Result<Vec<Group<'i, T, G>>, TopologicalError<'i, T, G>>
103 where
104 G: PartialEq,
105 {
106 let sorted = self.sort()?;
107 let mut group_index_map: Vec<(&G, usize)> = vec![];
108 let mut grouped: Vec<Group<T, G>> = vec![];
109 'outer: for task in sorted {
110 match task.group {
111 Some(s) => {
112 for (key, position) in group_index_map.iter().map(|(k, v)| (*k, *v)) {
113 if key == s {
115 grouped[position].tasks.push(task.id);
116 continue 'outer;
117 }
118 }
119 group_index_map.push((s, grouped.len()));
121 grouped.push(Group { id: Some(s), tasks: vec![task.id] })
122 }
123 None => grouped.push(Group { id: None, tasks: vec![task.id] }),
124 }
125 }
126 Ok(grouped)
127 }
128 pub fn sort_grouped_hash_specialization(&mut self) -> Result<Vec<Group<'i, T, G>>, TopologicalError<'i, T, G>>
130 where
131 G: PartialEq + Eq + Hash,
132 {
133 let sorted = self.sort()?;
134 let mut group_index_map: HashMap<&G, usize> = HashMap::new();
135 let mut grouped: Vec<Group<T, G>> = vec![];
136 for task in sorted {
137 match task.group {
138 Some(s) => match group_index_map.get(s) {
139 Some(position) => {
140 grouped[*position].tasks.push(task.id);
141 }
142 None => {
143 let position = grouped.len();
144 group_index_map.insert(s, position);
145 grouped.push(Group { id: Some(s), tasks: vec![task.id] })
146 }
147 },
148 None => grouped.push(Group { id: None, tasks: vec![task.id] }),
149 }
150 }
151 Ok(grouped)
152 }
153}
154
155impl<'i, T, G> FinalizeDependencies<'i, T, G>
156where
157 T: PartialEq,
158 G: PartialEq,
159{
160 fn virtualize(&mut self, task: &Task<'i, T, G>) -> Result<(), TopologicalError<'i, T, G>> {
161 let dependent_tasks = self.virtualize_dependent_tasks(&task.dependent_tasks)?;
162 let group_id = match task.group {
163 Some(reals) => self.virtualize_group(reals)? as isize,
164 None => -1,
165 };
166 self.task_map.push(task.id);
167 self.virtualized_groups.push(group_id);
168 self.virtualized_dependent_tasks.push(dependent_tasks);
169 Ok(())
170 }
171 fn virtualize_group(&self, group: &'i G) -> Result<usize, TopologicalError<'i, T, G>> {
172 match self.group_map.iter().position(|x| *x == group) {
173 Some(index) => Ok(index),
174 None => Err(TopologicalError::MissingGroup { group })?,
175 }
176 }
177 fn virtualize_dependent_tasks(&self, input: &[&'i T]) -> Result<Vec<usize>, TopologicalError<'i, T, G>> {
178 let mut output = Vec::with_capacity(input.len());
179 for task in input {
180 match self.task_map.iter().position(|x| x == task) {
181 Some(index) => output.push(index),
182 None => return Err(TopologicalError::MissingTask { task }),
183 }
184 }
185 Ok(output)
186 }
187}
188
189pub fn double_topological_sort(mut group: Vec<isize>, unique_groups: usize, dependent: Vec<Vec<usize>>) -> Vec<isize> {
190 let n = group.len();
191 let mut in_degree = vec![0; n];
192 let mut adj = vec![vec![]; n];
193 for (item, deps) in dependent.iter().enumerate() {
194 for &dep in deps {
195 adj[dep].push(item);
196 in_degree[item] += 1;
197 }
198 }
199 let items_ids = topological_sort(adj, in_degree);
200 if items_ids.len() != n {
201 return vec![];
202 }
203
204 let mut groups = items_ids.into_iter().fold(vec![vec![]; unique_groups], |mut acc, i| {
205 if group[i] == -1 {
206 group[i] = acc.len() as isize;
207 acc.push(vec![]);
208 }
209 acc[group[i] as usize].push(i as isize);
210 acc
211 });
212
213 let mut group_in_degree = vec![0; groups.len()];
214 let mut group_adj = vec![vec![]; groups.len()];
215 for (item, deps) in dependent.into_iter().enumerate() {
216 for dep in deps {
217 let (src, dst) = (group[dep] as usize, group[item] as usize);
218 if src == dst {
219 continue;
220 }
221 group_adj[src].push(dst);
222 group_in_degree[dst] += 1;
223 }
224 }
225 let group_ids = topological_sort(group_adj, group_in_degree);
226 if group_ids.len() != groups.len() {
227 return vec![];
228 }
229
230 group_ids.into_iter().fold(Vec::new(), |mut acc, i| {
231 acc.append(&mut groups[i]);
232 acc
233 })
234}
235
236fn topological_sort(adj: Vec<Vec<usize>>, mut indeg: Vec<u32>) -> Vec<usize> {
237 let mut q = indeg.iter().enumerate().filter(|(_, &d)| d == 0).map(|(node, _)| node).collect::<VecDeque<_>>();
238 let mut ret = Vec::new();
239 while let Some(node) = q.pop_front() {
240 ret.push(node);
241 for &new_node in adj[node].iter() {
242 indeg[new_node] -= 1;
243 if indeg[new_node] == 0 {
244 q.push_back(new_node)
245 }
246 }
247 }
248 ret
249}