temp
This commit is contained in:
commit
2e061e32bd
|
@ -0,0 +1 @@
|
||||||
|
/target
|
|
@ -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",
|
||||||
|
]
|
|
@ -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"
|
|
@ -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;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
Loading…
Reference in New Issue