diff --git a/src/main.rs b/src/main.rs index f671a4d..7772fd0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,14 +12,9 @@ trait Incrementable { fn increment(&mut self) -> IncrementResult; } -#[derive(Debug, Default, Clone)] -struct Atom { - smaller: Vec, -} - -impl Incrementable for Atom { +impl Incrementable for Vec { fn increment(&mut self) -> IncrementResult { - for a in &mut self.smaller { + for a in self { *a = !*a; if *a { return Good; @@ -29,14 +24,38 @@ impl Incrementable for Atom { } } +#[derive(Debug, Default, Clone)] +struct Atom { + smaller: Vec, +} + +impl Incrementable for Atom { + fn increment(&mut self) -> IncrementResult { + self.smaller.increment() + } +} + +#[derive(Debug, Default, Clone)] +struct AtomSet { + included: Vec, +} + +impl Incrementable for AtomSet { + fn increment(&mut self) -> IncrementResult { + self.included.increment() + } +} + #[derive(Debug, Default)] -struct Lattice { +struct Lattice { + ext: Ext, order: Vec, } trait LatticeAbstract { fn le(&self, a: usize, b: usize) -> bool; - fn grow(&mut self); + fn grow(&mut self) -> IncrementResult; + fn is_lattice(&self) -> bool; } impl Display for Lattice { @@ -64,41 +83,24 @@ impl Incrementable for Lattice { } } -impl Lattice +impl Lattice where Self: LatticeAbstract, { - fn next_lattice(&mut self) { + fn next_lattice(&mut self) -> IncrementResult { self.increment(); while !self.is_lattice() { if let Overflow = self.increment() { - self.grow(); + if let Overflow = self.grow() { + return Overflow; + } } } + return Good; } fn ge(&self, a: usize, b: usize) -> bool { return self.le(b, a); } - // The underlying ordering might not be transitive, this makes it so - fn le_transitive(&self, a: usize, b: usize) -> bool { - if self.le(a, b) { - return true; - } - for (b, &active) in self.order[b].smaller.iter().enumerate() { - if active && self.le_transitive(a, b) { - return true; - } - } - return false; - } - fn is_transitive(&self) -> bool { - for (i, j) in (0..self.order.len()).cartesian_product(0..self.order.len()) { - if !self.le(i, j) && self.le_transitive(i, j) { - return false; - } - } - return true; - } fn is_bounded(&self, subset: &Vec, bound_candidates: C, rel: F) -> bool where C: Iterator, @@ -122,10 +124,7 @@ where return true; } - fn is_lattice(&self) -> bool { - if !self.is_transitive() { - return false; - } + fn has_lub_glb(&self) -> bool { // A top/bottom element are inherent as are partial order conditions. // Lattice condition can only fail if a set of elements have non comparable upper/lower bounds // Possible optimization: a lack of LUB might imply no GLB so may only need to check one of them @@ -141,6 +140,49 @@ where } return true; } + fn monotone(&self, other: &Lattice) -> bool + where + Inc: Incrementable + Default, + Lattice: LatticeAbstract, + { + assert_eq!(self.order.len(), other.order.len()); + for (a, b) in (0..self.order.len()).cartesian_product((0..other.order.len())) { + if self.le(a, b) && !other.le(a, b) { + return false; + } + } + return true; + } + fn equal(&self, other: &Lattice) -> bool + where + Inc: Incrementable + Default, + Lattice: LatticeAbstract, + { + self.monotone(other) && other.monotone(self) + } +} + +impl Lattice { + fn is_transitive(&self) -> bool { + for (i, j) in (0..self.order.len()).cartesian_product(0..self.order.len()) { + if !self.le(i, j) && self.le_transitive(i, j) { + return false; + } + } + return true; + } + // The underlying ordering might not be transitive, this makes it so + fn le_transitive(&self, a: usize, b: usize) -> bool { + if self.le(a, b) { + return true; + } + for (b, &active) in self.order[b].smaller.iter().enumerate() { + if active && self.le_transitive(a, b) { + return true; + } + } + return false; + } } impl LatticeAbstract for Lattice { @@ -156,13 +198,17 @@ impl LatticeAbstract for Lattice { } return false; } - fn grow(&mut self) { + fn grow(&mut self) -> IncrementResult { self.order = vec![Default::default(); self.order.len() + 1]; for (i, atom) in self.order.iter_mut().enumerate() { *atom = Atom { smaller: vec![false; i], } } + return Good; + } + fn is_lattice(&self) -> bool { + self.is_transitive() && self.has_lub_glb() } } @@ -183,6 +229,7 @@ mod tests { #[test] fn test_is_lattice() -> Result<(), Box> { let lattice = Lattice { + ext: (), order: vec![ Atom { smaller: vec![] }, Atom { @@ -195,6 +242,7 @@ mod tests { }; assert!(lattice.is_lattice()); let lattice = Lattice { + ext: (), order: vec![ Atom { smaller: vec![] }, Atom { @@ -211,6 +259,7 @@ mod tests { #[test] fn test_is_not_lattice() -> Result<(), Box> { let lattice = Lattice { + ext: (), order: vec![ Atom { smaller: vec![] }, Atom { @@ -223,6 +272,7 @@ mod tests { }; assert!(!lattice.is_transitive()); let lattice = Lattice { + ext: (), order: vec![ Atom { smaller: vec![] }, Atom { @@ -242,45 +292,58 @@ mod tests { } } -// struct Operator<'a> { -// lattice: &'a Lattice, -// top: Vec, -// ul: Vec, -// ur: Vec, -// dl: Vec, -// dr: Vec, -// bot: Vec, -// } -// impl<'a> Operator<'a> { -// fn new(lattice: &'a Lattice) -> Self { -// Operator { -// lattice, -// top: vec![false; lattice.order.len()], -// ul: vec![false; lattice.order.len()], -// ur: vec![false; lattice.order.len()], -// dl: vec![false; lattice.order.len()], -// dr: vec![false; lattice.order.len()], -// bot: vec![false; lattice.order.len()], -// } -// } -// fn increment(&mut self) { -// let mut data = [ -// &mut self.bot, -// &mut self.dr, -// &mut self.dl, -// &mut self.ur, -// &mut self.ul, -// &mut self.top, -// ]; -// data[4][0] = false; -// for (i, el) in data.iter_mut().enumerate() { -// for a in el.iter_mut() { -// *a = !*a; -// if *a { -// return; -// } -// } -// } -// } -// } +struct Mapping<'a> { + domain: &'a Lattice, + image: &'a Lattice, +} + +// function: Lattice, + +type Operator<'a> = Lattice>; + +impl<'a> Operator<'a> { + fn new(domain: &'a Lattice, image: &'a Lattice) -> Operator<'a> { + Lattice { + ext: Mapping { domain, image }, + order: vec![AtomSet { included: vec![] }; image.order.len()], + } + } + fn all_nonempty(&self) -> bool { + self.order.iter().all(|set| set.included.iter().any(|&x| x)) + } + fn le_helper + Clone>(&self, a: I, b: I) -> bool { + b.clone() + .all(|right| a.clone().any(|left| self.ext.domain.le(left, right))) + } +} + +impl<'a> LatticeAbstract for Operator<'a> { + fn le(&self, a: usize, b: usize) -> bool { + let pick = |which: usize| { + self.order[which] + .included + .iter() + .enumerate() + .filter_map(|(i, &included)| if included { Some(i) } else { None }) + }; + let left = pick(a); + let right = pick(b); + + if !self.le_helper(left.clone(), right.clone()) { + return false; + } + if !self.le_helper(right, left) { + return false; + } + return true; + } + + fn grow(&mut self) -> IncrementResult { + return Overflow; + } + + fn is_lattice(&self) -> bool { + self.all_nonempty() && self.ext.image.equal() + } +}