Skip to main content

gammalooprs/graph/
ext.rs

1use ahash::AHashMap;
2use itertools::Itertools;
3use linnet::half_edge::{
4    HedgeGraph, HedgeGraphError, NoData, NodeIndex,
5    builder::HedgeGraphBuilder,
6    involution::{HedgePair, Orientation},
7    nodestore::NodeStorageOps,
8};
9use symbolica::graph::Graph as SymbolicaGraph;
10
11pub trait HedgeGraphExt<N, E> {
12    type Error;
13    fn from_sym(graph: SymbolicaGraph<N, E>) -> Self;
14
15    fn to_sym(graph: &Self) -> Result<SymbolicaGraph<&N, &E>, Self::Error>;
16}
17
18impl<N: Clone, E: Clone, S: NodeStorageOps<NodeData = N>> HedgeGraphExt<N, E>
19    for HedgeGraph<E, N, NoData, S>
20{
21    fn from_sym(graph: SymbolicaGraph<N, E>) -> Self {
22        let mut builder = HedgeGraphBuilder::new();
23        let mut map = AHashMap::new();
24
25        for (i, node) in graph.nodes().iter().enumerate() {
26            map.insert(i, builder.add_node(node.data.clone()));
27        }
28
29        // let mut edges = graph.edges().to_vec();
30        // edges.sort_by(|a, b| a.vertices.cmp(&b.vertices));
31
32        for edge in graph
33            .edges()
34            .iter()
35            .sorted_by(|a, b| a.vertices.cmp(&b.vertices))
36        {
37            let vertices = edge.vertices;
38            let source = map[&vertices.0];
39            let sink = map[&vertices.1];
40            builder.add_edge(source, sink, edge.data.clone(), edge.directed);
41        }
42
43        builder.into()
44    }
45
46    type Error = HedgeGraphError;
47
48    fn to_sym(value: &HedgeGraph<E, N, NoData, S>) -> Result<SymbolicaGraph<&N, &E>, Self::Error> {
49        let mut graph = SymbolicaGraph::new();
50        let mut map = AHashMap::new();
51
52        for (n, (_, _, node)) in value.iter_nodes().enumerate() {
53            map.insert(NodeIndex(n), graph.add_node(node));
54        }
55
56        for (i, _, d) in value.iter_edges() {
57            if let HedgePair::Paired { source, sink } = i {
58                let source = map[&value.node_id(source)];
59                let sink = map[&value.node_id(sink)];
60
61                let data = d.data;
62                let orientation = d.orientation;
63
64                match orientation {
65                    Orientation::Default => {
66                        graph
67                            .add_edge(source, sink, true, data)
68                            .map_err(HedgeGraphError::SymbolicaError)?;
69                    }
70                    Orientation::Reversed => {
71                        graph
72                            .add_edge(sink, source, true, data)
73                            .map_err(HedgeGraphError::SymbolicaError)?;
74                    }
75                    Orientation::Undirected => {
76                        graph
77                            .add_edge(source, sink, false, data)
78                            .map_err(HedgeGraphError::SymbolicaError)?;
79                    }
80                }
81            } else {
82                return Err(HedgeGraphError::HasIdentityHedge);
83            }
84        }
85
86        Ok(graph)
87    }
88}