open_hypergraphs/
operations.rs

1//! Tensorings of operations
2use crate::array::*;
3use crate::indexed_coproduct::*;
4use crate::semifinite::*;
5
6/// Column-oriented storage of operations and their types.
7#[non_exhaustive] // force construction via new
8pub struct Operations<K: ArrayKind, O, A> {
9    pub x: SemifiniteFunction<K, A>,
10    pub a: IndexedCoproduct<K, SemifiniteFunction<K, O>>,
11    pub b: IndexedCoproduct<K, SemifiniteFunction<K, O>>,
12}
13
14impl<K: ArrayKind, O, A> Operations<K, O, A>
15where
16    K::Type<A>: Array<K, A>,
17    K::Type<O>: Array<K, O>,
18    K::Type<K::I>: NaturalArray<K>, // TODO: can we remove this bound? required only for singleton.
19{
20    /// Safely create a list of operations which is guaranteed to have the right number of source
21    /// and target types for each operation.
22    pub fn new(
23        x: SemifiniteFunction<K, A>,
24        a: IndexedCoproduct<K, SemifiniteFunction<K, O>>,
25        b: IndexedCoproduct<K, SemifiniteFunction<K, O>>,
26    ) -> Option<Self> {
27        (Operations { x, a, b }).validate()
28    }
29
30    /// Ensure this list of operations has a source and target type for each operation label.
31    pub fn validate(self) -> Option<Self> {
32        let n = self.x.len();
33        if n != self.a.len() || n != self.b.len() {
34            None
35        } else {
36            Some(self)
37        }
38    }
39
40    /// A single operation (or a tensoring of length 1)
41    pub fn singleton(x: A, a: SemifiniteFunction<K, O>, b: SemifiniteFunction<K, O>) -> Self {
42        Self {
43            x: SemifiniteFunction::singleton(x),
44            a: IndexedCoproduct::<K, SemifiniteFunction<K, O>>::singleton(a),
45            b: IndexedCoproduct::<K, SemifiniteFunction<K, O>>::singleton(b),
46        }
47    }
48
49    // TODO: use `indexed_coproduct::HasLen`?
50    pub fn len(&self) -> K::I {
51        self.x.len()
52    }
53}
54
55impl<K: ArrayKind, O, A> std::fmt::Debug for Operations<K, O, A>
56where
57    K::Type<A>: std::fmt::Debug,
58    K::Type<O>: std::fmt::Debug,
59    K::Index: std::fmt::Debug,
60{
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        f.debug_struct("Operations")
63            .field("x", &self.x)
64            .field("a", &self.a)
65            .field("b", &self.b)
66            .finish()
67    }
68}
69
70impl<K: ArrayKind, O, A> Clone for Operations<K, O, A>
71where
72    K::Type<A>: Array<K, A>,
73    K::Type<O>: Array<K, O>,
74    K::Type<K::I>: NaturalArray<K>,
75{
76    fn clone(&self) -> Self {
77        Self {
78            x: self.x.clone(),
79            a: self.a.clone(),
80            b: self.b.clone(),
81        }
82    }
83}