1use crate::dbl::theory::*;
4use crate::one::{Path, fp_category::FpCategory};
5use crate::zero::name;
6
7pub fn th_empty() -> DiscreteDblTheory {
11 FpCategory::new().into()
12}
13
14pub fn th_category() -> DiscreteDblTheory {
18 let mut cat = FpCategory::new();
19 cat.add_ob_generator(name("Object"));
20 cat.into()
21}
22
23pub fn th_schema() -> DiscreteDblTheory {
27 let mut cat = FpCategory::new();
28 cat.add_ob_generator(name("Entity"));
29 cat.add_ob_generator(name("AttrType"));
30 cat.add_mor_generator(name("Attr"), name("Entity"), name("AttrType"));
31 cat.into()
32}
33
34pub fn th_signed_category() -> DiscreteDblTheory {
40 let mut sgn = FpCategory::new();
41 sgn.add_ob_generator(name("Object"));
42 sgn.add_mor_generator(name("Negative"), name("Object"), name("Object"));
43 sgn.equate(Path::pair(name("Negative"), name("Negative")), Path::empty(name("Object")));
44 sgn.into()
45}
46
47pub fn th_delayable_signed_category() -> DiscreteDblTheory {
52 let mut cat = FpCategory::new();
53 cat.add_ob_generator(name("Object"));
54 cat.add_mor_generator(name("Negative"), name("Object"), name("Object"));
55 cat.add_mor_generator(name("Slow"), name("Object"), name("Object"));
56 cat.equate(Path::pair(name("Negative"), name("Negative")), Path::empty(name("Object")));
57 cat.equate(Path::pair(name("Slow"), name("Slow")), name("Slow").into());
58 cat.equate(
59 Path::pair(name("Negative"), name("Slow")),
60 Path::pair(name("Slow"), name("Negative")),
61 );
62
63 cat.add_mor_generator(name("PositiveSlow"), name("Object"), name("Object"));
67 cat.add_mor_generator(name("NegativeSlow"), name("Object"), name("Object"));
68 cat.equate(name("PositiveSlow").into(), name("Slow").into());
69 cat.equate(name("NegativeSlow").into(), Path::pair(name("Negative"), name("Slow")));
70
71 cat.into()
72}
73
74pub fn th_nullable_signed_category() -> DiscreteDblTheory {
79 let mut sgn = FpCategory::new();
80 sgn.add_ob_generator(name("Object"));
81 sgn.add_mor_generator(name("Negative"), name("Object"), name("Object"));
82 sgn.add_mor_generator(name("Zero"), name("Object"), name("Object"));
83 sgn.equate(Path::pair(name("Negative"), name("Negative")), Path::empty(name("Object")));
84 sgn.equate(Path::pair(name("Negative"), name("Zero")), name("Zero").into());
85 sgn.equate(Path::pair(name("Zero"), name("Negative")), name("Zero").into());
86 sgn.equate(Path::pair(name("Zero"), name("Zero")), name("Zero").into());
87 sgn.into()
88}
89
90pub fn th_category_with_scalars() -> DiscreteDblTheory {
100 let mut idem = FpCategory::new();
101 idem.add_ob_generator(name("Object"));
102 idem.add_mor_generator(name("Nonscalar"), name("Object"), name("Object"));
103 idem.equate(Path::pair(name("Nonscalar"), name("Nonscalar")), name("Nonscalar").into());
104 idem.into()
105}
106
107pub fn th_category_links() -> DiscreteTabTheory {
115 let mut th = DiscreteTabTheory::new();
116 th.add_ob_type(name("Object"));
117 let ob_type = TabObType::Basic(name("Object"));
118 th.add_mor_type(name("Link"), ob_type.clone(), th.tabulator(th.hom_type(ob_type)));
119 th
120}
121
122pub fn th_category_signed_links() -> DiscreteTabTheory {
127 let mut th = DiscreteTabTheory::new();
128 th.add_ob_type(name("Object"));
129 let ob_type = TabObType::Basic(name("Object"));
130 th.add_mor_type(name("Link"), ob_type.clone(), th.tabulator(th.hom_type(ob_type.clone())));
131 th.add_mor_type(
132 name("NegativeLink"),
133 ob_type.clone(),
134 th.tabulator(th.hom_type(ob_type.clone())),
135 );
136 th
137}
138
139pub fn th_monoidal_category() -> ModalDblTheory<Unital> {
141 th_list_algebra(List::Plain)
142}
143
144pub fn th_lax_monoidal_category() -> ModalDblTheory<Unital> {
146 th_list_lax_algebra(List::Plain)
147}
148
149pub fn th_sym_monoidal_category() -> ModalDblTheory<Unital> {
151 th_list_algebra(List::Symmetric)
152}
153
154fn th_list_algebra(list: List) -> ModalDblTheory<Unital> {
159 let m = Modality::List(list);
160
161 let mut th = ModalDblTheory::new();
162 th.add_ob_type(name("Object"));
163 let x = ModeApp::new(name("Object"));
164 th.add_ob_op(name("tensor"), x.clone().apply(m), x.clone());
165 let a = ModeApp::new(name("tensor").into());
166
167 th.equate_ob_ops(
168 Path::pair(a.clone().apply(m), a.clone()),
169 Path::pair(ModeApp::new(ModalOp::Concat(list, 2, x.clone())), a.clone()),
170 );
171 th.equate_ob_ops(
172 Path::empty(x.clone()),
173 Path::pair(ModeApp::new(ModalOp::Concat(list, 0, x)), a),
174 );
175 th
176}
177
178fn th_list_lax_algebra(list: List) -> ModalDblTheory<Unital> {
180 let m = Modality::List(list);
181
182 let mut th = ModalDblTheory::new();
183 th.add_ob_type(name("Object"));
184 let x = ModeApp::new(name("Object"));
185 th.add_ob_op(name("tensor"), x.clone().apply(m), x.clone());
186 let a = ModeApp::new(name("tensor").into());
187
188 th.add_special_mor_op(
189 name("Associator"),
190 Path::pair(a.clone().apply(m), a.clone()),
191 Path::pair(ModeApp::new(ModalOp::Concat(list, 2, x.clone())), a.clone()),
192 );
193 th.add_special_mor_op(
194 name("Unitor"),
195 Path::empty(x.clone()),
196 Path::pair(ModeApp::new(ModalOp::Concat(list, 0, x)), a),
197 );
198 th
200}
201
202pub fn th_multicategory() -> ModalDblTheory<Unital> {
204 th_generalized_multicategory(List::Plain)
205}
206
207pub fn th_sym_multicategory() -> ModalDblTheory<Unital> {
209 th_generalized_multicategory(List::Symmetric)
210}
211
212pub fn th_polynomial_ode_system() -> ModalDblTheory<NonUnital> {
214 let mut th = ModalDblTheory::new();
215 th.add_ob_type(name("State"));
216 let x = ModeApp::new(name("State"));
217 th.add_mor_type(name("Contribution"), x.clone().apply(Modality::List(List::Symmetric)), x);
218 th
219}
220
221pub fn th_signed_polynomial_ode_system() -> ModalDblTheory<NonUnital> {
223 let mut th = ModalDblTheory::new();
224 th.add_ob_type(name("State"));
225 let x = ModeApp::new(name("State"));
226 th.add_mor_type(
227 name("Contribution"),
228 x.clone().apply(Modality::List(List::Symmetric)),
229 x.clone(),
230 );
231 th.add_mor_type(
232 name("NegativeContribution"),
233 x.clone().apply(Modality::List(List::Symmetric)),
234 x,
235 );
236 th
237}
238
239fn th_generalized_multicategory(list: List) -> ModalDblTheory<Unital> {
241 let mut th = ModalDblTheory::new();
242 th.add_ob_type(name("Object"));
243 let x = ModeApp::new(name("Object"));
244 th.add_mor_type(name("Multihom"), x.clone().apply(Modality::List(list)), x);
245 th
247}
248
249pub fn th_power_system() -> DiscreteDblTheory {
306 let mut cat = FpCategory::new();
307 cat.add_ob_generator(name("Bus"));
308 cat.add_mor_generator(name("Passive"), name("Bus"), name("Bus"));
309 cat.add_mor_generator(name("Branch"), name("Bus"), name("Bus"));
310 cat.equate(Path::pair(name("Passive"), name("Passive")), name("Passive").into());
311 cat.equate(Path::pair(name("Passive"), name("Branch")), name("Branch").into());
312 cat.equate(Path::pair(name("Branch"), name("Passive")), name("Branch").into());
313 cat.equate(Path::pair(name("Branch"), name("Branch")), name("Branch").into());
314 cat.into()
315}
316
317#[allow(dead_code)]
320fn modal_th_power_system() -> ModalDblTheory<Unital> {
321 let mut th = ModalDblTheory::new();
322
323 th.add_ob_type(name("Bus"));
325 let bus = ModeApp::new(name("Bus"));
326
327 th.add_mor_type(name("Passive"), bus.clone(), bus.clone());
329 let passive = ModeApp::new(name("Passive"));
330 th.set_composite(passive.clone(), passive.clone(), passive.clone().into());
331 th.add_globular_mor_op(name("line_is_passive"), Path::Id(bus.clone()), passive.clone().into());
332 th.add_mor_type(name("Branch"), bus.clone(), bus.clone());
336 let branch = ModeApp::new(name("Branch"));
337 th.set_composite(branch.clone(), passive.clone(), branch.clone().into());
338 th.set_composite(passive.clone(), branch.clone(), branch.clone().into());
339 th.set_composite(branch.clone(), branch.clone(), branch.clone().into());
340 th.add_globular_mor_op(
341 name("passive_is_branch"),
342 Path::single(passive.clone().into()),
343 branch.clone().into(),
344 );
345 th
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353 use crate::{one::Category, validate::Validate};
354 use nonempty::nonempty;
355
356 #[test]
357 fn validate_discrete_theories() {
358 assert!(th_empty().validate().is_ok());
359 assert!(th_category().validate().is_ok());
360 assert!(th_schema().validate().is_ok());
361 assert!(th_signed_category().validate().is_ok());
362 assert!(th_delayable_signed_category().validate().is_ok());
363 assert!(th_nullable_signed_category().validate().is_ok());
364 assert!(th_category_with_scalars().validate().is_ok());
365 assert!(th_power_system().validate().is_ok());
366 }
367
368 #[test]
369 fn validate_discrete_tabulator_theories() {
370 th_category_links();
372 }
373
374 #[test]
375 fn validate_modal_theories() {
376 assert!(th_monoidal_category().validate().is_ok());
377 assert!(th_lax_monoidal_category().validate().is_ok());
378 assert!(th_multicategory().validate().is_ok());
379 assert!(th_sym_multicategory().validate().is_ok());
380 assert!(modal_th_power_system().validate().is_ok());
381 assert!(th_polynomial_ode_system().validate().is_ok());
382 }
383
384 #[test]
385 fn delayable_signed_categories() {
386 let th = th_delayable_signed_category();
388 assert!(th.has_mor_type(&name("Negative").into()));
389 assert!(th.has_mor_type(&name("Slow").into()));
390 let path =
391 Path::Seq(nonempty![name("Negative"), name("Slow"), name("Negative"), name("Slow")]);
392 assert!(th.0.morphisms_are_equal(path, name("Slow").into()));
393 }
394}