1use super::{GraphConversion, IOError};
2use crate::{
3 utils::{fill_bitvector, get_size},
4 WriteGraph,
5};
6
7#[derive(Debug)]
9pub struct Graph {
10 pub bit_vec: Vec<usize>,
11 pub n: usize,
12}
13impl Graph {
14 pub fn from_g6(repr: &str) -> Result<Self, IOError> {
27 let bytes = repr.as_bytes();
28 let n = get_size(bytes, 0)?;
29 let bit_vec = Self::build_bitvector(bytes, n);
30 Ok(Self { bit_vec, n })
31 }
32
33 pub fn from_adj(adj: &[usize]) -> Result<Self, IOError> {
51 let n2 = adj.len();
52 let n = (n2 as f64).sqrt() as usize;
53 if n * n != n2 {
54 return Err(IOError::InvalidAdjacencyMatrix);
55 }
56 let mut bit_vec = vec![0; n * n];
57 for i in 0..n {
58 for j in 0..n {
59 if adj[i * n + j] == 1 {
60 let idx = i * n + j;
61 let jdx = j * n + i;
62 bit_vec[idx] = 1;
63 bit_vec[jdx] = 1;
64 }
65 }
66 }
67 Ok(Self { bit_vec, n })
68 }
69
70 fn build_bitvector(bytes: &[u8], n: usize) -> Vec<usize> {
72 let bv_len = n * (n - 1) / 2;
73 let bit_vec = fill_bitvector(bytes, bv_len, 1);
74 Self::fill_from_triangle(&bit_vec, n)
75 }
76
77 fn fill_from_triangle(tri: &[usize], n: usize) -> Vec<usize> {
79 let mut bit_vec = vec![0; n * n];
80 let mut tri_iter = tri.iter();
81 for i in 1..n {
82 for j in 0..i {
83 let idx = i * n + j;
84 let jdx = j * n + i;
85 let val = *tri_iter.next().unwrap();
86 bit_vec[idx] = val;
87 bit_vec[jdx] = val;
88 }
89 }
90 bit_vec
91 }
92}
93impl GraphConversion for Graph {
94 fn bit_vec(&self) -> &[usize] {
96 &self.bit_vec
97 }
98
99 fn size(&self) -> usize {
101 self.n
102 }
103
104 fn is_directed(&self) -> bool {
106 false
107 }
108}
109impl WriteGraph for Graph {}
110
111#[cfg(test)]
112mod testing {
113 use super::{Graph, GraphConversion, WriteGraph};
114
115 #[test]
116 fn test_graph_n2() {
117 let graph = Graph::from_g6("A_").unwrap();
118 assert_eq!(graph.size(), 2);
119 assert_eq!(graph.bit_vec(), &[0, 1, 1, 0]);
120 }
121
122 #[test]
123 fn test_graph_n2_empty() {
124 let graph = Graph::from_g6("A?").unwrap();
125 assert_eq!(graph.size(), 2);
126 assert_eq!(graph.bit_vec(), &[0, 0, 0, 0]);
127 }
128
129 #[test]
130 fn test_graph_n3() {
131 let graph = Graph::from_g6("Bw").unwrap();
132 assert_eq!(graph.size(), 3);
133 assert_eq!(graph.bit_vec(), &[0, 1, 1, 1, 0, 1, 1, 1, 0]);
134 }
135
136 #[test]
137 fn test_graph_n4() {
138 let graph = Graph::from_g6("C~").unwrap();
139 assert_eq!(graph.size(), 4);
140 assert_eq!(
141 graph.bit_vec(),
142 &[0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0]
143 );
144 }
145
146 #[test]
147 fn test_to_adjacency() {
148 let graph = Graph::from_g6("A_").unwrap();
149 let adj = graph.to_adjmat();
150 assert_eq!(adj, "0 1\n1 0\n");
151 }
152
153 #[test]
154 fn test_to_dot() {
155 let graph = Graph::from_g6("A_").unwrap();
156 let dot = graph.to_dot(None);
157 assert_eq!(dot, "graph {\n0 -- 1;\n}");
158 }
159
160 #[test]
161 fn test_to_dot_with_label() {
162 let graph = Graph::from_g6("A_").unwrap();
163 let dot = graph.to_dot(Some(1));
164 assert_eq!(dot, "graph graph_1 {\n0 -- 1;\n}");
165 }
166
167 #[test]
168 fn test_to_net() {
169 let repr = r"A_";
170 let graph = Graph::from_g6(repr).unwrap();
171 let net = graph.to_net();
172 assert_eq!(net, "*Vertices 2\n1 \"0\"\n2 \"1\"\n*Arcs\n1 2\n2 1\n");
173 }
174
175 #[test]
176 fn test_to_flat() {
177 let repr = r"A_";
178 let graph = Graph::from_g6(repr).unwrap();
179 let flat = graph.to_flat();
180 assert_eq!(flat, "0110");
181 }
182
183 #[test]
184 fn test_write_n2() {
185 let repr = r"A_";
186 let graph = Graph::from_g6(repr).unwrap();
187 let g6 = graph.write_graph();
188 assert_eq!(g6, repr);
189 }
190
191 #[test]
192 fn test_write_n3() {
193 let repr = r"Bw";
194 let graph = Graph::from_g6(repr).unwrap();
195 let g6 = graph.write_graph();
196 assert_eq!(g6, repr);
197 }
198
199 #[test]
200 fn test_write_n4() {
201 let repr = r"C~";
202 let graph = Graph::from_g6(repr).unwrap();
203 let g6 = graph.write_graph();
204 assert_eq!(g6, repr);
205 }
206
207 #[test]
208 fn test_from_adj() {
209 let adj = &[0, 0, 1, 0];
210 let graph = Graph::from_adj(adj).unwrap();
211 assert_eq!(graph.size(), 2);
212 assert_eq!(graph.bit_vec(), &[0, 1, 1, 0]);
213 assert_eq!(graph.write_graph(), "A_");
214 }
215
216 #[test]
217 fn test_from_nonsquare_adj() {
218 let adj = &[0, 0, 1, 0, 1];
219 let graph = Graph::from_adj(adj);
220 assert!(graph.is_err());
221 }
222}