1use 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 from_strict(h: crate::hypergraph::Hypergraph<VecKind, O, A>) -> Self {
54 let mut adjacency = Vec::with_capacity(h.x.0.len());
55 for (sources, targets) in h.s.into_iter().zip(h.t.into_iter()) {
56 adjacency.push(Hyperedge {
57 sources: sources.table.iter().map(|i| NodeId(*i)).collect(),
58 targets: targets.table.iter().map(|i| NodeId(*i)).collect(),
59 })
60 }
61
62 Hypergraph {
63 nodes: h.w.0 .0,
64 edges: h.x.0 .0,
65 adjacency,
66 quotient: (vec![], vec![]),
67 }
68 }
69
70 pub fn discrete(nodes: Vec<O>) -> Self {
71 let mut h = Self::empty();
72 h.nodes = nodes;
73 h
74 }
75
76 pub fn new_node(&mut self, w: O) -> NodeId {
78 let index = self.nodes.len();
79 self.nodes.push(w);
80 NodeId(index)
81 }
82
83 pub fn new_edge(&mut self, x: A, interface: Hyperedge) -> EdgeId {
87 let edge_idx = self.edges.len();
88 self.edges.push(x);
89 self.adjacency.push(interface);
90 EdgeId(edge_idx)
91 }
92
93 pub fn new_operation(
101 &mut self,
102 x: A,
103 source_type: Vec<O>,
104 target_type: Vec<O>,
105 ) -> (EdgeId, Interface) {
106 let sources: Vec<NodeId> = source_type.into_iter().map(|t| self.new_node(t)).collect();
107 let targets: Vec<NodeId> = target_type.into_iter().map(|t| self.new_node(t)).collect();
108 let interface = (sources.clone(), targets.clone());
109 let edge_id = self.new_edge(x, Hyperedge { sources, targets });
110 (edge_id, interface)
111 }
112
113 pub fn unify(&mut self, v: NodeId, w: NodeId) {
120 self.quotient.0.push(v);
122 self.quotient.1.push(w);
123 }
124
125 pub fn add_edge_source(&mut self, edge_id: EdgeId, w: O) -> NodeId {
127 let node_id = self.new_node(w);
128 self.adjacency[edge_id.0].sources.push(node_id);
129 node_id
130 }
131
132 pub fn add_edge_target(&mut self, edge_id: EdgeId, w: O) -> NodeId {
134 let node_id = self.new_node(w);
135 self.adjacency[edge_id.0].targets.push(node_id);
136 node_id
137 }
138}
139
140impl<O: Clone + PartialEq, A: Clone + PartialEq> Hypergraph<O, A> {
141 pub fn quotient(&mut self) -> FiniteFunction<VecKind> {
147 use std::mem::take;
148 let q = self.coequalizer();
149
150 self.nodes = coequalizer_universal(&q, &VecArray(take(&mut self.nodes)))
151 .unwrap()
152 .0;
153
154 for e in &mut self.adjacency {
156 e.sources.iter_mut().for_each(|x| *x = NodeId(q.table[x.0]));
157 e.targets.iter_mut().for_each(|x| *x = NodeId(q.table[x.0]));
158 }
159
160 self.quotient = (vec![], vec![]); q }
165
166 pub fn to_hypergraph(&self) -> crate::prelude::Hypergraph<O, A> {
167 make_hypergraph(self)
168 }
169
170 fn coequalizer(&self) -> FiniteFunction<VecKind> {
171 let s: FiniteFunction<VecKind> = FiniteFunction {
173 table: VecArray(self.quotient.0.iter().map(|x| x.0).collect()),
174 target: self.nodes.len(),
175 };
176
177 let t: FiniteFunction<VecKind> = FiniteFunction {
178 table: VecArray(self.quotient.1.iter().map(|x| x.0).collect()),
179 target: self.nodes.len(),
180 };
181
182 s.coequalizer(&t)
183 .expect("coequalizer must exist for any graph")
184 }
185}
186
187pub(crate) fn finite_function_coproduct(
188 v1: &[NodeId],
189 v2: &[NodeId],
190 target: usize,
191) -> Vec<NodeId> {
192 v1.iter()
193 .cloned()
194 .chain(v2.iter().map(|&s| NodeId(s.0 + target)))
195 .collect()
196}
197
198pub(crate) fn concat<T: Clone>(v1: &[T], v2: &[T]) -> Vec<T> {
199 v1.iter().cloned().chain(v2.iter().cloned()).collect()
200}
201
202impl<O: Clone, A: Clone> Hypergraph<O, A> {
203 pub(crate) fn coproduct(&self, other: &Hypergraph<O, A>) -> Hypergraph<O, A> {
204 let n = self.nodes.len();
205
206 let adjacency = self
207 .adjacency
208 .iter()
209 .cloned()
210 .chain(other.adjacency.iter().map(|edge| Hyperedge {
211 sources: edge.sources.iter().map(|&s| NodeId(s.0 + n)).collect(),
212 targets: edge.targets.iter().map(|&t| NodeId(t.0 + n)).collect(),
213 }))
214 .collect();
215
216 let quotient = (
217 finite_function_coproduct(&self.quotient.0, &other.quotient.0, n),
218 finite_function_coproduct(&self.quotient.1, &other.quotient.1, n),
219 );
220
221 Hypergraph {
222 nodes: concat(&self.nodes, &other.nodes),
223 edges: concat(&self.edges, &other.edges),
224 adjacency,
225 quotient,
226 }
227 }
228}
229
230fn make_hypergraph<O: Clone, A: Clone>(
232 h: &Hypergraph<O, A>,
233) -> crate::hypergraph::Hypergraph<VecKind, O, A> {
234 use crate::finite_function::*;
235 use crate::indexed_coproduct::*;
236 use crate::semifinite::*;
237
238 let s = {
239 let mut lengths = Vec::<usize>::with_capacity(h.edges.len());
240 let mut values = Vec::<usize>::new();
241 for e in h.adjacency.iter() {
242 lengths.push(e.sources.len());
243 values.extend(e.sources.iter().map(|x| x.0));
244 }
245
246 let sources = SemifiniteFunction(VecArray(lengths));
247 let values =
248 FiniteFunction::new(VecArray(values), h.nodes.len()).expect("invalid lax::Hypergraph!");
249 IndexedCoproduct::from_semifinite(sources, values).expect("valid IndexedCoproduct")
250 };
251
252 let t = {
253 let mut lengths = Vec::<usize>::with_capacity(h.edges.len());
254 let mut values = Vec::<usize>::new();
255 for e in h.adjacency.iter() {
256 lengths.push(e.targets.len());
257 values.extend(e.targets.iter().map(|x| x.0));
258 }
259
260 let sources = SemifiniteFunction(VecArray(lengths));
261 let values =
262 FiniteFunction::new(VecArray(values), h.nodes.len()).expect("invalid lax::Hypergraph!");
263 IndexedCoproduct::from_semifinite(sources, values).expect("valid IndexedCoproduct")
264 };
265
266 let w = SemifiniteFunction(VecArray(h.nodes.clone()));
267 let x = SemifiniteFunction(VecArray(h.edges.clone()));
268
269 crate::hypergraph::Hypergraph { s, t, w, x }
270}