rust_igraph/algorithms/properties/
ve_degree_indices.rs1#![allow(
17 clippy::cast_possible_truncation,
18 clippy::cast_precision_loss,
19 clippy::many_single_char_names,
20 clippy::needless_range_loop,
21 clippy::too_many_lines
22)]
23
24use crate::core::{Graph, IgraphResult};
25
26fn ve_degrees(graph: &Graph) -> IgraphResult<Vec<u64>> {
27 let n = graph.vcount() as usize;
28 let mut dve = vec![0_u64; n];
29
30 for v in 0..n {
31 let dv = graph.degree(v as u32)? as u64;
32 let nbs = graph.neighbors(v as u32)?;
33 let mut s_v = 0_u64;
34 for nb in nbs {
35 let du = graph.degree(nb)? as u64;
36 s_v = s_v.saturating_add(du);
37 }
38 dve[v] = dv
39 .saturating_mul(dv)
40 .saturating_add(s_v)
41 .saturating_sub(2 * dv);
42 }
43
44 Ok(dve)
45}
46
47pub fn first_ve_degree_zagreb_alpha(graph: &Graph) -> IgraphResult<u64> {
62 let dve = ve_degrees(graph)?;
63 let mut m1a = 0_u64;
64
65 for &d in &dve {
66 m1a = m1a.saturating_add(d.saturating_mul(d));
67 }
68
69 Ok(m1a)
70}
71
72pub fn first_ve_degree_zagreb_beta(graph: &Graph) -> IgraphResult<u64> {
88 let dve = ve_degrees(graph)?;
89 let mut m1b = 0_u64;
90
91 for (u, v) in graph.edges() {
92 if u == v {
93 continue;
94 }
95 let du = dve[u as usize];
96 let dv = dve[v as usize];
97 m1b = m1b.saturating_add(du.saturating_add(dv));
98 }
99
100 Ok(m1b)
101}
102
103pub fn second_ve_degree_zagreb(graph: &Graph) -> IgraphResult<u64> {
119 let dve = ve_degrees(graph)?;
120 let mut m2 = 0_u64;
121
122 for (u, v) in graph.edges() {
123 if u == v {
124 continue;
125 }
126 let du = dve[u as usize];
127 let dv = dve[v as usize];
128 m2 = m2.saturating_add(du.saturating_mul(dv));
129 }
130
131 Ok(m2)
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 fn single_edge() -> Graph {
139 Graph::from_edges(&[(0, 1)], false, Some(2)).unwrap()
140 }
141
142 fn path3() -> Graph {
143 Graph::from_edges(&[(0, 1), (1, 2)], false, Some(3)).unwrap()
144 }
145
146 fn path4() -> Graph {
147 Graph::from_edges(&[(0, 1), (1, 2), (2, 3)], false, Some(4)).unwrap()
148 }
149
150 fn k3() -> Graph {
151 Graph::from_edges(&[(0, 1), (1, 2), (0, 2)], false, Some(3)).unwrap()
152 }
153
154 fn k4() -> Graph {
155 Graph::from_edges(
156 &[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)],
157 false,
158 Some(4),
159 )
160 .unwrap()
161 }
162
163 fn cycle4() -> Graph {
164 Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 0)], false, Some(4)).unwrap()
165 }
166
167 fn cycle5() -> Graph {
168 Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)], false, Some(5)).unwrap()
169 }
170
171 fn star5() -> Graph {
172 Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (0, 4)], false, Some(5)).unwrap()
173 }
174
175 fn paw() -> Graph {
176 Graph::from_edges(&[(0, 1), (1, 2), (0, 2), (2, 3)], false, Some(4)).unwrap()
177 }
178
179 fn dve(g: &Graph) -> Vec<u64> {
180 ve_degrees(g).unwrap()
181 }
182
183 #[test]
186 fn dve_empty() {
187 let g = Graph::with_vertices(0);
188 assert_eq!(dve(&g), Vec::<u64>::new());
189 }
190
191 #[test]
192 fn dve_isolated() {
193 let g = Graph::with_vertices(3);
194 assert_eq!(dve(&g), vec![0, 0, 0]);
195 }
196
197 #[test]
198 fn dve_single_edge() {
199 assert_eq!(dve(&single_edge()), vec![0, 0]);
202 }
203
204 #[test]
205 fn dve_path3() {
206 assert_eq!(dve(&path3()), vec![1, 2, 1]);
209 }
210
211 #[test]
212 fn dve_path4() {
213 assert_eq!(dve(&path4()), vec![1, 3, 3, 1]);
216 }
217
218 #[test]
219 fn dve_k3() {
220 assert_eq!(dve(&k3()), vec![4, 4, 4]);
222 }
223
224 #[test]
225 fn dve_k4() {
226 assert_eq!(dve(&k4()), vec![12, 12, 12, 12]);
228 }
229
230 #[test]
231 fn dve_cycle4() {
232 assert_eq!(dve(&cycle4()), vec![4, 4, 4, 4]);
234 }
235
236 #[test]
237 fn dve_cycle5() {
238 assert_eq!(dve(&cycle5()), vec![4, 4, 4, 4, 4]);
240 }
241
242 #[test]
243 fn dve_star5() {
244 assert_eq!(dve(&star5()), vec![12, 3, 3, 3, 3]);
247 }
248
249 #[test]
250 fn dve_paw() {
251 assert_eq!(dve(&paw()), vec![5, 5, 8, 2]);
254 }
255
256 #[test]
259 fn m1a_empty() {
260 let g = Graph::with_vertices(0);
261 assert_eq!(first_ve_degree_zagreb_alpha(&g).unwrap(), 0);
262 }
263
264 #[test]
265 fn m1a_isolated() {
266 let g = Graph::with_vertices(5);
267 assert_eq!(first_ve_degree_zagreb_alpha(&g).unwrap(), 0);
268 }
269
270 #[test]
271 fn m1a_single_edge() {
272 assert_eq!(first_ve_degree_zagreb_alpha(&single_edge()).unwrap(), 0);
273 }
274
275 #[test]
276 fn m1a_path3() {
277 assert_eq!(first_ve_degree_zagreb_alpha(&path3()).unwrap(), 6);
279 }
280
281 #[test]
282 fn m1a_path4() {
283 assert_eq!(first_ve_degree_zagreb_alpha(&path4()).unwrap(), 20);
285 }
286
287 #[test]
288 fn m1a_k3() {
289 assert_eq!(first_ve_degree_zagreb_alpha(&k3()).unwrap(), 48);
291 }
292
293 #[test]
294 fn m1a_k4() {
295 assert_eq!(first_ve_degree_zagreb_alpha(&k4()).unwrap(), 576);
297 }
298
299 #[test]
300 fn m1a_cycle4() {
301 assert_eq!(first_ve_degree_zagreb_alpha(&cycle4()).unwrap(), 64);
303 }
304
305 #[test]
306 fn m1a_star5() {
307 assert_eq!(first_ve_degree_zagreb_alpha(&star5()).unwrap(), 180);
309 }
310
311 #[test]
312 fn m1a_paw() {
313 assert_eq!(first_ve_degree_zagreb_alpha(&paw()).unwrap(), 118);
315 }
316
317 #[test]
320 fn m1b_empty() {
321 let g = Graph::with_vertices(0);
322 assert_eq!(first_ve_degree_zagreb_beta(&g).unwrap(), 0);
323 }
324
325 #[test]
326 fn m1b_single_edge() {
327 assert_eq!(first_ve_degree_zagreb_beta(&single_edge()).unwrap(), 0);
328 }
329
330 #[test]
331 fn m1b_path3() {
332 assert_eq!(first_ve_degree_zagreb_beta(&path3()).unwrap(), 6);
334 }
335
336 #[test]
337 fn m1b_path4() {
338 assert_eq!(first_ve_degree_zagreb_beta(&path4()).unwrap(), 14);
340 }
341
342 #[test]
343 fn m1b_k3() {
344 assert_eq!(first_ve_degree_zagreb_beta(&k3()).unwrap(), 24);
346 }
347
348 #[test]
349 fn m1b_k4() {
350 assert_eq!(first_ve_degree_zagreb_beta(&k4()).unwrap(), 144);
352 }
353
354 #[test]
355 fn m1b_cycle4() {
356 assert_eq!(first_ve_degree_zagreb_beta(&cycle4()).unwrap(), 32);
358 }
359
360 #[test]
361 fn m1b_star5() {
362 assert_eq!(first_ve_degree_zagreb_beta(&star5()).unwrap(), 60);
364 }
365
366 #[test]
367 fn m1b_paw() {
368 assert_eq!(first_ve_degree_zagreb_beta(&paw()).unwrap(), 46);
371 }
372
373 #[test]
376 fn m2_empty() {
377 let g = Graph::with_vertices(0);
378 assert_eq!(second_ve_degree_zagreb(&g).unwrap(), 0);
379 }
380
381 #[test]
382 fn m2_single_edge() {
383 assert_eq!(second_ve_degree_zagreb(&single_edge()).unwrap(), 0);
384 }
385
386 #[test]
387 fn m2_path3() {
388 assert_eq!(second_ve_degree_zagreb(&path3()).unwrap(), 4);
390 }
391
392 #[test]
393 fn m2_path4() {
394 assert_eq!(second_ve_degree_zagreb(&path4()).unwrap(), 15);
396 }
397
398 #[test]
399 fn m2_k3() {
400 assert_eq!(second_ve_degree_zagreb(&k3()).unwrap(), 48);
402 }
403
404 #[test]
405 fn m2_k4() {
406 assert_eq!(second_ve_degree_zagreb(&k4()).unwrap(), 864);
408 }
409
410 #[test]
411 fn m2_cycle4() {
412 assert_eq!(second_ve_degree_zagreb(&cycle4()).unwrap(), 64);
414 }
415
416 #[test]
417 fn m2_star5() {
418 assert_eq!(second_ve_degree_zagreb(&star5()).unwrap(), 144);
420 }
421
422 #[test]
423 fn m2_paw() {
424 assert_eq!(second_ve_degree_zagreb(&paw()).unwrap(), 121);
427 }
428
429 #[test]
432 fn m1b_regular_formula() {
433 for g in &[k3(), k4(), cycle4(), cycle5()] {
436 let m = g.ecount() as u64;
437 let r = g.degree(0).unwrap() as u64;
438 let dve_val = 2 * r * (r - 1);
439 let expected = m * 2 * dve_val;
440 assert_eq!(first_ve_degree_zagreb_beta(g).unwrap(), expected);
441 }
442 }
443
444 #[test]
445 fn m2_regular_formula() {
446 for g in &[k3(), k4(), cycle4(), cycle5()] {
448 let m = g.ecount() as u64;
449 let r = g.degree(0).unwrap() as u64;
450 let dve_val = 2 * r * (r - 1);
451 let expected = m * dve_val * dve_val;
452 assert_eq!(second_ve_degree_zagreb(g).unwrap(), expected);
453 }
454 }
455
456 #[test]
457 fn all_positive_for_nontrivial() {
458 for g in &[path3(), k3(), k4(), cycle4(), star5(), paw()] {
459 assert!(first_ve_degree_zagreb_alpha(g).unwrap() > 0);
460 assert!(first_ve_degree_zagreb_beta(g).unwrap() > 0);
461 assert!(second_ve_degree_zagreb(g).unwrap() > 0);
462 }
463 }
464
465 #[test]
466 fn single_edge_all_zero() {
467 let g = single_edge();
469 assert_eq!(first_ve_degree_zagreb_alpha(&g).unwrap(), 0);
470 assert_eq!(first_ve_degree_zagreb_beta(&g).unwrap(), 0);
471 assert_eq!(second_ve_degree_zagreb(&g).unwrap(), 0);
472 }
473}