causal_hub/random/models/bayesian_network/categorical/
model.rs1use rand::prelude::*;
2
3use crate::{
4 models::{BN, CatBN, CatSupport},
5 random::{Random, RngCatCPD, RngDag},
6 set,
7 types::{Error, Labels, Result},
8};
9
10pub struct RngCatBN<'a, R>
12where
13 R: Rng,
14{
15 rng: &'a mut R,
16 support: &'a CatSupport,
17 alpha: f64,
18 probability: f64,
19}
20
21impl<'a, R> RngCatBN<'a, R>
22where
23 R: Rng,
24{
25 pub fn new(
44 rng: &'a mut R,
45 support: &'a CatSupport,
46 alpha: f64,
47 probability: f64,
48 ) -> Result<Self> {
49 if alpha <= 0.0 {
51 return Err(Error::InvalidParameter("alpha", "must be positive"));
52 }
53 if !(0.0..=1.0).contains(&probability) {
55 return Err(Error::InvalidParameter("p", "must be in [0, 1]"));
56 }
57
58 Ok(Self {
59 rng,
60 support,
61 alpha,
62 probability,
63 })
64 }
65}
66
67impl<R> Random for RngCatBN<'_, R>
68where
69 R: Rng,
70{
71 type Output = Result<CatBN>;
72
73 fn random(&mut self) -> Self::Output {
74 let labels: Labels = self.support.keys().cloned().collect();
76
77 let graph = RngDag::new(self.rng, &labels, self.probability)?.random()?;
79
80 let cpds = labels
82 .iter()
83 .enumerate()
84 .map(|(i, x)| {
85 let pa_i = graph.parents(&set![i])?;
87 let mut support = CatSupport::default();
89 support.insert(x.clone(), self.support[x].clone());
90 let conditioning_support = pa_i
92 .iter()
93 .map(|&j| {
94 let y = &labels[j];
95 (y.clone(), self.support[y].clone())
96 })
97 .collect();
98 RngCatCPD::new(self.rng, &support, &conditioning_support, self.alpha)?.random()
100 })
101 .collect::<Result<Vec<_>>>()?;
102
103 CatBN::new(graph, cpds)
105 }
106}