causal_hub/random/models/graphs/
missing.rs1use rand::{
2 Rng,
3 seq::{IndexedRandom, IteratorRandom, SliceRandom},
4};
5
6use crate::{
7 datasets::{MissingMechanism, MissingType},
8 inference::VStructures,
9 models::{DiGraph, Graph, HasLabels},
10 random::Random,
11 set,
12 types::{Error, Map, Result, Set},
13};
14
15pub struct RngMissingMechanism<'a, R> {
17 rng: &'a mut R,
18 graph: &'a DiGraph,
19 missing: MissingType,
20 probability: f64,
21}
22
23impl<'a, R> RngMissingMechanism<'a, R> {
24 pub fn new(
38 rng: &'a mut R,
39 graph: &'a DiGraph,
40 missing: MissingType,
41 probability: f64,
42 ) -> Result<Self> {
43 if !(0.0..=1.0).contains(&probability) {
45 return Err(Error::InvalidParameter("p", "must be in [0, 1]"));
46 }
47
48 Ok(Self {
49 rng,
50 graph,
51 missing,
52 probability,
53 })
54 }
55}
56
57impl<R: Rng> RngMissingMechanism<'_, R> {
58 pub fn random_mcar(&mut self) -> Result<MissingMechanism> {
65 let v = self.graph.vertices();
67 let n = (v.len() as f64 * self.probability).round() as usize;
69 let model = v.into_iter().sample(self.rng, n);
71 let pr = MissingMechanism::new(
73 self.graph.labels().clone(),
74 model.into_iter().map(|x| (x, set![])).collect(),
75 )?;
76
77 Ok(pr)
78 }
79
80 pub fn random_mar(&mut self) -> Result<MissingMechanism> {
87 let v = self.graph.vertices();
89 let n = (v.len() as f64 * self.probability).round() as usize;
91 let mut pr = MissingMechanism::new(self.graph.labels().clone(), Map::default())?;
93
94 let v_structs = self.graph.v_structures()?;
96
97 let mut model = Set::default();
98 let mut o = Set::default();
99
100 for (x, z, y) in v_structs {
102 if model.len() >= n {
103 break;
104 }
105
106 for &u in &[x, y] {
107 if !model.contains(&u) && !o.contains(&u) {
108 model.insert(u);
109 o.insert(z);
110 pr.insert(u, set![z]);
111
112 if model.len() >= n {
113 break;
114 }
115 }
116 }
117 }
118
119 if model.len() < n {
121 let mut remaining: Vec<_> = v
122 .iter()
123 .copied()
124 .filter(|&u| !model.contains(&u) && !o.contains(&u))
125 .collect();
126 remaining.shuffle(self.rng);
127 let extra_count = (n - model.len()).min(remaining.len());
128 for &u in &remaining[..extra_count] {
129 model.insert(u);
130 }
131 o = v.iter().copied().filter(|u| !model.contains(u)).collect();
132 }
133
134 let vars_obs_vec: Vec<_> = o.iter().copied().collect();
136 for &x in &model {
137 if pr.contains_key(&x) {
138 continue;
139 }
140
141 let predecessors = self.graph.parents(&set![x])?;
142 let successors = self.graph.children(&set![x])?;
143 let neighbors = predecessors.union(&successors).copied().collect::<Set<_>>();
144 let candidates: Vec<_> = neighbors.intersection(&o).copied().collect();
145
146 if let Some(&z) = candidates.choose(self.rng) {
147 pr.insert(x, set![z]);
148 } else if let Some(&z) = vars_obs_vec.choose(self.rng) {
149 pr.insert(x, set![z]);
150 }
151 }
152
153 Ok(pr)
154 }
155
156 pub fn random_mnar(&mut self) -> Result<MissingMechanism> {
163 let v = self.graph.vertices();
165 let n = (v.len() as f64 * self.probability).round() as usize;
167
168 let mut pr = MissingMechanism::new(self.graph.labels().clone(), Map::default())?;
170
171 let v_structs = self.graph.v_structures()?;
173
174 let p_mnar = (n as f64 / 2.0).round() as usize;
175
176 let mut vars_miss_mnar = Set::default();
177 let mut model = Set::default();
178
179 for (x, z, y) in v_structs {
181 if vars_miss_mnar.len() >= p_mnar {
182 break;
183 }
184
185 for &u in &[x, y] {
186 if !model.contains(&u) {
187 vars_miss_mnar.insert(u);
188 model.insert(u);
189 model.insert(z);
190 pr.insert(u, set![z]);
191
192 if vars_miss_mnar.len() >= p_mnar {
193 break;
194 }
195 }
196 }
197 }
198
199 let vars_miss_mar: Vec<_> = model.difference(&vars_miss_mnar).copied().collect();
201 let o: Set<_> = v.iter().copied().filter(|u| !model.contains(u)).collect();
202 let vars_obs_vec: Vec<_> = o.iter().copied().collect();
203
204 for &x in &vars_miss_mar {
205 let predecessors = self.graph.parents(&set![x])?;
206 let successors = self.graph.children(&set![x])?;
207 let neighbors = predecessors.union(&successors).copied().collect::<Set<_>>();
208 let candidates: Vec<_> = neighbors.intersection(&o).copied().collect();
209
210 if let Some(&z) = candidates.choose(self.rng) {
211 pr.insert(x, set![z]);
212 } else if let Some(&z) = vars_obs_vec.choose(self.rng) {
213 pr.insert(x, set![z]);
214 }
215 }
216
217 while model.len() < n {
219 let remaining: Vec<_> = v.iter().copied().filter(|u| !model.contains(u)).collect();
220 if remaining.is_empty() {
221 break;
222 }
223
224 if let Some(&x) = remaining.choose(self.rng) {
225 if let Some(&z) = remaining.choose(self.rng) {
228 model.insert(x);
229 pr.insert(x, set![z]);
230 }
231 }
232 }
233
234 Ok(pr)
235 }
236}
237
238impl<R: Rng> Random for RngMissingMechanism<'_, R> {
239 type Output = Result<MissingMechanism>;
240
241 fn random(&mut self) -> Self::Output {
242 match self.missing {
244 MissingType::MCAR => self.random_mcar(),
245 MissingType::MAR => self.random_mar(),
246 MissingType::MNAR => self.random_mnar(),
247 }
248 }
249}