use drcp_format::IntAtomic;
use drcp_format::IntComparison;
use crate::containers::HashMap;
use crate::engine::VariableNames;
use crate::engine::predicates::predicate::PredicateType;
use crate::predicates::Predicate;
use crate::variables::DomainId;
use crate::variables::Literal;
#[derive(Default, Debug)]
pub(crate) struct ProofAtomics {
reification_domains: HashMap<DomainId, Predicate>,
}
impl ProofAtomics {
pub(crate) fn map_predicate_to_proof_atomic<'names>(
&mut self,
predicate: Predicate,
variable_names: &'names VariableNames,
) -> IntAtomic<&'names str, i32> {
let predicate = self
.get_underlying_predicate(predicate)
.unwrap_or(predicate);
let name = variable_names
.get_int_name(predicate.get_domain())
.expect("integer domain is unnamed");
let value = predicate.get_right_hand_side();
let comparison = match predicate.get_predicate_type() {
PredicateType::UpperBound => IntComparison::LessEqual,
PredicateType::Equal => IntComparison::Equal,
PredicateType::LowerBound => IntComparison::GreaterEqual,
PredicateType::NotEqual => IntComparison::NotEqual,
};
IntAtomic::new(name, comparison, value)
}
pub(crate) fn reify_predicate(&mut self, literal: Literal, predicate: Predicate) {
let domain = literal.get_true_predicate().get_domain();
let _ = self.reification_domains.insert(domain, predicate);
}
fn get_underlying_predicate(&self, predicate: Predicate) -> Option<Predicate> {
let domain_id = predicate.get_domain();
let rhs = predicate.get_right_hand_side();
self.reification_domains
.get(&domain_id)
.map(|&reified_predicate| {
assert!(rhs == 0 || rhs == 1);
let value = predicate.get_right_hand_side();
match predicate.get_predicate_type() {
PredicateType::LowerBound => reified_predicate,
PredicateType::UpperBound => !reified_predicate,
PredicateType::NotEqual => {
if value == 0 {
reified_predicate
} else {
!reified_predicate
}
}
PredicateType::Equal => {
if value == 0 {
!reified_predicate
} else {
reified_predicate
}
}
}
})
}
}