extern crate linear_solver;
use linear_solver::{solve_minimum, Inference};
use linear_solver::Inference::*;
use std::collections::HashSet;
use self::Expr::*;
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Expr {
Var(&'static str),
Le(Box<Expr>, Box<Expr>),
Eq(Box<Expr>, Box<Expr>),
}
pub fn infer(cache: &HashSet<Expr>, facts: &[Expr]) -> Option<Inference<Expr>> {
for ea in facts {
if let Le(ref a, ref b) = *ea {
if a == b {
return Some(OneTrue {from: ea.clone()});
}
for eb in facts {
if let Le(ref c, ref d) = *eb {
if a == d && b == c {
return Some(Inference::replace(
vec![ea.clone(), eb.clone()],
Eq(a.clone(), b.clone()),
cache
))
}
}
}
}
if let Eq(ref a, ref b) = *ea {
for eb in facts {
if let Le(ref c, ref d) = *eb {
if c == b {
return Some(Inference::replace_one(
eb.clone(),
Le(a.clone(), d.clone()),
cache
));
} else if d == b {
return Some(Inference::replace_one(
eb.clone(),
Le(c.clone(), a.clone()),
cache
));
}
}
if let Eq(ref c, ref d) = *eb {
if b == c {
return Some(Inference::replace_one(
eb.clone(),
Eq(a.clone(), d.clone()),
cache
));
}
}
}
}
}
for ea in facts {
if let Le(ref a, ref b) = *ea {
for eb in facts {
if let Le(ref c, ref d) = *eb {
if b == c {
let new_expr = Le(a.clone(), d.clone());
if !cache.contains(&new_expr) {return Some(Propagate(new_expr))};
}
}
}
}
}
None
}
pub fn var(name: &'static str) -> Box<Expr> {Box::new(Var(name))}
fn main() {
let start = vec![
Le(var("X"), var("Y")), Le(var("Y"), var("Z")), Le(var("Z"), var("X")), ];
let res = solve_minimum(start, infer);
for i in 0..res.len() {
println!("{:?}", res[i]);
}
}