use crate::cnf::CnfFormula;
use crate::preprocess::pipelines::*;
use crate::tests::common::clause;
#[test]
fn eq_then_cadical_extracts_mapping() {
let formula = CnfFormula {
num_vars: 4,
clauses: vec![
clause(&[(0, false), (1, true)]),
clause(&[(0, true), (1, false)]),
clause(&[(0, true), (2, true)]),
clause(&[(2, false), (3, true)]),
],
};
let out = run_pipeline(&formula, &[Stage::Tarjan, Stage::CadicalSimplify], None);
assert_eq!(out.formula.num_vars, 4, "num_vars preserved");
let mapping = out.mapping.as_ref().expect("equivalence mapping present");
assert_eq!(
mapping.var_to_rep[0].var, mapping.var_to_rep[1].var,
"x0 and x1 must share a representative"
);
assert!(!out.formula.clauses.iter().any(|c| c.literals.is_empty()));
}
#[test]
fn eq_iter_matches_pass1_when_no_second_pass() {
let formula = CnfFormula {
num_vars: 4,
clauses: vec![
clause(&[(0, false), (1, true)]),
clause(&[(0, true), (1, false)]),
clause(&[(0, true), (2, true)]),
clause(&[(2, false), (3, true)]),
],
};
let p1 = run_pipeline(&formula, &[Stage::Tarjan, Stage::CadicalSimplify], None);
let it = preprocess_eq_iter_with_mapping(&formula, None);
assert_eq!(it.formula.num_vars, p1.formula.num_vars);
assert_eq!(it.stats.original_clauses, p1.stats.original_clauses);
assert!(it.stats.eliminated_clauses >= p1.stats.eliminated_clauses);
assert!(it.stats.forced_vars >= p1.stats.forced_vars);
assert_eq!(p1.mapping.is_some(), it.mapping.is_some());
}
#[test]
fn wrappers_preserve_unsat() {
let tarjan_unsat = CnfFormula {
num_vars: 2,
clauses: vec![
clause(&[(0, false), (1, true)]),
clause(&[(0, true), (1, false)]),
clause(&[(0, false), (1, false)]),
clause(&[(0, true), (1, true)]),
],
};
let orig_c = tarjan_unsat.clauses.len();
let p = run_pipeline(
&tarjan_unsat,
&[Stage::Tarjan, Stage::CadicalSimplify],
None,
);
assert!(
p.formula.clauses.iter().any(|c| c.literals.is_empty()),
"eq_then_cadical UNSAT formula"
);
assert!(p.mapping.is_none(), "no mapping on UNSAT");
assert_eq!(p.stats.original_clauses, orig_c);
assert_eq!(p.stats.eliminated_clauses, orig_c);
let it = preprocess_eq_iter_with_mapping(&tarjan_unsat, None);
assert!(
it.formula.clauses.iter().any(|c| c.literals.is_empty()),
"eq_iter UNSAT formula"
);
assert!(it.mapping.is_none());
assert_eq!(it.stats.original_clauses, orig_c);
assert_eq!(it.stats.eliminated_clauses, orig_c);
let cadical_unsat = CnfFormula {
num_vars: 1,
clauses: vec![clause(&[(0, true)]), clause(&[(0, false)])],
};
let pf = run_pipeline(&cadical_unsat, &[Stage::CadicalSimplify], None);
assert!(
pf.formula.clauses.iter().any(|c| c.literals.is_empty()),
"preprocess_full UNSAT formula"
);
}
#[test]
fn preprocess_full_unit_propagation() {
let formula = CnfFormula {
num_vars: 2,
clauses: vec![clause(&[(0, true)]), clause(&[(0, false), (1, true)])],
};
let out = preprocess_eq_iter_with_mapping(&formula, None);
assert_eq!(out.formula.num_vars, 2);
assert!(out.stats.forced_vars >= 1);
}
#[test]
fn preprocess_full_unsat() {
let formula = CnfFormula {
num_vars: 1,
clauses: vec![clause(&[(0, true)]), clause(&[(0, false)])],
};
let out = preprocess_eq_iter_with_mapping(&formula, None);
assert!(out.formula.clauses.iter().any(|c| c.literals.is_empty()));
}
#[test]
fn preprocess_full_preserves_num_vars() {
let formula = CnfFormula {
num_vars: 10,
clauses: vec![
clause(&[(0, true), (1, false), (2, true)]),
clause(&[(3, true), (4, false)]),
],
};
let out = preprocess_eq_iter_with_mapping(&formula, None);
assert_eq!(out.formula.num_vars, 10);
}