meshed/
graph.rs

1/*
2 * Copyright [2022] [Kevin Velasco]
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::graph::node::Node;
18
19use edge::Edge;
20use std::collections::{HashMap, HashSet};
21use std::fmt::Display;
22
23use dot::{Id, Nodes};
24use std::rc::Rc;
25
26use crate::extract::{Edges, ExtractData, Label, Query};
27
28use crate::graph::traversal::GraphTraversal;
29use crate::identify::{Identifiable, Identity};
30
31pub mod edge;
32pub mod node;
33
34pub mod traversal;
35
36pub type Graph<T> = ConcreteGraph<T>;
37
38pub trait GraphDefinition {
39    type Id: Identity;
40    type Label: Display + Clone;
41    type EdgeMeta;
42    type NodeData: 'static;
43
44    fn build_graph<V, Q>(source: &Q) -> ConcreteGraph<Self>
45    where
46        Q: Query<Self::Id, V>,
47        V: Identifiable<Self::Id>
48            + Edges<Self::Id, Self::EdgeMeta>
49            + ExtractData<Self::NodeData>
50            + Label<Label = Self::Label>,
51        Self: Sized,
52    {
53        let source = source.create_index();
54
55        let mut top_level_edges = source.all().into_iter().map(|value| value.get_id());
56
57        let mut output = HashMap::new();
58        let mut queue: Vec<Self::Id> = vec![];
59        let mut current: Option<Self::Id> = top_level_edges.next();
60        let mut seen_set = HashSet::new();
61        while let Some(current_identity) = current.take() {
62            // get next edges
63            if let Some(next) = queue.pop() {
64                current = Some(next);
65            } else if let Some(id) = top_level_edges.next() {
66                current = Some(id);
67            } else {
68                current = None;
69            }
70
71            if seen_set.contains(&current_identity) {
72                continue;
73            } else {
74                seen_set.insert(current_identity.clone());
75            }
76
77            let value: &V = source
78                .query(&current_identity)
79                .expect("Created a value that doesn't exist in the set");
80            let current_node = output
81                .entry(current_identity.clone() as Self::Id)
82                .or_insert_with(|| {
83                    Node::new(
84                        current_identity.clone(),
85                        value.label(),
86                        value.extract_data(),
87                    )
88                })
89                .clone();
90
91            let edge_iterator = value.edges();
92
93            for edge in edge_iterator {
94                // add the value to the queue
95                queue.push(edge.sink.clone());
96
97                let node = output
98                    .entry(edge.sink.clone() as Self::Id)
99                    .or_insert_with(|| {
100                        let data = source.query(&edge.sink);
101
102                        assert!(
103                            data.is_some(),
104                            "Created node that does not exist {}",
105                            edge.sink.clone()
106                        );
107                        let data = data.unwrap();
108                        Node::new(edge.sink, data.label(), data.extract_data())
109                    })
110                    .clone();
111
112                current_node.insert_edge(node.clone(), edge.meta);
113            }
114        }
115        output.into_values().collect()
116    }
117}
118
119pub struct SimpleGraphDefinition;
120impl GraphDefinition for SimpleGraphDefinition {
121    type Id = i32;
122    type Label = Self::Id;
123    type EdgeMeta = ();
124    type NodeData = ();
125}
126
127trait AbstractGraph {
128    type Definition: GraphDefinition;
129}
130
131pub struct ConcreteGraph<T>
132where
133    T: GraphDefinition,
134{
135    pub(crate) nodes: HashMap<T::Id, Node<T>>,
136}
137
138impl<T> ConcreteGraph<T>
139where
140    T: GraphDefinition,
141{
142    pub fn all_nodes(&self) -> impl Iterator<Item = Node<T>> + '_ {
143        self.nodes.values().cloned()
144    }
145
146    // all of the edges in the entire graph
147    pub fn all_edges(&self) -> impl Iterator<Item = Edge<T>> + '_ {
148        self.nodes
149            .values()
150            .flat_map(|node| node.get_edges().into_iter())
151    }
152
153    pub fn order(&self) -> usize {
154        self.nodes.len()
155    }
156}
157
158impl<T: GraphDefinition> Default for ConcreteGraph<T> {
159    fn default() -> Self {
160        Self {
161            nodes: Default::default(),
162        }
163    }
164}
165
166impl<T> FromIterator<Node<T>> for ConcreteGraph<T>
167where
168    T: GraphDefinition,
169{
170    fn from_iter<I: IntoIterator<Item = Node<T>>>(iter: I) -> Self {
171        let mut map = HashMap::default();
172
173        for node in iter {
174            map.insert(node.get_id(), node);
175        }
176
177        Self { nodes: map }
178    }
179}
180
181impl<'a, T: GraphDefinition> IntoIterator for &'a ConcreteGraph<T> {
182    type Item = Node<T>;
183    type IntoIter = <Vec<Self::Item> as IntoIterator>::IntoIter;
184
185    fn into_iter(self) -> Self::IntoIter {
186        let nodes: Vec<_> = self.nodes.values().cloned().collect();
187        nodes.into_iter()
188    }
189}
190
191impl<T> Query<T::Id, Node<T>> for ConcreteGraph<T>
192where
193    T: GraphDefinition,
194{
195    fn query(&self, identifier: &T::Id) -> Option<&Node<T>> {
196        self.nodes.get(identifier)
197    }
198
199    fn all(&self) -> Vec<&Node<T>> {
200        self.nodes.values().collect()
201    }
202}
203
204impl<T> ConcreteGraph<T>
205where
206    T: GraphDefinition,
207{
208    // takes the current nodes and makes every child point to it's parent and vv
209    pub fn invert(&self) -> Inverted<T> {
210        let edges = self.all_nodes(); // a graph always has edges.
211
212        let mut output_graph = Self::default();
213
214        for existing_node in edges {
215            let node = output_graph
216                .nodes
217                .entry(existing_node.get_id())
218                .or_insert_with(|| existing_node.new_derived())
219                .clone();
220
221            existing_node.with_edges_iter(|edge| {
222                for child in edge {
223                    let child_node = output_graph
224                        .nodes
225                        .entry(child.target.get_id())
226                        .or_insert_with(|| child.target.new_derived())
227                        .clone();
228
229                    child_node.derive_edge(node.clone(), &child);
230                }
231            });
232        }
233
234        Inverted {
235            graph: output_graph,
236        }
237    }
238}
239
240pub struct Inverted<T>
241where
242    T: GraphDefinition,
243{
244    graph: ConcreteGraph<T>,
245}
246
247impl<T> Inverted<T>
248where
249    T: GraphDefinition,
250{
251    pub fn inner(&self) -> &ConcreteGraph<T> {
252        &self.graph
253    }
254
255    pub fn map_project(mut self, traversal: GraphTraversal<T>) -> Self {
256        self.graph = traversal.project_into_graph(&self.graph);
257        self
258    }
259}
260
261impl Graph<SimpleGraphDefinition> {
262    pub fn insert_node(&mut self, node_id: <SimpleGraphDefinition as GraphDefinition>::Id) {
263        self.nodes
264            .entry(node_id.clone())
265            .or_insert_with(|| Node::<SimpleGraphDefinition>::new_bare(node_id));
266    }
267
268    pub fn insert_edge(
269        &mut self,
270        from: <SimpleGraphDefinition as GraphDefinition>::Id,
271        to: <SimpleGraphDefinition as GraphDefinition>::Id,
272    ) {
273        let node = self
274            .nodes
275            .entry(from.clone())
276            .or_insert_with(|| Node::<SimpleGraphDefinition>::new_bare(from))
277            .clone();
278        let target = self
279            .nodes
280            .entry(to.clone())
281            .or_insert_with(|| Node::<SimpleGraphDefinition>::new_bare(to))
282            .clone();
283        node.insert_edge(target, Rc::new(()));
284    }
285}
286
287#[cfg(test)]
288mod test {
289    type SimpleGraph = Graph<SimpleGraphDefinition>;
290
291    use crate::graph::node::Node;
292    use crate::graph::{Graph, GraphDefinition, SimpleGraphDefinition};
293    use std::collections::HashSet;
294
295    use crate::extract::{Edge, Edges, Label, Query};
296    use crate::identify::Identifiable;
297
298    type Id = i32;
299
300    struct Datastore {
301        store: Vec<Data>,
302    }
303
304    struct Data {
305        id: Id,
306        edges: Vec<Id>,
307    }
308
309    impl Label for Data {
310        type Label = Id;
311        fn label(&self) -> Self::Label {
312            self.id
313        }
314    }
315
316    impl Identifiable<Id> for Data {
317        fn get_id(&self) -> Id {
318            self.id.clone()
319        }
320    }
321
322    impl Query<Id, Data> for Datastore {
323        fn query(&self, identifier: &Id) -> Option<&Data> {
324            self.store.iter().find(|data| data.id == *identifier)
325        }
326
327        fn all(&self) -> Vec<&Data> {
328            self.store.iter().collect()
329        }
330    }
331
332    impl<'a> Edges<Id, ()> for Data {
333        fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<Id, ()>> {
334            let next_idx = previous_edge_index.map(|e| e + 1).unwrap_or_default();
335            let edge = self.edges.get(next_idx)?;
336            Some(Edge::new(self.get_id(), edge.clone(), next_idx, ()))
337        }
338    }
339
340    type TestGraph = Graph<SimpleGraph>;
341    #[test]
342    fn graph_can_be_linked_together() {
343        let store = Datastore {
344            store: vec![
345                Data {
346                    id: (1),
347                    edges: vec![(2), (3)],
348                },
349                Data {
350                    id: (2),
351                    edges: vec![(4)],
352                },
353                Data {
354                    id: (3),
355                    edges: vec![(4)],
356                },
357                Data {
358                    id: (4),
359                    edges: vec![(1)],
360                },
361            ],
362        };
363
364        let graph = SimpleGraphDefinition::build_graph(&store);
365
366        let node_edge_compare = |node: &Node<SimpleGraphDefinition>| {
367            let mut coll = vec![];
368            node.with_edges_iter(|edges| {
369                coll.extend(edges.cloned().map(|edge| edge.target.get_id()))
370            });
371            coll
372        };
373
374        let one: Node<SimpleGraphDefinition> = graph
375            .into_iter()
376            .find(|node: &Node<SimpleGraphDefinition>| node.get_id() == (1))
377            .unwrap();
378
379        assert_eq!(node_edge_compare(&one), vec![(2), (3)]);
380        let three = one.get_edge_ref(1).unwrap().target;
381
382        assert_eq!(node_edge_compare(&three), vec![(4)]);
383        let two = one.get_edge_ref(0).unwrap().target;
384        assert_eq!(node_edge_compare(&two), vec![(4)]);
385        let four = two.get_edge_ref(0).unwrap().target;
386        let alt_four = three.get_edge_ref(0).unwrap().target;
387        assert_eq!(node_edge_compare(&alt_four), node_edge_compare(&four));
388
389        assert_eq!(node_edge_compare(&four), vec![(1)]);
390        assert_eq!(node_edge_compare(&alt_four), vec![(1)]);
391    }
392
393    #[test]
394    fn graph_can_be_inverted() {
395        let store = Datastore {
396            store: vec![
397                Data {
398                    id: (1),
399                    edges: vec![(2), (3)],
400                },
401                Data {
402                    id: (2),
403                    edges: vec![(4)],
404                },
405                Data {
406                    id: (3),
407                    edges: vec![(4)],
408                },
409                Data {
410                    id: (4),
411                    edges: vec![(1)],
412                },
413            ],
414        };
415
416        let graph = SimpleGraphDefinition::build_graph(&store);
417        let graph = graph.invert();
418
419        let one = graph
420            .graph
421            .into_iter()
422            .find(|node| node.get_id() == (1))
423            .unwrap();
424
425        let node_edge_compare = |node: &Node<SimpleGraphDefinition>| {
426            let mut coll = vec![];
427            node.with_edges_iter(|edges| {
428                coll.extend(edges.cloned().map(|edge| edge.target.get_id()))
429            });
430            coll
431        };
432
433        assert_eq!(node_edge_compare(&one), vec![(4)]);
434
435        let four = one.get_edge_ref(0).unwrap().target;
436        let three = four.get_edge_ref(1).unwrap().target;
437        let two = four.get_edge_ref(0).unwrap().target;
438
439        assert_eq!(node_edge_compare(&three), vec![(1)]);
440        assert_eq!(node_edge_compare(&two), vec![(1)]);
441
442        let alt_one = two.get_edge_ref(0).unwrap().target;
443        assert_eq!(node_edge_compare(&alt_one), node_edge_compare(&one));
444
445        assert_eq!(
446            HashSet::from_iter(node_edge_compare(&four).into_iter()),
447            HashSet::from([2, 3])
448        );
449        assert_eq!(node_edge_compare(&alt_one), vec![(4)]);
450    }
451}
452impl<'a, T: GraphDefinition> dot::GraphWalk<'a, Node<T>, Edge<T>> for ConcreteGraph<T> {
453    fn nodes(&'a self) -> Nodes<'a, Node<T>> {
454        let nodes = self.all_nodes();
455        Nodes::Owned(nodes.collect())
456    }
457
458    fn edges(&'a self) -> dot::Edges<'a, Edge<T>> {
459        dot::Edges::Owned(self.all_edges().collect())
460    }
461
462    fn source(&'a self, edge: &Edge<T>) -> Node<T> {
463        edge.origin.clone()
464    }
465
466    fn target(&'a self, edge: &Edge<T>) -> Node<T> {
467        edge.target.clone()
468    }
469}
470
471impl<'a, T: GraphDefinition> dot::Labeller<'a, Node<T>, Edge<T>> for ConcreteGraph<T> {
472    fn graph_id(&'a self) -> Id<'a> {
473        Id::new("webpack_stats").unwrap()
474    }
475
476    fn node_id(&'a self, n: &Node<T>) -> Id<'a> {
477        Id::new(n.get_id().escaped()).unwrap()
478    }
479}