|
|
|
@ -96,19 +96,22 @@ fn remove_term(terms: &mut Vec<Expr>, term: &Expr) -> Option<Expr> {
@@ -96,19 +96,22 @@ fn remove_term(terms: &mut Vec<Expr>, term: &Expr) -> Option<Expr> {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn sum_fold(l: Expr, r: Expr) -> Expr { |
|
|
|
|
use itertools::Itertools; |
|
|
|
|
use Expr::*; |
|
|
|
|
match (l, r) { |
|
|
|
|
(Const(lc), Const(rc)) => Const(lc + rc), |
|
|
|
|
(Const(c), o) | (o, Const(c)) if relative_eq!(c, 0.) => o, |
|
|
|
|
(Product(mut l), Product(mut r)) => { |
|
|
|
|
let comm = remove_common_terms(&mut l, &mut r); |
|
|
|
|
Expr::new_product(Sum(comm), Expr::new_sum(Product(l), Product(r))).simplify() |
|
|
|
|
if comm.is_empty() { |
|
|
|
|
Expr::new_sum(Product(l), Product(r)) |
|
|
|
|
} else { |
|
|
|
|
Expr::new_product(Product(comm), Expr::new_sum(Product(l), Product(r))) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
(Product(mut l), r) | (r, Product(mut l)) => { |
|
|
|
|
let comm = remove_term(&mut l, &r); |
|
|
|
|
match comm { |
|
|
|
|
Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))).simplify(), |
|
|
|
|
Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))), |
|
|
|
|
None => Expr::new_sum(Product(l), r), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -143,6 +146,9 @@ fn group_sum(es: Exprs) -> Exprs {
@@ -143,6 +146,9 @@ fn group_sum(es: Exprs) -> Exprs {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
for c in common.values() { |
|
|
|
|
trace!("group sum value: {}", c); |
|
|
|
|
} |
|
|
|
|
common.into_iter().map(|(_, v)| v).collect() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -159,44 +165,49 @@ fn product_fold(l: Expr, r: Expr) -> Expr {
@@ -159,44 +165,49 @@ fn product_fold(l: Expr, r: Expr) -> Expr {
|
|
|
|
|
Expr::Div(Box::new(Expr::Product(vec![*num, mul])), den).simplify() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
(Product(mut ls), Product(mut rs)) => { |
|
|
|
|
ls.append(&mut rs); |
|
|
|
|
Product(ls) |
|
|
|
|
}, |
|
|
|
|
(Product(mut ps), o) | (o, Product(mut ps)) => { |
|
|
|
|
ps.push(o); |
|
|
|
|
Product(ps) |
|
|
|
|
}, |
|
|
|
|
(l, r) => Expr::new_product(l, r), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn group_product(es: Exprs) -> Exprs { |
|
|
|
|
use Expr::*; |
|
|
|
|
// let mut common: BTreeMap<UnknownSet, Expr> = BTreeMap::new();
|
|
|
|
|
let mut common: Option<Expr> = None; |
|
|
|
|
let es2 = es.clone(); |
|
|
|
|
let mut consts: Option<Scalar> = None; |
|
|
|
|
let mut other = Exprs::new(); |
|
|
|
|
for e in es { |
|
|
|
|
let unkns = e.unknowns(); |
|
|
|
|
// match common.get_mut(&unkns) {
|
|
|
|
|
match &mut common { |
|
|
|
|
None => { |
|
|
|
|
match e {
|
|
|
|
|
Const(c) if relative_eq!(c, 1.) => (), |
|
|
|
|
Const(c) => match consts { |
|
|
|
|
None => consts = Some(c), |
|
|
|
|
Some(cs) => consts = Some(c * cs), |
|
|
|
|
} |
|
|
|
|
e => { |
|
|
|
|
// common.insert(unkns, e);
|
|
|
|
|
common = Some(e); |
|
|
|
|
other.push(e) |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
Some(existing) => { |
|
|
|
|
match existing { |
|
|
|
|
// Product(ref mut es) => {
|
|
|
|
|
// already failed at merging, so just add it to the list
|
|
|
|
|
// es.push(e);
|
|
|
|
|
// }
|
|
|
|
|
other => *other = product_fold(other.clone(), e), |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
if let Some(cs) = consts {
|
|
|
|
|
if relative_eq!(cs, 0.0) { |
|
|
|
|
other.clear(); |
|
|
|
|
other.push(Const(0.0)) |
|
|
|
|
} else if relative_ne!(cs, 1.0) { |
|
|
|
|
other.push(Const(cs))
|
|
|
|
|
} |
|
|
|
|
// common.into_iter().map(|(_, v)| v).collect()
|
|
|
|
|
common.into_iter().collect() |
|
|
|
|
}; |
|
|
|
|
trace!("group product: {:?} => {:?}", es2, other); |
|
|
|
|
other |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn distribute_product_sums(mut es: Exprs) -> Expr { |
|
|
|
|
trace!("distribute_product_sums: {}", Product(es.clone())); |
|
|
|
|
let es_pre = es.clone(); |
|
|
|
|
use itertools::Itertools; |
|
|
|
|
use Expr::*; |
|
|
|
|
for e in &mut es { |
|
|
|
@ -209,14 +220,14 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
@@ -209,14 +220,14 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
|
|
|
|
|
}) |
|
|
|
|
.map(|e| { |
|
|
|
|
trace!("sum in product: {}", e); |
|
|
|
|
match e { |
|
|
|
|
match e.simplify() { |
|
|
|
|
Sum(es) => es, |
|
|
|
|
_ => unreachable!(), |
|
|
|
|
o => vec![o], |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
let products: Vec<_> = sums.multi_cartesian_product().collect(); |
|
|
|
|
if products.is_empty() { |
|
|
|
|
trace!("no sums to distribute"); |
|
|
|
|
trace!("distribute_product_sums: no sums to distribute"); |
|
|
|
|
return Product(es); |
|
|
|
|
} |
|
|
|
|
let sums = products |
|
|
|
@ -227,7 +238,9 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
@@ -227,7 +238,9 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
|
|
|
|
|
Product(prod) |
|
|
|
|
}) |
|
|
|
|
.collect(); |
|
|
|
|
Sum(sums) |
|
|
|
|
let res = Sum(sums); |
|
|
|
|
trace!("distribute_product_sums: {} => {}", Product(es_pre), res); |
|
|
|
|
res |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Unknowns for Expr { |
|
|
|
@ -336,6 +349,7 @@ impl Expr {
@@ -336,6 +349,7 @@ impl Expr {
|
|
|
|
|
use Expr::*; |
|
|
|
|
match self { |
|
|
|
|
Sum(es) => { |
|
|
|
|
let pre_new_es = es.clone(); |
|
|
|
|
let mut new_es: Vec<_> = es |
|
|
|
|
.into_iter() |
|
|
|
|
.map(|e| e.simplify()) |
|
|
|
@ -344,7 +358,6 @@ impl Expr {
@@ -344,7 +358,6 @@ impl Expr {
|
|
|
|
|
other => vec![other], |
|
|
|
|
}) |
|
|
|
|
.collect(); |
|
|
|
|
let pre_new_es = new_es.clone(); |
|
|
|
|
new_es = group_sum(new_es); |
|
|
|
|
trace!( |
|
|
|
|
"simplify sum {} => {}", |
|
|
|
@ -359,6 +372,7 @@ impl Expr {
@@ -359,6 +372,7 @@ impl Expr {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Product(es) => { |
|
|
|
|
let pre_new_es = es.clone(); |
|
|
|
|
let new_es: Vec<_> = es |
|
|
|
|
.into_iter() |
|
|
|
|
.map(|e| e.simplify()) |
|
|
|
@ -367,7 +381,6 @@ impl Expr {
@@ -367,7 +381,6 @@ impl Expr {
|
|
|
|
|
other => vec![other], |
|
|
|
|
}) |
|
|
|
|
.collect(); |
|
|
|
|
let pre_new_es = new_es.clone(); |
|
|
|
|
let new_es = group_product(new_es); |
|
|
|
|
trace!( |
|
|
|
|
"simplify product {} => {}", |
|
|
|
@ -388,7 +401,7 @@ impl Expr {
@@ -388,7 +401,7 @@ impl Expr {
|
|
|
|
|
box Neg(v) => *v, |
|
|
|
|
box Product(mut es) => { |
|
|
|
|
es.push(Const(-1.)); |
|
|
|
|
Product(es) |
|
|
|
|
Product(es).simplify() |
|
|
|
|
} |
|
|
|
|
e => Product(vec![Const(-1.), *e]), |
|
|
|
|
} |
|
|
|
@ -428,13 +441,15 @@ impl Expr {
@@ -428,13 +441,15 @@ impl Expr {
|
|
|
|
|
|
|
|
|
|
pub fn distribute(self) -> Expr { |
|
|
|
|
use Expr::*; |
|
|
|
|
trace!("distribute {}", self); |
|
|
|
|
match self { |
|
|
|
|
Sum(mut es) => { |
|
|
|
|
let es_pre = es.clone(); |
|
|
|
|
for e in &mut es { |
|
|
|
|
*e = e.clone().distribute(); |
|
|
|
|
} |
|
|
|
|
Sum(es) |
|
|
|
|
let res = Sum(es); |
|
|
|
|
trace!("distribute sum {} => {}", Sum(es_pre), res); |
|
|
|
|
res |
|
|
|
|
} |
|
|
|
|
Product(es) => distribute_product_sums(es), |
|
|
|
|
Div(mut num, mut den) => { |
|
|
|
|