use crate::Ddnnf;
use num::Zero;
use std::collections::HashSet;
impl Ddnnf {
pub(crate) fn calculate_core(&mut self) {
self.core = (-(self.number_of_variables as i32)..=self.number_of_variables as i32)
.filter(|f| self.literals.contains_key(f) && !self.literals.contains_key(&-f))
.collect::<HashSet<i32>>()
}
pub(crate) fn has_no_effect_on_query(&self, feature: &i32) -> bool {
feature.is_positive() && self.core.contains(feature)
|| feature.is_negative() && self.core.contains(feature)
}
pub(crate) fn makes_query_unsat(&self, feature: &i32) -> bool {
feature.is_negative() && self.core.contains(&-feature)
|| feature.is_positive() && self.core.contains(&-feature)
}
#[inline]
pub(crate) fn reduce_query(&mut self, features: &[i32]) -> Vec<i32> {
features
.iter()
.filter({
|&f| !self.has_no_effect_on_query(f)
})
.copied()
.collect::<Vec<i32>>()
}
#[inline]
pub(crate) fn query_is_not_sat(&mut self, features: &[i32]) -> bool {
features.iter().any(|f| self.makes_query_unsat(f))
}
pub fn core_dead_with_assumptions(self: &mut Ddnnf, assumptions: &[i32]) -> Vec<i32> {
if assumptions.is_empty() {
return self.core.iter().copied().collect();
}
let mut assumptions = assumptions.to_vec();
let mut core = Vec::new();
let reference = self.execute_query(&assumptions);
for i in 1_i32..=self.number_of_variables as i32 {
assumptions.push(i);
let inter = self.execute_query(&assumptions);
if reference == inter {
core.push(i);
}
if inter.is_zero() {
core.push(-i);
}
assumptions.pop();
}
core
}
pub fn core_with_assumptions(self: &mut Ddnnf, assumptions: &[i32]) -> Vec<i32> {
let mut features = self.core_dead_with_assumptions(assumptions);
features.retain(|feature| feature.is_positive());
features
}
pub fn dead_with_assumptions(self: &mut Ddnnf, assumptions: &[i32]) -> Vec<i32> {
let mut features = self.core_dead_with_assumptions(assumptions);
features.retain(|feature| feature.is_negative());
features
}
}