use crate::cnf::CnfFormula;
use crate::decompose::TreeDecomposition;
use crate::decompose::td_to_vtree::*;
use crate::tests::common::{make_formula, make_td};
use crate::vtree::{VarId, Vtree, VtreeIdx};
const CAP_NUM_VARS: u32 = 60;
fn cap_td() -> TreeDecomposition {
make_td(
vec![vec![0, 1, 2], vec![0, 3, 4], vec![0, 1, 2]],
vec![(0, 1), (0, 2)],
5,
)
}
fn hub_formula(len: usize) -> CnfFormula {
let mut hub = vec![1, 4, 5];
hub.extend(6..(3 + len as i32));
assert_eq!(hub.len(), len, "hub clause built to the wrong length");
make_formula(CAP_NUM_VARS, vec![hub])
}
fn placed_with_its_partners(formula: &CnfFormula) -> bool {
let reading = Reading {
root: Some(Root::First),
place: Some(Place::Deep),
binarize: Some(Binarization::Balanced),
};
let vtree = td_to_vtree_reading(&cap_td(), CAP_NUM_VARS, reading, Some(formula), None);
let join = vtree.lca(vtree.leaf_of(VarId(0)), vtree.leaf_of(VarId(3)));
!leaves_under(&vtree, join).contains(&1)
}
fn leaves_under(vtree: &Vtree, idx: VtreeIdx) -> Vec<u32> {
let mut out = Vec::new();
let mut stack = vec![idx];
while let Some(node) = stack.pop() {
if vtree.node(node).is_leaf() {
out.push(vtree.leaf_var(node).0);
} else {
let (l, r) = vtree.children(node);
stack.push(l);
stack.push(r);
}
}
out
}
#[test]
fn a_clause_over_the_length_cap_does_not_place_a_variable() {
let cap = crate::decompose::td_parse::COOC_CLAUSE_LEN_CAP;
assert!(
!placed_with_its_partners(&hub_formula(cap + 1)),
"a clause longer than the cap reached the co-occurrence graph the \
deep-placement tie-break ranks by"
);
assert!(
placed_with_its_partners(&hub_formula(cap)),
"control: the same clause one literal shorter must still reach it"
);
}
#[test]
fn a_component_centroid_ignores_other_components() {
let td = make_td(
vec![vec![0], vec![1], vec![2], vec![3], vec![4]],
vec![(0, 1), (1, 2), (3, 4)],
5,
);
assert_eq!(
crate::decompose::td_to_vtree::algo::find_centroid(&td, 0),
1,
);
}