Skip to main content

open_hypergraphs/strict/functor/
traits.rs

1//! Symmetric Monoidal Hypergraph Functors on Open Hypergraphs
2use crate::array::*;
3use crate::category::*;
4use crate::finite_function::*;
5use crate::indexed_coproduct::*;
6use crate::operations::*;
7use crate::semifinite::*;
8
9use crate::strict::open_hypergraph::*;
10
11/// Strict symmetric monoidal hypergraph functors
12pub trait Functor<K: ArrayKind, O1, A1, O2, A2> {
13    /// Action on objects
14    fn map_object(
15        &self,
16        a: &SemifiniteFunction<K, O1>,
17    ) -> IndexedCoproduct<K, SemifiniteFunction<K, O2>>;
18
19    /// Action on *tensoring of operations*, i.e., compute `F(f₀) ● F(f₁) ● .. ● F(fn)` for
20    /// generators `f_i`.
21    fn map_operations(&self, ops: Operations<K, O1, A1>) -> OpenHypergraph<K, O2, A2>;
22
23    /// Action on arrows.
24    /// If you have implemented `map_operations`, you can implement this simply as
25    /// `define_map_arrow(self, f)`.
26    fn map_arrow(&self, f: &OpenHypergraph<K, O1, A1>) -> OpenHypergraph<K, O2, A2>;
27}
28
29/// Define a functor (a mapping on [`OpenHypergraph`]s) by its action on [`Operations`].
30/// This is typically easier than implementing `map_arrow` directly.
31pub fn define_map_arrow<K: ArrayKind, O1, A1, O2, A2, F: Functor<K, O1, A1, O2, A2>>(
32    functor: &F,
33    f: &OpenHypergraph<K, O1, A1>,
34    // previously passed map_operations as an argument, but we since added it to the Functor trait
35    // since it's a useful special case.
36    //map_operations: impl Fn(Operations<K, O1, A1>) -> OpenHypergraph<K, O2, A2>,
37) -> OpenHypergraph<K, O2, A2>
38where
39    K::Type<K::I>: NaturalArray<K>,
40
41    K::Type<O1>: Array<K, O1> + PartialEq,
42    K::Type<A1>: Array<K, A1>,
43
44    K::Type<O2>: Array<K, O2> + PartialEq,
45    K::Type<A2>: Array<K, A2>,
46{
47    // Compute the tensoring of operations
48    // Fx = F(x₀) ● F(x₁) ● ... ● F(x_n)
49    //let fx = map_operations(to_operations(f));
50    let fx = functor.map_operations(to_operations(f));
51
52    // Compute the tensoring of objects
53    // Fw = F(w₀) ● F(w₁) ● ... ● ... F(w_n)
54    let fw = functor.map_object(&f.h.w);
55
56    spider_map_arrow::<K, O1, A1, O2, A2>(f, fw, fx)
57}
58
59// Given an arrow `f`, and a functor's action on its objects `fw` and operations `fx`,
60// return the value of the functor applied to `f`.
61pub(crate) fn spider_map_arrow<K: ArrayKind, O1, A1, O2, A2>(
62    f: &OpenHypergraph<K, O1, A1>,
63    fw: IndexedCoproduct<K, SemifiniteFunction<K, O2>>,
64    fx: OpenHypergraph<K, O2, A2>,
65) -> OpenHypergraph<K, O2, A2>
66where
67    K::Type<K::I>: NaturalArray<K>,
68
69    K::Type<O1>: Array<K, O1> + PartialEq,
70    K::Type<A1>: Array<K, A1>,
71
72    K::Type<O2>: Array<K, O2> + PartialEq,
73    K::Type<A2>: Array<K, A2>,
74{
75    // Construct the identity map on the wires of F(w)
76    let i = OpenHypergraph::<K, O2, A2>::identity(fw.values.clone());
77
78    let sx = {
79        let fs = map_half_spider(&fw, &f.s);
80        let e_s = map_half_spider(&fw, &f.h.s.values);
81        OpenHypergraph::<K, O2, A2>::spider(fs, i.t.coproduct(&e_s).unwrap(), i.h.w.clone())
82            .unwrap()
83    };
84
85    let yt = {
86        let ft = map_half_spider(&fw, &f.t);
87        let fe_t = map_half_spider(&fw, &f.h.t.values);
88        OpenHypergraph::<K, O2, A2>::spider(i.s.coproduct(&fe_t).unwrap(), ft, i.h.w.clone())
89            .unwrap()
90    };
91
92    // Construct the diagram
93    //
94    //          sx
95    //   _______|___________
96    //   |                 |
97    //
98    //
99    //           /-----------------------------\
100    //  -- F(s)--                               --- F(t) ---
101    //           \---F(e_s)---F(x)----F(e_t)---/
102    //
103    //
104    //                               |_______________________|
105    //                                           |
106    //                                           yt
107
108    sx.compose(&i.tensor(&fx)).unwrap().compose(&yt).unwrap()
109}
110
111pub(crate) fn to_operations<K: ArrayKind, O, A>(f: &OpenHypergraph<K, O, A>) -> Operations<K, O, A>
112where
113    K::Type<K::I>: NaturalArray<K>,
114    K::Type<O>: Array<K, O>,
115    K::Type<A>: Array<K, A>,
116{
117    Operations {
118        x: f.h.x.clone(),
119        a: f.h.s.map_semifinite(&f.h.w).unwrap(),
120        b: f.h.t.map_semifinite(&f.h.w).unwrap(),
121    }
122}
123
124pub(crate) fn map_half_spider<K: ArrayKind, O>(
125    w: &IndexedCoproduct<K, SemifiniteFunction<K, O>>,
126    f: &FiniteFunction<K>,
127) -> FiniteFunction<K> {
128    w.sources.injections(f).unwrap()
129}