use super::functions::*;
#[allow(dead_code)]
pub struct GaloisConnection<A, B> {
pub lower: Box<dyn Fn(A) -> B>,
pub upper: Box<dyn Fn(B) -> A>,
}
#[allow(dead_code)]
impl<A: Clone, B: Clone> GaloisConnection<A, B> {
pub fn new(lower: impl Fn(A) -> B + 'static, upper: impl Fn(B) -> A + 'static) -> Self {
Self {
lower: Box::new(lower),
upper: Box::new(upper),
}
}
pub fn apply_lower(&self, a: A) -> B {
(self.lower)(a)
}
pub fn apply_upper(&self, b: B) -> A {
(self.upper)(b)
}
pub fn verify(
&self,
a: A,
b: B,
le_a: impl Fn(&A, &A) -> bool,
le_b: impl Fn(&B, &B) -> bool,
) -> bool {
let la = (self.lower)(a.clone());
let ub = (self.upper)(b.clone());
le_b(&la, &b) == le_a(&a, &ub)
}
}
#[allow(dead_code)]
pub struct KnasterTarskiFixpoint<T> {
pub func: Box<dyn Fn(T) -> T>,
pub ssup: Box<dyn Fn(Box<dyn Fn(&T) -> bool>) -> T>,
}
#[allow(dead_code)]
impl<T: Clone + PartialEq> KnasterTarskiFixpoint<T> {
pub fn new(
func: impl Fn(T) -> T + 'static,
ssup: impl Fn(Box<dyn Fn(&T) -> bool>) -> T + 'static,
) -> Self {
Self {
func: Box::new(func),
ssup: Box::new(ssup),
}
}
pub fn lfp_iterate(&self, bot: T, max_iter: usize) -> Option<T> {
let mut x = bot;
for _ in 0..max_iter {
let fx = (self.func)(x.clone());
if fx == x {
return Some(x);
}
x = fx;
}
None
}
pub fn is_fixed_point(&self, x: T) -> bool {
let fx = (self.func)(x.clone());
fx == x
}
pub fn iterate_n(&self, x: T, n: usize) -> T {
let mut current = x;
for _ in 0..n {
current = (self.func)(current);
}
current
}
}
#[allow(dead_code)]
pub struct PartialOrderChecker<T> {
pub elements: Vec<T>,
pub le: Box<dyn Fn(&T, &T) -> bool>,
}
#[allow(dead_code)]
impl<T: Clone + PartialEq> PartialOrderChecker<T> {
pub fn new(elements: Vec<T>, le: impl Fn(&T, &T) -> bool + 'static) -> Self {
Self {
elements,
le: Box::new(le),
}
}
pub fn check_reflexive(&self) -> bool {
self.elements.iter().all(|a| (self.le)(a, a))
}
pub fn check_transitive(&self) -> bool {
for a in &self.elements {
for b in &self.elements {
for c in &self.elements {
if (self.le)(a, b) && (self.le)(b, c) && !(self.le)(a, c) {
return false;
}
}
}
}
true
}
pub fn check_antisymmetric(&self) -> bool {
for a in &self.elements {
for b in &self.elements {
if (self.le)(a, b) && (self.le)(b, a) && a != b {
return false;
}
}
}
true
}
pub fn is_partial_order(&self) -> bool {
self.check_reflexive() && self.check_transitive() && self.check_antisymmetric()
}
pub fn maximal_elements(&self) -> Vec<T> {
self.elements
.iter()
.filter(|a| {
!self
.elements
.iter()
.any(|b| (self.le)(a, b) && !(self.le)(b, a))
})
.cloned()
.collect()
}
pub fn minimal_elements(&self) -> Vec<T> {
self.elements
.iter()
.filter(|a| {
!self
.elements
.iter()
.any(|b| (self.le)(b, a) && !(self.le)(a, b))
})
.cloned()
.collect()
}
}
#[allow(dead_code)]
pub struct LatticeOps<T> {
pub join: Box<dyn Fn(T, T) -> T>,
pub meet: Box<dyn Fn(T, T) -> T>,
}
#[allow(dead_code)]
impl<T: Clone + PartialEq> LatticeOps<T> {
pub fn new(join: impl Fn(T, T) -> T + 'static, meet: impl Fn(T, T) -> T + 'static) -> Self {
Self {
join: Box::new(join),
meet: Box::new(meet),
}
}
pub fn fold_join(&self, elems: &[T]) -> Option<T> {
let mut iter = elems.iter().cloned();
let first = iter.next()?;
Some(iter.fold(first, |acc, x| (self.join)(acc, x)))
}
pub fn fold_meet(&self, elems: &[T]) -> Option<T> {
let mut iter = elems.iter().cloned();
let first = iter.next()?;
Some(iter.fold(first, |acc, x| (self.meet)(acc, x)))
}
pub fn check_absorption_join_meet(&self, a: T, b: T) -> bool {
let lhs = (self.join)(a.clone(), (self.meet)(a.clone(), b));
lhs == a
}
pub fn check_absorption_meet_join(&self, a: T, b: T) -> bool {
let lhs = (self.meet)(a.clone(), (self.join)(a.clone(), b));
lhs == a
}
}
#[allow(dead_code)]
pub struct ClosureOperator<T> {
pub close: Box<dyn Fn(T) -> T>,
pub le: Box<dyn Fn(&T, &T) -> bool>,
}
#[allow(dead_code)]
impl<T: Clone + PartialEq> ClosureOperator<T> {
pub fn new(close: impl Fn(T) -> T + 'static, le: impl Fn(&T, &T) -> bool + 'static) -> Self {
Self {
close: Box::new(close),
le: Box::new(le),
}
}
pub fn check_extensive(&self, a: T) -> bool {
let ca = (self.close)(a.clone());
(self.le)(&a, &ca)
}
pub fn check_monotone(&self, a: T, b: T) -> bool {
if (self.le)(&a, &b) {
let ca = (self.close)(a);
let cb = (self.close)(b);
(self.le)(&ca, &cb)
} else {
true
}
}
pub fn check_idempotent(&self, a: T) -> bool {
let ca = (self.close)(a);
let cca = (self.close)(ca.clone());
ca == cca
}
pub fn iterate_to_fixed_point(&self, a: T, max_iter: usize) -> Option<T> {
let mut current = a;
for _ in 0..max_iter {
let next = (self.close)(current.clone());
if next == current {
return Some(current);
}
current = next;
}
None
}
}