use super::*;
use crate::tests::pmc_oracle::brute_force_mc;
use num_bigint::BigUint;
#[test]
fn dve_preknown_only_preserves_mc() {
let f = make_formula(
12,
vec![
vec![3, 4, -5],
vec![1, -3],
vec![2, -3],
vec![-3, 5],
vec![-1, -2, 3],
vec![1, -4],
vec![-2, -4],
vec![-4, 5],
vec![-1, 2, 4],
vec![5, -12],
vec![-5, -10, -11, 12],
vec![10, -12],
vec![6, -10],
vec![7, -10],
vec![-6, -7, 10],
vec![11, -12],
vec![8, -11],
vec![9, -11],
vec![-8, -9, 11],
],
);
assert_eq!(brute_force_mc(&f), BigUint::from(64u32));
let preknown: Vec<u32> = vec![2, 4, 9, 10, 11];
let mut clauses = f.clauses.clone();
let mut fates = vec![DveFate::Kept; 12];
let orig_len = clauses.len();
let _ = apply_elimination(
&mut clauses,
&preknown,
&mut fates,
orig_len,
&Default::default(),
);
let appears = appearance_mask(&clauses, 12);
let mut num_free = 0;
for v in 0..12 {
if !fates[v].eliminated() && !appears[v] {
fates[v] = DveFate::Free;
num_free += 1;
}
}
let (reduced, _) = renumber_formula(&fates, 12, clauses);
let mc = brute_force_mc(&reduced);
let total = mc.clone() * BigUint::from(1u128 << num_free);
assert_eq!(
total,
BigUint::from(64u32),
"preknown-only elim should preserve MC: reduced_mc={} * 2^{} = {}",
mc,
num_free,
total
);
}
#[test]
fn dve_preknown_then_sat_defined_preserves_mc() {
let f = make_formula(
12,
vec![
vec![3, 4, -5],
vec![1, -3],
vec![2, -3],
vec![-3, 5],
vec![-1, -2, 3],
vec![1, -4],
vec![-2, -4],
vec![-4, 5],
vec![-1, 2, 4],
vec![5, -12],
vec![-5, -10, -11, 12],
vec![10, -12],
vec![6, -10],
vec![7, -10],
vec![-6, -7, 10],
vec![11, -12],
vec![8, -11],
vec![9, -11],
vec![-8, -9, 11],
],
);
let preknown: Vec<u32> = vec![2, 4, 9, 10, 11];
let mut clauses = f.clauses.clone();
let mut fates = vec![DveFate::Kept; 12];
let orig_len = clauses.len();
let _ = apply_elimination(
&mut clauses,
&preknown,
&mut fates,
orig_len,
&Default::default(),
);
let sat_candidates: Vec<u32> = vec![3];
let defined = pick_def_vars(&clauses, 12, &sat_candidates, 10_000);
if !defined.is_empty() {
let orig_len2 = clauses.len();
let _ = apply_elimination(
&mut clauses,
&defined,
&mut fates,
orig_len2,
&Default::default(),
);
}
let appears = appearance_mask(&clauses, 12);
let mut num_free = 0;
for v in 0..12 {
if !fates[v].eliminated() && !appears[v] {
fates[v] = DveFate::Free;
num_free += 1;
}
}
let (reduced, _) = renumber_formula(&fates, 12, clauses);
let mc = brute_force_mc(&reduced);
let total = mc.clone() * BigUint::from(1u128 << num_free);
assert_eq!(
total,
BigUint::from(64u32),
"two-phase preknown+sat elim should preserve MC: reduced_mc={} * 2^{} = {} (defined_set={:?})",
mc,
num_free,
total,
defined
);
}
#[test]
fn dve_preknown_first_preserves_mc() {
let f = make_formula(
12,
vec![
vec![3, 4, -5],
vec![1, -3],
vec![2, -3],
vec![-3, 5],
vec![-1, -2, 3],
vec![1, -4],
vec![-2, -4],
vec![-4, 5],
vec![-1, 2, 4],
vec![5, -12],
vec![-5, -10, -11, 12],
vec![10, -12],
vec![6, -10],
vec![7, -10],
vec![-6, -7, 10],
vec![11, -12],
vec![8, -11],
vec![9, -11],
vec![-8, -9, 11],
],
);
assert_eq!(brute_force_mc(&f), BigUint::from(64u32));
let mut known: rustc_hash::FxHashSet<VarId> = rustc_hash::FxHashSet::default();
for v in [2u32, 4, 9, 10, 11] {
known.insert(VarId(v));
}
let result = preprocess_dve(
&f,
10,
10_000,
false,
&known,
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
let reduced_mc = brute_force_mc(&result.formula);
let total = reduced_mc.clone() * BigUint::from(1u128 << result.num_free());
assert_eq!(
total,
BigUint::from(64u32),
"MC not preserved: reduced_mc={} * 2^{} = {}, expected 64 (defined={}, equiv={}, free={}, reduced_vars={})",
reduced_mc,
result.num_free(),
total,
result.num_defined(),
result.num_equiv(),
result.num_free(),
result.formula.num_vars,
);
}
#[test]
fn dve_pure_literal_on_defined_var_preserves_mc() {
let f = make_formula(2, vec![vec![1, 2]]);
assert_eq!(brute_force_mc(&f), BigUint::from(3u32));
let mut known: rustc_hash::FxHashSet<VarId> = rustc_hash::FxHashSet::default();
known.insert(VarId(0));
let result = preprocess_dve(
&f,
10,
10_000,
false,
&known,
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
let reduced_mc = brute_force_mc(&result.formula);
let total = reduced_mc.clone() * BigUint::from(1u128 << result.num_free());
assert_eq!(
total,
BigUint::from(3u32),
"Pure-literal corrupted MC: reduced={} * 2^{} = {}, \
expected 3 (defined={}, equiv={}, free={}, reduced_vars={})",
reduced_mc,
result.num_free(),
total,
result.num_defined(),
result.num_equiv(),
result.num_free(),
result.formula.num_vars,
);
}
#[test]
fn dve_equiv_followed_by_gate_elim_preserves_mc() {
let f = make_formula(
3,
vec![
vec![1, -3], vec![1, -2], vec![-1, 3, 2], vec![-1, 2], ],
);
assert_eq!(brute_force_mc(&f), BigUint::from(3u32));
let mut known: rustc_hash::FxHashSet<VarId> = rustc_hash::FxHashSet::default();
known.insert(VarId(0));
let result = preprocess_dve(
&f,
10,
10_000,
false,
&known,
&rustc_hash::FxHashSet::default(),
FrozenEquiv::Ignore,
);
let reduced_mc = brute_force_mc(&result.formula);
let total = reduced_mc.clone() * BigUint::from(1u128 << result.num_free());
assert_eq!(
total,
BigUint::from(3u32),
"MC not preserved: reduced_mc={} * 2^{} = {}, expected 3 (defined={}, equiv={}, free={}, reduced_vars={})",
reduced_mc,
result.num_free(),
total,
result.num_defined(),
result.num_equiv(),
result.num_free(),
result.formula.num_vars,
);
}