rust_igraph/algorithms/properties/
is_biregular.rs1use crate::algorithms::properties::is_bipartite::is_bipartite;
14use crate::core::{Graph, IgraphResult};
15
16pub fn is_biregular(graph: &Graph) -> IgraphResult<bool> {
47 let n = graph.vcount();
48 if n == 0 {
49 return Ok(true);
50 }
51
52 let bp = is_bipartite(graph)?;
53 if !bp.is_bipartite {
54 return Ok(false);
55 }
56
57 let mut deg_false: Option<usize> = None;
58 let mut deg_true: Option<usize> = None;
59
60 for v in 0..n {
61 let d = graph.degree(v)?;
62 let side = bp.types[v as usize];
63 let slot = if side { &mut deg_true } else { &mut deg_false };
64 match *slot {
65 None => *slot = Some(d),
66 Some(expected) => {
67 if d != expected {
68 return Ok(false);
69 }
70 }
71 }
72 }
73
74 Ok(true)
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn empty_graph() {
83 let g = Graph::with_vertices(0);
84 assert!(is_biregular(&g).unwrap());
85 }
86
87 #[test]
88 fn single_vertex() {
89 let g = Graph::with_vertices(1);
90 assert!(is_biregular(&g).unwrap());
91 }
92
93 #[test]
94 fn single_edge() {
95 let mut g = Graph::with_vertices(2);
96 g.add_edge(0, 1).unwrap();
97 assert!(is_biregular(&g).unwrap());
98 }
99
100 #[test]
101 fn triangle_not_bipartite() {
102 let mut g = Graph::with_vertices(3);
103 g.add_edge(0, 1).unwrap();
104 g.add_edge(1, 2).unwrap();
105 g.add_edge(2, 0).unwrap();
106 assert!(!is_biregular(&g).unwrap());
107 }
108
109 #[test]
110 fn c4_biregular() {
111 let mut g = Graph::with_vertices(4);
113 g.add_edge(0, 1).unwrap();
114 g.add_edge(1, 2).unwrap();
115 g.add_edge(2, 3).unwrap();
116 g.add_edge(3, 0).unwrap();
117 assert!(is_biregular(&g).unwrap());
118 }
119
120 #[test]
121 fn k23_biregular() {
122 let mut g = Graph::with_vertices(5);
124 g.add_edge(0, 2).unwrap();
125 g.add_edge(0, 3).unwrap();
126 g.add_edge(0, 4).unwrap();
127 g.add_edge(1, 2).unwrap();
128 g.add_edge(1, 3).unwrap();
129 g.add_edge(1, 4).unwrap();
130 assert!(is_biregular(&g).unwrap());
131 }
132
133 #[test]
134 fn k33_biregular() {
135 let mut g = Graph::with_vertices(6);
137 for i in 0..3u32 {
138 for j in 3..6u32 {
139 g.add_edge(i, j).unwrap();
140 }
141 }
142 assert!(is_biregular(&g).unwrap());
143 }
144
145 #[test]
146 fn path_p3_biregular() {
147 let mut g = Graph::with_vertices(3);
149 g.add_edge(0, 1).unwrap();
150 g.add_edge(1, 2).unwrap();
151 assert!(is_biregular(&g).unwrap());
152 }
153
154 #[test]
155 fn path_p4_not_biregular() {
156 let mut g = Graph::with_vertices(4);
158 g.add_edge(0, 1).unwrap();
159 g.add_edge(1, 2).unwrap();
160 g.add_edge(2, 3).unwrap();
161 assert!(!is_biregular(&g).unwrap());
162 }
163
164 #[test]
165 fn star_s4_biregular() {
166 let mut g = Graph::with_vertices(5);
168 g.add_edge(0, 1).unwrap();
169 g.add_edge(0, 2).unwrap();
170 g.add_edge(0, 3).unwrap();
171 g.add_edge(0, 4).unwrap();
172 assert!(is_biregular(&g).unwrap());
173 }
174
175 #[test]
176 fn edgeless_biregular() {
177 let g = Graph::with_vertices(5);
179 assert!(is_biregular(&g).unwrap());
180 }
181
182 #[test]
183 fn disconnected_biregular() {
184 let mut g = Graph::with_vertices(6);
186 g.add_edge(0, 1).unwrap();
187 g.add_edge(0, 2).unwrap();
188 g.add_edge(3, 4).unwrap();
189 g.add_edge(3, 5).unwrap();
190 assert!(is_biregular(&g).unwrap());
191 }
192
193 #[test]
194 fn disconnected_not_biregular() {
195 let mut g = Graph::with_vertices(5);
197 g.add_edge(0, 1).unwrap();
198 g.add_edge(2, 3).unwrap();
199 g.add_edge(2, 4).unwrap();
200 assert!(!is_biregular(&g).unwrap());
207 }
208
209 #[test]
210 fn cube_q3_biregular() {
211 let mut g = Graph::with_vertices(8);
213 let edges = [
214 (0, 1),
215 (0, 2),
216 (0, 4),
217 (1, 3),
218 (1, 5),
219 (2, 3),
220 (2, 6),
221 (3, 7),
222 (4, 5),
223 (4, 6),
224 (5, 7),
225 (6, 7),
226 ];
227 for (u, v) in edges {
228 g.add_edge(u, v).unwrap();
229 }
230 assert!(is_biregular(&g).unwrap());
231 }
232
233 #[test]
234 fn directed_treated_as_undirected() {
235 let mut g = Graph::new(4, true).unwrap();
236 g.add_edge(0, 1).unwrap();
237 g.add_edge(2, 1).unwrap();
238 g.add_edge(2, 3).unwrap();
239 g.add_edge(0, 3).unwrap();
240 assert!(is_biregular(&g).unwrap());
242 }
243}