1use super::functions::*;
5
6#[allow(dead_code)]
11pub struct GaloisConnection<A, B> {
12 pub lower: Box<dyn Fn(A) -> B>,
14 pub upper: Box<dyn Fn(B) -> A>,
16}
17#[allow(dead_code)]
18impl<A: Clone, B: Clone> GaloisConnection<A, B> {
19 pub fn new(lower: impl Fn(A) -> B + 'static, upper: impl Fn(B) -> A + 'static) -> Self {
21 Self {
22 lower: Box::new(lower),
23 upper: Box::new(upper),
24 }
25 }
26 pub fn apply_lower(&self, a: A) -> B {
28 (self.lower)(a)
29 }
30 pub fn apply_upper(&self, b: B) -> A {
32 (self.upper)(b)
33 }
34 pub fn verify(
37 &self,
38 a: A,
39 b: B,
40 le_a: impl Fn(&A, &A) -> bool,
41 le_b: impl Fn(&B, &B) -> bool,
42 ) -> bool {
43 let la = (self.lower)(a.clone());
44 let ub = (self.upper)(b.clone());
45 le_b(&la, &b) == le_a(&a, &ub)
46 }
47}
48#[allow(dead_code)]
51pub struct KnasterTarskiFixpoint<T> {
52 pub func: Box<dyn Fn(T) -> T>,
54 pub ssup: Box<dyn Fn(Box<dyn Fn(&T) -> bool>) -> T>,
56}
57#[allow(dead_code)]
58impl<T: Clone + PartialEq> KnasterTarskiFixpoint<T> {
59 pub fn new(
61 func: impl Fn(T) -> T + 'static,
62 ssup: impl Fn(Box<dyn Fn(&T) -> bool>) -> T + 'static,
63 ) -> Self {
64 Self {
65 func: Box::new(func),
66 ssup: Box::new(ssup),
67 }
68 }
69 pub fn lfp_iterate(&self, bot: T, max_iter: usize) -> Option<T> {
71 let mut x = bot;
72 for _ in 0..max_iter {
73 let fx = (self.func)(x.clone());
74 if fx == x {
75 return Some(x);
76 }
77 x = fx;
78 }
79 None
80 }
81 pub fn is_fixed_point(&self, x: T) -> bool {
83 let fx = (self.func)(x.clone());
84 fx == x
85 }
86 pub fn iterate_n(&self, x: T, n: usize) -> T {
88 let mut current = x;
89 for _ in 0..n {
90 current = (self.func)(current);
91 }
92 current
93 }
94}
95#[allow(dead_code)]
98pub struct PartialOrderChecker<T> {
99 pub elements: Vec<T>,
101 pub le: Box<dyn Fn(&T, &T) -> bool>,
103}
104#[allow(dead_code)]
105impl<T: Clone + PartialEq> PartialOrderChecker<T> {
106 pub fn new(elements: Vec<T>, le: impl Fn(&T, &T) -> bool + 'static) -> Self {
108 Self {
109 elements,
110 le: Box::new(le),
111 }
112 }
113 pub fn check_reflexive(&self) -> bool {
115 self.elements.iter().all(|a| (self.le)(a, a))
116 }
117 pub fn check_transitive(&self) -> bool {
119 for a in &self.elements {
120 for b in &self.elements {
121 for c in &self.elements {
122 if (self.le)(a, b) && (self.le)(b, c) && !(self.le)(a, c) {
123 return false;
124 }
125 }
126 }
127 }
128 true
129 }
130 pub fn check_antisymmetric(&self) -> bool {
132 for a in &self.elements {
133 for b in &self.elements {
134 if (self.le)(a, b) && (self.le)(b, a) && a != b {
135 return false;
136 }
137 }
138 }
139 true
140 }
141 pub fn is_partial_order(&self) -> bool {
143 self.check_reflexive() && self.check_transitive() && self.check_antisymmetric()
144 }
145 pub fn maximal_elements(&self) -> Vec<T> {
147 self.elements
148 .iter()
149 .filter(|a| {
150 !self
151 .elements
152 .iter()
153 .any(|b| (self.le)(a, b) && !(self.le)(b, a))
154 })
155 .cloned()
156 .collect()
157 }
158 pub fn minimal_elements(&self) -> Vec<T> {
160 self.elements
161 .iter()
162 .filter(|a| {
163 !self
164 .elements
165 .iter()
166 .any(|b| (self.le)(b, a) && !(self.le)(a, b))
167 })
168 .cloned()
169 .collect()
170 }
171}
172#[allow(dead_code)]
174pub struct LatticeOps<T> {
175 pub join: Box<dyn Fn(T, T) -> T>,
177 pub meet: Box<dyn Fn(T, T) -> T>,
179}
180#[allow(dead_code)]
181impl<T: Clone + PartialEq> LatticeOps<T> {
182 pub fn new(join: impl Fn(T, T) -> T + 'static, meet: impl Fn(T, T) -> T + 'static) -> Self {
184 Self {
185 join: Box::new(join),
186 meet: Box::new(meet),
187 }
188 }
189 pub fn fold_join(&self, elems: &[T]) -> Option<T> {
191 let mut iter = elems.iter().cloned();
192 let first = iter.next()?;
193 Some(iter.fold(first, |acc, x| (self.join)(acc, x)))
194 }
195 pub fn fold_meet(&self, elems: &[T]) -> Option<T> {
197 let mut iter = elems.iter().cloned();
198 let first = iter.next()?;
199 Some(iter.fold(first, |acc, x| (self.meet)(acc, x)))
200 }
201 pub fn check_absorption_join_meet(&self, a: T, b: T) -> bool {
203 let lhs = (self.join)(a.clone(), (self.meet)(a.clone(), b));
204 lhs == a
205 }
206 pub fn check_absorption_meet_join(&self, a: T, b: T) -> bool {
208 let lhs = (self.meet)(a.clone(), (self.join)(a.clone(), b));
209 lhs == a
210 }
211}
212#[allow(dead_code)]
215pub struct ClosureOperator<T> {
216 pub close: Box<dyn Fn(T) -> T>,
218 pub le: Box<dyn Fn(&T, &T) -> bool>,
220}
221#[allow(dead_code)]
222impl<T: Clone + PartialEq> ClosureOperator<T> {
223 pub fn new(close: impl Fn(T) -> T + 'static, le: impl Fn(&T, &T) -> bool + 'static) -> Self {
225 Self {
226 close: Box::new(close),
227 le: Box::new(le),
228 }
229 }
230 pub fn check_extensive(&self, a: T) -> bool {
232 let ca = (self.close)(a.clone());
233 (self.le)(&a, &ca)
234 }
235 pub fn check_monotone(&self, a: T, b: T) -> bool {
237 if (self.le)(&a, &b) {
238 let ca = (self.close)(a);
239 let cb = (self.close)(b);
240 (self.le)(&ca, &cb)
241 } else {
242 true
243 }
244 }
245 pub fn check_idempotent(&self, a: T) -> bool {
247 let ca = (self.close)(a);
248 let cca = (self.close)(ca.clone());
249 ca == cca
250 }
251 pub fn iterate_to_fixed_point(&self, a: T, max_iter: usize) -> Option<T> {
254 let mut current = a;
255 for _ in 0..max_iter {
256 let next = (self.close)(current.clone());
257 if next == current {
258 return Some(current);
259 }
260 current = next;
261 }
262 None
263 }
264}