Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
cp_constraints.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_SAT_CP_CONSTRAINTS_H_
15#define OR_TOOLS_SAT_CP_CONSTRAINTS_H_
16
17#include <cstdint>
18#include <functional>
19#include <vector>
20
21#include "absl/log/check.h"
22#include "absl/types/span.h"
24#include "ortools/sat/integer.h"
26#include "ortools/sat/model.h"
28
29namespace operations_research {
30namespace sat {
31
32// Propagate the fact that a XOR of literals is equal to the given value.
33// The complexity is in O(n).
34//
35// TODO(user): By using a two watcher mechanism, we can propagate this a lot
36// faster.
38 public:
39 BooleanXorPropagator(const std::vector<Literal>& literals, bool value,
40 Trail* trail, IntegerTrail* integer_trail)
41 : literals_(literals),
42 value_(value),
43 trail_(trail),
44 integer_trail_(integer_trail) {}
45
46 // This type is neither copyable nor movable.
49
50 bool Propagate() final;
52
53 private:
54 const std::vector<Literal> literals_;
55 const bool value_;
56 std::vector<Literal> literal_reason_;
57 Trail* trail_;
58 IntegerTrail* integer_trail_;
59};
60
61// If we have:
62// - selectors[i] => (target_var >= vars[i] + offset[i])
63// - and we known that at least one selectors[i] must be true
64// then we can propagate the fact that if no selectors is chosen yet, the lower
65// bound of target_var is greater than the min of the still possible
66// alternatives.
67//
68// This constraint take care of this case when no selectors[i] is chosen yet.
69//
70// This constraint support duplicate selectors.
72 public LazyReasonInterface {
73 public:
74 GreaterThanAtLeastOneOfPropagator(IntegerVariable target_var,
75 absl::Span<const AffineExpression> exprs,
76 absl::Span<const Literal> selectors,
77 absl::Span<const Literal> enforcements,
78 Model* model);
79
80 // This type is neither copyable nor movable.
82 delete;
84 const GreaterThanAtLeastOneOfPropagator&) = delete;
85
86 bool Propagate() final;
88
89 // For LazyReasonInterface.
90 void Explain(int id, IntegerValue propagation_slack,
91 IntegerVariable var_to_explain, int trail_index,
92 std::vector<Literal>* literals_reason,
93 std::vector<int>* trail_indices_reason) final;
94
95 private:
96 const IntegerVariable target_var_;
97 const std::vector<Literal> enforcements_;
98
99 // Non-const as we swap elements around.
100 std::vector<Literal> selectors_;
101 std::vector<AffineExpression> exprs_;
102
103 Trail* trail_;
104 IntegerTrail* integer_trail_;
105};
106
107// ============================================================================
108// Model based functions.
109// ============================================================================
110
111inline std::vector<IntegerValue> ToIntegerValueVector(
112 absl::Span<const int64_t> input) {
113 std::vector<IntegerValue> result(input.size());
114 for (int i = 0; i < input.size(); ++i) {
115 result[i] = IntegerValue(input[i]);
116 }
117 return result;
118}
119
120// Enforces the XOR of a set of literals to be equal to the given value.
121inline std::function<void(Model*)> LiteralXorIs(
122 const std::vector<Literal>& literals, bool value) {
123 return [=](Model* model) {
124 Trail* trail = model->GetOrCreate<Trail>();
125 IntegerTrail* integer_trail = model->GetOrCreate<IntegerTrail>();
126 BooleanXorPropagator* constraint =
127 new BooleanXorPropagator(literals, value, trail, integer_trail);
128 constraint->RegisterWith(model->GetOrCreate<GenericLiteralWatcher>());
129 model->TakeOwnership(constraint);
130 };
131}
132
133inline std::function<void(Model*)> GreaterThanAtLeastOneOf(
134 IntegerVariable target_var, const absl::Span<const IntegerVariable> vars,
135 const absl::Span<const IntegerValue> offsets,
136 const absl::Span<const Literal> selectors,
137 const absl::Span<const Literal> enforcements) {
138 return [=](Model* model) {
139 std::vector<AffineExpression> exprs;
140 for (int i = 0; i < vars.size(); ++i) {
141 exprs.push_back(AffineExpression(vars[i], 1, offsets[i]));
142 }
144 new GreaterThanAtLeastOneOfPropagator(target_var, exprs, selectors,
145 enforcements, model);
146 constraint->RegisterWith(model->GetOrCreate<GenericLiteralWatcher>());
147 model->TakeOwnership(constraint);
148 };
149}
150
151// The target variable is equal to exactly one of the candidate variable. The
152// equality is controlled by the given "selector" literals.
153//
154// Note(user): This only propagate from the min/max of still possible candidates
155// to the min/max of the target variable. The full constraint also requires
156// to deal with the case when one of the literal is true.
157//
158// Note(user): If there is just one or two candidates, this doesn't add
159// anything.
160inline std::function<void(Model*)> PartialIsOneOfVar(
161 IntegerVariable target_var, absl::Span<const IntegerVariable> vars,
162 absl::Span<const Literal> selectors) {
163 CHECK_EQ(vars.size(), selectors.size());
164 return [=,
165 selectors = std::vector<Literal>(selectors.begin(), selectors.end()),
166 vars = std::vector<IntegerVariable>(vars.begin(), vars.end())](
167 Model* model) {
168 const std::vector<IntegerValue> offsets(vars.size(), IntegerValue(0));
169 if (vars.size() > 2) {
170 // Propagate the min.
171 model->Add(
172 GreaterThanAtLeastOneOf(target_var, vars, offsets, selectors, {}));
173 }
174 if (vars.size() > 2) {
175 // Propagate the max.
177 NegationOf(target_var), NegationOf(vars), offsets, selectors, {}));
178 }
179 };
180}
181
182} // namespace sat
183} // namespace operations_research
184
185#endif // OR_TOOLS_SAT_CP_CONSTRAINTS_H_
Definition model.h:341
BooleanXorPropagator & operator=(const BooleanXorPropagator &)=delete
BooleanXorPropagator(const std::vector< Literal > &literals, bool value, Trail *trail, IntegerTrail *integer_trail)
void RegisterWith(GenericLiteralWatcher *watcher)
BooleanXorPropagator(const BooleanXorPropagator &)=delete
This type is neither copyable nor movable.
GreaterThanAtLeastOneOfPropagator & operator=(const GreaterThanAtLeastOneOfPropagator &)=delete
void Explain(int id, IntegerValue propagation_slack, IntegerVariable var_to_explain, int trail_index, std::vector< Literal > *literals_reason, std::vector< int > *trail_indices_reason) final
For LazyReasonInterface.
GreaterThanAtLeastOneOfPropagator(const GreaterThanAtLeastOneOfPropagator &)=delete
This type is neither copyable nor movable.
GreaterThanAtLeastOneOfPropagator(IntegerVariable target_var, absl::Span< const AffineExpression > exprs, absl::Span< const Literal > selectors, absl::Span< const Literal > enforcements, Model *model)
T Add(std::function< T(Model *)> f)
Definition model.h:87
std::function< void(Model *)> GreaterThanAtLeastOneOf(IntegerVariable target_var, const absl::Span< const IntegerVariable > vars, const absl::Span< const IntegerValue > offsets, const absl::Span< const Literal > selectors, const absl::Span< const Literal > enforcements)
std::function< void(Model *)> LiteralXorIs(const std::vector< Literal > &literals, bool value)
Enforces the XOR of a set of literals to be equal to the given value.
std::function< void(Model *)> PartialIsOneOfVar(IntegerVariable target_var, absl::Span< const IntegerVariable > vars, absl::Span< const Literal > selectors)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
Returns the vector of the negated variables.
Definition integer.cc:52
std::vector< IntegerValue > ToIntegerValueVector(absl::Span< const int64_t > input)
In SWIG mode, we don't want anything besides these top-level includes.
STL namespace.
static int input(yyscan_t yyscanner)