Skip to main content

causal_hub/io/gml/
mod.rs

1mod parser;
2use std::sync::Arc;
3
4pub use parser::*;
5
6use crate::{
7    models::{DiGraph, Graph, HasLabels, UnGraph},
8    types::{Error, Result},
9};
10
11/// Convert a directed graph into the graph-agnostic GML representation.
12impl From<&DiGraph> for GML {
13    fn from(graph: &DiGraph) -> Self {
14        let vertices = graph.labels().clone();
15        let labels: Vec<&String> = graph.labels().iter().collect();
16        let edges = graph
17            .edges()
18            .iter()
19            .map(|&(x, y)| (labels[x].clone(), labels[y].clone()))
20            .collect();
21        Self {
22            graph_type: "digraph".to_string(),
23            vertices,
24            edges,
25        }
26    }
27}
28
29/// Build a directed graph from the graph-agnostic GML representation.
30impl TryFrom<GML> for DiGraph {
31    type Error = Error;
32
33    fn try_from(gml: GML) -> Result<Self> {
34        if gml.graph_type != "digraph" {
35            return Err(Error::InvalidParameter(
36                "gml graph type",
37                "expected 'digraph' for a directed graph",
38            ));
39        }
40        let mut graph = DiGraph::empty(gml.vertices.clone())?;
41        for (stats, t) in gml.edges {
42            let x = graph.label_to_index(&stats)?;
43            let y = graph.label_to_index(&t)?;
44            graph.add_edge(x, y)?;
45        }
46        Ok(graph)
47    }
48}
49
50/// Convert an undirected graph into the graph-agnostic GML representation.
51impl From<&UnGraph> for GML {
52    fn from(graph: &UnGraph) -> Self {
53        let vertices = graph.labels().clone();
54        let labels: Vec<&String> = graph.labels().iter().collect();
55        let edges = graph
56            .edges()
57            .iter()
58            .map(|&(x, y)| (labels[x].clone(), labels[y].clone()))
59            .collect();
60        Self {
61            graph_type: "graph".to_string(),
62            vertices,
63            edges,
64        }
65    }
66}
67
68/// Build an undirected graph from the graph-agnostic GML representation.
69impl TryFrom<GML> for UnGraph {
70    type Error = Error;
71
72    fn try_from(gml: GML) -> Result<Self> {
73        if gml.graph_type != "graph" {
74            return Err(Error::InvalidParameter(
75                "gml graph type",
76                "expected 'graph' for an undirected graph",
77            ));
78        }
79        let mut graph = UnGraph::empty(gml.vertices.clone())?;
80        for (stats, t) in gml.edges {
81            let x = graph.label_to_index(&stats)?;
82            let y = graph.label_to_index(&t)?;
83            graph.add_edge(x, y)?;
84        }
85        Ok(graph)
86    }
87}
88
89impl GmlIO for DiGraph {
90    fn from_gml_string(gml: &str) -> Result<Self> {
91        DiGraph::try_from(GML::from_string(gml)?)
92    }
93
94    fn to_gml_string(&self) -> Result<String> {
95        serialize(&GML::from(self))
96    }
97
98    fn from_gml_file(path: &str) -> Result<Self> {
99        let string =
100            std::fs::read_to_string(path).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
101        Self::from_gml_string(&string)
102    }
103
104    fn to_gml_file(&self, path: &str) -> Result<()> {
105        let string = self.to_gml_string()?;
106        std::fs::write(path, string).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
107        Ok(())
108    }
109}
110
111impl GmlIO for UnGraph {
112    fn from_gml_string(gml: &str) -> Result<Self> {
113        UnGraph::try_from(GML::from_string(gml)?)
114    }
115
116    fn to_gml_string(&self) -> Result<String> {
117        serialize(&GML::from(self))
118    }
119
120    fn from_gml_file(path: &str) -> Result<Self> {
121        let string =
122            std::fs::read_to_string(path).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
123        Self::from_gml_string(&string)
124    }
125
126    fn to_gml_file(&self, path: &str) -> Result<()> {
127        let string = self.to_gml_string()?;
128        std::fs::write(path, string).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
129        Ok(())
130    }
131}