This commit is contained in:
Spencer Killen 2023-12-21 01:28:16 -07:00
commit 2e061e32bd
Signed by: sjkillen
GPG Key ID: 3AF3117BA6FBB75B
4 changed files with 321 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

25
Cargo.lock generated Normal file
View File

@ -0,0 +1,25 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "finset-lattice-experiments"
version = "0.1.0"
dependencies = [
"itertools",
]
[[package]]
name = "itertools"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
dependencies = [
"either",
]

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "finset-lattice-experiments"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itertools = "0.12.0"

286
src/main.rs Normal file
View File

@ -0,0 +1,286 @@
use std::{fmt::Display, iter::repeat};
use itertools::Itertools;
enum IncrementResult {
Overflow,
Good,
}
use IncrementResult::*;
trait Incrementable {
fn increment(&mut self) -> IncrementResult;
}
#[derive(Debug, Default, Clone)]
struct Atom {
smaller: Vec<bool>,
}
impl Incrementable for Atom {
fn increment(&mut self) -> IncrementResult {
for a in &mut self.smaller {
*a = !*a;
if *a {
return Good;
}
}
return Overflow;
}
}
#[derive(Debug, Default)]
struct Lattice<I: Incrementable + Default> {
order: Vec<I>,
}
trait LatticeAbstract {
fn le(&self, a: usize, b: usize) -> bool;
fn grow(&mut self);
}
impl Display for Lattice<Atom> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (i, atom) in self.order.iter().enumerate() {
let s = atom
.smaller
.iter()
.map(|&b| if b { "1 " } else { "0 " })
.collect::<String>();
writeln!(f, "{}: {}", i, s)?;
}
Ok(())
}
}
impl<I: Incrementable + Default> Incrementable for Lattice<I> {
fn increment(&mut self) -> IncrementResult {
for atom in &mut self.order {
if let Good = atom.increment() {
return Good;
}
}
return Overflow;
}
}
impl<I: Incrementable> Lattice<I>
where
Self: LatticeAbstract,
{
fn next_lattice(&mut self) {
self.increment();
while !self.is_lattice() {
if let Overflow = self.increment() {
self.grow();
}
}
}
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<C, F>(&self, subset: &Vec<usize>, bound_candidates: C, rel: F) -> bool
where
C: Iterator<Item = usize>,
F: Fn(&Self, usize, usize) -> bool,
{
let mut bound: Option<usize> = None;
for new_bound in bound_candidates {
let is_bound = || subset.iter().all(|&el| rel(self, el, new_bound));
if let Some(old_bound) = bound {
if rel(self, old_bound, new_bound) {
continue;
} else if rel(self, new_bound, old_bound) {
panic!("Bound candidates must be sorted topologically");
} else if is_bound() {
return false;
}
} else if is_bound() {
bound = Some(new_bound);
}
}
return true;
}
fn is_lattice(&self) -> bool {
if !self.is_transitive() {
return false;
}
// 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
let mut subsets = (0..self.order.len()).powerset();
subsets.next(); // Skip the empty set
for subset in subsets {
if !self.is_bounded(&subset, 0..self.order.len(), Lattice::le) {
return false;
}
if !self.is_bounded(&subset, (0..self.order.len()).rev(), Lattice::ge) {
return false;
}
}
return true;
}
}
impl LatticeAbstract for Lattice<Atom> {
fn le(&self, a: usize, b: usize) -> bool {
if a == b {
return true;
}
if a > b {
return false;
}
if self.order[b].smaller[a] {
return true;
}
return false;
}
fn grow(&mut self) {
self.order = vec![Default::default(); self.order.len() + 1];
for (i, atom) in self.order.iter_mut().enumerate() {
*atom = Atom {
smaller: vec![false; i],
}
}
}
}
fn main() {
let mut lattice = Lattice::default();
for (i, _) in repeat(0).enumerate() {
print!("{}", lattice);
println!("iteration {}", i);
lattice.next_lattice();
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error;
#[test]
fn test_is_lattice() -> Result<(), Box<dyn Error>> {
let lattice = Lattice {
order: vec![
Atom { smaller: vec![] },
Atom {
smaller: vec![true],
},
Atom {
smaller: vec![true, false],
},
],
};
assert!(lattice.is_lattice());
let lattice = Lattice {
order: vec![
Atom { smaller: vec![] },
Atom {
smaller: vec![false],
},
Atom {
smaller: vec![true, true],
},
],
};
assert!(lattice.is_lattice());
Ok(())
}
#[test]
fn test_is_not_lattice() -> Result<(), Box<dyn Error>> {
let lattice = Lattice {
order: vec![
Atom { smaller: vec![] },
Atom {
smaller: vec![true],
},
Atom {
smaller: vec![false, true],
},
],
};
assert!(!lattice.is_transitive());
let lattice = Lattice {
order: vec![
Atom { smaller: vec![] },
Atom {
smaller: vec![false],
},
Atom {
smaller: vec![true, true],
},
Atom {
smaller: vec![true, true, false],
},
],
};
assert!(lattice.is_transitive());
assert!(!lattice.is_lattice());
Ok(())
}
}
// 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> {
// 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;
// }
// }
// }
// }
// }