use super::*;
pub struct EqualityConstraint {
a: VariableId,
b: VariableId,
}
impl EqualityConstraint {
pub fn new(a: VariableId, b: VariableId) -> Self {
EqualityConstraint { a, b }
}
}
impl<'c> Constraint<'c> for EqualityConstraint {
fn variables(&self) -> VariableSet {
let mut vs = VariableSet::new_empty();
vs.set(self.a);
vs.set(self.b);
vs
}
fn estimate(&self, variable: VariableId, binding: &Binding) -> Option<usize> {
if variable == self.a {
if binding.get(self.b).is_some() {
Some(1)
} else {
None
}
} else if variable == self.b {
if binding.get(self.a).is_some() {
Some(1)
} else {
None
}
} else {
None
}
}
fn propose(
&self,
variable: VariableId,
frontier: &Frontier<'_>,
proposals: &mut ProposalBuffer,
) {
let peer = if variable == self.a {
self.b
} else if variable == self.b {
self.a
} else {
return;
};
for row in 0..frontier.len() {
if let Some(v) = frontier.row(row).get(peer) {
proposals.open(row as u32);
proposals.push(*v);
}
}
}
fn confirm(&self, variable: VariableId, frontier: &Frontier<'_>, cands: &mut Candidates<'_>) {
let peer = if variable == self.a {
self.b
} else if variable == self.b {
self.a
} else {
return;
};
cands.for_each_parent(|row, run| {
let Some(peer) = frontier.row(row as usize).get(peer) else {
return;
};
run.retain(|value| value == peer);
});
}
fn satisfied(&self, binding: &Binding) -> bool {
match (binding.get(self.a), binding.get(self.b)) {
(Some(a), Some(b)) => a == b,
_ => true,
}
}
}