Google OR-Tools v9.11
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-2024 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 <memory>
20#include <vector>
21
22#include "absl/log/check.h"
23#include "absl/types/span.h"
25#include "ortools/base/types.h"
26#include "ortools/sat/integer.h"
27#include "ortools/sat/model.h"
29#include "ortools/util/rev.h"
31
32namespace operations_research {
33namespace sat {
34
35// Propagate the fact that a XOR of literals is equal to the given value.
36// The complexity is in O(n).
37//
38// TODO(user): By using a two watcher mechanism, we can propagate this a lot
39// faster.
41 public:
42 BooleanXorPropagator(const std::vector<Literal>& literals, bool value,
43 Trail* trail, IntegerTrail* integer_trail)
44 : literals_(literals),
45 value_(value),
46 trail_(trail),
47 integer_trail_(integer_trail) {}
48
49 // This type is neither copyable nor movable.
52
53 bool Propagate() final;
55
56 private:
57 const std::vector<Literal> literals_;
58 const bool value_;
59 std::vector<Literal> literal_reason_;
60 Trail* trail_;
61 IntegerTrail* integer_trail_;
62};
63
64// If we have:
65// - selectors[i] => (target_var >= vars[i] + offset[i])
66// - and we known that at least one selectors[i] must be true
67// then we can propagate the fact that if no selectors is chosen yet, the lower
68// bound of target_var is greater than the min of the still possible
69// alternatives.
70//
71// This constraint take care of this case when no selectors[i] is chosen yet.
72//
73// This constraint support duplicate selectors.
75 public LazyReasonInterface {
76 public:
77 GreaterThanAtLeastOneOfPropagator(IntegerVariable target_var,
78 absl::Span<const AffineExpression> exprs,
79 absl::Span<const Literal> selectors,
80 absl::Span<const Literal> enforcements,
81 Model* model);
82
83 // This type is neither copyable nor movable.
85 delete;
87 const GreaterThanAtLeastOneOfPropagator&) = delete;
88
89 bool Propagate() final;
91
92 // For LazyReasonInterface.
93 void Explain(int id, IntegerValue propagation_slack,
94 IntegerVariable var_to_explain, int trail_index,
95 std::vector<Literal>* literals_reason,
96 std::vector<int>* trail_indices_reason) final;
97
98 private:
99 const IntegerVariable target_var_;
100 const std::vector<Literal> enforcements_;
101
102 // Non-const as we swap elements around.
103 std::vector<Literal> selectors_;
104 std::vector<AffineExpression> exprs_;
105
106 Trail* trail_;
107 IntegerTrail* integer_trail_;
108};
109
110// ============================================================================
111// Model based functions.
112// ============================================================================
113
114inline std::vector<IntegerValue> ToIntegerValueVector(
115 const std::vector<int64_t>& input) {
116 std::vector<IntegerValue> result(input.size());
117 for (int i = 0; i < input.size(); ++i) {
118 result[i] = IntegerValue(input[i]);
119 }
120 return result;
121}
122
123// Enforces the XOR of a set of literals to be equal to the given value.
124inline std::function<void(Model*)> LiteralXorIs(
125 const std::vector<Literal>& literals, bool value) {
126 return [=](Model* model) {
127 Trail* trail = model->GetOrCreate<Trail>();
128 IntegerTrail* integer_trail = model->GetOrCreate<IntegerTrail>();
129 BooleanXorPropagator* constraint =
130 new BooleanXorPropagator(literals, value, trail, integer_trail);
131 constraint->RegisterWith(model->GetOrCreate<GenericLiteralWatcher>());
132 model->TakeOwnership(constraint);
133 };
134}
135
136inline std::function<void(Model*)> GreaterThanAtLeastOneOf(
137 IntegerVariable target_var, const absl::Span<const IntegerVariable> vars,
138 const absl::Span<const IntegerValue> offsets,
139 const absl::Span<const Literal> selectors,
140 const absl::Span<const Literal> enforcements) {
141 return [=](Model* model) {
142 std::vector<AffineExpression> exprs;
143 for (int i = 0; i < vars.size(); ++i) {
144 exprs.push_back(AffineExpression(vars[i], 1, offsets[i]));
145 }
147 new GreaterThanAtLeastOneOfPropagator(target_var, exprs, selectors,
148 enforcements, model);
149 constraint->RegisterWith(model->GetOrCreate<GenericLiteralWatcher>());
150 model->TakeOwnership(constraint);
151 };
152}
153
154// The target variable is equal to exactly one of the candidate variable. The
155// equality is controlled by the given "selector" literals.
156//
157// Note(user): This only propagate from the min/max of still possible candidates
158// to the min/max of the target variable. The full constraint also requires
159// to deal with the case when one of the literal is true.
160//
161// Note(user): If there is just one or two candidates, this doesn't add
162// anything.
163inline std::function<void(Model*)> PartialIsOneOfVar(
164 IntegerVariable target_var, const std::vector<IntegerVariable>& vars,
165 const std::vector<Literal>& selectors) {
166 CHECK_EQ(vars.size(), selectors.size());
167 return [=](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_
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
GreaterThanAtLeastOneOfPropagator(const GreaterThanAtLeastOneOfPropagator &)=delete
This type is neither copyable nor movable.
Base class for CP like propagators.
Definition integer.h:1414
int64_t value
GRBmodel * model
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::vector< IntegerValue > ToIntegerValueVector(const std::vector< int64_t > &input)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Returns the vector of the negated variables.
Definition integer.cc:51
std::function< void(Model *)> PartialIsOneOfVar(IntegerVariable target_var, const std::vector< IntegerVariable > &vars, const std::vector< Literal > &selectors)
In SWIG mode, we don't want anything besides these top-level includes.
STL namespace.
static int input(yyscan_t yyscanner)