use alloc::vec::Vec;
use crate::ast::AstId;
use crate::ast::manager::AstManager;
use crate::ast::node::AstNode;
use crate::rewriter::{arith_rewriter, bool_rewriter};
pub fn simplify(m: &mut AstManager, root: AstId) -> AstId {
let order = m.postorder(root);
let mut cache: Vec<Option<AstId>> = alloc::vec![None; m.len()];
for &id in &order {
let simplified = match m.node(id).clone() {
AstNode::App(a) => {
let new_args: Vec<AstId> = a
.args
.iter()
.map(|&c| cache[c.0 as usize].unwrap())
.collect();
simplify_app(m, a.decl, &new_args)
}
_ => id,
};
cache[id.0 as usize] = Some(simplified);
}
cache[root.0 as usize].unwrap()
}
fn simplify_app(m: &mut AstManager, decl: AstId, args: &[AstId]) -> AstId {
if let Some(r) = bool_rewriter::try_fold(m, decl, args) {
return r;
}
if let Some(r) = arith_rewriter::try_fold(m, decl, args) {
return r;
}
m.mk_app(decl, args)
}
#[cfg(test)]
mod tests {
use crate::ast::manager::AstManager;
use crate::rewriter::simplify;
#[test]
fn mixed_boolean_and_arithmetic_simplification() {
let mut m = AstManager::new();
let x = m.mk_int_const("x");
let two = m.mk_int(2);
let three = m.mk_int(3);
let five = m.mk_int(5);
let t = m.mk_true();
let sum = m.mk_add(&[two, three]);
let le = m.mk_le(x, sum);
let formula = m.mk_and(&[t, le]);
let expected = m.mk_le(x, five);
assert_eq!(simplify(&mut m, formula), expected);
}
}