OR-Tools  9.0
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 
30 namespace operations_research {
31 namespace 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.
40 void 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,user): Make these public and unit test.
98  bool PresolveAutomaton(ConstraintProto* ct);
99  bool PresolveCircuit(ConstraintProto* ct);
100  bool PresolveRoutes(ConstraintProto* ct);
101  bool PresolveCumulative(ConstraintProto* ct);
102  bool PresolveNoOverlap(ConstraintProto* ct);
103  bool PresolveReservoir(ConstraintProto* ct);
104  bool PresolveAllDiff(ConstraintProto* ct);
105  bool PresolveTable(ConstraintProto* ct);
106  bool PresolveElement(ConstraintProto* ct);
107  bool PresolveInterval(int c, ConstraintProto* ct);
108  bool PresolveIntDiv(ConstraintProto* ct);
109  bool PresolveIntProd(ConstraintProto* ct);
110  bool PresolveIntMin(ConstraintProto* ct);
111  bool PresolveIntMax(ConstraintProto* ct);
112  bool PresolveLinMin(ConstraintProto* ct);
113  bool PresolveLinMax(ConstraintProto* ct);
114  bool PresolveIntAbs(ConstraintProto* ct);
115  bool PresolveBoolXor(ConstraintProto* ct);
116 
117  bool PresolveAtMostOrExactlyOne(ConstraintProto* ct);
118  bool PresolveAtMostOne(ConstraintProto* ct);
119  bool PresolveExactlyOne(ConstraintProto* ct);
120 
121  bool PresolveBoolAnd(ConstraintProto* ct);
122  bool PresolveBoolOr(ConstraintProto* ct);
123  bool PresolveEnforcementLiteral(ConstraintProto* ct);
124 
125  // Regroups terms and substitute affine relations.
126  // Returns true if the set of variables in the expression changed.
127  template <typename ProtoWithVarsAndCoeffs>
128  bool CanonicalizeLinearExpressionInternal(const ConstraintProto& ct,
129  ProtoWithVarsAndCoeffs* proto,
130  int64_t* offset);
131  bool CanonicalizeLinearExpression(const ConstraintProto& ct,
132  LinearExpressionProto* exp);
133 
134  // For the linear constraints, we have more than one function.
135  bool CanonicalizeLinear(ConstraintProto* ct);
136  bool PropagateDomainsInLinear(int c, ConstraintProto* ct);
137  bool RemoveSingletonInLinear(ConstraintProto* ct);
138  bool PresolveSmallLinear(ConstraintProto* ct);
139  bool PresolveLinearOnBooleans(ConstraintProto* ct);
140  void PresolveLinearEqualityModuloTwo(ConstraintProto* ct);
141 
142  // To simplify dealing with the two kind of intervals.
143  int64_t StartMin(const IntervalConstraintProto& interval) const;
144  int64_t EndMax(const IntervalConstraintProto& interval) const;
145  int64_t SizeMin(const IntervalConstraintProto& interval) const;
146  int64_t SizeMax(const IntervalConstraintProto& interval) const;
147 
148  // SetPPC is short for set packing, partitioning and covering constraints.
149  // These are sum of booleans <=, = and >= 1 respectively.
150  bool ProcessSetPPC();
151 
152  // Removes dominated constraints or fixes some variables for given pair of
153  // setppc constraints. This assumes that literals in constraint c1 is subset
154  // of literals in constraint c2.
155  bool ProcessSetPPCSubset(int c1, int c2, const std::vector<int>& c2_minus_c1,
156  const std::vector<int>& original_constraint_index,
157  std::vector<bool>* marked_for_removal);
158 
159  void PresolvePureSatPart();
160 
161  // Extracts AtMostOne constraint from Linear constraint.
162  void ExtractAtMostOneFromLinear(ConstraintProto* ct);
163 
164  void DivideLinearByGcd(ConstraintProto* ct);
165 
166  void ExtractEnforcementLiteralFromLinearConstraint(int ct_index,
167  ConstraintProto* ct);
168 
169  // Extracts cliques from bool_and and small at_most_one constraints and
170  // transforms them into maximal cliques.
171  void TransformIntoMaxCliques();
172 
173  // Converts bool_or and at_most_one of size 2 to bool_and.
174  void ExtractBoolAnd();
175 
176  void ExpandObjective();
177 
178  void TryToSimplifyDomain(int var);
179 
180  void MergeNoOverlapConstraints();
181 
182  // Boths function are responsible for dealing with affine relations.
183  // The second one returns false on UNSAT.
184  void EncodeAllAffineRelations();
185  bool PresolveAffineRelationIfAny(int var);
186 
187  bool ExploitEquivalenceRelations(int c, ConstraintProto* ct);
188 
189  ABSL_MUST_USE_RESULT bool RemoveConstraint(ConstraintProto* ct);
190  ABSL_MUST_USE_RESULT bool MarkConstraintAsFalse(ConstraintProto* ct);
191 
192  std::vector<int>* postsolve_mapping_;
193  PresolveContext* context_;
194  SolverLogger* logger_;
195 
196  // Used by CanonicalizeLinearExpressionInternal().
197  std::vector<std::pair<int, int64_t>> tmp_terms_;
198 };
199 
200 // This helper class perform copy with simplification from a model and a
201 // partial assignment to another model. The purpose is to miminize the size of
202 // the copied model, as well as to reduce the pressure on the memory sub-system.
203 //
204 // It is currently used by the LNS part, but could be used with any other scheme
205 // that generates partial assignments.
206 class ModelCopy {
207  public:
208  explicit ModelCopy(PresolveContext* context);
209 
210  // Copies all constraints from in_model to working model of the context.
211  //
212  // During the process, it will read variable domains from the context, and
213  // simplify constraints to minimize the size of the copied model.
214  // Thus it is important that the context->working_model already have the
215  // variables part copied.
216  //
217  // It returns false iff the model is proven infeasible.
218  //
219  // It does not clear the constraints part of the working model of the context.
221  const CpModelProto& in_model,
222  const std::vector<int>& ignored_constraints);
223 
224  private:
225  // Overwrites the out_model to be unsat. Returns false.
226  bool CreateUnsatModel();
227 
228  void CopyEnforcementLiterals(const ConstraintProto& orig,
229  ConstraintProto* dest);
230  bool OneEnforcementLiteralIsFalse(const ConstraintProto& ct) const;
231 
232  // All these functions return false if the constraint is found infeasible.
233  bool CopyBoolOr(const ConstraintProto& ct);
234  bool CopyBoolAnd(const ConstraintProto& ct);
235  bool CopyLinear(const ConstraintProto& ct);
236  bool CopyAtMostOne(const ConstraintProto& ct);
237  bool CopyExactlyOne(const ConstraintProto& ct);
238  bool CopyInterval(const ConstraintProto& ct, int c);
239 
240  PresolveContext* context_;
241  int64_t skipped_non_zero_ = 0;
242 
243  // Temp vectors.
244  std::vector<int> non_fixed_variables_;
245  std::vector<int64_t> non_fixed_coefficients_;
246  absl::flat_hash_map<int, int> interval_mapping_;
247  int starting_constraint_index_ = 0;
248  std::vector<int> temp_enforcement_literals_;
249  std::vector<int> temp_literals_;
250 };
251 
252 // Import the constraints from the in_model to the presolve context.
253 // It performs on the fly simplification, and returns false if the
254 // model is proved infeasible.
255 bool ImportConstraintsWithBasicPresolveIntoContext(const CpModelProto& in_model,
257 
258 // Copies the non constraint, non variables part of the model.
260  const CpModelProto& in_model, PresolveContext* context);
261 
262 // Convenient wrapper to call the full presolve.
264  std::vector<int>* postsolve_mapping);
265 
266 // Returns the index of exact duplicate constraints in the given proto. That
267 // is, all returned constraints will have an identical constraint before it in
268 // the model_proto.constraints() list. Empty constraints are ignored.
269 //
270 // Visible here for testing. This is meant to be called at the end of the
271 // presolve where constraints have been canonicalized.
272 //
273 // TODO(user): Ignore names? canonicalize constraint further by sorting
274 // enforcement literal list for instance...
275 std::vector<int> FindDuplicateConstraints(const CpModelProto& model_proto);
276 
277 } // namespace sat
278 } // namespace operations_research
279 
280 #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)
std::vector< int > FindDuplicateConstraints(const CpModelProto &model_proto)
bool ImportConstraintsWithBasicPresolveIntoContext(const CpModelProto &in_model, PresolveContext *context)
void ApplyVariableMapping(const std::vector< int > &mapping, const PresolveContext &context)
Collection of objects used to extend the Constraint Solver library.
IntervalVar * interval
Definition: resource.cc:100