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 }
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}