arboretum_td/
io.rs

1use crate::graph::BaseGraph;
2use crate::graph::HashMapGraph;
3use crate::graph::MutableGraph;
4use crate::tree_decomposition::TreeDecomposition;
5use std::convert::TryFrom;
6use std::io::{BufRead, ErrorKind, Write};
7
8pub struct PaceReader<T: BufRead>(pub T);
9
10pub struct PaceWriter<'a, 'b: 'a, T: Write> {
11    tree_decomposition: &'a TreeDecomposition,
12    graph: &'b HashMapGraph,
13    writer: T,
14}
15
16impl<'a, 'b: 'a, T: Write> PaceWriter<'a, 'b, T> {
17    pub fn output(mut self) -> Result<(), std::io::Error> {
18        let bag_count: usize = self.tree_decomposition.bags.len();
19        let max_bag: usize = self.tree_decomposition.max_bag_size;
20        writeln!(
21            self.writer,
22            "s td {} {} {}",
23            bag_count,
24            max_bag,
25            self.graph.order()
26        )?;
27        for b in self.tree_decomposition.bags() {
28            let mut tmp: Vec<_> = b.vertex_set.iter().copied().collect();
29            tmp.sort_unstable();
30            let vertices: Vec<_> = tmp.iter().map(|i| (i + 1).to_string()).collect();
31            let vertices = vertices.iter().fold(String::new(), |mut acc, v| {
32                acc.push_str(v.as_str());
33                acc.push(' ');
34                acc
35            });
36            writeln!(self.writer, "b {} {}", b.id + 1, vertices)?;
37        }
38        for b in self.tree_decomposition.bags() {
39            for child in b.neighbors.iter().copied().filter(|i| *i > b.id) {
40                writeln!(self.writer, "{} {}", b.id + 1, child + 1)?;
41            }
42        }
43        Ok(())
44    }
45
46    pub fn new(
47        tree_decomposition: &'a TreeDecomposition,
48        graph: &'b HashMapGraph,
49        writer: T,
50    ) -> Self {
51        Self {
52            tree_decomposition,
53            graph,
54            writer,
55        }
56    }
57}
58
59impl<T: BufRead> TryFrom<PaceReader<T>> for HashMapGraph {
60    type Error = std::io::Error;
61
62    fn try_from(reader: PaceReader<T>) -> Result<Self, Self::Error> {
63        let reader = reader.0;
64        let mut graph: Option<HashMapGraph> = None;
65        let mut order: Option<usize> = None;
66        for line in reader.lines() {
67            let line = line?;
68            let elements: Vec<_> = line.split(' ').collect();
69            match elements[0] {
70                "c" => {
71                    // who cares about comments..
72                }
73                "p" => {
74                    order = Some(parse_order(&elements)?);
75                    graph = Some(HashMapGraph::with_capacity(order.unwrap()));
76                    (0..order.unwrap()).for_each(|v| graph.as_mut().unwrap().add_vertex(v));
77                }
78                _ => match graph.as_mut() {
79                    Some(graph) => {
80                        let u = parse_vertex(elements[0], order.unwrap())?;
81                        let v = parse_vertex(elements[1], order.unwrap())?;
82                        graph.add_edge(u, v);
83                    }
84                    None => {
85                        return Err(std::io::Error::new(
86                            ErrorKind::Other,
87                            "Edges encountered before graph creation",
88                        ));
89                    }
90                },
91            };
92        }
93        match graph {
94            Some(graph) => Ok(graph),
95            None => Err(std::io::Error::new(
96                ErrorKind::Other,
97                "No graph created during parsing",
98            )),
99        }
100    }
101}
102
103fn parse_vertex(v: &str, order: usize) -> Result<usize, std::io::Error> {
104    match v.parse::<usize>() {
105        Ok(u) => {
106            if u == 0 || u > order {
107                Err(std::io::Error::new(
108                    std::io::ErrorKind::InvalidInput,
109                    "Invalid vertex label",
110                ))
111            } else {
112                Ok(u - 1)
113            }
114        }
115        Err(_) => Err(std::io::Error::new(
116            std::io::ErrorKind::InvalidInput,
117            "Invalid vertex label",
118        )),
119    }
120}
121
122fn parse_order(elements: &[&str]) -> Result<usize, std::io::Error> {
123    if elements.len() < 3 {
124        return Err(std::io::Error::new(
125            std::io::ErrorKind::InvalidInput,
126            "Invalid line received starting with p",
127        ));
128    }
129    match elements[2].parse::<usize>() {
130        Ok(order) => Ok(order),
131        Err(_) => Err(std::io::Error::new(
132            std::io::ErrorKind::InvalidInput,
133            "Invalid order of graph",
134        )),
135    }
136}