causal_hub/models/graphs/
directed.rs1use std::collections::VecDeque;
2
3use ndarray::prelude::*;
4use serde::{
5 Deserialize, Deserializer, Serialize, Serializer,
6 de::{MapAccess, Visitor},
7 ser::SerializeMap,
8};
9
10use crate::{
11 impl_json_io,
12 models::{Graph, HasLabels},
13 set,
14 types::{Error, Labels, Result, Set},
15};
16
17#[derive(Clone, Debug, Eq, PartialEq)]
19pub struct DiGraph {
20 labels: Labels,
21 adjacency_matrix: Array2<bool>,
22}
23
24impl DiGraph {
25 #[inline]
27 fn check_vertex(&self, x: usize) -> Result<()> {
28 if x >= self.labels.len() {
29 return Err(Error::IndexOutOfBounds(x));
30 }
31 Ok(())
32 }
33
34 pub fn parents(&self, x: &Set<usize>) -> Result<Set<usize>> {
49 x.iter().try_for_each(|&v| self.check_vertex(v))?;
51
52 let mut parents: Set<_> = x
54 .iter()
55 .flat_map(|&v| {
56 self.adjacency_matrix
57 .column(v)
58 .into_iter()
59 .enumerate()
60 .filter_map(|(y, &has_edge)| has_edge.then_some(y))
61 })
62 .collect();
63
64 parents.sort();
66
67 Ok(parents)
69 }
70
71 pub fn ancestors(&self, x: &Set<usize>) -> Result<Set<usize>> {
86 x.iter().try_for_each(|&v| self.check_vertex(v))?;
88
89 let mut stack = VecDeque::new();
91 let mut visited = set![];
92
93 stack.extend(x);
95
96 while let Some(y) = stack.pop_back() {
98 for z in self.parents(&set![y])? {
100 if !visited.contains(&z) {
102 visited.insert(z);
104 stack.push_back(z);
106 }
107 }
108 }
109
110 visited.sort();
112
113 Ok(visited)
115 }
116
117 pub fn children(&self, x: &Set<usize>) -> Result<Set<usize>> {
132 x.iter().try_for_each(|&v| self.check_vertex(v))?;
134
135 let mut children: Set<_> = x
137 .iter()
138 .flat_map(|&v| {
139 self.adjacency_matrix
140 .row(v)
141 .into_iter()
142 .enumerate()
143 .filter_map(|(y, &has_edge)| has_edge.then_some(y))
144 })
145 .collect();
146
147 children.sort();
149
150 Ok(children)
152 }
153
154 pub fn descendants(&self, x: &Set<usize>) -> Result<Set<usize>> {
169 x.iter().try_for_each(|&v| self.check_vertex(v))?;
171
172 let mut stack = VecDeque::new();
174 let mut visited = set![];
175
176 stack.extend(x);
178
179 while let Some(y) = stack.pop_back() {
181 for z in self.children(&set![y])? {
183 if !visited.contains(&z) {
185 visited.insert(z);
187 stack.push_back(z);
189 }
190 }
191 }
192
193 visited.sort();
195
196 Ok(visited)
198 }
199}
200
201impl HasLabels for DiGraph {
202 fn labels(&self) -> &Labels {
203 &self.labels
204 }
205}
206
207impl Graph for DiGraph {
208 fn empty<I, V>(labels: I) -> Result<Self>
209 where
210 I: IntoIterator<Item = V>,
211 V: AsRef<str>,
212 {
213 let mut n = 0;
215 let mut labels: Labels = labels
217 .into_iter()
218 .inspect(|_| n += 1)
219 .map(|x| x.as_ref().to_owned())
220 .collect();
221
222 if labels.len() != n {
224 return Err(Error::NonUniqueLabels());
225 }
226
227 labels.sort();
229
230 let adjacency_matrix: Array2<_> = Array::from_elem((n, n), false);
232
233 Ok(Self {
234 labels,
235 adjacency_matrix,
236 })
237 }
238
239 fn complete<I, V>(labels: I) -> Result<Self>
240 where
241 I: IntoIterator<Item = V>,
242 V: AsRef<str>,
243 {
244 let mut graph = Self::empty(labels)?;
246 graph.adjacency_matrix.fill(true);
248 graph.adjacency_matrix.diag_mut().fill(false);
250
251 Ok(graph)
252 }
253
254 fn vertices(&self) -> Set<usize> {
255 (0..self.labels.len()).collect()
256 }
257
258 fn has_vertex(&self, x: usize) -> bool {
259 x < self.labels.len()
261 }
262
263 fn add_vertex<V>(&mut self, x: V) -> usize
264 where
265 V: AsRef<str>,
266 {
267 let x = x.as_ref().to_owned();
269 let (i, f) = self.labels.insert_full(x.clone());
271
272 if !f {
274 return i;
276 }
277
278 self.labels.sort();
280
281 debug_assert!(self.labels.contains(&x));
283 debug_assert!(self.labels.iter().is_sorted());
285
286 let i = self
290 .labels
291 .iter()
292 .filter(|&y| y.as_str() < x.as_str())
293 .count();
294
295 let n = self.adjacency_matrix.nrows();
297 let mut adjacency_matrix = Array2::from_elem((n + 1, n + 1), false);
299 adjacency_matrix
301 .slice_mut(s![0..i, 0..i])
302 .assign(&self.adjacency_matrix.slice(s![0..i, 0..i]));
303 adjacency_matrix
305 .slice_mut(s![0..i, (i + 1)..(n + 1)])
306 .assign(&self.adjacency_matrix.slice(s![0..i, i..n]));
307 adjacency_matrix
309 .slice_mut(s![(i + 1)..(n + 1), 0..i])
310 .assign(&self.adjacency_matrix.slice(s![i..n, 0..i]));
311 adjacency_matrix
313 .slice_mut(s![(i + 1)..(n + 1), (i + 1)..(n + 1)])
314 .assign(&self.adjacency_matrix.slice(s![i..n, i..n]));
315 self.adjacency_matrix = adjacency_matrix;
317
318 debug_assert_eq!(self.labels.len(), self.adjacency_matrix.nrows());
320 debug_assert!(self.adjacency_matrix.is_square());
322
323 i
325 }
326
327 fn del_vertex(&mut self, x: usize) -> bool {
328 let Some(label) = self.labels.shift_remove_index(x) else {
330 return false;
332 };
333
334 debug_assert!(!self.labels.contains(&label));
336 debug_assert!(self.labels.iter().is_sorted());
338
339 let n = self.adjacency_matrix.nrows();
341 let mut adjacency_matrix = Array2::from_elem((n - 1, n - 1), false);
343 adjacency_matrix
345 .slice_mut(s![0..x, 0..x])
346 .assign(&self.adjacency_matrix.slice(s![0..x, 0..x]));
347 adjacency_matrix
349 .slice_mut(s![0..x, x..(n - 1)])
350 .assign(&self.adjacency_matrix.slice(s![0..x, (x + 1)..n]));
351 adjacency_matrix
353 .slice_mut(s![x..(n - 1), 0..x])
354 .assign(&self.adjacency_matrix.slice(s![(x + 1)..n, 0..x]));
355 adjacency_matrix
357 .slice_mut(s![x..(n - 1), x..(n - 1)])
358 .assign(&self.adjacency_matrix.slice(s![(x + 1)..n, (x + 1)..n]));
359 self.adjacency_matrix = adjacency_matrix;
361
362 debug_assert_eq!(self.labels.len(), self.adjacency_matrix.nrows());
364 debug_assert!(self.adjacency_matrix.is_square());
366
367 true
368 }
369
370 fn edges(&self) -> Set<(usize, usize)> {
371 self.adjacency_matrix
373 .indexed_iter()
374 .filter_map(|(idx, &has_edge)| has_edge.then_some(idx))
375 .collect()
376 }
377
378 fn has_edge(&self, x: usize, y: usize) -> Result<bool> {
379 self.check_vertex(x)?;
381 self.check_vertex(y)?;
382
383 Ok(self.adjacency_matrix[[x, y]])
384 }
385
386 fn add_edge(&mut self, x: usize, y: usize) -> Result<bool> {
387 self.check_vertex(x)?;
389 self.check_vertex(y)?;
390
391 if self.adjacency_matrix[[x, y]] {
393 return Ok(false);
394 }
395
396 self.adjacency_matrix[[x, y]] = true;
398
399 Ok(true)
400 }
401
402 fn del_edge(&mut self, x: usize, y: usize) -> Result<bool> {
403 self.check_vertex(x)?;
405 self.check_vertex(y)?;
406
407 if !self.adjacency_matrix[[x, y]] {
409 return Ok(false);
410 }
411
412 self.adjacency_matrix[[x, y]] = false;
414
415 Ok(true)
416 }
417
418 fn select(&self, x: &Set<usize>) -> Result<Self>
419 where
420 Self: Sized,
421 {
422 x.iter().try_for_each(|&v| self.check_vertex(v))?;
424
425 let mut x = x.clone();
427 x.sort();
428
429 let labels: Labels = x.iter().map(|&v| self.labels[v].clone()).collect();
431 let mut adjacency_matrix: Array2<bool> = Array::from_elem((x.len(), x.len()), false);
433 for (i, &v_i) in x.iter().enumerate() {
435 for (j, &v_j) in x.iter().enumerate() {
436 adjacency_matrix[[i, j]] = self.adjacency_matrix[[v_i, v_j]];
437 }
438 }
439
440 Self::from_adjacency_matrix(labels, adjacency_matrix)
441 }
442
443 fn from_adjacency_matrix(
444 mut labels: Labels,
445 mut adjacency_matrix: Array2<bool>,
446 ) -> Result<Self> {
447 if labels.len() != adjacency_matrix.nrows() {
449 return Err(Error::IncompatibleShape(
450 &labels.len().to_string(),
451 &adjacency_matrix.nrows().to_string(),
452 ));
453 }
454 if adjacency_matrix.nrows() != adjacency_matrix.ncols() {
456 return Err(Error::IncompatibleShape(
457 &adjacency_matrix.nrows().to_string(),
458 &adjacency_matrix.ncols().to_string(),
459 ));
460 }
461
462 if !labels.is_sorted() {
464 let mut indices: Vec<usize> = (0..labels.len()).collect();
466 indices.sort_by_key(|&i| &labels[i]);
468 labels.sort();
470 let mut new_adjacency_matrix = adjacency_matrix.clone();
472 indices.iter().enumerate().for_each(|(i, &j)| {
474 new_adjacency_matrix
475 .row_mut(i)
476 .assign(&adjacency_matrix.row(j));
477 });
478 adjacency_matrix = new_adjacency_matrix;
480 let mut new_adjacency_matrix = adjacency_matrix.clone();
482 indices.iter().enumerate().for_each(|(i, &j)| {
484 new_adjacency_matrix
485 .column_mut(i)
486 .assign(&adjacency_matrix.column(j));
487 });
488 adjacency_matrix = new_adjacency_matrix;
490 }
491
492 Ok(Self {
494 labels,
495 adjacency_matrix,
496 })
497 }
498
499 #[inline]
500 fn to_adjacency_matrix(&self) -> Array2<bool> {
501 self.adjacency_matrix.clone()
502 }
503}
504
505impl Serialize for DiGraph {
506 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
507 where
508 S: Serializer,
509 {
510 let edges = self
512 .edges()
513 .into_iter()
514 .map(|(x, y)| {
515 let x = self.index_to_label(x).map_err(serde::ser::Error::custom)?;
516 let y = self.index_to_label(y).map_err(serde::ser::Error::custom)?;
517 Ok((x.to_owned(), y.to_owned()))
518 })
519 .collect::<std::result::Result<Vec<_>, S::Error>>()?;
520
521 let mut map = serializer.serialize_map(Some(3))?;
523
524 map.serialize_entry("labels", &self.labels)?;
526 map.serialize_entry("edges", &edges)?;
528 map.serialize_entry("type", "digraph")?;
530
531 map.end()
533 }
534}
535
536impl<'de> Deserialize<'de> for DiGraph {
537 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
538 where
539 D: Deserializer<'de>,
540 {
541 #[derive(Deserialize)]
542 #[serde(field_identifier, rename_all = "snake_case")]
543 enum Field {
544 Labels,
545 Edges,
546 Type,
547 }
548
549 struct DiGraphVisitor;
550
551 impl<'de> Visitor<'de> for DiGraphVisitor {
552 type Value = DiGraph;
553
554 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
555 formatter.write_str("struct DiGraph")
556 }
557
558 fn visit_map<V>(self, mut map: V) -> std::result::Result<DiGraph, V::Error>
559 where
560 V: MapAccess<'de>,
561 {
562 use serde::de::Error as E;
563
564 let mut labels = None;
566 let mut edges = None;
567 let mut type_ = None;
568
569 while let Some(key) = map.next_key()? {
571 match key {
572 Field::Labels => {
573 if labels.is_some() {
574 return Err(E::duplicate_field("labels"));
575 }
576 labels = Some(map.next_value()?);
577 }
578 Field::Edges => {
579 if edges.is_some() {
580 return Err(E::duplicate_field("edges"));
581 }
582 edges = Some(map.next_value()?);
583 }
584 Field::Type => {
585 if type_.is_some() {
586 return Err(E::duplicate_field("type"));
587 }
588 type_ = Some(map.next_value()?);
589 }
590 }
591 }
592
593 let labels = labels.ok_or_else(|| E::missing_field("labels"))?;
595 let edges = edges.ok_or_else(|| E::missing_field("edges"))?;
596
597 let type_: String = type_.ok_or_else(|| E::missing_field("type"))?;
599 if type_ != "digraph" {
600 return Err(E::custom(format!(
601 "Invalid type for DiGraph: expected 'digraph', found '{type_}'"
602 )));
603 }
604
605 let labels: Labels = labels;
607 let edges: Vec<(String, String)> = edges;
608 let shape = (labels.len(), labels.len());
609 let mut adjacency_matrix = Array2::from_elem(shape, false);
610 edges.into_iter().try_for_each(|(x, y)| {
611 let x = labels
612 .get_index_of(&x)
613 .ok_or_else(|| E::custom(format!("Vertex `{x}` label does not exist")))?;
614 let y = labels
615 .get_index_of(&y)
616 .ok_or_else(|| E::custom(format!("Vertex `{y}` label does not exist")))?;
617 adjacency_matrix[(x, y)] = true;
618 Ok(())
619 })?;
620
621 DiGraph::from_adjacency_matrix(labels, adjacency_matrix)
622 .map_err(|evidence| E::custom(evidence.to_string()))
623 }
624 }
625
626 const FIELDS: &[&str] = &["labels", "edges", "type"];
627
628 deserializer.deserialize_struct("DiGraph", FIELDS, DiGraphVisitor)
629 }
630}
631
632impl_json_io!(DiGraph);