rust_igraph/algorithms/properties/
is_complete_bipartite.rs1use crate::algorithms::properties::is_bipartite::{BipartiteResult, is_bipartite};
14use crate::core::{Graph, IgraphResult};
15
16pub fn is_complete_bipartite(graph: &Graph) -> IgraphResult<bool> {
46 let n = graph.vcount();
47
48 if n < 2 {
49 return Ok(false);
50 }
51
52 let bip: BipartiteResult = is_bipartite(graph)?;
53 if !bip.is_bipartite {
54 return Ok(false);
55 }
56
57 let part_a = bip.types.iter().filter(|&&t| t).count();
58 let part_b = bip.types.iter().filter(|&&t| !t).count();
59
60 if part_a == 0 || part_b == 0 {
61 return Ok(false);
62 }
63
64 let expected_edges = part_a.saturating_mul(part_b);
65 Ok(graph.ecount() == expected_edges)
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn empty_graph() {
74 let g = Graph::with_vertices(0);
75 assert!(!is_complete_bipartite(&g).unwrap());
76 }
77
78 #[test]
79 fn single_vertex() {
80 let g = Graph::with_vertices(1);
81 assert!(!is_complete_bipartite(&g).unwrap());
82 }
83
84 #[test]
85 fn single_edge_k11() {
86 let mut g = Graph::with_vertices(2);
87 g.add_edge(0, 1).unwrap();
88 assert!(is_complete_bipartite(&g).unwrap());
89 }
90
91 #[test]
92 fn k12_star() {
93 let mut g = Graph::with_vertices(3);
94 g.add_edge(0, 1).unwrap();
95 g.add_edge(0, 2).unwrap();
96 assert!(is_complete_bipartite(&g).unwrap());
97 }
98
99 #[test]
100 fn k22() {
101 let mut g = Graph::with_vertices(4);
103 g.add_edge(0, 2).unwrap();
104 g.add_edge(0, 3).unwrap();
105 g.add_edge(1, 2).unwrap();
106 g.add_edge(1, 3).unwrap();
107 assert!(is_complete_bipartite(&g).unwrap());
108 }
109
110 #[test]
111 fn k23() {
112 let mut g = Graph::with_vertices(5);
113 for i in 0..2u32 {
114 for j in 2..5u32 {
115 g.add_edge(i, j).unwrap();
116 }
117 }
118 assert!(is_complete_bipartite(&g).unwrap());
119 }
120
121 #[test]
122 fn k33() {
123 let mut g = Graph::with_vertices(6);
124 for i in 0..3u32 {
125 for j in 3..6u32 {
126 g.add_edge(i, j).unwrap();
127 }
128 }
129 assert!(is_complete_bipartite(&g).unwrap());
130 }
131
132 #[test]
133 fn c4_is_k22() {
134 let mut g = Graph::with_vertices(4);
136 g.add_edge(0, 1).unwrap();
137 g.add_edge(1, 2).unwrap();
138 g.add_edge(2, 3).unwrap();
139 g.add_edge(3, 0).unwrap();
140 assert!(is_complete_bipartite(&g).unwrap());
141 }
142
143 #[test]
144 fn c6_not_complete_bipartite() {
145 let mut g = Graph::with_vertices(6);
146 for i in 0..6u32 {
147 g.add_edge(i, (i + 1) % 6).unwrap();
148 }
149 assert!(!is_complete_bipartite(&g).unwrap());
150 }
151
152 #[test]
153 fn triangle_not_bipartite() {
154 let mut g = Graph::with_vertices(3);
155 g.add_edge(0, 1).unwrap();
156 g.add_edge(1, 2).unwrap();
157 g.add_edge(2, 0).unwrap();
158 assert!(!is_complete_bipartite(&g).unwrap());
159 }
160
161 #[test]
162 fn k4_not_bipartite() {
163 let mut g = Graph::with_vertices(4);
164 for i in 0..4u32 {
165 for j in (i + 1)..4 {
166 g.add_edge(i, j).unwrap();
167 }
168 }
169 assert!(!is_complete_bipartite(&g).unwrap());
170 }
171
172 #[test]
173 fn edgeless() {
174 let g = Graph::with_vertices(4);
175 assert!(!is_complete_bipartite(&g).unwrap());
176 }
177
178 #[test]
179 fn two_components_not_complete_bipartite() {
180 let mut g = Graph::with_vertices(4);
182 g.add_edge(0, 1).unwrap();
183 g.add_edge(2, 3).unwrap();
184 assert!(!is_complete_bipartite(&g).unwrap());
185 }
186
187 #[test]
188 fn path_p3_is_k12() {
189 let mut g = Graph::with_vertices(3);
191 g.add_edge(0, 1).unwrap();
192 g.add_edge(1, 2).unwrap();
193 assert!(is_complete_bipartite(&g).unwrap());
194 }
195
196 #[test]
197 fn directed_treated_as_undirected() {
198 let mut g = Graph::new(3, true).unwrap();
200 g.add_edge(0, 1).unwrap();
201 g.add_edge(0, 2).unwrap();
202 assert!(is_complete_bipartite(&g).unwrap());
203 }
204}