use pumpkin_core::ConstraintOperationError;
use pumpkin_core::Solver;
use pumpkin_core::constraints::Constraint;
use pumpkin_core::proof::ConstraintTag;
use pumpkin_core::variables::IntegerVariable;
use pumpkin_core::variables::Literal;
use pumpkin_core::variables::TransformableVariable;
use pumpkin_propagators::disjunctive::ArgDisjunctiveTask;
use pumpkin_propagators::disjunctive::DisjunctiveConstructor;
pub fn disjunctive_strict<Var: IntegerVariable + 'static>(
tasks: impl IntoIterator<Item = ArgDisjunctiveTask<Var>>,
constraint_tag: ConstraintTag,
) -> impl Constraint {
DisjunctiveConstraint {
tasks: tasks.into_iter().collect::<Vec<_>>(),
constraint_tag,
}
}
struct DisjunctiveConstraint<Var> {
tasks: Vec<ArgDisjunctiveTask<Var>>,
constraint_tag: ConstraintTag,
}
impl<Var: IntegerVariable + 'static> Constraint for DisjunctiveConstraint<Var> {
fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError> {
DisjunctiveConstructor::new(self.tasks.clone(), self.constraint_tag).post(solver)?;
DisjunctiveConstructor::new(
self.tasks.iter().map(|task| ArgDisjunctiveTask {
start_time: task.start_time.offset(task.processing_time).scaled(-1),
processing_time: task.processing_time,
}),
self.constraint_tag,
)
.post(solver)
}
fn implied_by(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError> {
DisjunctiveConstructor::new(self.tasks.clone(), self.constraint_tag)
.implied_by(solver, reification_literal)?;
DisjunctiveConstructor::new(
self.tasks.iter().map(|task| ArgDisjunctiveTask {
start_time: task.start_time.offset(task.processing_time).scaled(-1),
processing_time: task.processing_time,
}),
self.constraint_tag,
)
.implied_by(solver, reification_literal)
}
}