use crate::ConstraintOperationError;
use crate::Solver;
use crate::propagation::PropagatorConstructor;
use crate::propagators::reified_propagator::ReifiedPropagatorArgs;
use crate::variables::Literal;
mod constraint_poster;
pub use constraint_poster::ConstraintPoster;
pub trait Constraint {
fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError>;
fn implied_by(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError>;
}
impl<ConcretePropagator> Constraint for ConcretePropagator
where
ConcretePropagator: PropagatorConstructor + 'static,
{
fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError> {
let _ = solver.add_propagator(self)?;
Ok(())
}
fn implied_by(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError> {
let _ = solver.add_propagator(ReifiedPropagatorArgs {
propagator: self,
reification_literal,
})?;
Ok(())
}
}
impl<C: Constraint> Constraint for Vec<C> {
fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError> {
self.into_iter().try_for_each(|c| c.post(solver))
}
fn implied_by(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError> {
self.into_iter()
.try_for_each(|c| c.implied_by(solver, reification_literal))
}
}
pub trait NegatableConstraint: Constraint {
type NegatedConstraint: NegatableConstraint + 'static;
fn negation(&self) -> Self::NegatedConstraint;
fn reify(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError>
where
Self: Sized,
{
let negation = self.negation();
self.implied_by(solver, reification_literal)?;
negation.implied_by(solver, !reification_literal)
}
}