1use std::collections::BTreeSet;
2
3use derive_more::derive::{AsRef, Deref, From};
4use graph_cycles::Cycles;
5use itertools::Itertools;
6use petgraph::{
7 Graph,
8 algo::dijkstra,
9 dot::Dot,
10 graph::{EdgeIndex, NodeIndex},
11};
12
13use crate::{
14 common::{Arrow, Imply, LabelledArrow, Quiver},
15 state::EffectiveState,
16};
17
18#[derive(Clone)]
20pub struct GraphDataMap {
21 nodes_graph: Vec<NodeIndex>,
22 nodes_object: Vec<EffectiveState>,
23
24 edges_graph: Vec<EdgeIndex>,
25 edges_object: Vec<LabelledArrow>,
26}
27
28impl GraphDataMap {
29 fn get_state_at_index(&self, index: &NodeIndex) -> Option<&EffectiveState> {
30 self.nodes_object
31 .get(self.nodes_graph.iter().position(|i| i == index)?)
32 }
33
34 fn get_edge_at_index(&self, index: &EdgeIndex) -> Option<&LabelledArrow> {
35 self.edges_object
36 .get(self.edges_graph.iter().position(|i| i == index)?)
37 }
38
39 fn get_edges_from_bounds(
40 &self,
41 source: &EffectiveState,
42 target: &EffectiveState,
43 ) -> Vec<&LabelledArrow> {
44 self.edges_object
45 .iter()
46 .filter(|x| ((**x).arrow.source == *source) && ((**x).arrow.target() == *target))
47 .collect_vec()
48 }
49
50 fn get_edges_from_indexes(
51 &self,
52 source: &NodeIndex,
53 target: &NodeIndex,
54 ) -> Vec<&LabelledArrow> {
55 let source_object = self.get_state_at_index(source);
56 let target_object = self.get_state_at_index(target);
57
58 if let (Some(s), Some(t)) = (source_object, target_object) {
59 self.get_edges_from_bounds(s, t)
60 } else {
61 vec![]
62 }
63 }
64}
65
66type InnerGraph = Graph<String, String>;
67#[derive(Deref, Clone, AsRef, From)]
69pub struct RewriteGraph(InnerGraph);
70
71pub struct GraphWithData {
73 pub data: GraphDataMap,
74 pub graph: RewriteGraph,
75}
76
77impl GraphWithData {
79 pub fn from_arrow_list(q: Quiver) -> Self {
81 let arrows = q.clone();
82 let mut arrows_to_visit = arrows.clone();
83 let mut visited_arrows = BTreeSet::new();
84 let mut nodes = BTreeSet::new();
85 let mut edges = BTreeSet::new();
86
87 while let Some(arrow) = arrows_to_visit.pop_first() {
88 let source = arrow.arrow.source.clone();
89 let target = arrow.arrow.target();
90
91 for ar in arrows.iter() {
92 let ar_source = ar.arrow.source.clone();
93 let ar_target = ar.arrow.target();
94
95 if source.implies(&ar_source) && !(source.implies(&ar_target)) {
96 let new_arrow = ar.move_base_point(source.clone());
100 if visited_arrows.get(&new_arrow).is_none() {
101 arrows_to_visit.insert(new_arrow);
102 }
103 }
104 if target.implies(&ar_source) && !(target.implies(&ar_target)) {
105 let new_arrow = ar.move_base_point(target.clone());
106 if visited_arrows.get(&new_arrow).is_none() {
107 arrows_to_visit.insert(new_arrow);
108 }
109 }
110 }
111 nodes.insert(source.clone());
112 nodes.insert(target.clone());
113 edges.insert((source.clone(), target.clone(), arrow.clone()));
114 visited_arrows.insert(arrow.clone());
115 }
116 let mut graph: Graph<String, String> = Graph::new();
117 let nodes_list = Vec::from_iter(nodes);
118 let edges_list = Vec::from_iter(edges);
119 let nodes_graph_elements: Vec<_> = nodes_list
120 .iter()
121 .map(|s| graph.add_node(s.to_string()))
122 .collect();
123 let edges_graph_elements: Vec<_> = edges_list
124 .iter()
125 .map(|(s, t, a)| {
126 let si = nodes_list.iter().position(|x| x == s).unwrap();
127 let ti = nodes_list.iter().position(|x| x == t).unwrap();
128
129 graph.add_edge(
130 nodes_graph_elements[si],
131 nodes_graph_elements[ti],
132 a.name.clone(),
133 )
134 })
135 .collect();
136
137 let graph_data = GraphDataMap {
138 nodes_graph: nodes_graph_elements,
139 nodes_object: nodes_list,
140 edges_graph: edges_graph_elements,
141 edges_object: edges_list.iter().map(|(_, _, a)| a.clone()).collect(),
142 };
143 GraphWithData {
144 data: graph_data,
145 graph: graph.into(),
146 }
147 }
148
149 pub fn dot<'a>(&'a self) -> Dot<'a, &'a InnerGraph> {
151 let g = self.graph.as_ref();
152 Dot::new(g)
153 }
154
155 pub fn find_cycles<'a>(&'a self) -> Vec<Cycle<'a>> {
156 let raw_cycles = self.graph.as_ref().cycles();
157 let cycles = raw_cycles
158 .iter()
159 .map(|c| Cycle::from_node_indices(self, c.clone()))
160 .collect_vec();
161 cycles
162 }
163
164 pub fn has_cycles(&self) -> bool {
165 self.graph.cycles().iter().len() > 0
166 }
167
168 pub fn sources(&self) -> Vec<&NodeIndex> {
170 self.data
171 .nodes_graph
172 .iter()
173 .filter(|n| {
174 self.graph
175 .neighbors_directed(**n, petgraph::Direction::Incoming)
176 .next()
177 .is_none()
178 })
179 .collect_vec()
180 }
181
182 pub fn sinks(&self) -> Vec<&NodeIndex> {
184 self.data
185 .nodes_graph
186 .iter()
187 .filter(|n| {
188 self.graph
189 .neighbors_directed(**n, petgraph::Direction::Outgoing)
190 .next()
191 .is_none()
192 })
193 .collect_vec()
194 }
195
196 fn sinks_from_node(&self, node: &NodeIndex) -> Vec<NodeIndex> {
197 let shortest_paths = dijkstra(self.graph.as_ref(), *node, None, |_| 1);
198 shortest_paths
199 .iter()
200 .filter_map(|(i, _)| {
201 if self
202 .graph
203 .neighbors_directed(*i, petgraph::Direction::Outgoing)
204 .next()
205 .is_none()
206 {
207 Some(i.clone())
208 } else {
209 None
210 }
211 })
212 .collect_vec()
213 }
214
215 fn longest_paths(&self) -> Vec<(NodeIndex, NodeIndex)> {
217 let sources = self.sources();
218 sources
219 .iter()
220 .flat_map(|x| {
221 self.sinks_from_node(*x)
222 .iter()
223 .map(|y| ((*x).clone(), y.clone()))
224 .collect_vec()
225 })
226 .collect_vec()
227 }
228
229 pub fn find_transformations(&self) -> Vec<Arrow> {
231 self.longest_paths()
232 .iter()
233 .map(|(s, t)| {
234 let source = self
235 .data
236 .get_state_at_index(s)
237 .expect("The state should exist.");
238 let target = self
239 .data
240 .get_state_at_index(t)
241 .expect("The state should exist.");
242
243 source.compute_vector(target)
244 })
245 .collect_vec()
246 }
247}
248
249pub struct Cycle<'a> {
250 arrows: Vec<&'a LabelledArrow>,
251 nodes: Vec<&'a EffectiveState>,
252}
253
254impl<'a> Cycle<'a> {
255 fn from_node_indices(g: &'a GraphWithData, cycle: Vec<NodeIndex>) -> Self {
256 let previous_index = cycle.last().expect("Cycles have length at most one.");
257 let mut previous = g
258 .data
259 .get_state_at_index(previous_index)
260 .expect("No user data in input, so this should always succeed.");
261
262 let mut nodes = Vec::new();
263 let mut arrows = Vec::new();
264 for element in cycle {
265 let node = g
266 .data
267 .get_state_at_index(&element)
268 .expect("Should always succeed.");
269 nodes.push(node);
270 let arrows_between = g.data.get_edges_from_bounds(previous, node);
271 arrows.extend(arrows_between);
272 previous = node;
273 }
274
275 Cycle { arrows, nodes }
276 }
277
278 const LONG_CYCLE: usize = 5;
279 const INDENT: &'static str = " ";
280
281 fn as_string_cycle_node(&self) -> String {
282 let separator = if self.nodes.iter().len() >= Self::LONG_CYCLE {
283 let indent = Self::INDENT;
284 format!("\n{indent}-> ")
285 } else {
286 " -> ".to_string()
287 };
288
289 let inner_string = self.nodes.iter().map(ToString::to_string).join(&separator);
290 format!("Cycle … -> {inner_string} -> …")
291 }
292
293 fn as_string_cycle_arrows(&self) -> String {
294 format!(
295 "Induced by rules: {}",
296 self.arrows.iter().map(|ar| &ar.name).join(", ")
297 )
298 }
299
300 pub fn as_string(&self) -> String {
301 format!(
302 "{}\n{}",
303 self.as_string_cycle_node(),
304 self.as_string_cycle_arrows()
305 )
306 }
307}