use crate::cnf::CnfFormula;
use crate::cnf::{Reduced, ShowMask, ShowSet};
use crate::preprocess::count_preserve::*;
use crate::tests::common::make_formula;
fn show(num_vars: u32, vars: &[u32]) -> ShowMask {
ShowSet::<Reduced>::from_zero_based(vars.iter().copied()).mask(num_vars)
}
fn units(f: &CnfFormula) -> Vec<(usize, bool)> {
let mut u: Vec<(usize, bool)> = f
.clauses
.iter()
.filter(|c| c.literals.len() == 1)
.map(|c| (c.literals[0].var.0 as usize, c.literals[0].positive))
.collect();
u.sort_unstable();
u
}
#[test]
fn no_units_leaves_formula_untouched() {
let f = make_formula(3, vec![vec![1, 2], vec![-2, 3]]);
let r = bcp_simplify(&f, &show(3, &[0, 1, 2]));
assert!(!r.unsat);
assert_eq!(r.formula.clauses.len(), 2);
assert!(units(&r.formula).is_empty(), "got {:?}", units(&r.formula));
}
#[test]
fn forced_show_var_is_re_pinned_with_its_polarity() {
let f = make_formula(3, vec![vec![1], vec![-1, 2], vec![2, 3]]);
let r = bcp_simplify(&f, &show(3, &[0, 1, 2]));
assert!(!r.unsat);
assert_eq!(units(&r.formula), vec![(0, true), (1, true)]);
assert_eq!(r.formula.clauses.len(), 2);
}
#[test]
fn forced_projected_var_is_not_re_pinned() {
let f = make_formula(3, vec![vec![1], vec![-1, 2], vec![2, 3]]);
let r = bcp_simplify(&f, &show(3, &[2])); assert!(!r.unsat);
assert!(r.formula.clauses.is_empty(), "got {:?}", r.formula.clauses);
}
#[test]
fn empty_show_set_re_pins_nothing() {
let f = make_formula(2, vec![vec![1], vec![-1, 2]]);
let r = bcp_simplify(&f, &show(2, &[]));
assert!(!r.unsat);
assert!(r.formula.clauses.is_empty(), "got {:?}", r.formula.clauses);
}
#[test]
fn conflict_marks_unsat() {
let f = make_formula(1, vec![vec![1], vec![-1]]);
let r = bcp_simplify(&f, &show(1, &[0]));
assert!(r.unsat);
}
#[test]
fn unsat_result_carries_no_re_pins() {
let f = make_formula(2, vec![vec![1], vec![-1]]);
let r = bcp_simplify(&f, &show(2, &[0, 1]));
assert!(r.unsat);
assert!(units(&r.formula).is_empty(), "got {:?}", units(&r.formula));
}