This commit is contained in:
Spencer Killen 2023-12-21 15:37:18 -07:00
parent 2e061e32bd
commit 6b0d72c3a1
Signed by: sjkillen
GPG Key ID: 3AF3117BA6FBB75B
1 changed files with 141 additions and 78 deletions

View File

@ -12,14 +12,9 @@ trait Incrementable {
fn increment(&mut self) -> IncrementResult; fn increment(&mut self) -> IncrementResult;
} }
#[derive(Debug, Default, Clone)] impl Incrementable for Vec<bool> {
struct Atom {
smaller: Vec<bool>,
}
impl Incrementable for Atom {
fn increment(&mut self) -> IncrementResult { fn increment(&mut self) -> IncrementResult {
for a in &mut self.smaller { for a in self {
*a = !*a; *a = !*a;
if *a { if *a {
return Good; return Good;
@ -29,14 +24,38 @@ impl Incrementable for Atom {
} }
} }
#[derive(Debug, Default, Clone)]
struct Atom {
smaller: Vec<bool>,
}
impl Incrementable for Atom {
fn increment(&mut self) -> IncrementResult {
self.smaller.increment()
}
}
#[derive(Debug, Default, Clone)]
struct AtomSet {
included: Vec<bool>,
}
impl Incrementable for AtomSet {
fn increment(&mut self) -> IncrementResult {
self.included.increment()
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct Lattice<I: Incrementable + Default> { struct Lattice<I: Incrementable + Default, Ext = ()> {
ext: Ext,
order: Vec<I>, order: Vec<I>,
} }
trait LatticeAbstract { trait LatticeAbstract {
fn le(&self, a: usize, b: usize) -> bool; 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<Atom> { impl Display for Lattice<Atom> {
@ -64,41 +83,24 @@ impl<I: Incrementable + Default> Incrementable for Lattice<I> {
} }
} }
impl<I: Incrementable> Lattice<I> impl<I: Incrementable + Default> Lattice<I>
where where
Self: LatticeAbstract, Self: LatticeAbstract,
{ {
fn next_lattice(&mut self) { fn next_lattice(&mut self) -> IncrementResult {
self.increment(); self.increment();
while !self.is_lattice() { while !self.is_lattice() {
if let Overflow = self.increment() { if let Overflow = self.increment() {
self.grow(); if let Overflow = self.grow() {
return Overflow;
} }
} }
} }
return Good;
}
fn ge(&self, a: usize, b: usize) -> bool { fn ge(&self, a: usize, b: usize) -> bool {
return self.le(b, a); 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<C, F>(&self, subset: &Vec<usize>, bound_candidates: C, rel: F) -> bool fn is_bounded<C, F>(&self, subset: &Vec<usize>, bound_candidates: C, rel: F) -> bool
where where
C: Iterator<Item = usize>, C: Iterator<Item = usize>,
@ -122,10 +124,7 @@ where
return true; return true;
} }
fn is_lattice(&self) -> bool { fn has_lub_glb(&self) -> bool {
if !self.is_transitive() {
return false;
}
// A top/bottom element are inherent as are partial order conditions. // 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 // 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 // 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; return true;
} }
fn monotone<Inc, Ext>(&self, other: &Lattice<Inc, Ext>) -> bool
where
Inc: Incrementable + Default,
Lattice<Inc, Ext>: 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<Inc, Ext>(&self, other: &Lattice<Inc, Ext>) -> bool
where
Inc: Incrementable + Default,
Lattice<Inc, Ext>: LatticeAbstract,
{
self.monotone(other) && other.monotone(self)
}
}
impl Lattice<Atom> {
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<Atom> { impl LatticeAbstract for Lattice<Atom> {
@ -156,13 +198,17 @@ impl LatticeAbstract for Lattice<Atom> {
} }
return false; return false;
} }
fn grow(&mut self) { fn grow(&mut self) -> IncrementResult {
self.order = vec![Default::default(); self.order.len() + 1]; self.order = vec![Default::default(); self.order.len() + 1];
for (i, atom) in self.order.iter_mut().enumerate() { for (i, atom) in self.order.iter_mut().enumerate() {
*atom = Atom { *atom = Atom {
smaller: vec![false; i], 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] #[test]
fn test_is_lattice() -> Result<(), Box<dyn Error>> { fn test_is_lattice() -> Result<(), Box<dyn Error>> {
let lattice = Lattice { let lattice = Lattice {
ext: (),
order: vec![ order: vec![
Atom { smaller: vec![] }, Atom { smaller: vec![] },
Atom { Atom {
@ -195,6 +242,7 @@ mod tests {
}; };
assert!(lattice.is_lattice()); assert!(lattice.is_lattice());
let lattice = Lattice { let lattice = Lattice {
ext: (),
order: vec![ order: vec![
Atom { smaller: vec![] }, Atom { smaller: vec![] },
Atom { Atom {
@ -211,6 +259,7 @@ mod tests {
#[test] #[test]
fn test_is_not_lattice() -> Result<(), Box<dyn Error>> { fn test_is_not_lattice() -> Result<(), Box<dyn Error>> {
let lattice = Lattice { let lattice = Lattice {
ext: (),
order: vec![ order: vec![
Atom { smaller: vec![] }, Atom { smaller: vec![] },
Atom { Atom {
@ -223,6 +272,7 @@ mod tests {
}; };
assert!(!lattice.is_transitive()); assert!(!lattice.is_transitive());
let lattice = Lattice { let lattice = Lattice {
ext: (),
order: vec![ order: vec![
Atom { smaller: vec![] }, Atom { smaller: vec![] },
Atom { Atom {
@ -242,45 +292,58 @@ mod tests {
} }
} }
// struct Operator<'a> {
// lattice: &'a Lattice,
// top: Vec<bool>,
// ul: Vec<bool>,
// ur: Vec<bool>,
// dl: Vec<bool>,
// dr: Vec<bool>,
// bot: Vec<bool>,
// }
// impl<'a> Operator<'a> { struct Mapping<'a> {
// fn new(lattice: &'a Lattice) -> Self { domain: &'a Lattice<Atom>,
// Operator { image: &'a Lattice<Atom>,
// lattice, }
// top: vec![false; lattice.order.len()],
// ul: vec![false; lattice.order.len()], // function: Lattice<AtomSet>,
// ur: vec![false; lattice.order.len()],
// dl: vec![false; lattice.order.len()], type Operator<'a> = Lattice<AtomSet, Mapping<'a>>;
// dr: vec![false; lattice.order.len()],
// bot: vec![false; lattice.order.len()], impl<'a> Operator<'a> {
// } fn new(domain: &'a Lattice<Atom>, image: &'a Lattice<Atom>) -> Operator<'a> {
// } Lattice {
// fn increment(&mut self) { ext: Mapping { domain, image },
// let mut data = [ order: vec![AtomSet { included: vec![] }; image.order.len()],
// &mut self.bot, }
// &mut self.dr, }
// &mut self.dl, fn all_nonempty(&self) -> bool {
// &mut self.ur, self.order.iter().all(|set| set.included.iter().any(|&x| x))
// &mut self.ul, }
// &mut self.top, fn le_helper<I: Iterator<Item = usize> + Clone>(&self, a: I, b: I) -> bool {
// ]; b.clone()
// data[4][0] = false; .all(|right| a.clone().any(|left| self.ext.domain.le(left, right)))
// for (i, el) in data.iter_mut().enumerate() { }
// for a in el.iter_mut() { }
// *a = !*a;
// if *a { impl<'a> LatticeAbstract for Operator<'a> {
// return; 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()
}
}