rust_igraph/algorithms/properties/
is_gem_free.rs1use crate::core::{Graph, IgraphResult};
11
12pub fn is_gem_free(graph: &Graph) -> IgraphResult<bool> {
32 if graph.is_directed() {
33 return Ok(false);
34 }
35
36 let n = graph.vcount();
37 if n < 5 {
38 return Ok(true);
39 }
40
41 let n_usize = n as usize;
42 let mut adj = vec![vec![false; n_usize]; n_usize];
43 let mut nbrs_list: Vec<Vec<u32>> = Vec::with_capacity(n_usize);
44
45 for v in 0..n {
46 let nbrs = graph.neighbors(v)?;
47 for &w in &nbrs {
48 adj[v as usize][w as usize] = true;
49 }
50 nbrs_list.push(nbrs);
51 }
52
53 for u in 0..n {
58 let u_idx = u as usize;
59 if nbrs_list[u_idx].len() < 4 {
60 continue;
61 }
62
63 let nbrs_u = &nbrs_list[u_idx];
64
65 for (i, &a) in nbrs_u.iter().enumerate() {
69 let ai = a as usize;
70 for &b in &nbrs_u[i + 1..] {
71 let bi = b as usize;
72 if !adj[ai][bi] {
73 continue;
74 }
75 for &c in nbrs_u {
77 if c == a || c == b {
78 continue;
79 }
80 let ci = c as usize;
81 if !adj[bi][ci] || adj[ai][ci] {
82 continue;
83 }
84 for &d in nbrs_u {
87 if d == a || d == b || d == c {
88 continue;
89 }
90 let di = d as usize;
91 if adj[ci][di] && !adj[bi][di] && !adj[ai][di] {
92 return Ok(false);
93 }
94 }
95 }
96 }
97 }
98 }
99
100 Ok(true)
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn empty_graph() {
109 let g = Graph::with_vertices(0);
110 assert!(is_gem_free(&g).unwrap());
111 }
112
113 #[test]
114 fn small_graphs() {
115 let g = Graph::with_vertices(4);
116 assert!(is_gem_free(&g).unwrap());
117 }
118
119 #[test]
120 fn triangle() {
121 let mut g = Graph::with_vertices(3);
122 g.add_edge(0, 1).unwrap();
123 g.add_edge(1, 2).unwrap();
124 g.add_edge(2, 0).unwrap();
125 assert!(is_gem_free(&g).unwrap());
126 }
127
128 #[test]
129 fn gem_graph() {
130 let mut g = Graph::with_vertices(5);
132 g.add_edge(0, 1).unwrap();
133 g.add_edge(0, 2).unwrap();
134 g.add_edge(0, 3).unwrap();
135 g.add_edge(0, 4).unwrap();
136 g.add_edge(1, 2).unwrap();
137 g.add_edge(2, 3).unwrap();
138 g.add_edge(3, 4).unwrap();
139 assert!(!is_gem_free(&g).unwrap());
140 }
141
142 #[test]
143 fn k5() {
144 let mut g = Graph::with_vertices(5);
147 for i in 0..5u32 {
148 for j in (i + 1)..5 {
149 g.add_edge(i, j).unwrap();
150 }
151 }
152 assert!(is_gem_free(&g).unwrap());
153 }
154
155 #[test]
156 fn star_k15() {
157 let mut g = Graph::with_vertices(5);
160 g.add_edge(0, 1).unwrap();
161 g.add_edge(0, 2).unwrap();
162 g.add_edge(0, 3).unwrap();
163 g.add_edge(0, 4).unwrap();
164 assert!(is_gem_free(&g).unwrap());
165 }
166
167 #[test]
168 fn c5_gem_free() {
169 let mut g = Graph::with_vertices(5);
170 g.add_edge(0, 1).unwrap();
171 g.add_edge(1, 2).unwrap();
172 g.add_edge(2, 3).unwrap();
173 g.add_edge(3, 4).unwrap();
174 g.add_edge(4, 0).unwrap();
175 assert!(is_gem_free(&g).unwrap());
176 }
177
178 #[test]
179 fn path_p5_gem_free() {
180 let mut g = Graph::with_vertices(5);
181 g.add_edge(0, 1).unwrap();
182 g.add_edge(1, 2).unwrap();
183 g.add_edge(2, 3).unwrap();
184 g.add_edge(3, 4).unwrap();
185 assert!(is_gem_free(&g).unwrap());
186 }
187
188 #[test]
189 fn wheel_w5_not_gem_free() {
190 let mut g = Graph::with_vertices(6);
192 g.add_edge(0, 1).unwrap();
193 g.add_edge(0, 2).unwrap();
194 g.add_edge(0, 3).unwrap();
195 g.add_edge(0, 4).unwrap();
196 g.add_edge(0, 5).unwrap();
197 g.add_edge(1, 2).unwrap();
198 g.add_edge(2, 3).unwrap();
199 g.add_edge(3, 4).unwrap();
200 g.add_edge(4, 5).unwrap();
201 g.add_edge(5, 1).unwrap();
202 assert!(!is_gem_free(&g).unwrap());
206 }
207
208 #[test]
209 fn directed_returns_false() {
210 let mut g = Graph::new(3, true).unwrap();
211 g.add_edge(0, 1).unwrap();
212 g.add_edge(1, 2).unwrap();
213 g.add_edge(2, 0).unwrap();
214 assert!(!is_gem_free(&g).unwrap());
215 }
216
217 #[test]
218 fn fan_3_plus_universal() {
219 let mut g = Graph::with_vertices(5);
223 g.add_edge(0, 1).unwrap();
224 g.add_edge(0, 2).unwrap();
225 g.add_edge(0, 3).unwrap();
226 g.add_edge(0, 4).unwrap();
227 g.add_edge(1, 2).unwrap();
228 g.add_edge(2, 3).unwrap();
229 assert!(is_gem_free(&g).unwrap());
230 }
231}