Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
cp_model_copy.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 ORTOOLS_SAT_CP_MODEL_COPY_H_
15#define ORTOOLS_SAT_CP_MODEL_COPY_H_
16
17#include <cstdint>
18#include <functional>
19#include <utility>
20#include <vector>
21
22#include "absl/container/flat_hash_map.h"
23#include "absl/container/flat_hash_set.h"
24#include "absl/types/span.h"
31
32namespace operations_research {
33namespace sat {
34
35// This helper class perform copy with simplification from a model and a
36// partial assignment to another model. The purpose is to minimize the size of
37// the copied model, as well as to reduce the pressure on the memory sub-system.
38//
39// It is currently used by the LNS part, but could be used with any other scheme
40// that generates partial assignments.
41class ModelCopy {
42 public:
43 explicit ModelCopy(PresolveContext* context,
44 LratProofHandler* lrat_proof_handler = nullptr);
45
46 // Copies all constraints from in_model to working model of the context.
47 //
48 // During the process, it will read variable domains from the context, and
49 // simplify constraints to minimize the size of the copied model.
50 // Thus it is important that the context->working_model already have the
51 // variables part copied.
52 //
53 // It returns false iff the model is proven infeasible.
54 //
55 // It does not clear the constraints part of the working model of the context.
56 //
57 // Note(user): If first_copy is true, we will reorder the scheduling
58 // constraint so that they only use reference to previously defined intervals.
59 // This allow to be more efficient later in a few preprocessing steps.
61 const CpModelProto& in_model, bool first_copy = false,
62 std::function<bool(int)> active_constraints = nullptr);
63
64 // Copy variables from the in_model to the working model.
65 // It reads the 'ignore_names' parameters from the context, and keeps or
66 // deletes names accordingly.
68
69 // Setup new variables from a vector of domains.
70 // Inactive variables will be fixed to their lower bound.
71 void CreateVariablesFromDomains(absl::Span<const Domain> domains);
72
73 // Advanced usage. When a model was copied, interval_mapping[i] will contain
74 // for a copied interval with original index i, its new index.
75 absl::Span<const int64_t> InternalIntervalMapping() const {
76 return interval_mapping_;
77 }
78
79 private:
80 // Overwrites the out_model to be unsat. Returns false.
81 // The arguments are used to log which constraint caused unsat.
82 bool CreateUnsatModel(int c, const ConstraintProto& ct);
83
84 // Returns false if the constraint is never enforced and can be skipped.
85 bool PrepareEnforcementCopy(const ConstraintProto& ct);
86 bool PrepareEnforcementCopyWithDup(const ConstraintProto& ct);
87 void FinishEnforcementCopy(ConstraintProto* ct);
88
89 // All these functions return false if the constraint is found infeasible.
90 bool CopyBoolOr(const ConstraintProto& ct);
91 bool CopyBoolOrWithDupSupport(const ConstraintProto& ct, ClauseId clause_id);
92 bool FinishBoolOrCopy(ClauseId clause_id = kNoClauseId);
93
94 bool CopyBoolAnd(const ConstraintProto& ct);
95 bool CopyBoolAndWithDupSupport(const ConstraintProto& ct);
96
97 bool CopyAtMostOne(const ConstraintProto& ct);
98 bool CopyExactlyOne(const ConstraintProto& ct);
99
100 bool CopyElement(const ConstraintProto& ct);
101 bool CopyIntProd(const ConstraintProto& ct, bool ignore_names);
102 bool CopyIntDiv(const ConstraintProto& ct, bool ignore_names);
103 bool CopyIntMod(const ConstraintProto& ct, bool ignore_names);
104 bool CopyLinear(const ConstraintProto& ct, bool canonicalize);
105 bool CopyLinearExpression(const LinearExpressionProto& expr,
107 absl::Span<const int> enforcement_literals = {});
108 bool CopyAutomaton(const ConstraintProto& ct);
109 bool CopyTable(const ConstraintProto& ct);
110 bool CopyAllDiff(const ConstraintProto& ct);
111 bool CopyLinMax(const ConstraintProto& ct);
112
113 // If we "copy" an interval for a first time, we make sure to create the
114 // linear constraint between the start, size and end. This allow to simplify
115 // the input proto and client side code. If there are more than one
116 // enforcement literals, we replace them with a new one, made equal to their
117 // conjunction with two new constraints.
118 bool CopyInterval(const ConstraintProto& ct, int c, bool ignore_names);
119 bool AddLinearConstraintForInterval(const ConstraintProto& ct);
120 int GetOrCreateVariableForConjunction(std::vector<int>* literals);
121
122 // These function remove unperformed intervals. Note that they requires
123 // interval to appear before (validated) as they test unperformed by testing
124 // if interval_mapping_ is empty.
125 void CopyAndMapNoOverlap(const ConstraintProto& ct);
126 void CopyAndMapNoOverlap2D(const ConstraintProto& ct);
127 bool CopyAndMapCumulative(const ConstraintProto& ct);
128
129 // Expands linear expressions with more than one variable in constraints which
130 // internally only support affine expressions (such as all_diff, element,
131 // interval, reservoir, table, etc). This creates new variables for each such
132 // expression, and replaces the original expressions with the new variables in
133 // the constraints.
134 void ExpandNonAffineExpressions();
135 // Replaces the expression sum a_i * x_i + c with gcd * y + c, where y is a
136 // new variable defined with an additional constraint y = sum a_i / gcd * x_i.
137 void MaybeExpandNonAffineExpression(LinearExpressionProto* expr);
138 void MaybeExpandNonAffineExpressions(LinearArgumentProto* linear_argument);
139
140 ClauseId NextInferredClauseId();
141
142 PresolveContext* context_;
143 LratProofHandler* lrat_proof_handler_;
144
145 // Temp vectors.
146 std::vector<int> non_fixed_variables_;
147 std::vector<int64_t> non_fixed_coefficients_;
148 std::vector<int64_t> interval_mapping_;
149 int starting_constraint_index_ = 0;
150
151 std::vector<int> temp_enforcement_literals_;
152 absl::flat_hash_set<int> temp_enforcement_literals_set_;
153
154 std::vector<int> temp_literals_;
155 absl::flat_hash_set<int> temp_literals_set_;
156
157 ConstraintProto tmp_constraint_;
158
159 // The unit clause IDs of the literals which are fixed to true. Only used if
160 // lrat_proof_handler_ is not null.
161 absl::flat_hash_map<Literal, ClauseId> unit_clause_ids_;
162 // Temp vectors used for LRAT.
163 std::vector<Literal> temp_clause_;
164 std::vector<Literal> temp_simplified_clause_;
165 std::vector<ClauseId> temp_clause_ids_;
166 ClauseId next_inferred_clause_id_;
167
168 // Map used in GetOrCreateVariableForConjunction() to avoid creating duplicate
169 // variables for identical sets of literals.
170 absl::flat_hash_map<std::vector<int>, int> boolean_product_encoding_;
171 // Map used in ExpandNonAffineExpressions() to avoid creating duplicate
172 // variables for the identical non affine expressions.
173 absl::flat_hash_map<std::vector<std::pair<int, int64_t>>, int>
174 non_affine_expression_to_new_var_;
175};
176
177// Copy in_model to the model in the presolve context.
178// It performs on the fly simplification, and returns false if the
179// model is proved infeasible. If reads the parameters 'ignore_names' and keeps
180// or deletes variables and constraints names accordingly.
181//
182// This should only be called on the first copy of the user given model.
183// Note that this reorder all constraints that use intervals last. We loose the
184// user-defined order, but hopefully that should not matter too much.
186 const CpModelProto& in_model, PresolveContext* context,
187 LratProofHandler* lrat_proof_handler = nullptr);
188
189// Same as ImportModelWithBasicPresolveIntoContext() except that variable
190// domains are read from domains and constraint might be filtered.
192 const CpModelProto& in_model, absl::Span<const Domain> domains,
193 std::function<bool(int)> active_constraints, PresolveContext* context,
194 std::vector<int>* interval_mapping);
195
196// Copies the non constraint, non variables part of the model.
198 const CpModelProto& in_model, PresolveContext* context);
199
200} // namespace sat
201} // namespace operations_research
202
203#endif // ORTOOLS_SAT_CP_MODEL_COPY_H_
ModelCopy(PresolveContext *context, LratProofHandler *lrat_proof_handler=nullptr)
void ImportVariablesAndMaybeIgnoreNames(const CpModelProto &in_model)
void CreateVariablesFromDomains(absl::Span< const Domain > domains)
absl::Span< const int64_t > InternalIntervalMapping() const
bool ImportAndSimplifyConstraints(const CpModelProto &in_model, bool first_copy=false, std::function< bool(int)> active_constraints=nullptr)
constexpr ClauseId kNoClauseId(0)
bool ImportModelWithBasicPresolveIntoContext(const CpModelProto &in_model, PresolveContext *context, LratProofHandler *lrat_proof_handler)
void CopyEverythingExceptVariablesAndConstraintsFieldsIntoContext(const CpModelProto &in_model, PresolveContext *context)
bool ImportModelAndDomainsWithBasicPresolveIntoContext(const CpModelProto &in_model, absl::Span< const Domain > domains, std::function< bool(int)> active_constraints, PresolveContext *context, std::vector< int > *interval_mapping)
OR-Tools root namespace.