causal_hub/inference/v_structures.rs
1use itertools::Itertools;
2
3use crate::{
4 models::{DiGraph, Graph},
5 set,
6 types::Result,
7};
8
9/// A trait for v-structures.
10pub trait VStructures {
11 /// Returns the v-structures of the graph.
12 ///
13 /// # Returns
14 ///
15 /// An iterator over the v-structures of the graph.
16 ///
17 fn v_structures(&self) -> Result<Vec<(usize, usize, usize)>>;
18}
19
20impl VStructures for DiGraph {
21 fn v_structures(&self) -> Result<Vec<(usize, usize, usize)>> {
22 // Initialize the v-structures list.
23 let mut v_structs = Vec::new();
24
25 // For each vertex z in the graph ...
26 for &z in &self.vertices() {
27 // ... get its parents.
28 let pa_z = self.parents(&set![z])?;
29 // If the vertex has at least two parents ...
30 if pa_z.len() >= 2 {
31 // ... for each pair of parents (x, y) ...
32 for x_y in pa_z.iter().copied().combinations(2) {
33 let (x, y) = (x_y[0], x_y[1]);
34 // ... if x and y are not connected ...
35 if !self.has_edge(x, y)? && !self.has_edge(y, x)? {
36 // ... then (x, z, y) is a v-structure.
37 v_structs.push((x, z, y));
38 }
39 }
40 }
41 }
42
43 Ok(v_structs)
44 }
45}