#![cfg_attr(test, feature(test))]
#![deny(missing_docs)]
use std::collections::HashMap;
use std::cell::RefCell;
#[derive(Clone)]
pub struct Graph {
pub exprs: Vec<Expression>,
pub havox: HashMap<(usize, usize), bool>,
pub map: HashMap<Expression, usize>,
pub history: Vec<(usize, usize)>,
pub cache: RefCell<Vec<Option<usize>>>,
}
impl Graph {
pub fn new() -> Graph {
let mut havox = HashMap::new();
havox.insert((0, 1), false);
let mut map = HashMap::new();
map.insert(Expression::False, 0);
map.insert(Expression::True, 1);
Graph {
exprs: vec![Expression::False, Expression::True],
havox,
map,
history: vec![],
cache: RefCell::new(vec![]),
}
}
pub fn false_(&self) -> usize {0}
pub fn true_(&self) -> usize {1}
pub fn contains(&self, expr: &Expression) -> Option<usize> {
self.map.get(expr).map(|&a| a)
}
fn add_expr(&mut self, new_expr: Expression) -> usize {
let id = self.exprs.len();
self.exprs.push(new_expr.clone());
self.map.insert(new_expr, id);
id
}
pub fn var(&mut self, name: usize) -> usize {
let new_expr = Expression::Var(name);
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn not(&mut self, a: usize) -> usize {
let new_expr = Expression::Not(a);
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn eq(&mut self, a: usize, b: usize) -> usize {
let new_expr = Expression::Eq(a.min(b), a.max(b));
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn and(&mut self, a: usize, b: usize) -> usize {
let new_expr = Expression::And(a.min(b), a.max(b));
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn or(&mut self, a: usize, b: usize) -> usize {
let new_expr = Expression::Or(a.min(b), a.max(b));
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn imply(&mut self, a: usize, b: usize) -> usize {
let new_expr = Expression::Imply(a, b);
if let Some(id) = self.contains(&new_expr) {
return id;
}
self.add_expr(new_expr)
}
pub fn havox(&self, id: (usize, usize)) -> Option<bool> {
if id.0 == id.1 {Some(true)}
else if self.havox.contains_key(&id) {Some(self.havox[&id])}
else {
let ref mut cache = self.cache.borrow_mut();
if cache.len() != self.exprs.len() {
**cache = vec![None; self.exprs.len()];
}
let min_a = self.min_index(id.0, cache);
let min_b = self.min_index(id.1, cache);
if min_a == min_b {
return Some(true)
};
let (min_a, min_b) = (min_a.min(min_b), min_a.max(min_b));
if self.havox.contains_key(&(min_a, min_b)) {return Some(self.havox[&(min_a, min_b)])};
for (&(a, b), &val) in self.havox.iter() {
if !val {
let ma = self.min_index(a, cache);
let mb = self.min_index(b, cache);
if ma.min(mb) == min_a && ma.max(mb) == min_b {
return Some(false);
}
}
}
None
}
}
fn min_index(&self, ind: usize, cache: &mut Vec<Option<usize>>) -> usize {
if let Some(min_ind) = cache[ind] {
return min_ind;
}
let mut min_ind: usize = ind;
let offset = cache.len();
loop {
let mut changed = false;
for (&(a, b), &val) in self.havox.iter() {
if val {
if b == min_ind {
if let Some(mi) = cache[a] {
for i in offset..cache.len() {
if let Some(id) = cache[i] {
cache[id] = Some(mi);
}
}
cache[min_ind] = Some(mi);
cache.truncate(offset);
return mi;
}
cache.push(Some(min_ind));
min_ind = a;
changed = true;
}
}
}
if !changed {break}
}
for i in offset..cache.len() {
if let Some(id) = cache[i] {
cache[id] = Some(min_ind);
}
}
cache[min_ind] = Some(min_ind);
cache.truncate(offset);
min_ind
}
pub fn are_eq(&self, a: usize, b: usize) -> Option<bool> {
let id = (a.min(b), a.max(b));
self.havox(id)
}
fn add_havox(&mut self, (a, b): (usize, usize), val: bool) {
let ref mut cache = self.cache.borrow_mut();
let a = self.min_index(a, cache);
let b = self.min_index(b, cache);
let id = (a.min(b), a.max(b));
self.history.push(id);
self.havox.insert(id, val);
cache.clear();
}
fn proof_add_havox(&mut self, id: (usize, usize), val: bool) -> Proof {
if let Some(v) = self.havox(id) {
(val == v).into()
} else {
self.add_havox(id, val);
Proof::True
}
}
pub fn true_and(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
let id = (self.true_(), a);
if let Some(val) = self.havox(id) {
if val {
return self.proof_add_havox((b.min(ind), b.max(ind)), true);
}
}
let id = (self.true_(), b);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(ind), a.max(ind)), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn false_and(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
let fa = self.false_();
let id = (fa, a);
if let Some(val) = self.havox(id) {
if val {
return self.proof_add_havox((fa, ind), true);
}
}
let id = (fa, b);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((fa, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn false_or(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
let id = (self.false_(), a);
if let Some(val) = self.havox(id) {
if val {
return self.proof_add_havox((b.min(ind), b.max(ind)), true);
};
}
let id = (self.false_(), b);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(ind), a.max(ind)), true)
} else {
Proof::Unknown
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn true_or(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
let tr = self.true_();
let id = (tr, a);
if let Some(val) = self.havox(id) {
if val {
return self.proof_add_havox((tr, ind), true);
}
}
let id = (tr, b);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn true_not(&mut self, ind: usize) -> Proof {
if let Expression::Not(a) = self.exprs[ind] {
let id = (self.true_(), a);
if let Some(val) = self.havox(id) {
if val {
let fa = self.false_();
self.proof_add_havox((fa, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn false_not(&mut self, ind: usize) -> Proof {
if let Expression::Not(a) = self.exprs[ind] {
let id = (self.false_(), a);
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn false_imply(&mut self, ind: usize) -> Proof {
if let Expression::Imply(a, _) = self.exprs[ind] {
let id = (self.false_(), a);
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn true_imply(&mut self, ind: usize) -> Proof {
if let Expression::Imply(a, b) = self.exprs[ind] {
let id = (self.true_(), a);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((b.min(ind), b.max(ind)), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn false_eq(&mut self, ind: usize) -> Proof {
if let Expression::Eq(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if !val {
let id = (self.false_(), ind);
self.proof_add_havox(id, true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn true_eq(&mut self, ind: usize) -> Proof {
if let Expression::Eq(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let id = (self.true_(), ind);
self.proof_add_havox(id, true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn eq_true(&mut self, ind: usize) -> Proof {
if let Expression::Eq(a, b) = self.exprs[ind] {
let id = (self.true_(), ind);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(b), a.max(b)), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn eq_false(&mut self, ind: usize) -> Proof {
if let Expression::Eq(a, b) = self.exprs[ind] {
let id = (self.false_(), ind);
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(b), a.max(b)), false)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn paradox(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
if let Expression::Not(b) = self.exprs[b] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let fa = self.false_();
self.proof_add_havox((fa, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else if let Expression::Not(a) = self.exprs[a] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let fa = self.false_();
self.proof_add_havox((fa, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
} else {
Proof::Error
}
}
pub fn tautology(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
if let Expression::Not(b) = self.exprs[b] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else if let Expression::Not(a) = self.exprs[a] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
} else {
Proof::Error
}
}
pub fn or_false(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
let fa = self.false_();
let id = (fa, ind);
if let Some(val) = self.havox(id) {
if val {
let id = (fa, a);
if let Some(val) = self.havox(id) {
if val {return Proof::False};
} else {
self.add_havox(id, true);
}
let id = (fa, b);
if let Some(val) = self.havox(id) {
if val {return Proof::False};
} else {
self.add_havox(id, true);
}
Proof::True
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn and_true(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
let tr = self.true_();
let id = (tr, ind);
if let Some(val) = self.havox(id) {
if val {
let id = (tr, a);
if let Some(val) = self.havox(id) {
if !val {return Proof::False};
} else {
self.add_havox(id, true);
}
let id = (tr, b);
if let Some(val) = self.havox(id) {
if !val {return Proof::False};
} else {
self.add_havox(id, true);
}
Proof::True
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn not_true(&mut self, ind: usize) -> Proof {
if let Expression::Not(a) = self.exprs[ind] {
let id = (self.true_(), ind);
if let Some(val) = self.havox(id) {
if val {
let fa = self.false_();
self.proof_add_havox((fa, a), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn not_false(&mut self, ind: usize) -> Proof {
if let Expression::Not(a) = self.exprs[ind] {
let id = (self.false_(), ind);
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, a), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn excluded_middle(&mut self, ind: usize) -> Proof {
let id = (self.false_(), ind);
if let Some(val) = self.havox(id) {
let tr = self.true_();
self.proof_add_havox((tr, ind), !val)
} else {
let id = (self.true_(), ind);
if let Some(val) = self.havox(id) {
let fa = self.false_();
self.proof_add_havox((fa, ind), !val)
} else {
Proof::Unknown
}
}
}
pub fn eq_and(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(ind), a.max(ind)), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn neq_and(&mut self, ind: usize) -> Proof {
if let Expression::And(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if !val {
let fa = self.false_();
self.proof_add_havox((fa, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn eq_or(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
self.proof_add_havox((a.min(ind), ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn neq_or(&mut self, ind: usize) -> Proof {
if let Expression::Or(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if !val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn eq_imply(&mut self, ind: usize) -> Proof {
if let Expression::Imply(a, b) = self.exprs[ind] {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {
if val {
let tr = self.true_();
self.proof_add_havox((tr, ind), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn neq_imply(&mut self, ind: usize) -> Proof {
if let Expression::Imply(a, b) = self.exprs[ind] {
let id = (a.min(b), b.max(b));
if let Some(val) = self.havox(id) {
if !val {
self.proof_add_havox((b.min(ind), b.max(ind)), true)
} else {
Proof::Unexpected
}
} else {
Proof::Unknown
}
} else {
Proof::Error
}
}
pub fn assume_eq(&mut self, a: usize, b: usize) -> Assumption {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {return Assumption::AlreadyKnown(val)};
let len = self.history.len();
self.add_havox(id, true);
Assumption::Eq {id, history: len}
}
pub fn assume_neq(&mut self, a: usize, b: usize) -> Assumption {
let id = (a.min(b), a.max(b));
if let Some(val) = self.havox(id) {return Assumption::AlreadyKnown(val)};
let len = self.history.len();
self.add_havox(id, false);
Assumption::Neq {id, history: len}
}
pub fn solve(&mut self) -> Proof {
loop {
let len = self.history.len();
for i in 0..self.exprs.len() {
if self.and_true(i) == Proof::False {return Proof::False};
if self.or_false(i) == Proof::False {return Proof::False};
if self.true_and(i) == Proof::False {return Proof::False};
if self.false_and(i) == Proof::False {return Proof::False};
if self.true_or(i) == Proof::False {return Proof::False};
if self.false_or(i) == Proof::False {return Proof::False};
if self.true_imply(i) == Proof::False {return Proof::False};
if self.false_imply(i) == Proof::False {return Proof::False};
if self.false_eq(i) == Proof::False {return Proof::False};
if self.true_eq(i) == Proof::False {return Proof::False};
if self.paradox(i) == Proof::False {return Proof::False};
if self.tautology(i) == Proof::False {return Proof::False};
if self.eq_true(i) == Proof::False {return Proof::False};
if self.eq_false(i) == Proof::False {return Proof::False};
if self.eq_and(i) == Proof::False {return Proof::False};
if self.neq_and(i) == Proof::False {return Proof::False};
if self.eq_or(i) == Proof::False {return Proof::False};
if self.neq_or(i) == Proof::False {return Proof::False};
if self.eq_imply(i) == Proof::False {return Proof::False};
if self.neq_imply(i) == Proof::False {return Proof::False};
if self.not_true(i) == Proof::False {return Proof::False};
if self.not_false(i) == Proof::False {return Proof::False};
if self.true_not(i) == Proof::False {return Proof::False};
if self.false_not(i) == Proof::False {return Proof::False};
if self.excluded_middle(i) == Proof::False {return Proof::False};
}
if self.history.len() == len {
return Proof::True;
}
}
}
}
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Assumption {
AlreadyKnown(bool),
Eq {
id: (usize, usize),
history: usize
},
Neq {
id: (usize, usize),
history: usize
},
}
impl Assumption {
pub fn undo(&self, graph: &mut Graph) {
match *self {
Assumption::AlreadyKnown(_) => {}
Assumption::Eq {history, ..} | Assumption::Neq {history, ..} => {
for i in history..graph.history.len() {
let id = graph.history[i];
graph.havox.remove(&id);
}
graph.history.truncate(history);
graph.cache.borrow_mut().clear();
}
}
}
pub fn invert(&self, graph: &mut Graph) -> Assumption {
self.undo(graph);
match *self {
Assumption::AlreadyKnown(_) => *self,
Assumption::Eq {id, ..} => graph.assume_neq(id.0, id.1),
Assumption::Neq {id, ..} => graph.assume_eq(id.0, id.1),
}
}
}
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Proof {
True,
False,
Unknown,
Unexpected,
Error,
}
impl From<bool> for Proof {
fn from(val: bool) -> Proof {
if val {Proof::True} else {Proof::False}
}
}
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
pub enum Expression {
True,
False,
Var(usize),
Not(usize),
And(usize, usize),
Or(usize, usize),
Eq(usize, usize),
Imply(usize, usize),
}
#[cfg(test)]
mod tests {
extern crate test;
use super::*;
use self::test::Bencher;
#[test]
fn false_imply() {
let mut g = Graph::new();
let a = g.var(0);
let fa = g.false_();
let b = g.imply(fa, a); assert_eq!(g.false_imply(b), Proof::True);
}
#[test]
fn true_imply() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let c = g.imply(a, b); let tr = g.true_();
let a_tr = g.assume_eq(tr, a); assert_eq!(g.true_imply(c), Proof::True);
let a_not_tr = a_tr.invert(g);
assert_eq!(g.false_imply(c), Proof::Unknown);
a_not_tr.undo(g);
}
#[test]
fn invert() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let _ab = g.assume_eq(a, b); let tr = g.true_();
let a_tr = g.assume_eq(tr, a); assert_eq!(g.are_eq(tr, b), Some(true));
let a_not_tr = a_tr.invert(g); assert_eq!(g.are_eq(tr, b), Some(false));
a_not_tr.undo(g);
}
#[test]
fn false_eq() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let eq = g.eq(a, b);
let _ = g.assume_neq(a, b);
assert_eq!(g.false_eq(eq), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(eq, fa), Some(true));
}
#[test]
fn true_eq() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let eq = g.eq(a, b);
let _ = g.assume_eq(a, b);
assert_eq!(g.true_eq(eq), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(eq, tr), Some(true));
}
#[test]
fn eq_true() {
let ref mut g = Graph::new();
let a = g.var(0);
let tr = g.true_();
let eq = g.eq(a, tr);
let eq_tr = g.assume_eq(eq, tr); assert_eq!(g.are_eq(a, tr), None);
assert_eq!(g.eq_true(eq), Proof::True);
assert_eq!(g.are_eq(a, tr), Some(true));
eq_tr.undo(g);
assert_eq!(g.eq_true(eq), Proof::Unknown);
let _a_neq_true = g.assume_neq(a, tr); let _eq_tr = g.assume_eq(eq, tr); assert_eq!(g.eq_true(eq), Proof::False);
}
#[test]
fn paradox() {
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let and = g.and(a, not_a);
assert_eq!(g.paradox(and), Proof::True);
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let and = g.and(not_a, a);
assert_eq!(g.paradox(and), Proof::True);
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let not_b = g.not(b);
let and = g.and(a, not_b);
assert_eq!(g.paradox(and), Proof::Unknown);
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let not_b = g.not(b);
let and = g.and(a, not_b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.paradox(and), Proof::Unexpected);
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let and = g.and(a, not_a);
let c = g.var(2);
let _c_is_and = g.assume_eq(c, and);
assert_eq!(g.paradox(c), Proof::Error);
assert_eq!(g.paradox(and), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(and, fa), Some(true));
assert_eq!(g.are_eq(c, fa), Some(true));
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let and = g.and(not_a, a);
let c = g.var(2);
let _c_is_and = g.assume_eq(c, and);
assert_eq!(g.paradox(c), Proof::Error);
assert_eq!(g.paradox(and), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(and, fa), Some(true));
assert_eq!(g.are_eq(c, fa), Some(true));
}
#[test]
fn true_or() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or = g.or(a, b);
let tr = g.true_();
let a_is_true = g.assume_eq(a, tr);
assert_eq!(g.true_or(or), Proof::True);
a_is_true.undo(g);
let b_is_true = g.assume_eq(b, tr);
assert_eq!(g.true_or(or), Proof::True);
b_is_true.undo(g);
}
#[test]
fn false_and() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and = g.and(a, b);
let fa = g.false_();
let a_is_false = g.assume_eq(a, fa);
assert_eq!(g.false_and(and), Proof::True);
a_is_false.undo(g);
let b_is_false = g.assume_eq(b, fa);
assert_eq!(g.false_and(and), Proof::True);
b_is_false.undo(g);
}
#[test]
fn eq_and() {
let ref mut g = Graph::new();
let a = g.var(0);
let and = g.and(a, a);
assert_eq!(g.eq_and(and), Proof::True);
assert_eq!(g.are_eq(and, a), Some(true));
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and = g.and(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.eq_and(and), Proof::True);
assert_eq!(g.are_eq(and, a), Some(true));
assert_eq!(g.are_eq(and, b), Some(true));
}
#[test]
fn neq_and() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and = g.and(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.neq_and(and), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(and, fa), Some(true));
}
#[test]
fn eq_or() {
let ref mut g = Graph::new();
let a = g.var(0);
let or = g.or(a, a);
assert_eq!(g.eq_or(or), Proof::True);
assert_eq!(g.are_eq(or, a), Some(true));
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or = g.or(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.eq_or(or), Proof::True);
assert_eq!(g.are_eq(or, a), Some(true));
assert_eq!(g.are_eq(or, b), Some(true));
}
#[test]
fn neq_or() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or = g.or(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.neq_or(or), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(or, tr), Some(true));
}
#[test]
fn eq_imply() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let imply = g.imply(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.eq_imply(imply), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(imply, tr), Some(true));
}
#[test]
fn neq_imply() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let imply = g.imply(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.neq_imply(imply), Proof::True);
assert_eq!(g.are_eq(imply, b), Some(true));
}
#[test]
fn and_commutative() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and1 = g.and(a, b);
let and2 = g.and(b, a);
assert_eq!(g.are_eq(and1, and2), Some(true));
}
#[test]
fn or_commutative() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or1 = g.or(a, b);
let or2 = g.or(b, a);
assert_eq!(g.are_eq(or1, or2), Some(true));
}
#[test]
fn eq_commutative() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let eq1 = g.eq(a, b);
let eq2 = g.eq(b, a);
assert_eq!(g.are_eq(eq1, eq2), Some(true));
}
#[test]
fn propagate_equality() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let c = g.var(2);
let d = g.var(3);
let _ = g.assume_eq(a, b);
let _ = g.assume_eq(b, c);
let _ = g.assume_eq(c, d);
assert_eq!(g.are_eq(a, c), Some(true));
assert_eq!(g.are_eq(a, d), Some(true));
}
#[test]
fn propagate_inequality() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let c = g.var(2);
let d = g.var(3);
let _ = g.assume_neq(a, b);
let _ = g.assume_eq(a, c);
let _ = g.assume_eq(b, d);
assert_eq!(g.are_eq(c, d), Some(false));
}
#[bench]
fn bench_propagate_equality(bencher: &mut Bencher) {
let ref mut g = Graph::new();
for i in 0..1000 {
let _ = g.var(i);
}
for i in 1..1000 {
let a = g.var(i-1);
let b = g.var(i);
let _ = g.assume_eq(a, b);
}
let a = g.var(0);
let b = g.var(999);
bencher.iter(|| {
assert_eq!(g.are_eq(a, b), Some(true));
});
}
#[bench]
fn bench_propagate_inequality(bencher: &mut Bencher) {
let ref mut g = Graph::new();
for i in 0..1000 {
let _ = g.var(i);
let _ = g.var(1000+i);
}
for i in 1..1000 {
let a = g.var(i-1);
let b = g.var(i);
let _ = g.assume_eq(a, b);
let a = g.var(1000+i-1);
let b = g.var(1000+i);
let _ = g.assume_eq(a, b);
}
let a = g.var(999);
let b = g.var(1000);
let _ = g.assume_neq(a, b);
let a = g.var(0);
let b = g.var(1999);
bencher.iter(|| {
assert_eq!(g.are_eq(a, b), Some(false));
});
}
#[test]
fn proof_1() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let a_imply_b = g.imply(a, b);
let and = g.and(a_imply_b, a);
let imply = g.imply(and, b);
let tr = g.true_();
let _ = g.assume_eq(imply, tr);
let _ = g.assume_eq(and, tr);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(b, tr), Some(true));
assert_eq!(g.are_eq(and, tr), Some(true));
assert_eq!(g.are_eq(a, tr), Some(true));
assert_eq!(g.are_eq(a_imply_b, tr), Some(true));
}
#[test]
fn proof_2() {
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let and = g.and(a, not_a);
assert_eq!(g.solve(), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(and, fa), Some(true));
}
#[test]
fn proof_3() {
let ref mut g = Graph::new();
let a = g.var(0);
let not_a = g.not(a);
let or = g.or(a, not_a);
assert_eq!(g.solve(), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(or, tr), Some(true));
}
#[test]
fn proof_4() {
let ref mut g = Graph::new();
let a = g.var(0);
let eq = g.eq(a, a);
assert_eq!(g.solve(), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(eq, tr), Some(true));
}
#[test]
fn proof_5() {
let ref mut g = Graph::new();
let a = g.var(0);
let tr = g.true_();
let eq = g.eq(a, tr);
let eq_tr = g.assume_eq(eq, tr); assert_eq!(g.are_eq(a, tr), None);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(a, tr), Some(true));
eq_tr.undo(g);
assert_eq!(g.eq_true(eq), Proof::Unknown);
let _a_neq_true = g.assume_neq(a, tr); let _eq_tr = g.assume_eq(eq, tr); assert_eq!(g.eq_true(eq), Proof::False);
}
#[test]
fn proof_6() {
let ref mut g = Graph::new();
let a = g.var(0);
let and = g.and(a, a);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and, a), Some(true));
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and = g.and(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and, a), Some(true));
assert_eq!(g.are_eq(and, b), Some(true));
}
#[test]
fn proof_7() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let and = g.and(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.solve(), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(and, fa), Some(true));
}
#[test]
fn proof_8() {
let ref mut g = Graph::new();
let a = g.var(0);
let or = g.or(a, a);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(or, a), Some(true));
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or = g.or(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(or, a), Some(true));
assert_eq!(g.are_eq(or, b), Some(true));
}
#[test]
fn proof_9() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let or = g.or(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.solve(), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(or, tr), Some(true));
}
#[test]
fn proof_10() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let imply = g.imply(a, b);
let _a_eq_b = g.assume_eq(a, b);
assert_eq!(g.solve(), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(imply, tr), Some(true));
}
#[test]
fn proof_11() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let imply = g.imply(a, b);
let _a_neq_b = g.assume_neq(a, b);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(imply, b), Some(true));
}
#[test]
fn proof_12() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let imply = g.imply(a, b);
let a_eq_b = g.eq(a, b);
let neq = g.not(a_eq_b);
let and1 = g.and(imply, neq);
let not_a = g.not(a);
let and2 = g.and(not_a, b);
let eq = g.eq(and1, and2);
let tr = g.true_();
let fa = g.false_();
let _ = g.assume_eq(eq, tr);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and1, and2), Some(true));
let and1_tr = g.assume_eq(and1, tr);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(imply, tr), Some(true));
assert_eq!(g.are_eq(neq, tr), Some(true));
assert_eq!(g.are_eq(a_eq_b, fa), Some(true));
assert_eq!(g.are_eq(a, b), Some(false));
assert_eq!(g.are_eq(imply, b), Some(true));
assert_eq!(g.are_eq(b, tr), Some(true));
assert_eq!(g.are_eq(not_a, tr), Some(true));
assert_eq!(g.are_eq(a, fa), Some(true));
let _ = and1_tr.invert(g);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and1, tr), Some(false));
assert_eq!(g.are_eq(and1, fa), Some(true));
assert_eq!(g.are_eq(and1, and2), Some(true));
assert_eq!(g.are_eq(and2, fa), Some(true));
assert_eq!(g.are_eq(and2, tr), Some(false));
assert_eq!(g.are_eq(b, fa), None);
assert_eq!(g.are_eq(not_a, fa), None);
let _ = g.assume_eq(b, tr);
let _ = g.assume_eq(not_a, fa);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(a, tr), Some(true));
assert_eq!(g.are_eq(not_a, fa), Some(true));
assert_eq!(g.are_eq(imply, fa), Some(false));
assert_eq!(g.are_eq(a_eq_b, tr), Some(true));
assert_eq!(g.are_eq(neq, fa), Some(true));
}
#[test]
fn proof_13() {
let ref mut g = Graph::new();
let a = g.var(0);
let tr = g.true_();
let and = g.and(a, tr);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and, a), Some(true));
}
#[test]
fn proof_14() {
let ref mut g = Graph::new();
let a = g.var(0);
let fa = g.false_();
let and = g.and(a, fa);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(and, fa), Some(true));
}
#[test]
fn proof_15() {
let ref mut g = Graph::new();
let a = g.var(0);
let fa = g.false_();
let or = g.or(a, fa);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(or, a), Some(true));
}
#[test]
fn proof_16() {
let ref mut g = Graph::new();
let a = g.var(0);
let tr = g.true_();
let or = g.or(a, tr);
assert_eq!(g.solve(), Proof::True);
assert_eq!(g.are_eq(or, tr), Some(true));
}
#[test]
fn proof_17() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let eq = g.eq(a, b);
let _ = g.assume_neq(a, b);
assert_eq!(g.solve(), Proof::True);
let fa = g.false_();
assert_eq!(g.are_eq(eq, fa), Some(true));
}
#[test]
fn proof_18() {
let ref mut g = Graph::new();
let a = g.var(0);
let b = g.var(1);
let eq = g.eq(a, b);
let _ = g.assume_eq(a, b);
assert_eq!(g.solve(), Proof::True);
let tr = g.true_();
assert_eq!(g.are_eq(eq, tr), Some(true));
}
}