use crate::datastructures::Assignment;
use crate::formulas::{EncodedFormula, Formula, FormulaFactory, Literal};
pub fn restrict(formula: EncodedFormula, assignment: &Assignment, f: &FormulaFactory) -> EncodedFormula {
use Formula::{And, Cc, Equiv, False, Impl, Lit, Not, Or, Pbc, True};
match formula.unpack(f) {
Lit(lit) => assignment.restrict_lit(lit),
Equiv((left, right)) => {
let rec_left = restrict(left, assignment, f);
let rec_right = restrict(right, assignment, f);
f.equivalence(rec_left, rec_right)
}
Impl((left, right)) => {
let rec_left = restrict(left, assignment, f);
let rec_right = restrict(right, assignment, f);
f.implication(rec_left, rec_right)
}
Or(ops) => {
let rec_ops = ops.map(|op| restrict(op, assignment, f)).collect::<Box<[_]>>();
f.or(&rec_ops)
}
And(ops) => {
let rec_ops = ops.map(|op| restrict(op, assignment, f)).collect::<Box<[_]>>();
f.and(&rec_ops)
}
Not(op) => {
let rec_op = restrict(op, assignment, f);
f.not(rec_op)
}
True | False => formula,
Pbc(pbc) => pbc.clone().restrict(assignment, f),
Cc(cc) => cc.clone().restrict(assignment, f),
}
}
pub fn restrict_lit(formula: EncodedFormula, lit: Literal, f: &FormulaFactory) -> EncodedFormula {
use Formula::{And, Cc, Equiv, False, Impl, Lit, Not, Or, Pbc, True};
match formula.unpack(f) {
Lit(this_lit) => {
if this_lit.variable() != lit.variable() {
formula
} else if this_lit.phase() == lit.phase() {
f.verum()
} else {
f.falsum()
}
}
Equiv((left, right)) => {
let rec_left = restrict_lit(left, lit, f);
let rec_right = restrict_lit(right, lit, f);
f.equivalence(rec_left, rec_right)
}
Impl((left, right)) => {
let rec_left = restrict_lit(left, lit, f);
let rec_right = restrict_lit(right, lit, f);
f.implication(rec_left, rec_right)
}
Or(ops) => {
let rec_ops = ops.map(|op| restrict_lit(op, lit, f)).collect::<Box<[_]>>();
f.or(&rec_ops)
}
And(ops) => {
let rec_ops = ops.map(|op| restrict_lit(op, lit, f)).collect::<Box<[_]>>();
f.and(&rec_ops)
}
Not(op) => {
let rec_op = restrict_lit(op, lit, f);
f.not(rec_op)
}
True | False => formula,
Pbc(pbc) => pbc.clone().restrict(&Assignment::from_lit(lit), f),
Cc(cc) => cc.clone().restrict(&Assignment::from_lit(lit), f),
}
}