use std::rc::Rc;
use std::collections::HashMap;
extern crate symbolic_polynomials;
extern crate num;
use symbolic_polynomials::*;
use num::Integer;
type TestMonomial = Monomial<String, i64, u8>;
type TestPolynomial = Polynomial<String, i64, u8>;
#[test]
pub fn max_test() {
let thirteen = TestPolynomial::from(13);
let three = TestPolynomial::from(3);
let thirteen_v2 = max(&thirteen, &three);
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let a_square = &a * &a;
let a_third = &a_square * &a;
let a_v2 = max(&a_square, &a);
let max_a_square_b = max(&a_square, &b);
let max_a_third_b = max(&a_third, &b);
assert!(thirteen_v2 == 13 && 13 == thirteen_v2);
assert!(a_v2.monomials.len() == 1);
assert!(a_v2.monomials[0].coefficient == 1);
assert!(a_v2.monomials[0].powers == vec![(Composite::Max(Rc::new(a_square.clone()), Rc::new(a)), 1)]);
assert!(max_a_square_b.monomials.len() == 1);
assert!(max_a_square_b.monomials[0].coefficient == 1);
assert!(max_a_square_b.monomials[0].powers == vec![(Composite::Max(Rc::new(a_square), Rc::new(b.clone())), 1)]);
assert!(max_a_third_b.monomials.len() == 1);
assert!(max_a_third_b.monomials[0].coefficient == 1);
assert!(max_a_third_b.monomials[0].powers == vec![(Composite::Max(Rc::new(a_third), Rc::new(b)), 1)]);
let mut values = HashMap::<String, i64>::new();
values.insert("a".into(), 3);
values.insert("b".into(), 13);
assert!(thirteen.eval(&values) == Ok(13));
assert!(max_a_square_b.eval(&values) == Ok(13));
assert!(max_a_third_b.eval(&values) == Ok(27));
}
#[test]
pub fn min_test() {
let thirteen = TestPolynomial::from(13);
let three = TestPolynomial::from(3);
let three_v2 = min(&thirteen, &three);
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let a_square = &a * &a;
let a_third = &a_square * &a;
let a_v2 = min(&a_square, &a);
let min_a_square_b = min(&a_square, &b);
let min_a_third_b = min(&a_third, &b);
assert!(three_v2 == 3 && 3 == three_v2);
assert!(a_v2.monomials.len() == 1);
assert!(a_v2.monomials[0].coefficient == 1);
assert!(a_v2.monomials[0].powers == vec![(Composite::Min(Rc::new(a_square.clone()), Rc::new(a)), 1)]);
assert!(min_a_square_b.monomials.len() == 1);
assert!(min_a_square_b.monomials[0].coefficient == 1);
assert!(min_a_square_b.monomials[0].powers == vec![(Composite::Min(Rc::new(a_square), Rc::new(b.clone())), 1)]);
assert!(min_a_third_b.monomials.len() == 1);
assert!(min_a_third_b.monomials[0].coefficient == 1);
assert!(min_a_third_b.monomials[0].powers == vec![(Composite::Min(Rc::new(a_third), Rc::new(b)), 1)]);
let mut values = HashMap::<String, i64>::new();
values.insert("a".into(), 3);
values.insert("b".into(), 13);
assert!(three_v2.eval(&values) == Ok(3));
assert!(min_a_square_b.eval(&values) == Ok(9));
assert!(min_a_third_b.eval(&values) == Ok(13));
}
#[test]
pub fn ceil_test() {
let thirteen = TestPolynomial::from(13);
let three = TestPolynomial::from(3);
let five = ceil(&thirteen, &three);
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let a_square = &a * &a;
let a_third = &a_square * &a;
let a_v2 = ceil(&a_square, &a);
let ceil_a_square_b = ceil(&a_square, &b);
let ceil_a_third_b = ceil(&a_third, &b);
assert!(five == 5 && 5 == five);
assert!(a_v2 == a);
assert!(ceil_a_square_b.monomials.len() == 1);
assert!(ceil_a_square_b.monomials[0].coefficient == 1);
assert!(ceil_a_square_b.monomials[0].powers == vec![(Composite::Ceil(Rc::new(a_square), Rc::new(b.clone())), 1)]);
assert!(ceil_a_third_b.monomials.len() == 1);
assert!(ceil_a_third_b.monomials[0].coefficient == 1);
assert!(ceil_a_third_b.monomials[0].powers == vec![(Composite::Ceil(Rc::new(a_third), Rc::new(b)), 1)]);
let mut values = HashMap::<String, i64>::new();
values.insert("a".into(), 3);
values.insert("b".into(), 13);
assert!(five.eval(&values) == Ok(5));
assert!(ceil_a_square_b.eval(&values) == Ok(1));
assert!(ceil_a_third_b.eval(&values) == Ok(3));
}
#[test]
pub fn floor_test() {
let thirteen = TestPolynomial::from(13);
let three = TestPolynomial::from(3);
let four = floor(&thirteen, &three);
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let a_square = &a * &a;
let a_third = &a_square * &a;
let a_v2 = floor(&a_square, &a);
let floor_a_square_b = floor(&a_square, &b);
let floor_a_third_b = floor(&a_third, &b);
assert!(four == 4 && 4 == four);
assert!(a_v2 == a && a == a_v2);
assert!(floor_a_square_b.monomials.len() == 1);
assert!(floor_a_square_b.monomials[0].coefficient == 1);
assert!(floor_a_square_b.monomials[0].powers == vec![(Composite::Floor(Rc::new(a_square), Rc::new(b.clone())), 1)]);
assert!(floor_a_third_b.monomials.len() == 1);
assert!(floor_a_third_b.monomials[0].coefficient == 1);
assert!(floor_a_third_b.monomials[0].powers == vec![(Composite::Floor(Rc::new(a_third), Rc::new(b)), 1)]);
let mut values = HashMap::<String, i64>::new();
values.insert("a".into(), 3);
values.insert("b".into(), 13);
assert!(four.eval(&values) == Ok(4));
assert!(floor_a_square_b.eval(&values) == Ok(0));
assert!(floor_a_third_b.eval(&values) == Ok(2));
}
#[test]
pub fn deduce_values_test1() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 1;
let b_val: i64 = 3;
let c_val: i64 = 7;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = a.clone();
let val1 = a_val;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&a * &b) * 2) + 1;
let val2 = 2 * a_val * b_val + 1;
implicit_values.push((poly2.clone(), val2));
let poly3 = &(&(&(&(&a * &a) * &(&b * &b)) * &(&c * &c)) * 5) + &(&(&(&a * &a) * &b) + 3);
let val3 = 5 * a_val * a_val * b_val * b_val * c_val * c_val + a_val * a_val * b_val + 3;
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test2() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 2;
let b_val: i64 = 3;
let c_val: i64 = 5;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = &(&(&(&a * &b) * &c) + &(&(&(&a * &c) * &c) * &b)) + 1;
let val1 = a_val * b_val * c_val + a_val * c_val * c_val * b_val + 1;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&a * &a) + &(&c * &c)) + 2;
let val2 = a_val * a_val + c_val * c_val + 2;
implicit_values.push((poly2.clone(), val2));
let poly3 = 5 * &c;
let val3 = 5 * c_val;
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test3() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 1;
let b_val: i64 = 2;
let c_val: i64 = 3;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = 3 * &(&b * &b);
let val1 = 3 * b_val * b_val;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&(&a * &a) * &a) + &(&(&b * &b) * &b)) - 10;
let val2 = a_val * a_val * a_val + b_val * b_val * b_val - 10;
implicit_values.push((poly2.clone(), val2));
let poly3 = &(&(&(&a * &b) + &(&a * &c)) + &(&b * &c)) + 3;
let val3 = a_val * b_val + a_val * c_val + b_val * c_val + 3;
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test_floor_min() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 1;
let b_val: i64 = 3;
let c_val: i64 = 7;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = a.clone();
let val1 = a_val;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&a * &b) * 2) + 1;
let val2 = 2 * a_val * b_val + 1;
implicit_values.push((poly2.clone(), val2));
let poly3 = &(&(&(&(&a * &a) * &(&b * &b)) * &(&c * &c)) * 5) +
&(&floor(&(&(&a * &b) * &b), &2.into()) + &(&min(&(&a * &a), &(&b * &b)) + 3));
let val3 = 5 * a_val * a_val * b_val * b_val * c_val * c_val + (a_val * b_val * b_val).div_floor(&2) +
::std::cmp::min(a_val * a_val, b_val * b_val) + 3;
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test_ceil_max() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 2;
let b_val: i64 = 3;
let c_val: i64 = 5;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = &(&(&(&a * &b) * &c) + &(&(&(&a * &c) * &c) * &b)) + 1;
let val1 = a_val * b_val * c_val + a_val * c_val * c_val * b_val + 1;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&a * &a) + &ceil(&(&c * &c), &6.into())) + &(&max(&(&c * &c), &12.into()) + 2);
let mut val2 = a_val * a_val + (c_val * c_val).div_floor(&6) + ::std::cmp::max(c_val * c_val, 12) + 2;
if c_val * c_val % 6 != 0 {
val2 += 1;
}
implicit_values.push((poly2.clone(), val2));
let poly3 = 5 * &c;
let val3 = 5 * c_val;
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test_all() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 2;
let b_val: i64 = 3;
let c_val: i64 = 5;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = 3 * &(&b * &b);
let val1 = 3 * b_val * b_val;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&(&(&(&a * &a) * &a) + &floor(&(&(&b * &b) * &b), &3.into())) - &(&min(&(&b * &b), &17.into()) + 10));
let val2 = a_val * a_val * a_val + (b_val * b_val * b_val).div_floor(&3) - 10 - ::std::cmp::min(b_val * b_val, 17);
implicit_values.push((poly2.clone(), val2));
let poly3 = &(&(&ceil(&(&(&(&a * &b) * 7)), &5.into()) + &(&a * &c)) + &(&b * &c)) +
&(&max(&(&(&a * &b) - 5), &(&a + &(2 * &b))) + 3);
let mut val3 = (7 * a_val * b_val).div_floor(&5) + a_val * c_val + b_val * c_val + 3 +
::std::cmp::max(a_val * b_val - 5, a_val + 2 * b_val);
if 7 * a_val * b_val % 5 != 0 {
val3 += 1;
}
implicit_values.push((poly3.clone(), val3));
let values = deduce_values(&implicit_values).unwrap();
assert!(a.eval(&values) == Ok(a_val));
assert!(b.eval(&values) == Ok(b_val));
assert!(c.eval(&values) == Ok(c_val));
assert!(poly1.eval(&values) == Ok(val1));
assert!(poly2.eval(&values) == Ok(val2));
assert!(poly3.eval(&values) == Ok(val3));
}
#[test]
pub fn deduce_values_test_fails() {
let a: TestPolynomial = variable("a".into());
let b: TestPolynomial = variable("b".into());
let c: TestPolynomial = variable("c".into());
let a_val: i64 = 1;
let b_val: i64 = 2;
let c_val: i64 = 3;
let mut implicit_values = Vec::<(TestPolynomial, i64)>::new();
let poly1 = &a * &(&b * &b);
let val1 = a_val * b_val * b_val;
implicit_values.push((poly1.clone(), val1));
let poly2 = &(&b * 2) + 1;
let val2 = 2 * b_val + 1;
implicit_values.push((poly2.clone(), val2));
let poly3 = &(&(&(&a * &c) * &c) + &(&b * &c)) + 2;
let val3 = a_val * c_val * c_val + b_val * c_val + 2;
implicit_values.push((poly3.clone(), val3));
assert!(deduce_values(&implicit_values) == Err("Could not deduce all variables.".into()));
let poly2 = &(&(&b * &c) * 2) + 1;
let val2 = 2 * b_val * c_val + 1;
implicit_values.remove(1);
implicit_values.push((poly2.clone(), val2));
assert!(deduce_values(&implicit_values) == Err("Could not deduce all variables.".into()));
}