open_hypergraphs/lax/
hypergraph.rs1use crate::array::vec::{VecArray, VecKind};
2use crate::finite_function::*;
3
4use core::fmt::Debug;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
7#[repr(transparent)]
8pub struct NodeId(pub usize);
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11#[repr(transparent)]
12pub struct EdgeId(pub usize);
13
14#[derive(Debug, Clone)]
15pub struct Hyperedge {
16 pub sources: Vec<NodeId>,
17 pub targets: Vec<NodeId>,
18}
19
20pub type Interface = (Vec<NodeId>, Vec<NodeId>);
21
22#[derive(Debug, Clone)]
27pub struct Hypergraph<O, A> {
28 pub nodes: Vec<O>,
30
31 pub edges: Vec<A>,
33
34 pub adjacency: Vec<Hyperedge>,
36
37 pub quotient: (Vec<NodeId>, Vec<NodeId>),
40}
41
42impl<O, A> Hypergraph<O, A> {
43 pub fn empty() -> Self {
45 Hypergraph {
46 nodes: vec![],
47 edges: vec![],
48 adjacency: vec![],
49 quotient: (vec![], vec![]),
50 }
51 }
52
53 pub fn new_node(&mut self, w: O) -> NodeId {
55 let index = self.nodes.len();
56 self.nodes.push(w);
57 NodeId(index)
58 }
59
60 pub fn new_edge(&mut self, x: A, interface: Hyperedge) -> EdgeId {
64 let edge_idx = self.edges.len();
65 self.edges.push(x);
66 self.adjacency.push(interface);
67 EdgeId(edge_idx)
68 }
69
70 pub fn new_operation(
78 &mut self,
79 x: A,
80 source_type: Vec<O>,
81 target_type: Vec<O>,
82 ) -> (EdgeId, Interface) {
83 let sources: Vec<NodeId> = source_type.into_iter().map(|t| self.new_node(t)).collect();
84 let targets: Vec<NodeId> = target_type.into_iter().map(|t| self.new_node(t)).collect();
85 let interface = (sources.clone(), targets.clone());
86 let edge_id = self.new_edge(x, Hyperedge { sources, targets });
87 (edge_id, interface)
88 }
89
90 pub fn unify(&mut self, v: NodeId, w: NodeId) {
97 self.quotient.0.push(v);
99 self.quotient.1.push(w);
100 }
101
102 pub fn add_edge_source(&mut self, edge_id: EdgeId, w: O) -> NodeId {
104 let node_id = self.new_node(w);
105 self.adjacency[edge_id.0].sources.push(node_id);
106 node_id
107 }
108
109 pub fn add_edge_target(&mut self, edge_id: EdgeId, w: O) -> NodeId {
111 let node_id = self.new_node(w);
112 self.adjacency[edge_id.0].targets.push(node_id);
113 node_id
114 }
115}
116
117impl<O: Clone + PartialEq, A: Clone + PartialEq> Hypergraph<O, A> {
118 pub fn quotient(&mut self) -> FiniteFunction<VecKind> {
124 use std::mem::take;
125 let q = self.coequalizer();
126
127 self.nodes = coequalizer_universal(&q, &VecArray(take(&mut self.nodes)))
128 .unwrap()
129 .0;
130
131 for e in &mut self.adjacency {
133 e.sources.iter_mut().for_each(|x| *x = NodeId(q.table[x.0]));
134 e.targets.iter_mut().for_each(|x| *x = NodeId(q.table[x.0]));
135 }
136
137 self.quotient = (vec![], vec![]); q }
142
143 pub fn to_hypergraph(&self) -> crate::prelude::Hypergraph<O, A> {
144 make_hypergraph(self)
145 }
146
147 fn coequalizer(&self) -> FiniteFunction<VecKind> {
148 let s: FiniteFunction<VecKind> = FiniteFunction {
150 table: VecArray(self.quotient.0.iter().map(|x| x.0).collect()),
151 target: self.nodes.len(),
152 };
153
154 let t: FiniteFunction<VecKind> = FiniteFunction {
155 table: VecArray(self.quotient.1.iter().map(|x| x.0).collect()),
156 target: self.nodes.len(),
157 };
158
159 s.coequalizer(&t)
160 .expect("coequalizer must exist for any graph")
161 }
162}
163
164fn make_hypergraph<O: Clone, A: Clone>(
166 h: &Hypergraph<O, A>,
167) -> crate::hypergraph::Hypergraph<VecKind, O, A> {
168 use crate::finite_function::*;
169 use crate::indexed_coproduct::*;
170 use crate::semifinite::*;
171
172 let s = {
173 let mut lengths = Vec::<usize>::with_capacity(h.edges.len());
174 let mut values = Vec::<usize>::new();
175 for e in h.adjacency.iter() {
176 lengths.push(e.sources.len());
177 values.extend(e.sources.iter().map(|x| x.0));
178 }
179
180 let sources = SemifiniteFunction(VecArray(lengths));
181 let values =
182 FiniteFunction::new(VecArray(values), h.nodes.len()).expect("invalid lax::Hypergraph!");
183 IndexedCoproduct::from_semifinite(sources, values).expect("valid IndexedCoproduct")
184 };
185
186 let t = {
187 let mut lengths = Vec::<usize>::with_capacity(h.edges.len());
188 let mut values = Vec::<usize>::new();
189 for e in h.adjacency.iter() {
190 lengths.push(e.targets.len());
191 values.extend(e.targets.iter().map(|x| x.0));
192 }
193
194 let sources = SemifiniteFunction(VecArray(lengths));
195 let values =
196 FiniteFunction::new(VecArray(values), h.nodes.len()).expect("invalid lax::Hypergraph!");
197 IndexedCoproduct::from_semifinite(sources, values).expect("valid IndexedCoproduct")
198 };
199
200 let w = SemifiniteFunction(VecArray(h.nodes.clone()));
201 let x = SemifiniteFunction(VecArray(h.edges.clone()));
202
203 crate::hypergraph::Hypergraph { s, t, w, x }
204}