use super::*;
use crate::tests::learnt_clauses::assert_learnts_are_implied;
#[test]
fn arjun_learnts_harvest_sound_and_in_reduced_space() {
use crate::preprocess::cadical_ffi::{CaDiCal, Status};
let clauses: &[&[i32]] = &[
&[1, 2, 3],
&[-1, -2, 4],
&[2, -3, 5],
&[-4, 5, 6],
&[1, -5, -6],
&[3, 4, -6],
&[7, 8, -1],
&[-7, 9, 2],
&[8, -9, 10],
&[-8, -10, 11],
&[9, 10, -12],
&[-11, 12, 1],
&[4, 7, -10],
&[-3, -8, 11],
&[5, -9, 12],
&[6, -7, -11],
&[-2, 8, 12],
&[1, -4, 9],
&[2, 5, -7],
&[-6, 10, -12],
&[3, -5, 8],
&[-1, 7, 11],
&[4, -8, -9],
&[-3, 6, 10],
&[2, -4, -11],
&[5, 9, -12],
&[-1, -6, 8],
&[3, 7, -10],
&[-2, -5, 11],
&[1, 6, -9],
];
let mut a = ArjunLib::new(ArjunOptions::default().seed).expect("shim ctor");
a.new_vars(12);
for c in clauses {
a.add_clause_dimacs(c);
}
a.set_sampl(&[0, 1, 2, 3, 4, 5]);
assert!(a.stage_minimize_indep(false), "minimize stage failed");
assert!(
a.stage_simplify(false, true, false, true),
"simplify stage failed"
);
let reduced = a.cur_formula();
let nv = reduced.num_vars;
let raw = a.red_clauses();
let learnts: Vec<Vec<i32>> = raw
.iter()
.filter(|cl| !cl.is_empty() && cl.iter().all(|&l| l.unsigned_abs().saturating_sub(1) < nv))
.cloned()
.collect();
eprintln!(
"[test] red_clauses harvested: {} raw, {} after surviving-var filter, reduced {}v/{}c",
raw.len(),
learnts.len(),
nv,
reduced.clauses.len(),
);
assert!(
!learnts.is_empty(),
"expected a non-empty learnt-clause harvest"
);
for cl in &learnts {
for &l in cl {
assert!(
l.unsigned_abs().saturating_sub(1) < nv,
"harvested learnt lit {l} out of reduced var space (nv={nv})",
);
}
}
for cl in &learnts {
let mut s = CaDiCal::new().expect("the solver allocates");
if nv > 0 {
s.reserve(nv as i32);
}
for rc in &reduced.clauses {
for lit in &rc.literals {
s.add(lit.to_dimacs());
}
s.add(0);
}
for &l in cl {
s.add(-l);
s.add(0);
}
assert_eq!(
s.solve(),
Status::Unsatisfiable,
"reduced ∧ ¬C is SAT — harvested learnt {cl:?} is NOT implied (unsound)",
);
}
}
#[test]
fn arjun_learnts_appended_preserve_count() {
let mut a = ArjunLib::new(ArjunOptions::default().seed).expect("shim ctor");
a.new_vars(12);
let clauses: &[&[i32]] = &[
&[1, 2, 3],
&[-1, -2, 4],
&[2, -3, 5],
&[-4, 5, 6],
&[1, -5, -6],
&[3, 4, -6],
&[7, 8, -1],
&[-7, 9, 2],
&[8, -9, 10],
&[-8, -10, 11],
&[9, 10, -12],
&[-11, 12, 1],
&[4, 7, -10],
&[-3, -8, 11],
&[5, -9, 12],
&[6, -7, -11],
&[-2, 8, 12],
&[1, -4, 9],
];
for c in clauses {
a.add_clause_dimacs(c);
}
a.set_sampl(&[0, 1, 2, 3, 4, 5]);
assert!(a.stage_minimize_indep(false));
assert!(a.stage_simplify(false, true, false, true));
let reduced = a.cur_formula();
let nv = reduced.num_vars;
assert!(nv <= 20, "brute count needs small nv");
let learnts: Vec<Vec<i32>> = a
.red_clauses()
.into_iter()
.filter(|cl| !cl.is_empty() && cl.iter().all(|&l| l.unsigned_abs().saturating_sub(1) < nv))
.collect();
assert_learnts_are_implied(&reduced, &learnts);
}