use crate::cnf::{Clause, CnfFormula, Literal};
use crate::preprocess::renumber::Renumber;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum DveFate {
Kept,
Defined,
Free,
Equiv {
rep: Literal,
},
}
impl DveFate {
pub(crate) fn eliminated(self) -> bool {
!matches!(self, DveFate::Kept)
}
pub(crate) fn as_equiv(self) -> Option<Literal> {
match self {
DveFate::Equiv { rep } => Some(rep),
_ => None,
}
}
}
pub(crate) fn free_vars(fates: &[DveFate]) -> impl Iterator<Item = usize> + '_ {
fates
.iter()
.enumerate()
.filter(|(_, f)| matches!(f, DveFate::Free))
.map(|(v, _)| v)
}
#[derive(Clone, Debug)]
pub(crate) struct DveResult {
pub formula: CnfFormula,
pub definition_clauses: Vec<Vec<Clause>>,
pub renumbering: Option<Renumber>,
pub fates: Vec<DveFate>,
pub elapsed_ms: u64,
}
impl DveResult {
pub(crate) fn unchanged(formula: &CnfFormula, fates: Vec<DveFate>, elapsed_ms: u64) -> Self {
DveResult {
formula: formula.clone(),
definition_clauses: Vec::new(),
renumbering: None,
fates,
elapsed_ms,
}
}
pub(crate) fn original_num_vars(&self) -> usize {
self.fates.len()
}
pub(crate) fn num_defined(&self) -> usize {
self.count(|f| matches!(f, DveFate::Defined))
}
pub(crate) fn num_equiv(&self) -> usize {
self.count(|f| matches!(f, DveFate::Equiv { .. }))
}
pub(crate) fn num_free(&self) -> usize {
free_vars(&self.fates).count()
}
pub(crate) fn total_eliminated(&self) -> usize {
self.count(|f| f.eliminated())
}
fn count(&self, pred: impl Fn(DveFate) -> bool) -> usize {
self.fates.iter().filter(|&&f| pred(f)).count()
}
pub(crate) fn debug_validate(&self) {
if !cfg!(debug_assertions) {
return;
}
let orig = self.original_num_vars();
if let Some(renumbering) = &self.renumbering {
for (new_id, &old_var) in renumbering.kept().iter().enumerate() {
assert!(
old_var.idx() < orig,
"renumbering maps {} to {} but original_num_vars={}",
new_id,
old_var.0,
orig
);
}
}
let expected_defs = self.num_defined() + self.num_equiv();
assert_eq!(
self.definition_clauses.len(),
expected_defs,
"definition_clauses.len()={} but num_defined+num_equiv={}",
self.definition_clauses.len(),
expected_defs
);
}
}