use super::PredicateIdAssignments;
use crate::basic_types::PredicateId;
use crate::basic_types::PredicateIdGenerator;
use crate::containers::KeyedVec;
use crate::containers::StorageKey;
use crate::engine::Assignments;
use crate::engine::TrailedValues;
use crate::engine::notifications::DomainEvent;
use crate::engine::notifications::predicate_notification::predicate_tracker::PredicateTracker;
use crate::predicates::Predicate;
use crate::predicates::PredicateType;
use crate::variables::DomainId;
#[derive(Default, Debug, Clone)]
pub(crate) struct PredicateNotifier {
pub(crate) predicate_to_id: PredicateIdGenerator,
pub(crate) predicate_id_assignments: PredicateIdAssignments,
domain_id_to_predicate_tracker: KeyedVec<DomainId, PredicateTracker>,
}
impl PredicateNotifier {
pub(crate) fn debug_empty_clone(&self) -> Self {
let predicate_id_assignments = self.predicate_id_assignments.debug_empty_clone();
Self {
predicate_to_id: self.predicate_to_id.clone(),
predicate_id_assignments,
..Default::default()
}
}
pub(crate) fn debug_create_from_assignments(&mut self, assignments: &Assignments) {
self.predicate_id_assignments
.debug_create_from_assignments(assignments, &mut self.predicate_to_id);
}
pub(crate) fn drain_satisfied_predicates(&mut self) -> impl Iterator<Item = PredicateId> + '_ {
self.predicate_id_assignments.drain_satisfied_predicates()
}
pub(crate) fn get_predicate(&self, predicate_id: PredicateId) -> Predicate {
self.predicate_to_id.get_predicate(predicate_id)
}
pub(crate) fn on_update(
&mut self,
trailed_values: &mut TrailedValues,
assignments: &Assignments,
event: DomainEvent,
domain: DomainId,
) {
if self.domain_id_to_predicate_tracker.len() <= domain.index() {
return;
}
let predicate_type: PredicateType = event.into();
let predicate_tracker = &mut self.domain_id_to_predicate_tracker[domain];
if predicate_type.is_disequality() {
if predicate_tracker.can_be_updated_by_disequality()
&& !predicate_tracker.is_fixed(trailed_values)
{
for removed_value in assignments.get_holes_at_current_checkpoint(domain) {
let predicate =
predicate_type.into_predicate(domain, assignments, Some(removed_value));
predicate_tracker.on_update(
predicate,
trailed_values,
&mut self.predicate_id_assignments,
);
}
}
} else {
predicate_tracker.on_update(
predicate_type.into_predicate(domain, assignments, None),
trailed_values,
&mut self.predicate_id_assignments,
);
}
}
pub(crate) fn track_predicate(
&mut self,
id: PredicateId,
trailed_values: &mut TrailedValues,
assignments: &Assignments,
) {
let predicate = self.predicate_to_id.get_predicate(id);
if self.domain_id_to_predicate_tracker.len() <= predicate.get_domain().index() {
self.domain_id_to_predicate_tracker
.resize(predicate.get_domain().index() + 1, PredicateTracker::new());
}
self.domain_id_to_predicate_tracker[predicate.get_domain()].initialise(
predicate.get_domain(),
assignments.get_initial_lower_bound(predicate.get_domain()),
assignments.get_initial_upper_bound(predicate.get_domain()),
trailed_values,
);
let _ = self.domain_id_to_predicate_tracker[predicate.get_domain()].track(predicate, id);
}
}