use std::rc::Rc;
use malachite_bigint::BigInt;
use veripb_formula::{
lit::Lit,
prelude::{DBConstraint, PBConstraintEnum},
};
use crate::{
cardinality_watcher::CardinalityWatcher,
clause_watcher::ClauseWatcher,
error::PropagatorError,
general_pb_watcher::GeneralPBWatcher,
propagator::{PropagationResult, Propagator},
trail::{Propagation, Trail},
};
#[derive(Debug, Default)]
pub struct PropagationSet {
clause_prop: Propagator<ClauseWatcher>,
card_prop: Propagator<CardinalityWatcher>,
constraint_i64_prop: Propagator<GeneralPBWatcher<i64>>,
constraint_i128_prop: Propagator<GeneralPBWatcher<i128>>,
constraint_bigint_prop: Propagator<GeneralPBWatcher<BigInt>>,
}
impl PropagationSet {
#[inline]
pub fn with_size(num_variables: usize) -> Self {
PropagationSet {
clause_prop: Propagator::with_size(num_variables),
card_prop: Propagator::with_size(num_variables),
constraint_i64_prop: Propagator::with_size(num_variables),
constraint_i128_prop: Propagator::with_size(num_variables),
constraint_bigint_prop: Propagator::with_size(num_variables),
}
}
#[inline]
pub fn resize(&mut self, num_variables: usize) {
self.clause_prop.resize(num_variables);
self.card_prop.resize(num_variables);
self.constraint_i64_prop.resize(num_variables);
self.constraint_i128_prop.resize(num_variables);
self.constraint_bigint_prop.resize(num_variables);
}
#[inline]
pub fn add(&mut self, constraint: &Rc<DBConstraint>) -> Result<(), PropagatorError> {
match constraint.constraint {
PBConstraintEnum::Clause(_) => self.clause_prop.add(constraint),
PBConstraintEnum::Cardinality(_) => self.card_prop.add(constraint),
PBConstraintEnum::GeneralPBI64(_) => self.constraint_i64_prop.add(constraint),
PBConstraintEnum::GeneralPBI128(_) => self.constraint_i128_prop.add(constraint),
PBConstraintEnum::GeneralPBBigInt(_) => self.constraint_bigint_prop.add(constraint),
}
}
#[inline]
pub fn remove(&mut self, constraint: &Rc<DBConstraint>) -> Result<(), PropagatorError> {
match constraint.constraint {
PBConstraintEnum::Clause(_) => self.clause_prop.remove(constraint),
PBConstraintEnum::Cardinality(_) => self.card_prop.remove(constraint),
PBConstraintEnum::GeneralPBI64(_) => self.constraint_i64_prop.remove(constraint),
PBConstraintEnum::GeneralPBI128(_) => self.constraint_i128_prop.remove(constraint),
PBConstraintEnum::GeneralPBBigInt(_) => self.constraint_bigint_prop.remove(constraint),
}
}
#[inline]
pub fn remove_all(&mut self) -> Vec<Rc<DBConstraint>> {
let mut constraints = Vec::new();
self.clause_prop.remove_all(&mut constraints);
self.card_prop.remove_all(&mut constraints);
self.constraint_i64_prop.remove_all(&mut constraints);
self.constraint_i128_prop.remove_all(&mut constraints);
self.constraint_bigint_prop.remove_all(&mut constraints);
constraints
}
#[inline]
pub fn get_assignment_independent_propagations(&mut self) -> Vec<Propagation> {
let mut propagations = self
.clause_prop
.get_assignment_independent_propagations()
.clone();
propagations.extend_from_slice(
self.card_prop
.get_assignment_independent_propagations()
.as_slice(),
);
propagations.extend_from_slice(
self.constraint_i64_prop
.get_assignment_independent_propagations()
.as_slice(),
);
propagations.extend_from_slice(
self.constraint_i128_prop
.get_assignment_independent_propagations()
.as_slice(),
);
propagations.extend_from_slice(
self.constraint_bigint_prop
.get_assignment_independent_propagations()
.as_slice(),
);
propagations
}
#[inline]
pub fn get_new_assignment_independent_propagations(
&mut self,
new_propagations: &mut Vec<Propagation>,
) {
self.clause_prop
.get_new_assignment_independent_propagations(new_propagations);
self.card_prop
.get_new_assignment_independent_propagations(new_propagations);
self.constraint_i64_prop
.get_new_assignment_independent_propagations(new_propagations);
self.constraint_i128_prop
.get_new_assignment_independent_propagations(new_propagations);
self.constraint_bigint_prop
.get_new_assignment_independent_propagations(new_propagations);
}
#[inline]
pub fn propagate(&mut self, trail: &mut Trail, mark_reasons: bool) -> PropagationResult {
loop {
let prev_len = trail.len();
if self
.clause_prop
.propagate(trail, mark_reasons, false)
.is_conflict()
|| self
.card_prop
.propagate(trail, mark_reasons, false)
.is_conflict()
|| self
.constraint_i64_prop
.propagate(trail, mark_reasons, true)
.is_conflict()
|| self
.constraint_i128_prop
.propagate(trail, mark_reasons, true)
.is_conflict()
|| self
.constraint_bigint_prop
.propagate(trail, mark_reasons, true)
.is_conflict()
{
return PropagationResult::Conflict;
}
if trail.len() == prev_len {
return PropagationResult::Unknown;
}
}
}
#[inline]
pub fn has_saved_reason(&self) -> bool {
self.clause_prop.has_saved_reason()
|| self.card_prop.has_saved_reason()
|| self.constraint_i64_prop.has_saved_reason()
|| self.constraint_i128_prop.has_saved_reason()
|| self.constraint_bigint_prop.has_saved_reason()
}
#[inline]
pub fn reset(&mut self, prev_trail_len: usize) {
self.clause_prop.reset(prev_trail_len);
self.card_prop.reset(prev_trail_len);
self.constraint_i64_prop.reset(prev_trail_len);
self.constraint_i128_prop.reset(prev_trail_len);
self.constraint_bigint_prop.reset(prev_trail_len);
}
#[inline]
pub fn reset_last_pos(&mut self) {
self.constraint_i64_prop.reset_last_pos();
self.constraint_i128_prop.reset_last_pos();
self.constraint_bigint_prop.reset_last_pos();
}
#[inline]
pub fn increase_slack(&mut self, lit: Lit) {
self.constraint_i64_prop.increase_slack(lit);
self.constraint_i128_prop.increase_slack(lit);
self.constraint_bigint_prop.increase_slack(lit);
}
#[inline]
pub fn clear(&mut self) {
self.clause_prop.clear();
self.card_prop.clear();
self.constraint_i64_prop.clear();
self.constraint_i128_prop.clear();
self.constraint_bigint_prop.clear();
}
}