use crate::constraint::{ConstraintEnum, Revision};
use crate::domain::Domain;
use crate::variable::Variable;
use crate::{SolveStats, Unsatisfiable};
pub fn propagate_monotonic<D: Domain>(
variables: &mut [Variable<D>],
constraints: &[ConstraintEnum<D>],
stats: &mut SolveStats,
) -> Result<(), Unsatisfiable>
where
D::Value: PartialEq,
{
loop {
let mut changed = false;
for c in constraints {
match c.revise(variables, 0) {
Revision::Unchanged => {}
Revision::Changed => {
changed = true;
stats.propagations += 1;
}
Revision::Unsatisfiable => return Err(Unsatisfiable),
}
}
if !changed {
break;
}
}
Ok(())
}
pub fn propagate_stratified<D: Domain>(
variables: &mut [Variable<D>],
constraints: &[ConstraintEnum<D>],
scc_order: &[usize],
scc_ids: &[usize],
cyclic_sccs: &[bool],
stats: &mut SolveStats,
) -> Result<(), Unsatisfiable>
where
D::Value: PartialEq,
{
let mut i = 0;
while i < scc_order.len() {
let ci = scc_order[i];
let scc_id = scc_ids[ci];
if !cyclic_sccs[scc_id] {
match constraints[ci].revise(variables, 0) {
Revision::Unchanged | Revision::Changed => {
stats.propagations += 1;
}
Revision::Unsatisfiable => return Err(Unsatisfiable),
}
i += 1;
} else {
let scc_start = i;
while i < scc_order.len() && scc_ids[scc_order[i]] == scc_id {
i += 1;
}
let scc_constraints = &scc_order[scc_start..i];
loop {
let mut changed = false;
for &ci in scc_constraints {
match constraints[ci].revise(variables, 0) {
Revision::Unchanged => {}
Revision::Changed => {
changed = true;
stats.propagations += 1;
}
Revision::Unsatisfiable => return Err(Unsatisfiable),
}
}
if !changed {
break;
}
}
}
}
Ok(())
}