mod common;
use hashconsing::HConsign;
use simple_term_rewriter::position::PositionInLanguageTerm;
use simple_term_rewriter::rule::RewriteRule;
use simple_term_rewriter::rules::primitives::factorization::{
defactorize::{DefactorizeLeftRule, DefactorizeRightRule},
factorize_modulo_ac::{FactorizeLeftModACRule, FactorizeRightModACRule},
factorize_simple::{FactorizeLeftRule, FactorizeRightRule},
};
use simple_term_rewriter::term::syntax::TermFactory;
use common::arith::constructors::*;
use common::arith::lang::ArithOp;
use common::arith::rules::ArithChecker;
fn root_pos() -> PositionInLanguageTerm {
PositionInLanguageTerm::get_root_position()
}
#[test]
fn factorize_left_fires() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x.clone(), var('b', &mut f), &mut f),
&mut f,
);
let expected = mul(x, add(var('a', &mut f), var('b', &mut f), &mut f), &mut f);
let rule = FactorizeLeftRule::new("factL", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_left_no_fire_different_left_factors() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
mul(var('x', &mut f), var('a', &mut f), &mut f),
mul(var('y', &mut f), var('b', &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftRule::new("factL", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_left_no_fire_inner_ops_differ() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(x.clone(), var('a', &mut f), &mut f),
add(x, var('b', &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftRule::new("factL", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_left_no_fire_outer_op_not_distributive() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x, var('b', &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftRule::new("factL", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_right_fires() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x.clone(), &mut f),
&mut f,
);
let expected = mul(add(var('a', &mut f), var('b', &mut f), &mut f), x, &mut f);
let rule = FactorizeRightRule::new("factR", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_right_no_fire_different_right_factors() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
mul(var('a', &mut f), var('x', &mut f), &mut f),
mul(var('b', &mut f), var('y', &mut f), &mut f),
&mut f,
);
let rule = FactorizeRightRule::new("factR", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_right_no_fire_outer_op_not_distributive() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x, &mut f),
&mut f,
);
let rule = FactorizeRightRule::new("factR", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn defactorize_left_fires() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
x.clone(),
add(var('a', &mut f), var('b', &mut f), &mut f),
&mut f,
);
let expected = add(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x, var('b', &mut f), &mut f),
&mut f,
);
let rule = DefactorizeLeftRule::new("defactL", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn defactorize_left_no_fire_right_subterm_not_binary() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = mul(var('x', &mut f), var('y', &mut f), &mut f);
let rule = DefactorizeLeftRule::new("defactL", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn defactorize_left_no_fire_op_not_left_distributive() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
var('x', &mut f),
mul(var('a', &mut f), var('b', &mut f), &mut f),
&mut f,
);
let rule = DefactorizeLeftRule::new("defactL", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn defactorize_right_fires() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
add(var('a', &mut f), var('b', &mut f), &mut f),
x.clone(),
&mut f,
);
let expected = add(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x, &mut f),
&mut f,
);
let rule = DefactorizeRightRule::new("defactR", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn defactorize_right_no_fire_left_subterm_not_binary() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = mul(var('x', &mut f), var('y', &mut f), &mut f);
let rule = DefactorizeRightRule::new("defactR", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn defactorize_right_no_fire_op_not_right_distributive() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
mul(var('a', &mut f), var('b', &mut f), &mut f),
var('x', &mut f),
&mut f,
);
let rule = DefactorizeRightRule::new("defactR", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_left_mod_ac_fires_two_subterms() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x.clone(), var('b', &mut f), &mut f),
&mut f,
);
let expected = mul(x, add(var('a', &mut f), var('b', &mut f), &mut f), &mut f);
let rule = FactorizeLeftModACRule::new("factLAC", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_left_mod_ac_fires_with_associative_flattening() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(x.clone(), var('a', &mut f), &mut f),
add(
mul(x.clone(), var('b', &mut f), &mut f),
var('w', &mut f),
&mut f,
),
&mut f,
);
let expected = add(
var('w', &mut f),
mul(x, add(var('a', &mut f), var('b', &mut f), &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftModACRule::new("factLAC", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_left_mod_ac_no_fire_outer_op_not_commutative() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x, var('b', &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftModACRule::new("factLAC", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_left_mod_ac_no_fire_no_common_left_factor() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
mul(var('x', &mut f), var('a', &mut f), &mut f),
mul(var('y', &mut f), var('b', &mut f), &mut f),
&mut f,
);
let rule = FactorizeLeftModACRule::new("factLAC", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_right_mod_ac_fires_two_subterms() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x.clone(), &mut f),
&mut f,
);
let expected = mul(add(var('a', &mut f), var('b', &mut f), &mut f), x, &mut f);
let rule = FactorizeRightModACRule::new("factRAC", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_right_mod_ac_fires_with_associative_flattening() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = add(
mul(var('a', &mut f), x.clone(), &mut f),
add(
mul(var('b', &mut f), x.clone(), &mut f),
var('w', &mut f),
&mut f,
),
&mut f,
);
let expected = add(
var('w', &mut f),
mul(add(var('a', &mut f), var('b', &mut f), &mut f), x, &mut f),
&mut f,
);
let rule = FactorizeRightModACRule::new("factRAC", ArithChecker);
assert_eq!(rule.try_apply(&t, &t, &root_pos(), &mut f), Some(expected));
}
#[test]
fn factorize_right_mod_ac_no_fire_outer_op_not_commutative() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let t = mul(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x, &mut f),
&mut f,
);
let rule = FactorizeRightModACRule::new("factRAC", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_right_mod_ac_no_fire_no_common_right_factor() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let t = add(
mul(var('a', &mut f), var('x', &mut f), &mut f),
mul(var('b', &mut f), var('y', &mut f), &mut f),
&mut f,
);
let rule = FactorizeRightModACRule::new("factRAC", ArithChecker);
assert!(rule.try_apply(&t, &t, &root_pos(), &mut f).is_none());
}
#[test]
fn factorize_left_mod_ac_no_fire_when_parent_is_same_op() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let term = add(
mul(x.clone(), var('a', &mut f), &mut f),
mul(x.clone(), var('b', &mut f), &mut f),
&mut f,
);
let context = add(term.clone(), var('w', &mut f), &mut f);
let child_pos = PositionInLanguageTerm::get_root_position().get_position_of_nth_child(0);
let rule = FactorizeLeftModACRule::new("factLAC", ArithChecker);
assert!(
rule.try_apply(&term, &context, &child_pos, &mut f)
.is_none(),
"guard must block when parent operator == op2"
);
assert!(
rule.try_apply(&term, &term, &root_pos(), &mut f).is_some(),
"must fire at root where there is no parent"
);
}
#[test]
fn factorize_right_mod_ac_no_fire_when_parent_is_same_op() {
let mut f: TermFactory<ArithOp> = HConsign::empty();
let x = var('x', &mut f);
let term = add(
mul(var('a', &mut f), x.clone(), &mut f),
mul(var('b', &mut f), x.clone(), &mut f),
&mut f,
);
let context = add(term.clone(), var('w', &mut f), &mut f);
let child_pos = PositionInLanguageTerm::get_root_position().get_position_of_nth_child(0);
let rule = FactorizeRightModACRule::new("factRAC", ArithChecker);
assert!(
rule.try_apply(&term, &context, &child_pos, &mut f)
.is_none(),
"guard must block when parent operator == op2"
);
assert!(
rule.try_apply(&term, &term, &root_pos(), &mut f).is_some(),
"must fire at root where there is no parent"
);
}
#[test]
fn factorize_rule_get_desc() {
assert_eq!(
FactorizeLeftRule::new("factL", ArithChecker).get_desc(),
"factL"
);
assert_eq!(
FactorizeRightRule::new("factR", ArithChecker).get_desc(),
"factR"
);
}
#[test]
fn defactorize_rule_get_desc() {
assert_eq!(
DefactorizeLeftRule::new("defactL", ArithChecker).get_desc(),
"defactL"
);
assert_eq!(
DefactorizeRightRule::new("defactR", ArithChecker).get_desc(),
"defactR"
);
}
#[test]
fn factorize_mod_ac_rule_get_desc() {
assert_eq!(
FactorizeLeftModACRule::new("factLAC", ArithChecker).get_desc(),
"factLAC"
);
assert_eq!(
FactorizeRightModACRule::new("factRAC", ArithChecker).get_desc(),
"factRAC"
);
}