Skip to main content

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}