1use super::hypergraph::*;
3use crate::strict::vec::{FiniteFunction, VecKind};
4
5#[derive(Debug, Clone, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(
10 feature = "serde",
11 serde(
12 bound = "O: serde::Serialize + serde::de::DeserializeOwned, A: serde::Serialize + serde::de::DeserializeOwned"
13 )
14)]
15pub struct OpenHypergraph<O, A> {
16 pub sources: Vec<NodeId>,
17 pub targets: Vec<NodeId>,
18 pub hypergraph: Hypergraph<O, A>,
19}
20
21impl<O, A> OpenHypergraph<O, A> {
23 pub fn empty() -> Self {
27 OpenHypergraph {
28 sources: vec![],
29 targets: vec![],
30 hypergraph: Hypergraph::empty(),
31 }
32 }
33
34 pub fn from_strict(f: crate::strict::open_hypergraph::OpenHypergraph<VecKind, O, A>) -> Self {
35 let sources = f.s.table.0.into_iter().map(NodeId).collect();
36 let targets = f.t.table.0.into_iter().map(NodeId).collect();
37 let hypergraph = Hypergraph::from_strict(f.h);
38 OpenHypergraph {
39 sources,
40 targets,
41 hypergraph,
42 }
43 }
44
45 pub fn new_node(&mut self, w: O) -> NodeId {
47 self.hypergraph.new_node(w)
48 }
49
50 pub fn new_edge(&mut self, x: A, interface: impl Into<Hyperedge>) -> EdgeId {
51 self.hypergraph.new_edge(x, interface)
52 }
53
54 pub fn new_operation(
65 &mut self,
66 x: A,
67 source_type: Vec<O>,
68 target_type: Vec<O>,
69 ) -> (EdgeId, Interface) {
70 self.hypergraph.new_operation(x, source_type, target_type)
71 }
72
73 pub fn singleton(x: A, source_type: Vec<O>, target_type: Vec<O>) -> Self {
75 let mut f = Self::empty();
76 let (_, (s, t)) = f.new_operation(x, source_type, target_type);
77 f.sources = s;
78 f.targets = t;
79 f
80 }
81
82 pub fn unify(&mut self, v: NodeId, w: NodeId) {
84 self.hypergraph.unify(v, w);
85 }
86
87 pub fn delete_edges(&mut self, edge_ids: &[EdgeId]) {
91 self.hypergraph.delete_edges(edge_ids);
92 }
93
94 pub fn delete_nodes(&mut self, node_ids: &[NodeId]) {
98 let new_index = self.hypergraph.delete_nodes_witness(node_ids);
99 self.sources = self
100 .sources
101 .iter()
102 .filter_map(|n| new_index[n.0].map(NodeId))
103 .collect();
104 self.targets = self
105 .targets
106 .iter()
107 .filter_map(|n| new_index[n.0].map(NodeId))
108 .collect();
109 }
110
111 pub fn add_edge_source(&mut self, edge_id: EdgeId, w: O) -> NodeId {
112 self.hypergraph.add_edge_source(edge_id, w)
113 }
114
115 pub fn add_edge_target(&mut self, edge_id: EdgeId, w: O) -> NodeId {
116 self.hypergraph.add_edge_target(edge_id, w)
117 }
118
119 pub fn with_nodes<T, F: FnOnce(Vec<O>) -> Vec<T>>(self, f: F) -> Option<OpenHypergraph<T, A>> {
122 self.hypergraph
123 .with_nodes(f)
124 .map(|hypergraph| OpenHypergraph {
125 sources: self.sources,
126 targets: self.targets,
127 hypergraph,
128 })
129 }
130
131 pub fn map_nodes<F: Fn(O) -> T, T>(self, f: F) -> OpenHypergraph<T, A> {
133 OpenHypergraph {
134 sources: self.sources,
135 targets: self.targets,
136 hypergraph: self.hypergraph.map_nodes(f),
137 }
138 }
139
140 pub fn with_edges<T, F: FnOnce(Vec<A>) -> Vec<T>>(self, f: F) -> Option<OpenHypergraph<O, T>> {
143 self.hypergraph
144 .with_edges(f)
145 .map(|hypergraph| OpenHypergraph {
146 sources: self.sources,
147 targets: self.targets,
148 hypergraph,
149 })
150 }
151
152 pub fn map_edges<F: Fn(A) -> T, T>(self, f: F) -> OpenHypergraph<O, T> {
154 OpenHypergraph {
155 sources: self.sources,
156 targets: self.targets,
157 hypergraph: self.hypergraph.map_edges(f),
158 }
159 }
160}
161
162impl<O, A> OpenHypergraph<O, A> {
163 pub fn identity(a: Vec<O>) -> Self {
164 let mut f = OpenHypergraph::empty();
165 f.sources = (0..a.len()).map(NodeId).collect();
166 f.targets = (0..a.len()).map(NodeId).collect();
167 f.hypergraph.nodes = a;
168 f
169 }
170
171 pub fn spider(s: FiniteFunction, t: FiniteFunction, w: Vec<O>) -> Option<Self> {
172 if s.target != t.target || s.target != w.len() {
174 return None;
175 }
176
177 let mut f = OpenHypergraph::empty();
178 f.hypergraph.nodes = w;
179 f.sources = s.table.0.into_iter().map(NodeId).collect();
180 f.targets = t.table.0.into_iter().map(NodeId).collect();
181 Some(f)
182 }
183}
184
185impl<O: Clone, A: Clone> OpenHypergraph<O, A> {
186 pub fn tensor(&self, other: &Self) -> Self {
187 let hypergraph = Hypergraph::coproduct(&self.hypergraph, &other.hypergraph);
188
189 let n = self.hypergraph.nodes.len();
191
192 let sources = self
193 .sources
194 .iter()
195 .cloned()
196 .chain(other.sources.iter().map(|&i| NodeId(i.0 + n)))
197 .collect();
198
199 let targets = self
200 .targets
201 .iter()
202 .cloned()
203 .chain(other.targets.iter().map(|&i| NodeId(i.0 + n)))
204 .collect();
205
206 OpenHypergraph {
207 sources,
208 targets,
209 hypergraph,
210 }
211 }
212}
213
214impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
215 pub fn quotient(&mut self) -> Result<FiniteFunction, FiniteFunction> {
218 let q = self.hypergraph.quotient()?;
220
221 self.sources
224 .iter_mut()
225 .for_each(|x| *x = NodeId(q.table[x.0]));
226 self.targets
227 .iter_mut()
228 .for_each(|x| *x = NodeId(q.table[x.0]));
229
230 Ok(q)
231 }
232
233 #[deprecated(since = "0.2.10", note = "use OpenHypergraph::quotient")]
235 pub fn quotient_witness(&mut self) -> Result<FiniteFunction, FiniteFunction> {
236 self.quotient()
237 }
238
239 pub fn to_strict(mut self) -> crate::strict::OpenHypergraph<VecKind, O, A> {
242 use crate::array::vec::VecArray;
243 use crate::finite_function::FiniteFunction;
244 use crate::strict::open_hypergraph::OpenHypergraph;
245
246 self.quotient().unwrap();
247
248 let target = self.hypergraph.nodes.len();
249
250 let s = {
251 let table = self.sources.iter().map(|x| x.0).collect();
252 FiniteFunction::new(VecArray(table), target).expect("Valid by construction")
253 };
254
255 let t = {
256 let table = self.targets.iter().map(|x| x.0).collect();
257 FiniteFunction::new(VecArray(table), target).expect("Valid by construction")
258 };
259
260 let h = self.hypergraph.to_hypergraph();
261
262 OpenHypergraph::new(s, t, h).expect("any valid lax::Hypergraph must be quotientable!")
263 }
264
265 #[deprecated(since = "0.2.4", note = "renamed to_strict")]
267 pub fn to_open_hypergraph(self) -> crate::strict::OpenHypergraph<VecKind, O, A> {
268 self.to_strict()
269 }
270}