OR-Tools  9.1
presolve_context.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_PRESOLVE_CONTEXT_H_
15#define OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_
16
17#include <cstdint>
18#include <deque>
19#include <string>
20#include <vector>
21
24#include "ortools/sat/model.h"
27#include "ortools/sat/util.h"
29#include "ortools/util/bitset.h"
33
34namespace operations_research {
35namespace sat {
36
37// We use some special constraint index in our variable <-> constraint graph.
38constexpr int kObjectiveConstraint = -1;
39constexpr int kAffineRelationConstraint = -2;
40constexpr int kAssumptionsConstraint = -3;
41
42class PresolveContext;
43
44// When storing a reference to a literal, it is important not to forget when
45// reading it back to take its representative. Otherwise, we might introduce
46// literal that have already been removed, which will break invariants in a
47// bunch of places.
49 public:
51 explicit SavedLiteral(int ref) : ref_(ref) {}
52 int Get(PresolveContext* context) const;
53
54 private:
55 int ref_ = 0;
56};
57
58// Same as SavedLiteral for variable.
60 public:
62 explicit SavedVariable(int ref) : ref_(ref) {}
63 int Get(PresolveContext* context) const;
64
65 private:
66 int ref_ = 0;
67};
68
69// Wrap the CpModelProto we are presolving with extra data structure like the
70// in-memory domain of each variables and the constraint variable graph.
72 public:
74 : working_model(cp_model),
75 mapping_model(mapping),
76 logger_(model->GetOrCreate<SolverLogger>()),
77 params_(*model->GetOrCreate<SatParameters>()),
78 time_limit_(model->GetOrCreate<TimeLimit>()),
79 random_(model->GetOrCreate<ModelRandomGenerator>()) {}
80
81 // Helpers to adds new variables to the presolved model.
82 //
83 // TODO(user): We should control more how this is called so we can update
84 // a solution hint accordingly.
85 int NewIntVar(const Domain& domain);
86 int NewBoolVar();
87 int GetOrCreateConstantVar(int64_t cst);
88
89 // a => b.
90 void AddImplication(int a, int b);
91
92 // b => x in [lb, ub].
93 void AddImplyInDomain(int b, int x, const Domain& domain);
94
95 // Helpers to query the current domain of a variable.
96 bool DomainIsEmpty(int ref) const;
97 bool IsFixed(int ref) const;
98 bool CanBeUsedAsLiteral(int ref) const;
99 bool LiteralIsTrue(int lit) const;
100 bool LiteralIsFalse(int lit) const;
101 int64_t MinOf(int ref) const;
102 int64_t MaxOf(int ref) const;
103 bool DomainContains(int ref, int64_t value) const;
104 Domain DomainOf(int ref) const;
105
106 // Helper to query the state of an interval.
107 bool IntervalIsConstant(int ct_ref) const;
108 int64_t StartMin(int ct_ref) const;
109 int64_t StartMax(int ct_ref) const;
110 int64_t SizeMin(int ct_ref) const;
111 int64_t SizeMax(int ct_ref) const;
112 int64_t EndMin(int ct_ref) const;
113 int64_t EndMax(int ct_ref) const;
114 std::string IntervalDebugString(int ct_ref) const;
115
116 // Helpers to query the current domain of a linear expression.
117 // This doesn't check for integer overflow, but our linear expression
118 // should be such that this cannot happen (tested at validation).
119 int64_t MinOf(const LinearExpressionProto& expr) const;
120 int64_t MaxOf(const LinearExpressionProto& expr) const;
121
122 // Return a super-set of the domain of the linear expression.
124
125 // Returns true iff the expr is of the for a * literal + b.
126 // The other function can be used to get the liteal that achieve MaxOf().
127 bool ExpressionIsAffineBoolean(const LinearExpressionProto& expr) const;
128 int LiteralForExpressionMax(const LinearExpressionProto& expr) const;
129
130 // This function takes a positive variable reference.
131 bool DomainOfVarIsIncludedIn(int var, const Domain& domain) {
132 return domains[var].IsIncludedIn(domain);
133 }
134
135 // Returns true if a presolve transformation is allowed to remove this
136 // variable.
137 bool VariableIsRemovable(int ref) const;
138
139 // Returns true if this ref only appear in one constraint.
140 bool VariableIsUniqueAndRemovable(int ref) const;
141
142 // Returns true if this ref no longer appears in the model.
143 bool VariableIsNotUsedAnymore(int ref) const;
144
145 // Functions to make sure that once we remove a variable, we no longer reuse
146 // it.
147 void MarkVariableAsRemoved(int ref);
148 bool VariableWasRemoved(int ref) const;
149
150 // Same as VariableIsUniqueAndRemovable() except that in this case the
151 // variable also appear in the objective in addition to a single constraint.
152 bool VariableWithCostIsUniqueAndRemovable(int ref) const;
153
154 // Returns true if an integer variable is only appearing in the rhs of
155 // constraints of the form lit => var in domain. When this is the case, then
156 // we can usually remove this variable and replace these constraints with
157 // the proper constraints on the enforcement literals.
159
160 // Returns false if the new domain is empty. Sets 'domain_modified' (if
161 // provided) to true iff the domain is modified otherwise does not change it.
162 ABSL_MUST_USE_RESULT bool IntersectDomainWith(
163 int ref, const Domain& domain, bool* domain_modified = nullptr);
164
165 // Returns false if the 'lit' doesn't have the desired value in the domain.
166 ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit);
167 ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit);
168
169 // Same as IntersectDomainWith() but take a linear expression as input.
170 // If this expression if of size > 1, this does nothing for now, so it will
171 // only propagates for constant and affine expression.
172 ABSL_MUST_USE_RESULT bool IntersectDomainWith(
173 const LinearExpressionProto& expr, const Domain& domain,
174 bool* domain_modified = nullptr);
175
176 // This function always return false. It is just a way to make a little bit
177 // more sure that we abort right away when infeasibility is detected.
178 ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(
179 const std::string& message = "") {
180 // TODO(user): Report any explanation for the client in a nicer way?
181 VLOG(1) << "INFEASIBLE: '" << message << "'";
182 DCHECK(!is_unsat_);
183 is_unsat_ = true;
184 return false;
185 }
186 bool ModelIsUnsat() const { return is_unsat_; }
187
188 // Stores a description of a rule that was just applied to have a summary of
189 // what the presolve did at the end.
190 void UpdateRuleStats(const std::string& name, int num_times = 1);
191
192 // Updates the constraints <-> variables graph. This needs to be called each
193 // time a constraint is modified.
195
196 // At the beginning of the presolve, we delay the costly creation of this
197 // "graph" until we at least ran some basic presolve. This is because during
198 // a LNS neighbhorhood, many constraints will be reduced significantly by
199 // this "simple" presolve.
201
202 // Calls UpdateConstraintVariableUsage() on all newly created constraints.
204
205 // Returns true if our current constraints <-> variables graph is ok.
206 // This is meant to be used in DEBUG mode only.
208
209 // Regroups fixed variables with the same value.
210 // TODO(user): Also regroup cte and -cte?
211 void ExploitFixedDomain(int var);
212
213 // Adds the relation (ref_x = coeff * ref_y + offset) to the repository.
214 // Once the relation is added, it doesn't need to be enforced by a constraint
215 // in the model proto, since we will propagate such relation directly and add
216 // them to the proto at the end of the presolve.
217 //
218 // Returns true if the relation was added.
219 // In some rare case, like if x = 3*z and y = 5*t are already added, we
220 // currently cannot add x = 2 * y and we will return false in these case. So
221 // when this returns false, the relation needs to be enforced by a separate
222 // constraint.
223 //
224 // If the relation was added, both variables will be marked to appear in the
225 // special kAffineRelationConstraint. This will allow to identify when a
226 // variable is no longer needed (only appear there and is not a
227 // representative).
228 bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset);
229
230 // Adds the fact that ref_a == ref_b using StoreAffineRelation() above.
231 // This should never fail, so the relation will always be added.
232 void StoreBooleanEqualityRelation(int ref_a, int ref_b);
233
234 // Stores/Get the relation target_ref = abs(ref); The first function returns
235 // false if it already exist and the second false if it is not present.
236 bool StoreAbsRelation(int target_ref, int ref);
237 bool GetAbsRelation(int target_ref, int* ref);
238
239 // Returns the representative of a literal.
240 int GetLiteralRepresentative(int ref) const;
241
242 // Returns another reference with exactly the same value.
243 int GetVariableRepresentative(int ref) const;
244
245 // Used for statistics.
246 int NumAffineRelations() const { return affine_relations_.NumRelations(); }
247 int NumEquivRelations() const { return var_equiv_relations_.NumRelations(); }
248
249 // This makes sure that the affine relation only uses one of the
250 // representative from the var_equiv_relations.
252
253 // To facilitate debugging.
254 std::string RefDebugString(int ref) const;
255 std::string AffineRelationDebugString(int ref) const;
256
257 // Makes sure the domain of ref and of its representative are in sync.
258 // Returns false on unsat.
259 bool PropagateAffineRelation(int ref);
260
261 // Creates the internal structure for any new variables in working_model.
263
264 // Clears the "rules" statistics.
265 void ClearStats();
266
267 // Inserts the given literal to encode ref == value.
268 // If an encoding already exists, it adds the two implications between
269 // the previous encoding and the new encoding.
270 //
271 // Important: This does not update the constraint<->variable graph, so
272 // ConstraintVariableGraphIsUpToDate() will be false until
273 // UpdateNewConstraintsVariableUsage() is called.
274 //
275 // Returns false if the model become UNSAT.
276 //
277 // TODO(user): This function is not always correct if
278 // !context->DomainOf(ref).contains(value), we could make it correct but it
279 // might be a bit expansive to do so. For now we just have a DCHECK().
280 bool InsertVarValueEncoding(int literal, int ref, int64_t value);
281
282 // Gets the associated literal if it is already created. Otherwise
283 // create it, add the corresponding constraints and returns it.
284 //
285 // Important: This does not update the constraint<->variable graph, so
286 // ConstraintVariableGraphIsUpToDate() will be false until
287 // UpdateNewConstraintsVariableUsage() is called.
288 int GetOrCreateVarValueEncoding(int ref, int64_t value);
289
290 // If not already done, adds a Boolean to represent any integer variables that
291 // take only two values. Make sure all the relevant affine and encoding
292 // relations are updated.
293 //
294 // Note that this might create a new Boolean variable.
296
297 // Returns true if a literal attached to ref == var exists.
298 // It assigns the corresponding to `literal` if non null.
299 bool HasVarValueEncoding(int ref, int64_t value, int* literal = nullptr);
300
301 // Stores the fact that literal implies var == value.
302 // It returns true if that information is new.
303 bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value);
304
305 // Stores the fact that literal implies var != value.
306 // It returns true if that information is new.
307 bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value);
308
309 // Objective handling functions. We load it at the beginning so that during
310 // presolve we can work on the more efficient hash_map representation.
311 //
312 // Note that ReadObjectiveFromProto() makes sure that var_to_constraints of
313 // all the variable that appear in the objective contains -1. This is later
314 // enforced by all the functions modifying the objective.
315 //
316 // Note(user): Because we process affine relation only on
317 // CanonicalizeObjective(), it is possible that when processing a
318 // canonicalized linear constraint, we don't detect that a variable in affine
319 // relation is in the objective. For now this is fine, because when this is
320 // the case, we also have an affine linear constraint, so we can't really do
321 // anything with that variable since it appear in at least two constraints.
323 ABSL_MUST_USE_RESULT bool CanonicalizeObjective();
324 void WriteObjectiveToProto() const;
325
326 // Checks if the given exactly_one is included in the objective, and simplify
327 // the objective by adding a constant value to all the exactly one terms.
328 bool ExploitExactlyOneInObjective(absl::Span<const int> exactly_one);
329
330 // Allows to manipulate the objective coefficients.
332 void AddToObjective(int var, int64_t value);
333 void AddToObjectiveOffset(int64_t value);
334
335 // Given a variable defined by the given inequality that also appear in the
336 // objective, remove it from the objective by transferring its cost to other
337 // variables in the equality.
338 //
339 // If new_vars_in_objective is not nullptr, it will be filled with "new"
340 // variables that where not in the objective before and are after
341 // substitution.
342 //
343 // Returns false, if the substitution cannot be done. This is the case if the
344 // model become UNSAT or if doing it will result in an objective that do not
345 // satisfy our overflow preconditions. Note that this can only happen if the
346 // substitued variable is not implied free (i.e. if its domain is smaller than
347 // the implied domain from the equality).
348 ABSL_MUST_USE_RESULT bool SubstituteVariableInObjective(
349 int var_in_equality, int64_t coeff_in_equality,
350 const ConstraintProto& equality,
351 std::vector<int>* new_vars_in_objective = nullptr);
352
353 // Objective getters.
354 const Domain& ObjectiveDomain() const { return objective_domain_; }
355 const absl::flat_hash_map<int, int64_t>& ObjectiveMap() const {
356 return objective_map_;
357 }
359 return objective_domain_is_constraining_;
360 }
361
362 // Advanced usage. This should be called when a variable can be removed from
363 // the problem, so we don't count it as part of an affine relation anymore.
366
367 // Variable <-> constraint graph.
368 // The vector list is sorted and contains unique elements.
369 //
370 // Important: To properly handle the objective, var_to_constraints[objective]
371 // contains -1 so that if the objective appear in only one constraint, the
372 // constraint cannot be simplified.
373 const std::vector<int>& ConstraintToVars(int c) const {
375 return constraint_to_vars_[c];
376 }
377 const absl::flat_hash_set<int>& VarToConstraints(int var) const {
379 return var_to_constraints_[var];
380 }
381 int IntervalUsage(int c) const {
383 return interval_usage_[c];
384 }
385
386 // Checks if a constraint contains an enforcement literal set to false,
387 // or if it has been cleared.
388 bool ConstraintIsInactive(int ct_index) const;
389
390 // Checks if a constraint contains an enforcement literal not fixed, and
391 // no enforcement literals set to false.
392 bool ConstraintIsOptional(int ct_ref) const;
393
394 // Make sure we never delete an "assumption" literal by using a special
395 // constraint for that.
397 for (const int ref : working_model->assumptions()) {
398 var_to_constraints_[PositiveRef(ref)].insert(kAssumptionsConstraint);
399 }
400 }
401
402 // The "expansion" phase should be done once and allow to transform complex
403 // constraints into basic ones (see cp_model_expand.h). Some presolve rules
404 // need to know if the expansion was ran before beeing applied.
405 bool ModelIsExpanded() const { return model_is_expanded_; }
406 void NotifyThatModelIsExpanded() { model_is_expanded_ = true; }
407
408 // The following helper adds the following constraint:
409 // result <=> (time_i <= time_j && active_i is true && active_j is true)
410 // and returns the (cached) literal result.
411 //
412 // Note that this cache should just be used temporarily and then cleared
413 // with ClearPrecedenceCache() because there is no mechanism to update the
414 // cached literals when literal equivalence are detected.
415 int GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, int active_i,
416 int active_j);
417
418 // Clear the precedence cache.
420
421 // Logs stats to the logger.
422 void LogInfo();
423
424 SolverLogger* logger() const { return logger_; }
425 const SatParameters& params() const { return params_; }
426 TimeLimit* time_limit() { return time_limit_; }
427 ModelRandomGenerator* random() { return random_; }
428
429 // For each variables, list the constraints that just enforce a lower bound
430 // (resp. upper bound) on that variable. If all the constraints in which a
431 // variable appear are in the same direction, then we can usually fix a
432 // variable to one of its bound (modulo its cost).
433 //
434 // TODO(user): Keeping these extra vector of hash_set seems inefficient. Come
435 // up with a better way to detect if a variable is only constrainted in one
436 // direction.
437 std::vector<absl::flat_hash_set<int>> var_to_ub_only_constraints;
438 std::vector<absl::flat_hash_set<int>> var_to_lb_only_constraints;
439
442
443 // Indicate if we are allowed to remove irrelevant feasible solution from the
444 // set of feasible solution. For example, if a variable is unused, can we fix
445 // it to an arbitrary value (or its mimimum objective one)? This must be true
446 // if the client wants to enumerate all solutions or wants correct tightened
447 // bounds in the response.
449
450 // Number of "rules" applied. This should be equal to the sum of all numbers
451 // in stats_by_rule_name. This is used to decide if we should do one more pass
452 // of the presolve or not. Note that depending on the presolve transformation,
453 // a rule can correspond to a tiny change or a big change. Because of that,
454 // this isn't a perfect proxy for the efficacy of the presolve.
456
457 // Temporary storage.
458 std::vector<int> tmp_literals;
459 std::vector<Domain> tmp_term_domains;
460 std::vector<Domain> tmp_left_domains;
461 absl::flat_hash_set<int> tmp_literal_set;
462
463 // Each time a domain is modified this is set to true.
465
466 // Advanced presolve. See this class comment.
468
469 private:
470 // Helper to add an affine relation x = c.y + o to the given repository.
471 bool AddRelation(int x, int y, int64_t c, int64_t o, AffineRelation* repo);
472
473 void AddVariableUsage(int c);
474 void UpdateLinear1Usage(const ConstraintProto& ct, int c);
475
476 // Returns true iff the variable is not the representative of an equivalence
477 // class of size at least 2.
478 bool VariableIsNotRepresentativeOfEquivalenceClass(int var) const;
479
480 // Process encoding_remap_queue_ and updates the encoding maps. This could
481 // lead to UNSAT being detected, in which case it will return false.
482 bool RemapEncodingMaps();
483
484 // Makes sure we only insert encoding about the current representative.
485 //
486 // Returns false if ref cannot take the given value (it might not have been
487 // propagated yet).
488 bool CanonicalizeEncoding(int* ref, int64_t* value);
489
490 // Inserts an half reified var value encoding (literal => var ==/!= value).
491 // It returns true if the new state is different from the old state.
492 // Not that if imply_eq is false, the literal will be stored in its negated
493 // form.
494 //
495 // Thus, if you detect literal <=> var == value, then two calls must be made:
496 // InsertHalfVarValueEncoding(literal, var, value, true);
497 // InsertHalfVarValueEncoding(NegatedRef(literal), var, value, false);
498 bool InsertHalfVarValueEncoding(int literal, int var, int64_t value,
499 bool imply_eq);
500
501 // Insert fully reified var-value encoding.
502 void InsertVarValueEncodingInternal(int literal, int var, int64_t value,
503 bool add_constraints);
504
505 SolverLogger* logger_;
506 const SatParameters& params_;
507 TimeLimit* time_limit_;
508 ModelRandomGenerator* random_;
509
510 // Initially false, and set to true on the first inconsistency.
511 bool is_unsat_ = false;
512
513 // The current domain of each variables.
514 std::vector<Domain> domains;
515
516 // Internal representation of the objective. During presolve, we first load
517 // the objective in this format in order to have more efficient substitution
518 // on large problems (also because the objective is often dense). At the end
519 // we re-convert it to its proto form.
520 absl::flat_hash_map<int, int64_t> objective_map_;
521 int64_t objective_overflow_detection_;
522 std::vector<std::pair<int, int64_t>> tmp_entries_;
523 bool objective_domain_is_constraining_ = false;
524 Domain objective_domain_;
525 double objective_offset_;
526 double objective_scaling_factor_;
527
528 // Constraints <-> Variables graph.
529 std::vector<std::vector<int>> constraint_to_vars_;
530 std::vector<absl::flat_hash_set<int>> var_to_constraints_;
531
532 // Number of constraints of the form [lit =>] var in domain.
533 std::vector<int> constraint_to_linear1_var_;
534 std::vector<int> var_to_num_linear1_;
535
536 // We maintain how many time each interval is used.
537 std::vector<std::vector<int>> constraint_to_intervals_;
538 std::vector<int> interval_usage_;
539
540 // Contains abs relation (key = abs(saved_variable)).
541 absl::flat_hash_map<int, SavedVariable> abs_relations_;
542
543 // For each constant variable appearing in the model, we maintain a reference
544 // variable with the same constant value. If two variables end up having the
545 // same fixed value, then we can detect it using this and add a new
546 // equivalence relation. See ExploitFixedDomain().
547 absl::flat_hash_map<int64_t, SavedVariable> constant_to_ref_;
548
549 // When a "representative" gets a new representative, it should be enqueued
550 // here so that we can lazily update the *encoding_ maps below.
551 std::deque<int> encoding_remap_queue_;
552
553 // Contains variables with some encoded value: encoding_[i][v] points
554 // to the literal attached to the value v of the variable i.
555 absl::flat_hash_map<int, absl::flat_hash_map<int64_t, SavedLiteral>>
556 encoding_;
557
558 // Contains the currently collected half value encodings:
559 // i.e.: literal => var ==/!= value
560 // The state is accumulated (adding x => var == value then !x => var != value)
561 // will deduce that x equivalent to var == value.
562 absl::flat_hash_map<int,
563 absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>>
564 eq_half_encoding_;
565 absl::flat_hash_map<int,
566 absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>>
567 neq_half_encoding_;
568
569 // This regroups all the affine relations between variables. Note that the
570 // constraints used to detect such relations will not be removed from the
571 // model at detection time (thus allowing proper domain propagation). However,
572 // if the arity of a variable becomes one, then such constraint will be
573 // removed.
574 AffineRelation affine_relations_;
575 AffineRelation var_equiv_relations_;
576
577 std::vector<int> tmp_new_usage_;
578
579 // Used by SetVariableAsRemoved() and VariableWasRemoved().
580 absl::flat_hash_set<int> removed_variables_;
581
582 // Cache for the reified precedence literals created during the expansion of
583 // the reservoir constraint. This cache is only valid during the expansion
584 // phase, and is cleared afterwards.
585 absl::flat_hash_map<std::tuple<int, int, int, int>, int>
586 reified_precedences_cache_;
587
588 // Just used to display statistics on the presolve rules that were used.
589 absl::flat_hash_map<std::string, int> stats_by_rule_name_;
590
591 bool model_is_expanded_ = false;
592};
593
594} // namespace sat
595} // namespace operations_research
596
597#endif // OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_
#define DCHECK(condition)
Definition: base/logging.h:885
#define VLOG(verboselevel)
Definition: base/logging.h:979
We call domain any subset of Int64 = [kint64min, kint64max].
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
::PROTOBUF_NAMESPACE_ID::int32 assumptions(int index) const
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
bool StoreAbsRelation(int target_ref, int ref)
const absl::flat_hash_set< int > & VarToConstraints(int var) const
PresolveContext(Model *model, CpModelProto *cp_model, CpModelProto *mapping)
void AddToObjective(int var, int64_t value)
ABSL_MUST_USE_RESULT bool IntersectDomainWith(int ref, const Domain &domain, bool *domain_modified=nullptr)
std::vector< absl::flat_hash_set< int > > var_to_lb_only_constraints
bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value)
bool DomainOfVarIsIncludedIn(int var, const Domain &domain)
bool VariableWithCostIsUniqueAndRemovable(int ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit)
bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset)
std::vector< absl::flat_hash_set< int > > var_to_ub_only_constraints
ABSL_MUST_USE_RESULT bool SubstituteVariableInObjective(int var_in_equality, int64_t coeff_in_equality, const ConstraintProto &equality, std::vector< int > *new_vars_in_objective=nullptr)
int GetOrCreateVarValueEncoding(int ref, int64_t value)
ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(const std::string &message="")
std::string AffineRelationDebugString(int ref) const
bool InsertVarValueEncoding(int literal, int ref, int64_t value)
const std::vector< int > & ConstraintToVars(int c) const
const absl::flat_hash_map< int, int64_t > & ObjectiveMap() const
void StoreBooleanEqualityRelation(int ref_a, int ref_b)
bool HasVarValueEncoding(int ref, int64_t value, int *literal=nullptr)
bool DomainContains(int ref, int64_t value) const
void UpdateRuleStats(const std::string &name, int num_times=1)
ABSL_MUST_USE_RESULT bool CanonicalizeObjective()
AffineRelation::Relation GetAffineRelation(int ref) const
std::string IntervalDebugString(int ct_ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit)
int LiteralForExpressionMax(const LinearExpressionProto &expr) const
int GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, int active_i, int active_j)
const SatParameters & params() const
bool ExpressionIsAffineBoolean(const LinearExpressionProto &expr) const
bool ExploitExactlyOneInObjective(absl::Span< const int > exactly_one)
Domain DomainSuperSetOf(const LinearExpressionProto &expr) const
absl::flat_hash_set< int > tmp_literal_set
void AddImplyInDomain(int b, int x, const Domain &domain)
bool VariableIsOnlyUsedInEncodingAndMaybeInObjective(int ref) const
bool GetAbsRelation(int target_ref, int *ref)
bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value)
int Get(PresolveContext *context) const
int Get(PresolveContext *context) const
int64_t b
int64_t a
const std::string name
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
GurobiMPCallbackContext * context
constexpr int kAffineRelationConstraint
constexpr int kAssumptionsConstraint
constexpr int kObjectiveConstraint
Collection of objects used to extend the Constraint Solver library.
Literal literal
Definition: optimization.cc:85
std::string message
Definition: trace.cc:398