rust_igraph/algorithms/properties/
is_claw_free.rs1use crate::core::{Graph, IgraphResult};
17
18pub fn is_claw_free(graph: &Graph) -> IgraphResult<bool> {
46 if graph.is_directed() {
47 return Ok(false);
48 }
49
50 let n = graph.vcount();
51 if n <= 3 {
52 return Ok(true);
54 }
55
56 let n_usize = n as usize;
58 let mut adj = vec![vec![false; n_usize]; n_usize];
59 for v in 0..n {
60 let nbrs = graph.neighbors(v)?;
61 for &w in &nbrs {
62 adj[v as usize][w as usize] = true;
63 }
64 }
65
66 for v in 0..n {
68 let nbrs = graph.neighbors(v)?;
69 let deg = nbrs.len();
70 if deg < 3 {
71 continue;
72 }
73
74 for i in 0..deg {
76 for j in (i + 1)..deg {
77 if adj[nbrs[i] as usize][nbrs[j] as usize] {
78 continue;
79 }
80 for k in (j + 1)..deg {
82 if !adj[nbrs[i] as usize][nbrs[k] as usize]
83 && !adj[nbrs[j] as usize][nbrs[k] as usize]
84 {
85 return Ok(false);
87 }
88 }
89 }
90 }
91 }
92
93 Ok(true)
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn empty_graph() {
102 let g = Graph::with_vertices(0);
103 assert!(is_claw_free(&g).unwrap());
104 }
105
106 #[test]
107 fn single_vertex() {
108 let g = Graph::with_vertices(1);
109 assert!(is_claw_free(&g).unwrap());
110 }
111
112 #[test]
113 fn single_edge() {
114 let mut g = Graph::with_vertices(2);
115 g.add_edge(0, 1).unwrap();
116 assert!(is_claw_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_claw_free(&g).unwrap());
126 }
127
128 #[test]
129 fn k4() {
130 let mut g = Graph::with_vertices(4);
131 g.add_edge(0, 1).unwrap();
132 g.add_edge(0, 2).unwrap();
133 g.add_edge(0, 3).unwrap();
134 g.add_edge(1, 2).unwrap();
135 g.add_edge(1, 3).unwrap();
136 g.add_edge(2, 3).unwrap();
137 assert!(is_claw_free(&g).unwrap());
138 }
139
140 #[test]
141 fn star_k13_is_claw() {
142 let mut g = Graph::with_vertices(4);
143 g.add_edge(0, 1).unwrap();
144 g.add_edge(0, 2).unwrap();
145 g.add_edge(0, 3).unwrap();
146 assert!(!is_claw_free(&g).unwrap());
147 }
148
149 #[test]
150 fn star_k14_not_claw_free() {
151 let mut g = Graph::with_vertices(5);
152 g.add_edge(0, 1).unwrap();
153 g.add_edge(0, 2).unwrap();
154 g.add_edge(0, 3).unwrap();
155 g.add_edge(0, 4).unwrap();
156 assert!(!is_claw_free(&g).unwrap());
157 }
158
159 #[test]
160 fn path_claw_free() {
161 let mut g = Graph::with_vertices(4);
163 g.add_edge(0, 1).unwrap();
164 g.add_edge(1, 2).unwrap();
165 g.add_edge(2, 3).unwrap();
166 assert!(is_claw_free(&g).unwrap());
167 }
168
169 #[test]
170 fn cycle_c5_claw_free() {
171 let mut g = Graph::with_vertices(5);
172 g.add_edge(0, 1).unwrap();
173 g.add_edge(1, 2).unwrap();
174 g.add_edge(2, 3).unwrap();
175 g.add_edge(3, 4).unwrap();
176 g.add_edge(4, 0).unwrap();
177 assert!(is_claw_free(&g).unwrap());
178 }
179
180 #[test]
181 fn line_graph_of_k4() {
182 let mut g = Graph::with_vertices(6);
187 g.add_edge(0, 1).unwrap(); g.add_edge(0, 2).unwrap(); g.add_edge(0, 3).unwrap(); g.add_edge(0, 4).unwrap(); g.add_edge(1, 2).unwrap(); g.add_edge(1, 3).unwrap(); g.add_edge(1, 5).unwrap(); g.add_edge(2, 4).unwrap(); g.add_edge(2, 5).unwrap(); g.add_edge(3, 4).unwrap(); g.add_edge(3, 5).unwrap(); g.add_edge(4, 5).unwrap(); assert!(is_claw_free(&g).unwrap());
205 }
206
207 #[test]
208 fn directed_returns_false() {
209 let mut g = Graph::new(3, true).unwrap();
210 g.add_edge(0, 1).unwrap();
211 g.add_edge(1, 2).unwrap();
212 g.add_edge(2, 0).unwrap();
213 assert!(!is_claw_free(&g).unwrap());
214 }
215
216 #[test]
217 fn diamond_claw_free() {
218 let mut g = Graph::with_vertices(4);
220 g.add_edge(0, 1).unwrap();
221 g.add_edge(0, 2).unwrap();
222 g.add_edge(0, 3).unwrap();
223 g.add_edge(1, 2).unwrap();
224 g.add_edge(2, 3).unwrap();
225 assert!(is_claw_free(&g).unwrap());
229 }
230
231 #[test]
232 fn petersen_not_claw_free() {
233 let mut g = Graph::with_vertices(10);
235 g.add_edge(0, 1).unwrap();
237 g.add_edge(1, 2).unwrap();
238 g.add_edge(2, 3).unwrap();
239 g.add_edge(3, 4).unwrap();
240 g.add_edge(4, 0).unwrap();
241 g.add_edge(5, 7).unwrap();
243 g.add_edge(7, 9).unwrap();
244 g.add_edge(9, 6).unwrap();
245 g.add_edge(6, 8).unwrap();
246 g.add_edge(8, 5).unwrap();
247 g.add_edge(0, 5).unwrap();
249 g.add_edge(1, 6).unwrap();
250 g.add_edge(2, 7).unwrap();
251 g.add_edge(3, 8).unwrap();
252 g.add_edge(4, 9).unwrap();
253 assert!(!is_claw_free(&g).unwrap());
254 }
255
256 #[test]
257 fn two_triangles_sharing_edge_claw_free() {
258 let mut g = Graph::with_vertices(4);
260 g.add_edge(0, 1).unwrap();
261 g.add_edge(1, 2).unwrap();
262 g.add_edge(2, 0).unwrap();
263 g.add_edge(1, 3).unwrap();
264 g.add_edge(2, 3).unwrap();
265 assert!(is_claw_free(&g).unwrap());
266 }
267}