use super::*;
#[test]
fn a_variable_defined_by_an_and_gate_is_eliminated() {
let f = make_formula(
3,
vec![vec![-3, 1], vec![-3, 2], vec![3, -1, -2], vec![1, 2]],
);
let result = preprocess_dve(
&f,
10,
10_000,
false,
&rustc_hash::FxHashSet::default(),
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
assert!(
result.num_defined() >= 1,
"Expected at least 1 defined var eliminated, got {}",
result.num_defined()
);
assert!(
result.formula.num_vars <= 2,
"Expected at most 2 vars remaining, got {}",
result.formula.num_vars
);
}
#[test]
fn nothing_is_eliminated_when_no_variable_is_a_function_of_the_others() {
let f = make_formula(3, vec![vec![1, 2, 3], vec![-1, 2, -3], vec![1, -2, -3]]);
let result = preprocess_dve(
&f,
10,
10_000,
false,
&rustc_hash::FxHashSet::default(),
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
assert_eq!(result.num_defined(), 0, "Expected no defined vars");
}
#[test]
fn a_gate_defined_in_terms_of_another_gate_is_eliminated_too() {
let f = make_formula(
5,
vec![
vec![-3, 1],
vec![-3, 2],
vec![3, -1, -2],
vec![-4, 3],
vec![-4, 5],
vec![4, -3, -5],
],
);
let result = preprocess_dve(
&f,
10,
10_000,
false,
&rustc_hash::FxHashSet::default(),
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
assert!(
result.num_defined() >= 2,
"Expected at least 2 defined vars, got {}",
result.num_defined()
);
}
#[test]
fn bve_definition_clauses_cover_all_eliminated() {
let f = make_formula(
5,
vec![
vec![-3, 1],
vec![-3, 2],
vec![3, -1, -2],
vec![-4, 3],
vec![-4, 5],
vec![4, -3, -5],
],
);
let result = preprocess_dve(
&f,
10,
10_000,
true,
&rustc_hash::FxHashSet::default(),
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
let expected = result.num_defined() + result.num_equiv();
assert_eq!(
result.definition_clauses.len(),
expected,
"definition_clauses.len()={} but num_defined+num_equiv={}",
result.definition_clauses.len(),
expected,
);
}
#[test]
fn bve_equiv_within_dve_folded() {
let f = make_formula(
4,
vec![
vec![1, -2],
vec![-1, 2], vec![-4, 1],
vec![-4, 3],
vec![4, -1, -3], ],
);
let result = preprocess_dve(
&f,
10,
10_000,
true,
&rustc_hash::FxHashSet::default(),
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
assert!(
result.num_equiv() >= 1,
"Expected at least 1 equiv var, got {}",
result.num_equiv()
);
assert_eq!(
result.definition_clauses.len(),
result.num_defined() + result.num_equiv(),
"definition_clauses.len()={} but num_defined+num_equiv={}",
result.definition_clauses.len(),
result.num_defined() + result.num_equiv(),
);
}
#[test]
fn dve_shared_xor_counts_second_var_as_free() {
let f = make_formula(
3,
vec![
vec![1, 2, -3],
vec![1, -2, 3],
vec![-1, 2, 3],
vec![-1, -2, -3],
],
);
let mut known: rustc_hash::FxHashSet<VarId> = rustc_hash::FxHashSet::default();
known.insert(VarId(0));
known.insert(VarId(1));
let result = preprocess_dve(
&f,
10,
10_000,
false,
&known,
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
let reduced_mc: u128 = if result.formula.clauses.is_empty() {
1
} else {
0
};
let multiplier = 1u128 << result.num_free();
assert_eq!(
reduced_mc * multiplier,
4,
"MC mismatch: reduced={} * 2^{} = {}, expected 4 (stats: defined={}, free={})",
reduced_mc,
result.num_free(),
reduced_mc * multiplier,
result.num_defined(),
result.num_free(),
);
}
#[test]
fn elim_vars_eliminates_non_rb_when_formula_fits_after_prior_elims() {
let f = make_formula(
5,
vec![
vec![1, 5], vec![-1, 3], vec![2, 3], vec![2, 4], vec![-2, 3], vec![-2, 4], vec![-2, 5], ],
);
let mut clauses = f.clauses.clone();
sort_clause_literals(&mut clauses);
let orig_len = clauses.len();
let (elim_ids, _, _) = elim_vars(&mut clauses, &[0u32, 1u32], orig_len, &Default::default());
assert!(
elim_ids.contains(&0u32),
"a (var 0) should be eliminated (R-bounded); elim_ids={:?}",
elim_ids,
);
assert!(
elim_ids.contains(&1u32),
"b (var 1) should also be eliminated (fits within max_clauses after a shrinks formula); elim_ids={:?}",
elim_ids,
);
}