pumpkin_constraints/constraints/
clause.rs1use pumpkin_core::ConstraintOperationError;
2use pumpkin_core::Solver;
3use pumpkin_core::constraints::Constraint;
4use pumpkin_core::constraints::NegatableConstraint;
5use pumpkin_core::proof::ConstraintTag;
6use pumpkin_core::variables::Literal;
7
8pub fn clause(
12 literals: impl Into<Vec<Literal>>,
13 constraint_tag: ConstraintTag,
14) -> impl NegatableConstraint {
15 Clause(literals.into(), constraint_tag)
16}
17
18pub fn conjunction(
22 literals: impl Into<Vec<Literal>>,
23 constraint_tag: ConstraintTag,
24) -> impl NegatableConstraint {
25 Conjunction(literals.into(), constraint_tag)
26}
27
28struct Clause(Vec<Literal>, ConstraintTag);
29
30impl Constraint for Clause {
31 fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError> {
32 let Clause(clause, constraint_tag) = self;
33
34 solver.add_clause(
35 clause.iter().map(|literal| literal.get_true_predicate()),
36 constraint_tag,
37 )
38 }
39
40 fn implied_by(
41 self,
42 solver: &mut Solver,
43 reification_literal: Literal,
44 ) -> Result<(), ConstraintOperationError> {
45 let Clause(clause, constraint_tag) = self;
46
47 solver.add_clause(
48 clause
49 .into_iter()
50 .chain(std::iter::once(!reification_literal))
51 .map(|literal| literal.get_true_predicate()),
52 constraint_tag,
53 )
54 }
55}
56
57impl NegatableConstraint for Clause {
58 type NegatedConstraint = Conjunction;
59
60 fn negation(&self) -> Self::NegatedConstraint {
61 let Clause(clause, constraint_tag) = self;
62
63 Conjunction(clause.iter().map(|&lit| !lit).collect(), *constraint_tag)
64 }
65}
66
67struct Conjunction(Vec<Literal>, ConstraintTag);
68
69impl Constraint for Conjunction {
70 fn post(self, solver: &mut Solver) -> Result<(), ConstraintOperationError> {
71 let Conjunction(conjunction, constraint_tag) = self;
72
73 conjunction
74 .into_iter()
75 .try_for_each(|lit| solver.add_clause([lit.get_true_predicate()], constraint_tag))
76 }
77
78 fn implied_by(
79 self,
80 solver: &mut Solver,
81 reification_literal: Literal,
82 ) -> Result<(), ConstraintOperationError> {
83 let Conjunction(conjunction, constraint_tag) = self;
84
85 conjunction.into_iter().try_for_each(|lit| {
86 solver.add_clause(
87 [
88 (!(reification_literal)).get_true_predicate(),
89 lit.get_true_predicate(),
90 ],
91 constraint_tag,
92 )
93 })
94 }
95}
96
97impl NegatableConstraint for Conjunction {
98 type NegatedConstraint = Clause;
99
100 fn negation(&self) -> Self::NegatedConstraint {
101 let Conjunction(conjunction, constraint_tag) = self;
102
103 Clause(
104 conjunction.iter().map(|&lit| !lit).collect(),
105 *constraint_tag,
106 )
107 }
108}