pumpkin_solver/constraints/constraint_poster.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use std::num::NonZero;
use log::warn;
use super::Constraint;
use super::NegatableConstraint;
use crate::variables::Literal;
use crate::ConstraintOperationError;
use crate::Solver;
/// A structure which is responsible for adding the created [`Constraint`]s to the
/// [`Solver`]. For an example on how to use this, see [`crate::constraints`].
#[derive(Debug)]
pub struct ConstraintPoster<'solver, ConstraintImpl> {
solver: &'solver mut Solver,
constraint: Option<ConstraintImpl>,
tag: Option<NonZero<u32>>,
}
impl<'a, ConstraintImpl> ConstraintPoster<'a, ConstraintImpl> {
pub(crate) fn new(solver: &'a mut Solver, constraint: ConstraintImpl) -> Self {
ConstraintPoster {
solver,
constraint: Some(constraint),
tag: None,
}
}
/// Tag the constraint with an integer. This tag is used in the proof to identify which
/// constraints trigger particular inferences.
pub fn with_tag(mut self, tag: NonZero<u32>) -> Self {
self.tag = Some(tag);
self
}
}
impl<ConstraintImpl: Constraint> ConstraintPoster<'_, ConstraintImpl> {
/// Add the [`Constraint`] to the [`Solver`].
///
/// This method returns a [`ConstraintOperationError`] if the addition of the [`Constraint`] led
/// to a root-level conflict.
pub fn post(mut self) -> Result<(), ConstraintOperationError> {
self.constraint.take().unwrap().post(self.solver, self.tag)
}
/// Add the half-reified version of the [`Constraint`] to the [`Solver`]; i.e. post the
/// constraint `r -> constraint` where `r` is a reification literal.
///
/// This method returns a [`ConstraintOperationError`] if the addition of the [`Constraint`] led
/// to a root-level conflict.
pub fn implied_by(
mut self,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError> {
self.constraint
.take()
.unwrap()
.implied_by(self.solver, reification_literal, self.tag)
}
}
impl<ConstraintImpl: NegatableConstraint> ConstraintPoster<'_, ConstraintImpl> {
/// Add the reified version of the [`Constraint`] to the [`Solver`]; i.e. post the constraint
/// `r <-> constraint` where `r` is a reification literal.
///
/// This method returns a [`ConstraintOperationError`] if the addition of the [`Constraint`] led
/// to a root-level conflict.
pub fn reify(mut self, reification_literal: Literal) -> Result<(), ConstraintOperationError> {
self.constraint
.take()
.unwrap()
.reify(self.solver, reification_literal, self.tag)
}
}
impl<ConstraintImpl> Drop for ConstraintPoster<'_, ConstraintImpl> {
fn drop(&mut self) {
if self.constraint.is_some() {
warn!("A constraint poster is never used, this is likely a mistake.");
}
}
}