1use std::sync::Arc;
4use ustr::{Ustr, ustr};
5
6use crate::dbl::{model::*, theory::*};
7use crate::one::fin_category::FinMor;
8
9pub fn positive_loop(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
15 loop_of_type(th, ustr("Object"), FinMor::Id(ustr("Object")))
16}
17
18pub fn negative_loop(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
24 loop_of_type(th, ustr("Object"), FinMor::Generator(ustr("Negative")))
25}
26
27pub fn delayed_positive_loop(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
32 loop_of_type(th, ustr("Object"), FinMor::Generator(ustr("PositiveSlow")))
33}
34
35pub fn delayed_negative_loop(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
40 loop_of_type(th, ustr("Object"), FinMor::Generator(ustr("NegativeSlow")))
41}
42
43fn loop_of_type(
45 th: Arc<UstrDiscreteDblTheory>,
46 ob_type: Ustr,
47 mor_type: FinMor<Ustr, Ustr>,
48) -> UstrDiscreteDblModel {
49 let mut model = UstrDiscreteDblModel::new(th);
50 let x = ustr("x");
51 model.add_ob(x, ob_type);
52 model.add_mor(ustr("loop"), x, x, mor_type);
53 model
54}
55
56pub fn positive_feedback(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
61 let mut model = UstrDiscreteDblModel::new(th);
62 let (x, y) = (ustr("x"), ustr("y"));
63 model.add_ob(x, ustr("Object"));
64 model.add_ob(y, ustr("Object"));
65 model.add_mor(ustr("positive1"), x, y, FinMor::Id(ustr("Object")));
66 model.add_mor(ustr("positive2"), y, x, FinMor::Id(ustr("Object")));
67 model
68}
69
70pub fn negative_feedback(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
75 let mut model = UstrDiscreteDblModel::new(th);
76 let (x, y) = (ustr("x"), ustr("y"));
77 model.add_ob(x, ustr("Object"));
78 model.add_ob(y, ustr("Object"));
79 model.add_mor(ustr("positive"), x, y, FinMor::Id(ustr("Object")));
80 model.add_mor(ustr("negative"), y, x, FinMor::Generator(ustr("Negative")));
81 model
82}
83
84pub fn walking_attr(th: Arc<UstrDiscreteDblTheory>) -> UstrDiscreteDblModel {
89 let mut model = UstrDiscreteDblModel::new(th);
90 let (entity, attr_type) = (ustr("entity"), ustr("type"));
91 model.add_ob(entity, ustr("Entity"));
92 model.add_ob(attr_type, ustr("AttrType"));
93 model.add_mor(ustr("attr"), entity, attr_type, FinMor::Generator(ustr("Attr")));
94 model
95}
96
97pub fn backward_link(th: Arc<UstrDiscreteTabTheory>) -> UstrDiscreteTabModel {
109 let mut model = UstrDiscreteTabModel::new(th.clone());
110 let (x, y, f) = (ustr("x"), ustr("y"), ustr("f"));
111 let ob_type = TabObType::Basic(ustr("Object"));
112 model.add_ob(x, ob_type.clone());
113 model.add_ob(y, ob_type.clone());
114 model.add_mor(f, TabOb::Basic(x), TabOb::Basic(y), th.hom_type(ob_type));
115 model.add_mor(
116 ustr("link"),
117 TabOb::Basic(y),
118 model.tabulated_gen(f),
119 TabMorType::Basic(ustr("Link")),
120 );
121 model
122}
123
124#[cfg(test)]
125mod tests {
126 use super::super::theories::*;
127 use super::*;
128 use crate::validate::Validate;
129
130 #[test]
131 fn signed_categories() {
132 let th = Arc::new(th_signed_category());
133 assert!(positive_loop(th.clone()).validate().is_ok());
134 assert!(negative_loop(th.clone()).validate().is_ok());
135 assert!(positive_feedback(th.clone()).validate().is_ok());
136 assert!(negative_feedback(th.clone()).validate().is_ok());
137 }
138
139 #[test]
140 fn delayable_signed_categories() {
141 let th = Arc::new(th_delayable_signed_category());
142 assert!(positive_loop(th.clone()).validate().is_ok());
143 assert!(negative_loop(th.clone()).validate().is_ok());
144 assert!(delayed_positive_loop(th.clone()).validate().is_ok());
145 assert!(delayed_negative_loop(th.clone()).validate().is_ok());
146 }
147
148 #[test]
149 fn schemas() {
150 let th = Arc::new(th_schema());
151 assert!(walking_attr(th).validate().is_ok());
152 }
153
154 #[test]
155 fn categories_with_links() {
156 let th = Arc::new(th_category_links());
157 assert!(backward_link(th).validate().is_ok());
158 }
159}