OR-Tools  9.1
cp_model_presolve.h
Go to the documentation of this file.
1// Copyright 2010-2021 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_MODEL_PRESOLVE_H_
15#define OR_TOOLS_SAT_CP_MODEL_PRESOLVE_H_
16
17#include <cstdint>
18#include <vector>
19
26#include "ortools/util/bitset.h"
29
30namespace operations_research {
31namespace sat {
32
33// Replaces all the instance of a variable i (and the literals referring to it)
34// by mapping[i]. The definition of variables i is also moved to its new index.
35// Variables with a negative mapping value are ignored and it is an error if
36// such variable is referenced anywhere (this is CHECKed).
37//
38// The image of the mapping should be dense in [0, new_num_variables), this is
39// also CHECKed.
40void ApplyVariableMapping(const std::vector<int>& mapping,
41 const PresolveContext& context);
42
43// Presolves the initial content of presolved_model.
44//
45// This also creates a mapping model that encode the correspondence between the
46// two problems. This works as follow:
47// - The first variables of mapping_model are in one to one correspondence with
48// the variables of the initial model.
49// - The presolved_model variables are in one to one correspondence with the
50// variable at the indices given by postsolve_mapping in the mapping model.
51// - Fixing one of the two sets of variables and solving the model will assign
52// the other set to a feasible solution of the other problem. Moreover, the
53// objective value of these solutions will be the same. Note that solving such
54// problems will take little time in practice because the propagation will
55// basically do all the work.
56//
57// Note(user): an optimization model can be transformed into a decision problem,
58// if for instance the objective is fixed, or independent from the rest of the
59// problem.
60//
61// TODO(user): Identify disconnected components and returns a vector of
62// presolved model? If we go this route, it may be nicer to store the indices
63// inside the model. We can add a IntegerVariableProto::initial_index;
65 public:
67 std::vector<int>* postsolve_mapping);
68
69 // Returns false if a non-recoverable error was encountered.
70 //
71 // TODO(user): Make sure this can never run into this case provided that the
72 // initial model is valid!
73 bool Presolve();
74
75 // Executes presolve method for the given constraint. Public for testing only.
76 bool PresolveOneConstraint(int c);
77
78 // Public for testing only.
80
81 private:
82 void PresolveToFixPoint();
83
84 // Runs the probing.
85 void Probe();
86
87 // Presolve functions.
88 //
89 // They should return false only if the constraint <-> variable graph didn't
90 // change. This is just an optimization, returning true is always correct.
91 //
92 // Invariant about UNSAT: All these functions should abort right away if
93 // context_.IsUnsat() is true. And the only way to change the status to unsat
94 // is through ABSL_MUST_USE_RESULT function that should also abort right away
95 // the current code. This way we shouldn't keep doing computation on an
96 // inconsistent state.
97 // TODO(user): Make these public and unit test.
98 bool ConvertIntMax(ConstraintProto* ct);
99 bool PresolveAllDiff(ConstraintProto* ct);
100 bool PresolveAutomaton(ConstraintProto* ct);
101 bool PresolveElement(ConstraintProto* ct);
102 bool PresolveIntAbs(ConstraintProto* ct);
103 bool PresolveIntDiv(ConstraintProto* ct);
104 bool PresolveIntMax(ConstraintProto* ct);
105 bool PresolveIntMin(ConstraintProto* ct);
106 bool PresolveIntMod(ConstraintProto* ct);
107 bool PresolveIntProd(ConstraintProto* ct);
108 bool PresolveInterval(int c, ConstraintProto* ct);
109 bool PresolveInverse(ConstraintProto* ct);
110 bool PresolveLinMax(ConstraintProto* ct);
111 bool PresolveLinMin(ConstraintProto* ct);
112 bool PresolveTable(ConstraintProto* ct);
113
114 bool PresolveCumulative(ConstraintProto* ct);
115 bool PresolveNoOverlap(ConstraintProto* ct);
116 bool PresolveNoOverlap2D(int c, ConstraintProto* ct);
117 bool PresolveReservoir(ConstraintProto* ct);
118
119 bool PresolveCircuit(ConstraintProto* ct);
120 bool PresolveRoutes(ConstraintProto* ct);
121
122 bool PresolveAtMostOrExactlyOne(ConstraintProto* ct);
123 bool PresolveAtMostOne(ConstraintProto* ct);
124 bool PresolveExactlyOne(ConstraintProto* ct);
125
126 bool PresolveBoolAnd(ConstraintProto* ct);
127 bool PresolveBoolOr(ConstraintProto* ct);
128 bool PresolveBoolXor(ConstraintProto* ct);
129 bool PresolveEnforcementLiteral(ConstraintProto* ct);
130
131 // Regroups terms and substitute affine relations.
132 // Returns true if the set of variables in the expression changed.
133 template <typename ProtoWithVarsAndCoeffs>
134 bool CanonicalizeLinearExpressionInternal(const ConstraintProto& ct,
135 ProtoWithVarsAndCoeffs* proto,
136 int64_t* offset);
137 bool CanonicalizeLinearExpression(const ConstraintProto& ct,
139
140 // For the linear constraints, we have more than one function.
141 bool CanonicalizeLinear(ConstraintProto* ct);
142 bool PropagateDomainsInLinear(int c, ConstraintProto* ct);
143 bool RemoveSingletonInLinear(ConstraintProto* ct);
144 bool PresolveSmallLinear(ConstraintProto* ct);
145 bool PresolveLinearOnBooleans(ConstraintProto* ct);
146 void PresolveLinearEqualityModuloTwo(ConstraintProto* ct);
147
148 // Scheduling helpers.
149 void AddLinearConstraintFromInterval(const ConstraintProto& ct);
150
151 // SetPPC is short for set packing, partitioning and covering constraints.
152 // These are sum of booleans <=, = and >= 1 respectively.
153 bool ProcessSetPPC();
154
155 // Removes dominated constraints or fixes some variables for given pair of
156 // setppc constraints. This assumes that literals in constraint c1 is subset
157 // of literals in constraint c2.
158 bool ProcessSetPPCSubset(int c1, int c2, const std::vector<int>& c2_minus_c1,
159 const std::vector<int>& original_constraint_index,
160 std::vector<bool>* marked_for_removal);
161
162 void PresolvePureSatPart();
163
164 // Extracts AtMostOne constraint from Linear constraint.
165 void ExtractAtMostOneFromLinear(ConstraintProto* ct);
166
167 void DivideLinearByGcd(ConstraintProto* ct);
168
169 void ExtractEnforcementLiteralFromLinearConstraint(int ct_index,
171
172 // Extracts cliques from bool_and and small at_most_one constraints and
173 // transforms them into maximal cliques.
174 void TransformIntoMaxCliques();
175
176 // Converts bool_or and at_most_one of size 2 to bool_and.
177 void ExtractBoolAnd();
178
179 void ExpandObjective();
180
181 void TryToSimplifyDomain(int var);
182
183 void MergeNoOverlapConstraints();
184
185 // Boths function are responsible for dealing with affine relations.
186 // The second one returns false on UNSAT.
187 void EncodeAllAffineRelations();
188 bool PresolveAffineRelationIfAny(int var);
189
190 bool ExploitEquivalenceRelations(int c, ConstraintProto* ct);
191
192 ABSL_MUST_USE_RESULT bool RemoveConstraint(ConstraintProto* ct);
193 ABSL_MUST_USE_RESULT bool MarkConstraintAsFalse(ConstraintProto* ct);
194
195 std::vector<int>* postsolve_mapping_;
196 PresolveContext* context_;
197 SolverLogger* logger_;
198
199 // Used by CanonicalizeLinearExpressionInternal().
200 std::vector<std::pair<int, int64_t>> tmp_terms_;
201};
202
203// This helper class perform copy with simplification from a model and a
204// partial assignment to another model. The purpose is to miminize the size of
205// the copied model, as well as to reduce the pressure on the memory sub-system.
206//
207// It is currently used by the LNS part, but could be used with any other scheme
208// that generates partial assignments.
210 public:
212
213 // Copies all constraints from in_model to working model of the context.
214 //
215 // During the process, it will read variable domains from the context, and
216 // simplify constraints to minimize the size of the copied model.
217 // Thus it is important that the context->working_model already have the
218 // variables part copied.
219 //
220 // It returns false iff the model is proven infeasible.
221 //
222 // It does not clear the constraints part of the working model of the context.
224 const CpModelProto& in_model,
225 const std::vector<int>& ignored_constraints);
226
227 private:
228 // Overwrites the out_model to be unsat. Returns false.
229 bool CreateUnsatModel();
230
231 void CopyEnforcementLiterals(const ConstraintProto& orig,
232 ConstraintProto* dest);
233 bool OneEnforcementLiteralIsFalse(const ConstraintProto& ct) const;
234
235 // All these functions return false if the constraint is found infeasible.
236 bool CopyBoolOr(const ConstraintProto& ct);
237 bool CopyBoolAnd(const ConstraintProto& ct);
238 bool CopyLinear(const ConstraintProto& ct);
239 bool CopyAtMostOne(const ConstraintProto& ct);
240 bool CopyExactlyOne(const ConstraintProto& ct);
241 bool CopyInterval(const ConstraintProto& ct, int c);
242
243 PresolveContext* context_;
244 int64_t skipped_non_zero_ = 0;
245
246 // Temp vectors.
247 std::vector<int> non_fixed_variables_;
248 std::vector<int64_t> non_fixed_coefficients_;
249 absl::flat_hash_map<int, int> interval_mapping_;
250 int starting_constraint_index_ = 0;
251 std::vector<int> temp_enforcement_literals_;
252 std::vector<int> temp_literals_;
253};
254
255// Import the constraints from the in_model to the presolve context.
256// It performs on the fly simplification, and returns false if the
257// model is proved infeasible.
260
261// Copies the non constraint, non variables part of the model.
263 const CpModelProto& in_model, PresolveContext* context);
264
265// Convenient wrapper to call the full presolve.
267 std::vector<int>* postsolve_mapping);
268
269// Returns the index of duplicate constraints in the given proto in the first
270// element of each pair. The second element of each pair is the "representative"
271// that is the first constraint in the proto in a set of duplicate constraints.
272//
273// Empty constraints are ignored. We also do a bit more:
274// - We ignore names when comparing constraint.
275// - For linear constraints, we ignore the domain. This is because we can
276// just merge them if the constraints are the same.
277//
278// Visible here for testing. This is meant to be called at the end of the
279// presolve where constraints have been canonicalized.
280std::vector<std::pair<int, int>> FindDuplicateConstraints(
282
283} // namespace sat
284} // namespace operations_research
285
286#endif // OR_TOOLS_SAT_CP_MODEL_PRESOLVE_H_
CpModelPresolver(PresolveContext *context, std::vector< int > *postsolve_mapping)
bool ImportAndSimplifyConstraints(const CpModelProto &in_model, const std::vector< int > &ignored_constraints)
CpModelProto proto
CpModelProto const * model_proto
const Constraint * ct
IntVar * var
Definition: expr_array.cc:1874
GurobiMPCallbackContext * context
bool PresolveCpModel(PresolveContext *context, std::vector< int > *postsolve_mapping)
void CopyEverythingExceptVariablesAndConstraintsFieldsIntoContext(const CpModelProto &in_model, PresolveContext *context)
bool ImportConstraintsWithBasicPresolveIntoContext(const CpModelProto &in_model, PresolveContext *context)
std::vector< std::pair< int, int > > FindDuplicateConstraints(const CpModelProto &model_proto)
void ApplyVariableMapping(const std::vector< int > &mapping, const PresolveContext &context)
Collection of objects used to extend the Constraint Solver library.