Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
integer.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 OR_TOOLS_SAT_INTEGER_H_
15#define OR_TOOLS_SAT_INTEGER_H_
16
17#include <stdlib.h>
18
19#include <algorithm>
20#include <cstdint>
21#include <deque>
22#include <functional>
23#include <limits>
24#include <string>
25#include <utility>
26#include <vector>
27
28#include "absl/base/attributes.h"
29#include "absl/container/btree_map.h"
30#include "absl/container/flat_hash_map.h"
31#include "absl/container/inlined_vector.h"
32#include "absl/log/check.h"
33#include "absl/strings/str_cat.h"
34#include "absl/types/span.h"
38#include "ortools/sat/model.h"
40#include "ortools/sat/sat_parameters.pb.h"
42#include "ortools/util/bitset.h"
43#include "ortools/util/rev.h"
47
48namespace operations_research {
49namespace sat {
50
51using InlinedIntegerLiteralVector = absl::InlinedVector<IntegerLiteral, 2>;
53 absl::InlinedVector<std::pair<IntegerVariable, IntegerValue>, 2>;
54
57 IntegerValue left_value;
58 IntegerValue right_value;
59
60 // Used for testing.
61 bool operator==(const LiteralValueValue& rhs) const {
62 return literal.Index() == rhs.literal.Index() &&
64 }
65
66 std::string DebugString() const {
67 return absl::StrCat("(lit(", literal.Index().value(), ") * ",
68 left_value.value(), " * ", right_value.value(), ")");
69 }
70};
71
72// Sometimes we propagate fact with no reason at a positive level, those
73// will automatically be fixed on the next restart.
74//
75// TODO(user): If we change the logic to not restart right away, we probably
76// need to remove duplicates bounds for the same variable.
78 std::vector<Literal> literal_to_fix;
79 std::vector<IntegerLiteral> integer_literal_to_fix;
80};
81
82// Each integer variable x will be associated with a set of literals encoding
83// (x >= v) for some values of v. This class maintains the relationship between
84// the integer variables and such literals which can be created by a call to
85// CreateAssociatedLiteral().
86//
87// The advantage of creating such Boolean variables is that the SatSolver which
88// is driving the search can then take this variable as a decision and maintain
89// these variables activity and so on. These variables can also be propagated
90// directly by the learned clauses.
91//
92// This class also support a non-lazy full domain encoding which will create one
93// literal per possible value in the domain. See FullyEncodeVariable(). This is
94// meant to be called by constraints that directly work on the variable values
95// like a table constraint or an all-diff constraint.
96//
97// TODO(user): We could also lazily create precedences Booleans between two
98// arbitrary IntegerVariable. This is better done in the PrecedencesPropagator
99// though.
101 public:
102 explicit IntegerEncoder(Model* model)
103 : sat_solver_(model->GetOrCreate<SatSolver>()),
104 trail_(model->GetOrCreate<Trail>()),
105 delayed_to_fix_(model->GetOrCreate<DelayedRootLevelDeduction>()),
106 domains_(*model->GetOrCreate<IntegerDomains>()),
107 num_created_variables_(0) {}
108
109 // This type is neither copyable nor movable.
112
114 VLOG(1) << "#variables created = " << num_created_variables_;
115 }
116
117 // Memory optimization: you can call this before encoding variables.
118 void ReserveSpaceForNumVariables(int num_vars);
119
120 // Fully encode a variable using its current initial domain.
121 // If the variable is already fully encoded, this does nothing.
122 //
123 // This creates new Booleans variables as needed:
124 // 1) num_values for the literals X == value. Except when there is just
125 // two value in which case only one variable is created.
126 // 2) num_values - 3 for the literals X >= value or X <= value (using their
127 // negation). The -3 comes from the fact that we can reuse the equality
128 // literals for the two extreme points.
129 //
130 // The encoding for NegationOf(var) is automatically created too. It reuses
131 // the same Boolean variable as the encoding of var.
132 //
133 // TODO(user): It is currently only possible to call that at the decision
134 // level zero because we cannot add ternary clause in the middle of the
135 // search (for now). This is Checked.
136 void FullyEncodeVariable(IntegerVariable var);
137
138 // Returns true if we know that PartialDomainEncoding(var) span the full
139 // domain of var. This is always true if FullyEncodeVariable(var) has been
140 // called.
141 bool VariableIsFullyEncoded(IntegerVariable var) const;
142
143 // Returns the list of literal <=> var == value currently associated to the
144 // given variable. The result is sorted by value. We filter literal at false,
145 // and if a literal is true, then you will get a singleton. To be sure to get
146 // the full set of encoded value, then you should call this at level zero.
147 //
148 // The FullDomainEncoding() just check VariableIsFullyEncoded() and returns
149 // the same result.
150 //
151 // WARNING: The reference returned is only valid until the next call to one
152 // of these functions.
153 const std::vector<ValueLiteralPair>& FullDomainEncoding(
154 IntegerVariable var) const;
155 const std::vector<ValueLiteralPair>& PartialDomainEncoding(
156 IntegerVariable var) const;
157
158 // Returns the "canonical" (i_lit, negation of i_lit) pair. This mainly
159 // deal with domain with initial hole like [1,2][5,6] so that if one ask
160 // for x <= 3, this get canonicalized in the pair (x <= 2, x >= 5).
161 //
162 // Note that it is an error to call this with a literal that is trivially true
163 // or trivially false according to the initial variable domain. This is
164 // CHECKed to make sure we don't create wasteful literal.
165 //
166 // TODO(user): This is linear in the domain "complexity", we can do better if
167 // needed.
168 std::pair<IntegerLiteral, IntegerLiteral> Canonicalize(
169 IntegerLiteral i_lit) const;
170
171 // Returns, after creating it if needed, a Boolean literal such that:
172 // - if true, then the IntegerLiteral is true.
173 // - if false, then the negated IntegerLiteral is true.
174 //
175 // Note that this "canonicalize" the given literal first.
176 //
177 // This add the proper implications with the two "neighbor" literals of this
178 // one if they exist. This is the "list encoding" in: Thibaut Feydy, Peter J.
179 // Stuckey, "Lazy Clause Generation Reengineered", CP 2009.
182 IntegerValue value);
183
184 // Associates the Boolean literal to (X >= bound) or (X == value). If a
185 // literal was already associated to this fact, this will add an equality
186 // constraints between both literals. If the fact is trivially true or false,
187 // this will fix the given literal.
189 void AssociateToIntegerEqualValue(Literal literal, IntegerVariable var,
190 IntegerValue value);
191
192 // Returns kNoLiteralIndex if there is no associated or the associated literal
193 // otherwise.
194 //
195 // Tricky: for domain with hole, like [0,1][5,6], we assume some equivalence
196 // classes, like >=2, >=3, >=4 are all the same as >= 5.
198 LiteralIndex GetAssociatedLiteral(IntegerLiteral i_lit) const;
199 LiteralIndex GetAssociatedEqualityLiteral(IntegerVariable var,
200 IntegerValue value) const;
201
202 // Advanced usage. It is more efficient to create the associated literals in
203 // order, but it might be anoying to do so. Instead, you can first call
204 // DisableImplicationBetweenLiteral() and when you are done creating all the
205 // associated literals, you can call (only at level zero)
206 // AddAllImplicationsBetweenAssociatedLiterals() which will also turn back on
207 // the implications between literals for the one that will be added
208 // afterwards.
209 void DisableImplicationBetweenLiteral() { add_implications_ = false; }
211
212 // Returns the IntegerLiterals that were associated with the given Literal.
214 if (lit.Index() >= reverse_encoding_.size()) {
215 return empty_integer_literal_vector_;
216 }
217 return reverse_encoding_[lit];
218 }
219
220 // Returns the variable == value pairs that were associated with the given
221 // Literal. Note that only positive IntegerVariable appears here.
223 if (lit.Index() >= reverse_equality_encoding_.size()) {
224 return empty_integer_value_vector_;
225 }
226 return reverse_equality_encoding_[lit];
227 }
228
229 // Returns all the variables for which this literal is associated to either
230 // var >= value or var == value.
231 const std::vector<IntegerVariable>& GetAllAssociatedVariables(
232 Literal lit) const {
233 temp_associated_vars_.clear();
234 for (const IntegerLiteral l : GetIntegerLiterals(lit)) {
235 temp_associated_vars_.push_back(l.var);
236 }
237 for (const auto& [var, value] : GetEqualityLiterals(lit)) {
238 temp_associated_vars_.push_back(var);
239 }
240 return temp_associated_vars_;
241 }
242
243 // If it exists, returns a [0,1] integer variable which is equal to 1 iff the
244 // given literal is true. Returns kNoIntegerVariable if such variable does not
245 // exist. Note that one can create one by creating a new IntegerVariable and
246 // calling AssociateToIntegerEqualValue().
247 IntegerVariable GetLiteralView(Literal lit) const {
248 if (lit.Index() >= literal_view_.size()) return kNoIntegerVariable;
249 return literal_view_[lit];
250 }
251
252 // If this is true, then a literal can be linearized with an affine expression
253 // involving an integer variable.
254 ABSL_MUST_USE_RESULT bool LiteralOrNegationHasView(
255 Literal lit, IntegerVariable* view = nullptr,
256 bool* view_is_direct = nullptr) const;
257
258 // Returns a Boolean literal associated with a bound lower than or equal to
259 // the one of the given IntegerLiteral. If the given IntegerLiteral is true,
260 // then the returned literal should be true too. Returns kNoLiteralIndex if no
261 // such literal was created.
262 //
263 // Ex: if 'i' is (x >= 4) and we already created a literal associated to
264 // (x >= 2) but not to (x >= 3), we will return the literal associated with
265 // (x >= 2).
267 IntegerValue* bound) const;
268
269 // Gets the literal always set to true, make it if it does not exist.
271 if (literal_index_true_ == kNoLiteralIndex) {
272 DCHECK_EQ(0, sat_solver_->CurrentDecisionLevel());
273 const Literal literal_true =
274 Literal(sat_solver_->NewBooleanVariable(), true);
275 literal_index_true_ = literal_true.Index();
276
277 // This might return false if we are already UNSAT.
278 // TODO(user): Make sure we abort right away on unsat!
279 (void)sat_solver_->AddUnitClause(literal_true);
280 }
281 return Literal(literal_index_true_);
282 }
284
285 // Returns the set of Literal associated to IntegerLiteral of the form var >=
286 // value. We make a copy, because this can be easily invalidated when calling
287 // any function of this class. So it is less efficient but safer.
288 std::vector<ValueLiteralPair> PartialGreaterThanEncoding(
289 IntegerVariable var) const;
290
291 // Makes sure all element in the >= encoding are non-trivial and canonical.
292 // The input variable must be positive.
293 bool UpdateEncodingOnInitialDomainChange(IntegerVariable var, Domain domain);
294
295 private:
296 // Adds the implications:
297 // Literal(before) <= associated_lit <= Literal(after).
298 // Arguments:
299 // - map is just encoding_by_var_[associated_lit.var] and is passed as a
300 // slight optimization.
301 // - 'it' is the current position of associated_lit in map, i.e. we must have
302 // it->second == associated_lit.
303 void AddImplications(
304 const absl::btree_map<IntegerValue, Literal>& map,
305 absl::btree_map<IntegerValue, Literal>::const_iterator it,
306 Literal associated_lit);
307
308 SatSolver* sat_solver_;
309 Trail* trail_;
310 DelayedRootLevelDeduction* delayed_to_fix_;
311 const IntegerDomains& domains_;
312
313 bool add_implications_ = true;
314 int64_t num_created_variables_ = 0;
315
316 // We keep all the literals associated to an Integer variable in a map ordered
317 // by bound (so we can properly add implications between the literals
318 // corresponding to the same variable).
319 //
320 // Note that we only keep this for positive variable.
321 // The one for the negation can be infered by it.
322 //
323 // Like x >= 1 x >= 4 x >= 5
324 // Correspond to x <= 0 x <= 3 x <= 4
325 // That is -x >= 0 -x >= -2 -x >= -4
326 //
327 // With potentially stronger <= bound if we fall into domain holes.
328 //
329 // TODO(user): Remove the entry no longer needed because of level zero
330 // propagations.
331 util_intops::StrongVector<PositiveOnlyIndex,
332 absl::btree_map<IntegerValue, Literal>>
333 encoding_by_var_;
334
335 // Store for a given LiteralIndex the list of its associated IntegerLiterals.
336 const InlinedIntegerLiteralVector empty_integer_literal_vector_;
338 reverse_encoding_;
339 const InlinedIntegerValueVector empty_integer_value_vector_;
341 reverse_equality_encoding_;
342
343 // Used by GetAllAssociatedVariables().
344 mutable std::vector<IntegerVariable> temp_associated_vars_;
345
346 // Store for a given LiteralIndex its IntegerVariable view or kNoLiteralIndex
347 // if there is none.
349
350 // Mapping (variable == value) -> associated literal. Note that even if
351 // there is more than one literal associated to the same fact, we just keep
352 // the first one that was added.
353 //
354 // Note that we only keep positive IntegerVariable here to reduce memory
355 // usage.
356 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>, Literal>
357 equality_to_associated_literal_;
358
359 // Mutable because this is lazily cleaned-up by PartialDomainEncoding().
360 mutable util_intops::StrongVector<PositiveOnlyIndex,
361 absl::InlinedVector<ValueLiteralPair, 2>>
362 equality_by_var_;
363
364 // Variables that are fully encoded.
366
367 // A literal that is always true, convenient to encode trivial domains.
368 // This will be lazily created when needed.
369 LiteralIndex literal_index_true_ = kNoLiteralIndex;
370
371 // Temporary memory used by FullyEncodeVariable().
372 std::vector<IntegerValue> tmp_values_;
373 std::vector<ValueLiteralPair> tmp_encoding_;
374
375 // Temporary memory for the result of PartialDomainEncoding().
376 mutable std::vector<ValueLiteralPair> partial_encoding_;
377};
378
380 public:
382 virtual ~LazyReasonInterface() = default;
383
384 // When called, this must fill the two vectors so that literals contains any
385 // Literal part of the reason and dependencies contains the trail index of any
386 // IntegerLiteral that is also part of the reason.
387 //
388 // Remark: integer_literal[trail_index] might not exist or has nothing to
389 // do with what was propagated.
390 //
391 // TODO(user): {id, propagation_slack, var_to_explain, trail_index} is just a
392 // generic "payload" and we should probably rename it as such so that each
393 // implementation can store different things.
394 virtual void Explain(int id, IntegerValue propagation_slack,
395 IntegerVariable var_to_explain, int trail_index,
396 std::vector<Literal>* literals_reason,
397 std::vector<int>* trail_indices_reason) = 0;
398};
399
400// This class maintains a set of integer variables with their current bounds.
401// Bounds can be propagated from an external "source" and this class helps
402// to maintain the reason for each propagation.
403class IntegerTrail final : public SatPropagator {
404 public:
405 explicit IntegerTrail(Model* model)
406 : SatPropagator("IntegerTrail"),
407 delayed_to_fix_(model->GetOrCreate<DelayedRootLevelDeduction>()),
408 domains_(model->GetOrCreate<IntegerDomains>()),
409 encoder_(model->GetOrCreate<IntegerEncoder>()),
410 trail_(model->GetOrCreate<Trail>()),
411 sat_solver_(model->GetOrCreate<SatSolver>()),
412 time_limit_(model->GetOrCreate<TimeLimit>()),
413 parameters_(*model->GetOrCreate<SatParameters>()) {
414 model->GetOrCreate<SatSolver>()->AddPropagator(this);
415 }
416
417 // This type is neither copyable nor movable.
418 IntegerTrail(const IntegerTrail&) = delete;
420 ~IntegerTrail() final;
421
422 // SatPropagator interface. These functions make sure the current bounds
423 // information is in sync with the current solver literal trail. Any
424 // class/propagator using this class must make sure it is synced to the
425 // correct state before calling any of its functions.
426 bool Propagate(Trail* trail) final;
427 void Untrail(const Trail& trail, int literal_trail_index) final;
428 absl::Span<const Literal> Reason(const Trail& trail, int trail_index,
429 int64_t conflict_id) const final;
430
431 // Returns the number of created integer variables.
432 //
433 // Note that this is twice the number of call to AddIntegerVariable() since
434 // we automatically create the NegationOf() variable too.
435 IntegerVariable NumIntegerVariables() const {
436 return IntegerVariable(var_lbs_.size());
437 }
438
439 // Optimization: you can call this before calling AddIntegerVariable()
440 // num_vars time.
441 void ReserveSpaceForNumVariables(int num_vars);
442
443 // Adds a new integer variable. Adding integer variable can only be done when
444 // the decision level is zero (checked). The given bounds are INCLUSIVE and
445 // must not cross.
446 //
447 // Note on integer overflow: 'upper_bound - lower_bound' must fit on an
448 // int64_t, this is DCHECKed. More generally, depending on the constraints
449 // that are added, the bounds magnitude must be small enough to satisfy each
450 // constraint overflow precondition.
451 IntegerVariable AddIntegerVariable(IntegerValue lower_bound,
452 IntegerValue upper_bound);
453
454 // Same as above but for a more complex domain specified as a sorted list of
455 // disjoint intervals. See the Domain class.
456 IntegerVariable AddIntegerVariable(const Domain& domain);
457
458 // Returns the initial domain of the given variable. Note that the min/max
459 // are updated with level zero propagation, but not holes.
460 const Domain& InitialVariableDomain(IntegerVariable var) const;
461
462 // Takes the intersection with the current initial variable domain.
463 //
464 // TODO(user): There is some memory inefficiency if this is called many time
465 // because of the underlying data structure we use. In practice, when used
466 // with a presolve, this is not often used, so that is fine though.
467 bool UpdateInitialDomain(IntegerVariable var, Domain domain);
468
469 // Same as AddIntegerVariable(value, value), but this is a bit more efficient
470 // because it reuses another constant with the same value if its exist.
471 //
472 // Note(user): Creating constant integer variable is a bit wasteful, but not
473 // that much, and it allows to simplify a lot of constraints that do not need
474 // to handle this case any differently than the general one. Maybe there is a
475 // better solution, but this is not really high priority as of December 2016.
476 IntegerVariable GetOrCreateConstantIntegerVariable(IntegerValue value);
477 int NumConstantVariables() const;
478
479 // Same as AddIntegerVariable() but uses the maximum possible range. Note
480 // that since we take negation of bounds in various places, we make sure that
481 // we don't have overflow when we take the negation of the lower bound or of
482 // the upper bound.
486
487 // Returns the current lower/upper bound of the given integer variable.
488 IntegerValue LowerBound(IntegerVariable i) const;
489 IntegerValue UpperBound(IntegerVariable i) const;
490
491 // If one needs to do a lot of LowerBound()/UpperBound() it will be faster
492 // to cache the current pointer to the underlying vector.
493 const IntegerValue* LowerBoundsData() const { return var_lbs_.data(); }
494
495 // Checks if the variable is fixed.
496 bool IsFixed(IntegerVariable i) const;
497
498 // Checks that the variable is fixed and returns its value.
499 IntegerValue FixedValue(IntegerVariable i) const;
500
501 // Same as above for an affine expression.
502 IntegerValue LowerBound(AffineExpression expr) const;
503 IntegerValue UpperBound(AffineExpression expr) const;
504 bool IsFixed(AffineExpression expr) const;
505 IntegerValue FixedValue(AffineExpression expr) const;
506
507 // Returns the integer literal that represent the current lower/upper bound of
508 // the given integer variable.
509 IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const;
510 IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const;
511
512 // Returns the integer literal that represent the current lower/upper bound of
513 // the given affine expression. In case the expression is constant, it returns
514 // IntegerLiteral::TrueLiteral().
517
518 // Returns the current value (if known) of an IntegerLiteral.
521
522 // Returns globally valid lower/upper bound on the given integer variable.
523 IntegerValue LevelZeroLowerBound(IntegerVariable var) const;
524 IntegerValue LevelZeroUpperBound(IntegerVariable var) const;
525
526 // Returns globally valid lower/upper bound on the given affine expression.
527 IntegerValue LevelZeroLowerBound(AffineExpression exp) const;
528 IntegerValue LevelZeroUpperBound(AffineExpression exp) const;
529
530 // Returns true if the variable is fixed at level 0.
531 bool IsFixedAtLevelZero(IntegerVariable var) const;
532
533 // Returns true if the affine expression is fixed at level 0.
534 bool IsFixedAtLevelZero(AffineExpression expr) const;
535
536 // Advanced usage.
537 // Returns the current lower bound assuming the literal is true.
538 IntegerValue ConditionalLowerBound(Literal l, IntegerVariable i) const;
539 IntegerValue ConditionalLowerBound(Literal l, AffineExpression expr) const;
540
541 // Returns the current upper bound assuming the literal is true.
542 IntegerValue ConditionalUpperBound(Literal l, IntegerVariable i) const;
543 IntegerValue ConditionalUpperBound(Literal l, AffineExpression expr) const;
544
545 // Advanced usage. Given the reason for
546 // (Sum_i coeffs[i] * reason[i].var >= current_lb) initially in reason,
547 // this function relaxes the reason given that we only need the explanation of
548 // (Sum_i coeffs[i] * reason[i].var >= current_lb - slack).
549 //
550 // Preconditions:
551 // - coeffs must be of same size as reason, and all entry must be positive.
552 // - *reason must initially contains the trivial initial reason, that is
553 // the current lower-bound of each variables.
554 //
555 // TODO(user): Requiring all initial literal to be at their current bound is
556 // not really clean. Maybe we can change the API to only take IntegerVariable
557 // and produce the reason directly.
558 //
559 // TODO(user): change API so that this work is performed during the conflict
560 // analysis where we can be smarter in how we relax the reason. Note however
561 // that this function is mainly used when we have a conflict, so this is not
562 // really high priority.
563 //
564 // TODO(user): Test that the code work in the presence of integer overflow.
565 void RelaxLinearReason(IntegerValue slack,
566 absl::Span<const IntegerValue> coeffs,
567 std::vector<IntegerLiteral>* reason) const;
568
569 // Same as above but take in IntegerVariables instead of IntegerLiterals.
570 void AppendRelaxedLinearReason(IntegerValue slack,
571 absl::Span<const IntegerValue> coeffs,
572 absl::Span<const IntegerVariable> vars,
573 std::vector<IntegerLiteral>* reason) const;
574
575 // Same as above but relax the given trail indices.
576 void RelaxLinearReason(IntegerValue slack,
577 absl::Span<const IntegerValue> coeffs,
578 std::vector<int>* trail_indices) const;
579
580 // Removes from the reasons the literal that are always true.
581 // This is mainly useful for experiments/testing.
582 void RemoveLevelZeroBounds(std::vector<IntegerLiteral>* reason) const;
583
584 // Enqueue new information about a variable bound. Calling this with a less
585 // restrictive bound than the current one will have no effect.
586 //
587 // The reason for this "assignment" must be provided as:
588 // - A set of Literal currently being all false.
589 // - A set of IntegerLiteral currently being all true.
590 //
591 // IMPORTANT: Notice the inversed sign in the literal reason. This is a bit
592 // confusing but internally SAT use this direction for efficiency.
593 //
594 // Note(user): Duplicates Literal/IntegerLiteral are supported because we call
595 // STLSortAndRemoveDuplicates() in MergeReasonInto(), but maybe they shouldn't
596 // for efficiency reason.
597 //
598 // TODO(user): If the given bound is equal to the current bound, maybe the new
599 // reason is better? how to decide and what to do in this case? to think about
600 // it. Currently we simply don't do anything.
601 ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit) {
602 return EnqueueInternal(i_lit, false, {}, {}, integer_trail_.size());
603 }
604 ABSL_MUST_USE_RESULT bool Enqueue(
605 IntegerLiteral i_lit, absl::Span<const Literal> literal_reason,
606 absl::Span<const IntegerLiteral> integer_reason) {
607 return EnqueueInternal(i_lit, false, literal_reason, integer_reason,
608 integer_trail_.size());
609 }
610
611 // Enqueue new information about a variable bound. It has the same behavior
612 // as the Enqueue() method, except that it accepts true and false integer
613 // literals, both for i_lit, and for the integer reason.
614 //
615 // This method will do nothing if i_lit is a true literal. It will report a
616 // conflict if i_lit is a false literal, and enqueue i_lit normally otherwise.
617 // Furthemore, it will check that the integer reason does not contain any
618 // false literals, and will remove true literals before calling
619 // ReportConflict() or Enqueue().
620 ABSL_MUST_USE_RESULT bool SafeEnqueue(
621 IntegerLiteral i_lit, absl::Span<const IntegerLiteral> integer_reason);
622
623 // Pushes the given integer literal assuming that the Boolean literal is true.
624 // This can do a few things:
625 // - If lit it true, add it to the reason and push the integer bound.
626 // - If the bound is infeasible, push lit to false.
627 // - If the underlying variable is optional and also controlled by lit, push
628 // the bound even if lit is not assigned.
629 ABSL_MUST_USE_RESULT bool ConditionalEnqueue(
630 Literal lit, IntegerLiteral i_lit, std::vector<Literal>* literal_reason,
631 std::vector<IntegerLiteral>* integer_reason);
632
633 // Same as Enqueue(), but takes an extra argument which if smaller than
634 // integer_trail_.size() is interpreted as the trail index of an old Enqueue()
635 // that had the same reason as this one. Note that the given Span must still
636 // be valid as they are used in case of conflict.
637 //
638 // TODO(user): This currently cannot refer to a trail_index with a lazy
639 // reason. Fix or at least check that this is the case.
640 ABSL_MUST_USE_RESULT bool Enqueue(
641 IntegerLiteral i_lit, absl::Span<const Literal> literal_reason,
642 absl::Span<const IntegerLiteral> integer_reason,
643 int trail_index_with_same_reason) {
644 return EnqueueInternal(i_lit, false, literal_reason, integer_reason,
645 trail_index_with_same_reason);
646 }
647
648 // Lazy reason API.
649 ABSL_MUST_USE_RESULT bool EnqueueWithLazyReason(
650 IntegerLiteral i_lit, int id, IntegerValue propagation_slack,
651 LazyReasonInterface* explainer) {
652 const int trail_index = integer_trail_.size();
653 lazy_reasons_.push_back(LazyReasonEntry{explainer, propagation_slack,
654 i_lit.var, id, trail_index});
655 return EnqueueInternal(i_lit, true, {}, {}, 0);
656 }
657
658 // Sometimes we infer some root level bounds but we are not at the root level.
659 // In this case, we will update the level-zero bounds right away, but will
660 // delay the current push until the next restart.
661 //
662 // Note that if you want to also push the literal at the current level, then
663 // just calling Enqueue() is enough. Since there is no reason, the literal
664 // will still be recorded properly.
665 ABSL_MUST_USE_RESULT bool RootLevelEnqueue(IntegerLiteral i_lit);
666
667 // Enqueues the given literal on the trail.
668 // See the comment of Enqueue() for the reason format.
669 void EnqueueLiteral(Literal literal, absl::Span<const Literal> literal_reason,
670 absl::Span<const IntegerLiteral> integer_reason);
671
672 // Returns the reason (as set of Literal currently false) for a given integer
673 // literal. Note that the bound must be less restrictive than the current
674 // bound (checked).
675 std::vector<Literal> ReasonFor(IntegerLiteral literal) const;
676
677 // Appends the reason for the given integer literals to the output and call
678 // STLSortAndRemoveDuplicates() on it. This function accept "constant"
679 // literal.
680 void MergeReasonInto(absl::Span<const IntegerLiteral> literals,
681 std::vector<Literal>* output) const;
682
683 // Returns the number of enqueues that changed a variable bounds. We don't
684 // count enqueues called with a less restrictive bound than the current one.
685 //
686 // Note(user): this can be used to see if any of the bounds changed. Just
687 // looking at the integer trail index is not enough because at level zero it
688 // doesn't change since we directly update the "fixed" bounds.
689 int64_t num_enqueues() const { return num_enqueues_; }
690 int64_t timestamp() const { return num_enqueues_ + num_untrails_; }
691
692 // Same as num_enqueues but only count the level zero changes.
693 int64_t num_level_zero_enqueues() const { return num_level_zero_enqueues_; }
694
695 // All the registered bitsets will be set to one each time a LbVar is
696 // modified. It is up to the client to clear it if it wants to be notified
697 // with the newly modified variables.
700 watchers_.push_back(p);
701 }
702
703 // Helper functions to report a conflict. Always return false so a client can
704 // simply do: return integer_trail_->ReportConflict(...);
705 bool ReportConflict(absl::Span<const Literal> literal_reason,
706 absl::Span<const IntegerLiteral> integer_reason) {
707 DCHECK(ReasonIsValid(literal_reason, integer_reason));
708 std::vector<Literal>* conflict = trail_->MutableConflict();
709 conflict->assign(literal_reason.begin(), literal_reason.end());
710 MergeReasonInto(integer_reason, conflict);
711 return false;
712 }
713 bool ReportConflict(absl::Span<const IntegerLiteral> integer_reason) {
714 DCHECK(ReasonIsValid({}, integer_reason));
715 std::vector<Literal>* conflict = trail_->MutableConflict();
716 conflict->clear();
717 MergeReasonInto(integer_reason, conflict);
718 return false;
719 }
720
721 // Returns true if the variable lower bound is still the one from level zero.
722 bool VariableLowerBoundIsFromLevelZero(IntegerVariable var) const {
723 return var_trail_index_[var] < var_lbs_.size();
724 }
725
726 // Registers a reversible class. This class will always be synced with the
727 // correct decision level.
729 reversible_classes_.push_back(rev);
730 }
731
732 int Index() const { return integer_trail_.size(); }
733
734 // Inspects the trail and output all the non-level zero bounds (one per
735 // variables) to the output. The algo is sparse if there is only a few
736 // propagations on the trail.
737 void AppendNewBounds(std::vector<IntegerLiteral>* output) const;
738
739 // Inspects the trail and output all the non-level zero bounds from the base
740 // index (one per variables) to the output. The algo is sparse if there is
741 // only a few propagations on the trail.
742 void AppendNewBoundsFrom(int base_index,
743 std::vector<IntegerLiteral>* output) const;
744
745 // Returns the trail index < threshold of a TrailEntry about var. Returns -1
746 // if there is no such entry (at a positive decision level). This is basically
747 // the trail index of the lower bound of var at the time.
748 //
749 // Important: We do some optimization internally, so this should only be
750 // used from within a LazyReasonFunction().
751 int FindTrailIndexOfVarBefore(IntegerVariable var, int threshold) const;
752
753 // Basic heuristic to detect when we are in a propagation loop, and suggest
754 // a good variable to branch on (taking the middle value) to get out of it.
755 bool InPropagationLoop() const;
757 IntegerVariable NextVariableToBranchOnInPropagationLoop() const;
758
759 // If we had an incomplete propagation, it is important to fix all the
760 // variables and not really on the propagation to do so. This is related to
761 // the InPropagationLoop() code above.
763 IntegerVariable FirstUnassignedVariable() const;
764
765 // Return true if we can fix new fact at level zero.
767 return !delayed_to_fix_->literal_to_fix.empty() ||
768 !delayed_to_fix_->integer_literal_to_fix.empty();
769 }
770
771 // If this is set, and in debug mode, we will call this on all conflict to
772 // be checked for potential issue. Usually against a known optimal solution.
774 std::function<bool(absl::Span<const Literal> clause,
775 absl::Span<const IntegerLiteral> integers)>
776 checker) {
777 debug_checker_ = std::move(checker);
778 }
779
780 // This is used by the GreaterThanAtLeastOneOf() lazy reason.
781 //
782 // TODO(user): This might better lives together with the propagation code,
783 // but it does need access to data about the reason/conflict being currently
784 // computed. Also for speed we do need all the code here in on block. Given
785 // than we have just a few "lazy integer reason", we might not really want a
786 // generic code in any case.
787 void AddAllGreaterThanConstantReason(absl::Span<AffineExpression> exprs,
788 IntegerValue target_min,
789 std::vector<int>* indices) const {
790 int64_t num_processed = 0;
791 for (const AffineExpression& expr : exprs) {
792 if (expr.IsConstant()) {
793 DCHECK_GE(expr.constant, target_min);
794 continue;
795 }
796 DCHECK_NE(expr.var, kNoIntegerVariable);
797
798 // On large routing problems, we can spend a lot of time in this loop.
799 // We check the time limit every 5 processed expressions.
800 if (++num_processed % 5 == 0 && time_limit_->LimitReached()) return;
801
802 // Skip if we already have an explanation for expr >= target_min. Note
803 // that we already do that while processing the returned indices, so this
804 // mainly save a FindLowestTrailIndexThatExplainBound() call per skipped
805 // indices, which can still be costly.
806 {
807 const int index = tmp_var_to_trail_index_in_queue_[expr.var];
808 if (index == std::numeric_limits<int>::max()) continue;
809 if (index > 0 &&
810 expr.ValueAt(integer_trail_[index].bound) >= target_min) {
811 has_dependency_ = true;
812 continue;
813 }
814 }
815
816 // We need to find the index that explain the bound.
817 // Note that this will skip if the condition is true at level zero.
818 const int index =
819 FindLowestTrailIndexThatExplainBound(expr.GreaterOrEqual(target_min));
820 if (index >= 0) {
821 indices->push_back(index);
822 }
823 }
824 }
825
826 private:
827 // Used for DHECKs to validate the reason given to the public functions above.
828 // Tests that all Literal are false. Tests that all IntegerLiteral are true.
829 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
830 absl::Span<const IntegerLiteral> integer_reason);
831
832 // Same as above, but with the literal for which this is the reason for.
833 bool ReasonIsValid(Literal lit, absl::Span<const Literal> literal_reason,
834 absl::Span<const IntegerLiteral> integer_reason);
835 bool ReasonIsValid(IntegerLiteral i_lit,
836 absl::Span<const Literal> literal_reason,
837 absl::Span<const IntegerLiteral> integer_reason);
838
839 // If the variable has holes in its domain, make sure the literal is
840 // canonicalized.
841 void CanonicalizeLiteralIfNeeded(IntegerLiteral* i_lit);
842
843 // Called by the Enqueue() functions that detected a conflict. This does some
844 // common conflict initialization that must terminate by a call to
845 // MergeReasonIntoInternal(conflict) where conflict is the returned vector.
846 std::vector<Literal>* InitializeConflict(
847 IntegerLiteral integer_literal, bool use_lazy_reason,
848 absl::Span<const Literal> literals_reason,
849 absl::Span<const IntegerLiteral> bounds_reason);
850
851 // Saves the given reason and return its index.
852 int AppendReasonToInternalBuffers(
853 absl::Span<const Literal> literal_reason,
854 absl::Span<const IntegerLiteral> integer_reason);
855
856 // Internal implementation of the different public Enqueue() functions.
857 ABSL_MUST_USE_RESULT bool EnqueueInternal(
858 IntegerLiteral i_lit, bool use_lazy_reason,
859 absl::Span<const Literal> literal_reason,
860 absl::Span<const IntegerLiteral> integer_reason,
861 int trail_index_with_same_reason);
862
863 // Internal implementation of the EnqueueLiteral() functions.
864 void EnqueueLiteralInternal(Literal literal, bool use_lazy_reason,
865 absl::Span<const Literal> literal_reason,
866 absl::Span<const IntegerLiteral> integer_reason);
867
868 // Same as EnqueueInternal() but for the case where we push an IntegerLiteral
869 // because an associated Literal is true (and we know it). In this case, we
870 // have less work to do, so this has the same effect but is faster.
871 ABSL_MUST_USE_RESULT bool EnqueueAssociatedIntegerLiteral(
872 IntegerLiteral i_lit, Literal literal_reason);
873
874 // Does the work of MergeReasonInto() when queue_ is already initialized.
875 void MergeReasonIntoInternal(std::vector<Literal>* output,
876 int64_t conflict_id) const;
877
878 // Returns the lowest trail index of a TrailEntry that can be used to explain
879 // the given IntegerLiteral. The literal must be currently true (CHECKed).
880 // Returns -1 if the explanation is trivial.
881 int FindLowestTrailIndexThatExplainBound(IntegerLiteral i_lit) const;
882
883 // This must be called before Dependencies() or AppendLiteralsReason().
884 //
885 // TODO(user): Not really robust, try to find a better way.
886 void ComputeLazyReasonIfNeeded(int reason_index) const;
887
888 // Helper function to return the "dependencies" of a bound assignment.
889 // All the TrailEntry at these indices are part of the reason for this
890 // assignment.
891 //
892 // Important: The returned Span is only valid up to the next call.
893 absl::Span<const int> Dependencies(int reason_index) const;
894
895 // Helper function to append the Literal part of the reason for this bound
896 // assignment. We use added_variables_ to not add the same literal twice.
897 // Note that looking at literal.Variable() is enough since all the literals
898 // of a reason must be false.
899 void AppendLiteralsReason(int reason_index,
900 std::vector<Literal>* output) const;
901
902 // Returns some debugging info.
903 std::string DebugString();
904
905 // Used internally to return the next conflict number.
906 int64_t NextConflictId();
907
908 // Information for each integer variable about its current lower bound and
909 // position of the last TrailEntry in the trail referring to this var.
912
913 // This is used by FindLowestTrailIndexThatExplainBound() and
914 // FindTrailIndexOfVarBefore() to speed up the lookup. It keeps a trail index
915 // for each variable that may or may not point to a TrailEntry regarding this
916 // variable. The validity of the index is verified before being used.
917 //
918 // The cache will only be updated with trail_index >= threshold.
919 mutable int var_trail_index_cache_threshold_ = 0;
921 var_trail_index_cache_;
922
923 // Used by GetOrCreateConstantIntegerVariable() to return already created
924 // constant variables that share the same value.
925 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
926
927 // The integer trail. It always start by num_vars sentinel values with the
928 // level 0 bounds (in one to one correspondence with var_lbs_).
929 struct TrailEntry {
930 IntegerValue bound;
931 IntegerVariable var;
932 int32_t prev_trail_index;
933
934 // Index in literals_reason_start_/bounds_reason_starts_ If this is negative
935 // then it is a lazy reason.
936 int32_t reason_index;
937 };
938 std::vector<TrailEntry> integer_trail_;
939
940 struct LazyReasonEntry {
941 LazyReasonInterface* explainer;
942 IntegerValue propagation_slack;
943 IntegerVariable var_to_explain;
944 int id;
945 int trail_index_at_propagation_time;
946
947 void Explain(std::vector<Literal>* literals,
948 std::vector<int>* dependencies) const {
949 explainer->Explain(id, propagation_slack, var_to_explain,
950 trail_index_at_propagation_time, literals,
951 dependencies);
952 }
953 };
954 std::vector<int> lazy_reason_decision_levels_;
955 std::vector<LazyReasonEntry> lazy_reasons_;
956
957 // Start of each decision levels in integer_trail_.
958 // TODO(user): use more general reversible mechanism?
959 std::vector<int> integer_search_levels_;
960
961 // Buffer to store the reason of each trail entry.
962 std::vector<int> reason_decision_levels_;
963 std::vector<int> literals_reason_starts_;
964 std::vector<Literal> literals_reason_buffer_;
965
966 // The last two vectors are in one to one correspondence. Dependencies() will
967 // "cache" the result of the conversion from IntegerLiteral to trail indices
968 // in trail_index_reason_buffer_.
969 std::vector<int> bounds_reason_starts_;
970 mutable std::vector<int> cached_sizes_;
971 std::vector<IntegerLiteral> bounds_reason_buffer_;
972 mutable std::vector<int> trail_index_reason_buffer_;
973
974 // Temporary vector filled by calls to LazyReasonFunction().
975 mutable std::vector<Literal> lazy_reason_literals_;
976 mutable std::vector<int> lazy_reason_trail_indices_;
977
978 // Temporary data used by MergeReasonInto().
979 mutable bool has_dependency_ = false;
980 mutable std::vector<int> tmp_queue_;
981 mutable std::vector<IntegerVariable> tmp_to_clear_;
982 mutable util_intops::StrongVector<IntegerVariable, int>
983 tmp_var_to_trail_index_in_queue_;
984 mutable SparseBitset<BooleanVariable> added_variables_;
985
986 // Temporary heap used by RelaxLinearReason();
987 struct RelaxHeapEntry {
988 int index;
989 IntegerValue coeff;
990 int64_t diff;
991 bool operator<(const RelaxHeapEntry& o) const { return index < o.index; }
992 };
993 mutable std::vector<RelaxHeapEntry> relax_heap_;
994 mutable std::vector<int> tmp_indices_;
995
996 // Temporary data used by AppendNewBounds().
997 mutable SparseBitset<IntegerVariable> tmp_marked_;
998
999 // Temporary data used by SafeEnqueue();
1000 std::vector<IntegerLiteral> tmp_cleaned_reason_;
1001
1002 // For EnqueueLiteral(), we store the reason index at its Boolean trail index.
1003 std::vector<int> boolean_trail_index_to_reason_index_;
1004
1005 // We need to know if we skipped some propagation in the current branch.
1006 // This is reverted as we backtrack over it.
1007 int first_level_without_full_propagation_ = -1;
1008
1009 // This is used to detect when MergeReasonIntoInternal() is called multiple
1010 // time while processing the same conflict. It allows to optimize the reason
1011 // and the time taken to compute it.
1012 mutable int64_t last_conflict_id_ = -1;
1013 mutable bool info_is_valid_on_subsequent_last_level_expansion_ = false;
1014 mutable util_intops::StrongVector<IntegerVariable, int>
1015 var_to_trail_index_at_lower_level_;
1016 mutable std::vector<int> tmp_seen_;
1017 mutable std::vector<IntegerVariable> to_clear_for_lower_level_;
1018
1019 int64_t num_enqueues_ = 0;
1020 int64_t num_untrails_ = 0;
1021 int64_t num_level_zero_enqueues_ = 0;
1022 mutable int64_t num_decisions_to_break_loop_ = 0;
1023
1024 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1025 std::vector<ReversibleInterface*> reversible_classes_;
1026
1027 mutable Domain temp_domain_;
1028 DelayedRootLevelDeduction* delayed_to_fix_;
1029 IntegerDomains* domains_;
1030 IntegerEncoder* encoder_;
1031 Trail* trail_;
1032 SatSolver* sat_solver_;
1033 TimeLimit* time_limit_;
1034 const SatParameters& parameters_;
1035
1036 // Temporary "hash" to keep track of all the conditional enqueue that were
1037 // done. Note that we currently do not keep any reason for them, and as such,
1038 // we can only use this in heuristics. See ConditionalLowerBound().
1039 absl::flat_hash_map<std::pair<LiteralIndex, IntegerVariable>, IntegerValue>
1040 conditional_lbs_;
1041
1042 std::function<bool(absl::Span<const Literal> clause,
1043 absl::Span<const IntegerLiteral> integers)>
1044 debug_checker_ = nullptr;
1045};
1046
1047// Base class for CP like propagators.
1049 public:
1051 virtual ~PropagatorInterface() = default;
1052
1053 // This will be called after one or more literals that are watched by this
1054 // propagator changed. It will also always be called on the first propagation
1055 // cycle after registration.
1056 virtual bool Propagate() = 0;
1057
1058 // This will only be called on a non-empty vector, otherwise Propagate() will
1059 // be called. The passed vector will contain the "watch index" of all the
1060 // literals that were given one at registration and that changed since the
1061 // last call to Propagate(). This is only true when going down in the search
1062 // tree, on backjump this list will be cleared.
1063 //
1064 // Notes:
1065 // - The indices may contain duplicates if the same integer variable as been
1066 // updated many times or if different watched literals have the same
1067 // watch_index.
1068 // - At level zero, it will not contain any indices associated with literals
1069 // that were already fixed when the propagator was registered. Only the
1070 // indices of the literals modified after the registration will be present.
1071 virtual bool IncrementalPropagate(const std::vector<int>& /*watch_indices*/) {
1072 LOG(FATAL) << "Not implemented.";
1073 return false; // Remove warning in Windows
1074 }
1075};
1076
1077// Singleton for basic reversible types. We need the wrapper so that they can be
1078// accessed with model->GetOrCreate<>() and properly registered at creation.
1079class RevIntRepository : public RevRepository<int> {
1080 public:
1081 explicit RevIntRepository(Model* model) {
1082 model->GetOrCreate<IntegerTrail>()->RegisterReversibleClass(this);
1083 }
1084};
1085class RevIntegerValueRepository : public RevRepository<IntegerValue> {
1086 public:
1088 model->GetOrCreate<IntegerTrail>()->RegisterReversibleClass(this);
1089 }
1090};
1091
1092// This class allows registering Propagator that will be called if a
1093// watched Literal or LbVar changes.
1094//
1095// TODO(user): Move this to its own file. Add unit tests!
1097 public:
1098 explicit GenericLiteralWatcher(Model* model);
1099
1100 // This type is neither copyable nor movable.
1103
1104 ~GenericLiteralWatcher() final = default;
1105
1106 // Memory optimization: you can call this before registering watchers.
1107 void ReserveSpaceForNumVariables(int num_vars);
1108
1109 // On propagate, the registered propagators will be called if they need to
1110 // until a fixed point is reached. Propagators with low ids will tend to be
1111 // called first, but it ultimately depends on their "waking" order.
1112 bool Propagate(Trail* trail) final;
1113 void Untrail(const Trail& trail, int literal_trail_index) final;
1114
1115 // Registers a propagator and returns its unique ids.
1116 int Register(PropagatorInterface* propagator);
1117
1118 // Changes the priority of the propagator with given id. The priority is a
1119 // non-negative integer. Propagators with a lower priority will always be
1120 // run before the ones with a higher one. The default priority is one.
1121 void SetPropagatorPriority(int id, int priority);
1122
1123 // The default behavior is to assume that a propagator does not need to be
1124 // called twice in a row. However, propagators on which this is called will be
1125 // called again if they change one of their own watched variables.
1127
1128 // Whether we call a propagator even if its watched variables didn't change.
1129 // This is only used when we are back to level zero. This was introduced for
1130 // the LP propagator where we might need to continue an interrupted solve or
1131 // add extra cuts at level zero.
1132 void AlwaysCallAtLevelZero(int id);
1133
1134 // Watches the corresponding quantity. The propagator with given id will be
1135 // called if it changes. Note that WatchLiteral() only trigger when the
1136 // literal becomes true.
1137 //
1138 // If watch_index is specified, it is associated with the watched literal.
1139 // Doing this will cause IncrementalPropagate() to be called (see the
1140 // documentation of this interface for more detail).
1141 void WatchLiteral(Literal l, int id, int watch_index = -1);
1142 void WatchLowerBound(IntegerVariable var, int id, int watch_index = -1);
1143 void WatchUpperBound(IntegerVariable var, int id, int watch_index = -1);
1144 void WatchIntegerVariable(IntegerVariable i, int id, int watch_index = -1);
1145
1146 // Because the coeff is always positive, watching an affine expression is
1147 // the same as watching its var.
1149 WatchLowerBound(e.var, id);
1150 }
1152 WatchUpperBound(e.var, id);
1153 }
1157
1158 // No-op overload for "constant" IntegerVariable that are sometimes templated
1159 // as an IntegerValue.
1160 void WatchLowerBound(IntegerValue /*i*/, int /*id*/) {}
1161 void WatchUpperBound(IntegerValue /*i*/, int /*id*/) {}
1162 void WatchIntegerVariable(IntegerValue /*v*/, int /*id*/) {}
1163
1164 // Registers a reversible class with a given propagator. This class will be
1165 // changed to the correct state just before the propagator is called.
1166 //
1167 // Doing it just before should minimize cache-misses and bundle as much as
1168 // possible the "backtracking" together. Many propagators only watches a
1169 // few variables and will not be called at each decision levels.
1171
1172 // Registers a reversible int with a given propagator. The int will be changed
1173 // to its correct value just before Propagate() is called.
1174 //
1175 // Note that this will work in O(num_rev_int_of_propagator_id) per call to
1176 // Propagate() and happens at most once per decision level. As such this is
1177 // meant for classes that have just a few reversible ints or that will have a
1178 // similar complexity anyway.
1179 //
1180 // Alternatively, one can directly get the underlying RevRepository<int> with
1181 // a call to model.Get<>(), and use SaveWithStamp() before each modification
1182 // to have just a slight overhead per int updates. This later option is what
1183 // is usually done in a CP solver at the cost of a slightly more complex API.
1184 void RegisterReversibleInt(int id, int* rev);
1185
1186 // A simple form of incremental update is to maintain state as we dive into
1187 // the search tree but forget everything on every backtrack. A propagator
1188 // can be called many times by decision, so this can make a large proportion
1189 // of the calls incremental.
1190 //
1191 // This allows to achieve this with a really low overhead.
1192 //
1193 // The propagator can define a bool rev_is_in_dive_ = false; and at the
1194 // beginning of each propagate do:
1195 // const bool no_backtrack_since_last_call = rev_is_in_dive_;
1196 // watcher_->SetUntilNextBacktrack(&rev_is_in_dive_);
1197 void SetUntilNextBacktrack(bool* is_in_dive) {
1198 if (!*is_in_dive) {
1199 *is_in_dive = true;
1200 bool_to_reset_on_backtrack_.push_back(is_in_dive);
1201 }
1202 }
1203
1204 // Returns the number of registered propagators.
1205 int NumPropagators() const { return in_queue_.size(); }
1206
1207 // Set a callback for new variable bounds at level 0.
1208 //
1209 // This will be called (only at level zero) with the list of IntegerVariable
1210 // with changed lower bounds. Note that it might be called more than once
1211 // during the same propagation cycle if we fix variables in "stages".
1212 //
1213 // Also note that this will be called if some BooleanVariable where fixed even
1214 // if no IntegerVariable are changed, so the passed vector to the function
1215 // might be empty.
1217 const std::function<void(const std::vector<IntegerVariable>&)> cb) {
1218 level_zero_modified_variable_callback_.push_back(cb);
1219 }
1220
1221 // This will be called not too often during propagation (when we finish
1222 // propagating one priority). If it returns true, we will stop propagation
1223 // there. It is used by LbTreeSearch as we can stop as soon as the objective
1224 // lower bound crossed a threshold and do not need to call expensive
1225 // propagator when this is the case.
1226 void SetStopPropagationCallback(std::function<bool()> callback) {
1227 stop_propagation_callback_ = callback;
1228 }
1229
1230 // Returns the id of the propagator we are currently calling. This is meant
1231 // to be used from inside Propagate() in case a propagator was registered
1232 // more than once at different priority for instance.
1233 int GetCurrentId() const { return current_id_; }
1234
1235 // Add the given propagator to its queue.
1236 void CallOnNextPropagate(int id);
1237
1238 private:
1239 // Updates queue_ and in_queue_ with the propagator ids that need to be
1240 // called.
1241 void UpdateCallingNeeds(Trail* trail);
1242
1243 TimeLimit* time_limit_;
1244 IntegerTrail* integer_trail_;
1245 RevIntRepository* rev_int_repository_;
1246
1247 struct WatchData {
1248 int id;
1249 int watch_index;
1250 bool operator==(const WatchData& o) const {
1251 return id == o.id && watch_index == o.watch_index;
1252 }
1253 };
1255 literal_to_watcher_;
1257 var_to_watcher_;
1258 std::vector<PropagatorInterface*> watchers_;
1259 SparseBitset<IntegerVariable> modified_vars_;
1260
1261 // For RegisterLevelZeroModifiedVariablesCallback().
1262 SparseBitset<IntegerVariable> modified_vars_for_callback_;
1263
1264 // Propagator ids that needs to be called. There is one queue per priority but
1265 // just one Boolean to indicate if a propagator is in one of them.
1266 std::vector<std::deque<int>> queue_by_priority_;
1267 std::vector<bool> in_queue_;
1268
1269 // Data for each propagator.
1271 std::vector<bool> id_need_reversible_support_;
1272 std::vector<int> id_to_level_at_last_call_;
1273 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1274 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1275 std::vector<std::vector<int*>> id_to_reversible_ints_;
1276
1277 std::vector<std::vector<int>> id_to_watch_indices_;
1278 std::vector<int> id_to_priority_;
1279 std::vector<int> id_to_idempotence_;
1280
1281 // Special propagators that needs to always be called at level zero.
1282 std::vector<int> propagator_ids_to_call_at_level_zero_;
1283
1284 // The id of the propagator we just called.
1285 int current_id_;
1286
1287 std::vector<std::function<void(const std::vector<IntegerVariable>&)>>
1288 level_zero_modified_variable_callback_;
1289
1290 std::function<bool()> stop_propagation_callback_;
1291
1292 std::vector<bool*> bool_to_reset_on_backtrack_;
1293};
1294
1295// ============================================================================
1296// Implementation.
1297// ============================================================================
1298
1299inline IntegerValue IntegerTrail::LowerBound(IntegerVariable i) const {
1300 return var_lbs_[i];
1302
1303inline IntegerValue IntegerTrail::UpperBound(IntegerVariable i) const {
1304 return -var_lbs_[NegationOf(i)];
1306
1307inline bool IntegerTrail::IsFixed(IntegerVariable i) const {
1308 return var_lbs_[i] == -var_lbs_[NegationOf(i)];
1310
1311inline IntegerValue IntegerTrail::FixedValue(IntegerVariable i) const {
1312 DCHECK(IsFixed(i));
1313 return var_lbs_[i];
1314}
1315
1316inline IntegerValue IntegerTrail::ConditionalLowerBound(
1317 Literal l, IntegerVariable i) const {
1318 const auto it = conditional_lbs_.find({l.Index(), i});
1319 if (it != conditional_lbs_.end()) {
1320 return std::max(var_lbs_[i], it->second);
1321 }
1322 return var_lbs_[i];
1323}
1324
1325inline IntegerValue IntegerTrail::ConditionalLowerBound(
1326 Literal l, AffineExpression expr) const {
1327 if (expr.var == kNoIntegerVariable) return expr.constant;
1328 return ConditionalLowerBound(l, expr.var) * expr.coeff + expr.constant;
1329}
1330
1331inline IntegerValue IntegerTrail::ConditionalUpperBound(
1332 Literal l, IntegerVariable i) const {
1334}
1335
1336inline IntegerValue IntegerTrail::ConditionalUpperBound(
1337 Literal l, AffineExpression expr) const {
1338 if (expr.var == kNoIntegerVariable) return expr.constant;
1339 return ConditionalUpperBound(l, expr.var) * expr.coeff + expr.constant;
1340}
1341
1343 IntegerVariable i) const {
1348 IntegerVariable i) const {
1350}
1351
1352inline IntegerValue IntegerTrail::LowerBound(AffineExpression expr) const {
1353 if (expr.var == kNoIntegerVariable) return expr.constant;
1354 return LowerBound(expr.var) * expr.coeff + expr.constant;
1355}
1356
1357inline IntegerValue IntegerTrail::UpperBound(AffineExpression expr) const {
1358 if (expr.var == kNoIntegerVariable) return expr.constant;
1359 return UpperBound(expr.var) * expr.coeff + expr.constant;
1360}
1361
1362inline bool IntegerTrail::IsFixed(AffineExpression expr) const {
1363 if (expr.var == kNoIntegerVariable) return true;
1364 return IsFixed(expr.var);
1365}
1366
1367inline IntegerValue IntegerTrail::FixedValue(AffineExpression expr) const {
1368 if (expr.var == kNoIntegerVariable) return expr.constant;
1369 return FixedValue(expr.var) * expr.coeff + expr.constant;
1370}
1371
1373 AffineExpression expr) const {
1379 AffineExpression expr) const {
1381 return IntegerLiteral::LowerOrEqual(expr.var, UpperBound(expr.var));
1382}
1383
1385 return l.bound <= LowerBound(l.var);
1387
1389 return l.bound > UpperBound(l.var);
1391
1392// The level zero bounds are stored at the beginning of the trail and they also
1393// serves as sentinels. Their index match the variables index.
1394inline IntegerValue IntegerTrail::LevelZeroLowerBound(
1395 IntegerVariable var) const {
1396 return integer_trail_[var.value()].bound;
1397}
1398
1399inline IntegerValue IntegerTrail::LevelZeroUpperBound(
1400 IntegerVariable var) const {
1401 return -integer_trail_[NegationOf(var).value()].bound;
1402}
1403
1404inline bool IntegerTrail::IsFixedAtLevelZero(IntegerVariable var) const {
1405 return integer_trail_[var.value()].bound ==
1406 -integer_trail_[NegationOf(var).value()].bound;
1407}
1408
1409inline IntegerValue IntegerTrail::LevelZeroLowerBound(
1410 AffineExpression expr) const {
1411 if (expr.var == kNoIntegerVariable) return expr.constant;
1412 return expr.ValueAt(LevelZeroLowerBound(expr.var));
1413}
1414
1415inline IntegerValue IntegerTrail::LevelZeroUpperBound(
1416 AffineExpression expr) const {
1417 if (expr.var == kNoIntegerVariable) return expr.constant;
1418 return expr.ValueAt(LevelZeroUpperBound(expr.var));
1419}
1420
1421inline bool IntegerTrail::IsFixedAtLevelZero(AffineExpression expr) const {
1422 if (expr.var == kNoIntegerVariable) return true;
1424}
1425
1426inline void GenericLiteralWatcher::WatchLiteral(Literal l, int id,
1427 int watch_index) {
1428 if (l.Index() >= literal_to_watcher_.size()) {
1429 literal_to_watcher_.resize(l.Index().value() + 1);
1430 }
1431 literal_to_watcher_[l].push_back({id, watch_index});
1432}
1433
1434inline void GenericLiteralWatcher::WatchLowerBound(IntegerVariable var, int id,
1435 int watch_index) {
1436 if (var == kNoIntegerVariable) return;
1437 if (var.value() >= var_to_watcher_.size()) {
1438 var_to_watcher_.resize(var.value() + 1);
1439 }
1440
1441 // Minor optim, so that we don't watch the same variable twice. Propagator
1442 // code is easier this way since for example when one wants to watch both
1443 // an interval start and interval end, both might have the same underlying
1444 // variable.
1445 const WatchData data = {id, watch_index};
1446 if (!var_to_watcher_[var].empty() && var_to_watcher_[var].back() == data) {
1447 return;
1448 }
1449 var_to_watcher_[var].push_back(data);
1450}
1451
1452inline void GenericLiteralWatcher::WatchUpperBound(IntegerVariable var, int id,
1453 int watch_index) {
1454 if (var == kNoIntegerVariable) return;
1455 WatchLowerBound(NegationOf(var), id, watch_index);
1456}
1457
1458inline void GenericLiteralWatcher::WatchIntegerVariable(IntegerVariable i,
1459 int id,
1460 int watch_index) {
1461 WatchLowerBound(i, id, watch_index);
1462 WatchUpperBound(i, id, watch_index);
1463}
1464
1465// ============================================================================
1466// Model based functions.
1467//
1468// Note that in the model API, we simply use int64_t for the integer values, so
1469// that it is nicer for the client. Internally these are converted to
1470// IntegerValue which is typechecked.
1471// ============================================================================
1472
1473inline std::function<BooleanVariable(Model*)> NewBooleanVariable() {
1474 return [=](Model* model) {
1475 return model->GetOrCreate<SatSolver>()->NewBooleanVariable();
1476 };
1478
1479inline std::function<IntegerVariable(Model*)> ConstantIntegerVariable(
1480 int64_t value) {
1481 return [=](Model* model) {
1482 return model->GetOrCreate<IntegerTrail>()
1483 ->GetOrCreateConstantIntegerVariable(IntegerValue(value));
1484 };
1485}
1486
1487inline std::function<IntegerVariable(Model*)> NewIntegerVariable(int64_t lb,
1488 int64_t ub) {
1489 return [=](Model* model) {
1490 CHECK_LE(lb, ub);
1491 return model->GetOrCreate<IntegerTrail>()->AddIntegerVariable(
1492 IntegerValue(lb), IntegerValue(ub));
1493 };
1494}
1495
1496inline std::function<IntegerVariable(Model*)> NewIntegerVariable(
1497 const Domain& domain) {
1498 return [=](Model* model) {
1499 return model->GetOrCreate<IntegerTrail>()->AddIntegerVariable(domain);
1501}
1502
1503// Creates a 0-1 integer variable "view" of the given literal. It will have a
1504// value of 1 when the literal is true, and 0 when the literal is false.
1505inline IntegerVariable CreateNewIntegerVariableFromLiteral(Literal lit,
1506 Model* model) {
1507 auto* encoder = model->GetOrCreate<IntegerEncoder>();
1508 const IntegerVariable candidate = encoder->GetLiteralView(lit);
1509 if (candidate != kNoIntegerVariable) return candidate;
1510
1511 IntegerVariable var;
1512 auto* integer_trail = model->GetOrCreate<IntegerTrail>();
1513 const auto& assignment = model->GetOrCreate<SatSolver>()->Assignment();
1514 if (assignment.LiteralIsTrue(lit)) {
1515 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(1));
1516 } else if (assignment.LiteralIsFalse(lit)) {
1517 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(0));
1518 } else {
1519 var = integer_trail->AddIntegerVariable(IntegerValue(0), IntegerValue(1));
1520 }
1521
1522 encoder->AssociateToIntegerEqualValue(lit, var, IntegerValue(1));
1523 DCHECK_NE(encoder->GetLiteralView(lit), kNoIntegerVariable);
1524 return var;
1525}
1526
1527// Deprecated.
1528inline std::function<IntegerVariable(Model*)> NewIntegerVariableFromLiteral(
1529 Literal lit) {
1530 return [=](Model* model) {
1531 return CreateNewIntegerVariableFromLiteral(lit, model);
1533}
1534
1535inline std::function<int64_t(const Model&)> LowerBound(IntegerVariable v) {
1536 return [=](const Model& model) {
1537 return model.Get<IntegerTrail>()->LowerBound(v).value();
1538 };
1540
1541inline std::function<int64_t(const Model&)> UpperBound(IntegerVariable v) {
1542 return [=](const Model& model) {
1543 return model.Get<IntegerTrail>()->UpperBound(v).value();
1544 };
1546
1547inline std::function<bool(const Model&)> IsFixed(IntegerVariable v) {
1548 return [=](const Model& model) {
1549 const IntegerTrail* trail = model.Get<IntegerTrail>();
1550 return trail->LowerBound(v) == trail->UpperBound(v);
1552}
1553
1554// This checks that the variable is fixed.
1555inline std::function<int64_t(const Model&)> Value(IntegerVariable v) {
1556 return [=](const Model& model) {
1557 const IntegerTrail* trail = model.Get<IntegerTrail>();
1558 CHECK_EQ(trail->LowerBound(v), trail->UpperBound(v)) << v;
1559 return trail->LowerBound(v).value();
1560 };
1561}
1562
1563inline std::function<void(Model*)> GreaterOrEqual(IntegerVariable v,
1564 int64_t lb) {
1565 return [=](Model* model) {
1566 if (!model->GetOrCreate<IntegerTrail>()->Enqueue(
1568 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1569 model->GetOrCreate<SatSolver>()->NotifyThatModelIsUnsat();
1570 VLOG(1) << "Model trivially infeasible, variable " << v
1571 << " has upper bound " << model->Get(UpperBound(v))
1572 << " and GreaterOrEqual() was called with a lower bound of "
1573 << lb;
1574 }
1575 };
1576}
1577
1578inline std::function<void(Model*)> LowerOrEqual(IntegerVariable v, int64_t ub) {
1579 return [=](Model* model) {
1580 if (!model->GetOrCreate<IntegerTrail>()->Enqueue(
1581 IntegerLiteral::LowerOrEqual(v, IntegerValue(ub)),
1582 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1583 model->GetOrCreate<SatSolver>()->NotifyThatModelIsUnsat();
1584 VLOG(1) << "Model trivially infeasible, variable " << v
1585 << " has lower bound " << model->Get(LowerBound(v))
1586 << " and LowerOrEqual() was called with an upper bound of " << ub;
1587 }
1588 };
1589}
1590
1591// Fix v to a given value.
1592inline std::function<void(Model*)> Equality(IntegerVariable v, int64_t value) {
1593 return [=](Model* model) {
1594 model->Add(LowerOrEqual(v, value));
1595 model->Add(GreaterOrEqual(v, value));
1597}
1598
1599// TODO(user): This is one of the rare case where it is better to use Equality()
1600// rather than two Implications(). Maybe we should modify our internal
1601// implementation to use half-reified encoding? that is do not propagate the
1602// direction integer-bound => literal, but just literal => integer-bound? This
1603// is the same as using different underlying variable for an integer literal and
1604// its negation.
1605inline std::function<void(Model*)> Implication(
1606 absl::Span<const Literal> enforcement_literals, IntegerLiteral i) {
1607 return [=](Model* model) {
1608 auto* sat_solver = model->GetOrCreate<SatSolver>();
1609 auto* integer_trail = model->GetOrCreate<IntegerTrail>();
1610 if (i.bound <= integer_trail->LowerBound(i.var)) {
1611 // Always true! nothing to do.
1612 } else if (i.bound > integer_trail->UpperBound(i.var)) {
1613 // Always false.
1614 std::vector<Literal> clause;
1615 for (const Literal literal : enforcement_literals) {
1616 clause.push_back(literal.Negated());
1617 }
1618 sat_solver->AddClauseDuringSearch(clause);
1619 } else {
1620 // TODO(user): Double check what happen when we associate a trivially
1621 // true or false literal.
1622 IntegerEncoder* encoder = model->GetOrCreate<IntegerEncoder>();
1623 std::vector<Literal> clause{encoder->GetOrCreateAssociatedLiteral(i)};
1624 for (const Literal literal : enforcement_literals) {
1625 clause.push_back(literal.Negated());
1626 }
1627 sat_solver->AddClauseDuringSearch(clause);
1628 }
1629 };
1630}
1631
1632// in_interval => v in [lb, ub].
1633inline std::function<void(Model*)> ImpliesInInterval(Literal in_interval,
1634 IntegerVariable v,
1635 int64_t lb, int64_t ub) {
1636 return [=](Model* model) {
1637 if (lb == ub) {
1638 IntegerEncoder* encoder = model->GetOrCreate<IntegerEncoder>();
1639 model->Add(Implication({in_interval},
1641 v, IntegerValue(lb))));
1642 return;
1643 }
1644 model->Add(Implication(
1645 {in_interval}, IntegerLiteral::GreaterOrEqual(v, IntegerValue(lb))));
1646 model->Add(Implication({in_interval},
1647 IntegerLiteral::LowerOrEqual(v, IntegerValue(ub))));
1648 };
1649}
1650
1651// Calling model.Add(FullyEncodeVariable(var)) will create one literal per value
1652// in the domain of var (if not already done), and wire everything correctly.
1653// This also returns the full encoding, see the FullDomainEncoding() method of
1654// the IntegerEncoder class.
1655inline std::function<std::vector<ValueLiteralPair>(Model*)> FullyEncodeVariable(
1656 IntegerVariable var) {
1657 return [=](Model* model) {
1658 IntegerEncoder* encoder = model->GetOrCreate<IntegerEncoder>();
1659 if (!encoder->VariableIsFullyEncoded(var)) {
1660 encoder->FullyEncodeVariable(var);
1661 }
1662 return encoder->FullDomainEncoding(var);
1663 };
1664}
1665
1666} // namespace sat
1667} // namespace operations_research
1668
1669#endif // OR_TOOLS_SAT_INTEGER_H_
Definition model.h:341
void ClearAndResize(IntegerType size)
Definition bitset.h:860
int NumPropagators() const
Returns the number of registered propagators.
Definition integer.h:1205
void WatchUpperBound(AffineExpression e, int id)
Definition integer.h:1151
void WatchAffineExpression(AffineExpression e, int id)
Definition integer.h:1154
void WatchLiteral(Literal l, int id, int watch_index=-1)
Definition integer.h:1428
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
Definition integer.h:1454
void Untrail(const Trail &trail, int literal_trail_index) final
Definition integer.cc:2292
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
Definition integer.h:1436
void RegisterLevelZeroModifiedVariablesCallback(const std::function< void(const std::vector< IntegerVariable > &)> cb)
Definition integer.h:1216
void SetStopPropagationCallback(std::function< bool()> callback)
Definition integer.h:1226
void SetPropagatorPriority(int id, int priority)
Definition integer.cc:2353
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
Definition integer.h:1460
void RegisterReversibleClass(int id, ReversibleInterface *rev)
Definition integer.cc:2369
void ReserveSpaceForNumVariables(int num_vars)
Memory optimization: you can call this before registering watchers.
Definition integer.cc:2105
int Register(PropagatorInterface *propagator)
Registers a propagator and returns its unique ids.
Definition integer.cc:2327
GenericLiteralWatcher & operator=(const GenericLiteralWatcher &)=delete
void CallOnNextPropagate(int id)
Add the given propagator to its queue.
Definition integer.cc:2109
GenericLiteralWatcher(const GenericLiteralWatcher &)=delete
This type is neither copyable nor movable.
const std::vector< ValueLiteralPair > & FullDomainEncoding(IntegerVariable var) const
Definition integer.cc:146
IntegerEncoder & operator=(const IntegerEncoder &)=delete
std::pair< IntegerLiteral, IntegerLiteral > Canonicalize(IntegerLiteral i_lit) const
Definition integer.cc:247
void AssociateToIntegerLiteral(Literal literal, IntegerLiteral i_lit)
Definition integer.cc:365
const InlinedIntegerValueVector & GetEqualityLiterals(Literal lit) const
Definition integer.h:222
IntegerVariable GetLiteralView(Literal lit) const
Definition integer.h:247
void FullyEncodeVariable(IntegerVariable var)
Definition integer.cc:80
IntegerEncoder(const IntegerEncoder &)=delete
This type is neither copyable nor movable.
Literal GetTrueLiteral()
Gets the literal always set to true, make it if it does not exist.
Definition integer.h:270
bool VariableIsFullyEncoded(IntegerVariable var) const
Definition integer.cc:111
bool IsFixedOrHasAssociatedLiteral(IntegerLiteral i_lit) const
Definition integer.cc:532
const std::vector< ValueLiteralPair > & PartialDomainEncoding(IntegerVariable var) const
Definition integer.cc:152
LiteralIndex GetAssociatedEqualityLiteral(IntegerVariable var, IntegerValue value) const
Definition integer.cc:318
const InlinedIntegerLiteralVector & GetIntegerLiterals(Literal lit) const
Returns the IntegerLiterals that were associated with the given Literal.
Definition integer.h:213
LiteralIndex SearchForLiteralAtOrBefore(IntegerLiteral i_lit, IntegerValue *bound) const
Definition integer.cc:555
void ReserveSpaceForNumVariables(int num_vars)
Memory optimization: you can call this before encoding variables.
Definition integer.cc:74
Literal GetOrCreateAssociatedLiteral(IntegerLiteral i_lit)
Definition integer.cc:274
void AssociateToIntegerEqualValue(Literal literal, IntegerVariable var, IntegerValue value)
Definition integer.cc:435
ABSL_MUST_USE_RESULT bool LiteralOrNegationHasView(Literal lit, IntegerVariable *view=nullptr, bool *view_is_direct=nullptr) const
Definition integer.cc:583
const std::vector< IntegerVariable > & GetAllAssociatedVariables(Literal lit) const
Definition integer.h:231
std::vector< ValueLiteralPair > PartialGreaterThanEncoding(IntegerVariable var) const
Definition integer.cc:603
LiteralIndex GetAssociatedLiteral(IntegerLiteral i_lit) const
Definition integer.cc:541
bool UpdateEncodingOnInitialDomainChange(IntegerVariable var, Domain domain)
Definition integer.cc:639
Literal GetOrCreateLiteralAssociatedToEquality(IntegerVariable var, IntegerValue value)
Definition integer.cc:328
ABSL_MUST_USE_RESULT bool ConditionalEnqueue(Literal lit, IntegerLiteral i_lit, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason)
Definition integer.cc:1270
absl::Span< const Literal > Reason(const Trail &trail, int trail_index, int64_t conflict_id) const final
Definition integer.cc:2048
IntegerValue LowerBound(IntegerVariable i) const
Returns the current lower/upper bound of the given integer variable.
Definition integer.h:1301
void RemoveLevelZeroBounds(std::vector< IntegerLiteral > *reason) const
Definition integer.cc:1160
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition integer.h:604
int FindTrailIndexOfVarBefore(IntegerVariable var, int threshold) const
Definition integer.cc:947
bool VariableLowerBoundIsFromLevelZero(IntegerVariable var) const
Returns true if the variable lower bound is still the one from level zero.
Definition integer.h:722
IntegerTrail & operator=(const IntegerTrail &)=delete
void RegisterWatcher(SparseBitset< IntegerVariable > *p)
Definition integer.h:698
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
Definition integer.h:1349
bool IsFixedAtLevelZero(IntegerVariable var) const
Returns true if the variable is fixed at level 0.
Definition integer.h:1406
ABSL_MUST_USE_RESULT bool SafeEnqueue(IntegerLiteral i_lit, absl::Span< const IntegerLiteral > integer_reason)
Definition integer.cc:1253
void RelaxLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, std::vector< IntegerLiteral > *reason) const
Definition integer.cc:1026
bool IntegerLiteralIsTrue(IntegerLiteral l) const
Returns the current value (if known) of an IntegerLiteral.
Definition integer.h:1386
IntegerValue UpperBound(IntegerVariable i) const
Definition integer.h:1305
void AppendNewBoundsFrom(int base_index, std::vector< IntegerLiteral > *output) const
Definition integer.cc:2072
IntegerValue FixedValue(IntegerVariable i) const
Checks that the variable is fixed and returns its value.
Definition integer.h:1313
bool IntegerLiteralIsFalse(IntegerLiteral l) const
Definition integer.h:1390
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
Definition integer.h:1344
bool HasPendingRootLevelDeduction() const
Return true if we can fix new fact at level zero.
Definition integer.h:766
void AddAllGreaterThanConstantReason(absl::Span< AffineExpression > exprs, IntegerValue target_min, std::vector< int > *indices) const
Definition integer.h:787
void RegisterReversibleClass(ReversibleInterface *rev)
Definition integer.h:728
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition integer.h:705
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
Same as above but take in IntegerVariables instead of IntegerLiterals.
Definition integer.cc:1048
IntegerTrail(const IntegerTrail &)=delete
This type is neither copyable nor movable.
bool ReportConflict(absl::Span< const IntegerLiteral > integer_reason)
Definition integer.h:713
ABSL_MUST_USE_RESULT bool EnqueueWithLazyReason(IntegerLiteral i_lit, int id, IntegerValue propagation_slack, LazyReasonInterface *explainer)
Lazy reason API.
Definition integer.h:649
void AppendNewBounds(std::vector< IntegerLiteral > *output) const
Definition integer.cc:2066
bool UpdateInitialDomain(IntegerVariable var, Domain domain)
Definition integer.cc:887
bool IsFixed(IntegerVariable i) const
Checks if the variable is fixed.
Definition integer.h:1309
IntegerVariable NumIntegerVariables() const
Definition integer.h:435
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason, int trail_index_with_same_reason)
Definition integer.h:640
IntegerValue ConditionalLowerBound(Literal l, IntegerVariable i) const
Definition integer.h:1318
IntegerVariable NextVariableToBranchOnInPropagationLoop() const
Definition integer.cc:1453
IntegerValue ConditionalUpperBound(Literal l, IntegerVariable i) const
Returns the current upper bound assuming the literal is true.
Definition integer.h:1333
const IntegerValue * LowerBoundsData() const
Definition integer.h:493
void RegisterDebugChecker(std::function< bool(absl::Span< const Literal > clause, absl::Span< const IntegerLiteral > integers)> checker)
Definition integer.h:773
int64_t num_level_zero_enqueues() const
Same as num_enqueues but only count the level zero changes.
Definition integer.h:693
ABSL_MUST_USE_RESULT bool RootLevelEnqueue(IntegerLiteral i_lit)
Definition integer.cc:1230
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
Definition integer.h:1401
void MergeReasonInto(absl::Span< const IntegerLiteral > literals, std::vector< Literal > *output) const
Definition integer.cc:1826
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition integer.cc:1393
const Domain & InitialVariableDomain(IntegerVariable var) const
Definition integer.cc:877
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
Returns globally valid lower/upper bound on the given integer variable.
Definition integer.h:1396
void Untrail(const Trail &trail, int literal_trail_index) final
Definition integer.cc:769
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit)
Definition integer.h:601
IntegerVariable FirstUnassignedVariable() const
Definition integer.cc:1486
void ReserveSpaceForNumVariables(int num_vars)
Definition integer.cc:822
bool Propagate(Trail *trail) final
Definition integer.cc:706
IntegerVariable GetOrCreateConstantIntegerVariable(IntegerValue value)
Definition integer.cc:926
std::vector< Literal > ReasonFor(IntegerLiteral literal) const
Definition integer.cc:1820
virtual void Explain(int id, IntegerValue propagation_slack, IntegerVariable var_to_explain, int trail_index, std::vector< Literal > *literals_reason, std::vector< int > *trail_indices_reason)=0
LiteralIndex Index() const
Definition sat_base.h:91
Base class for CP like propagators.
Definition integer.h:1048
virtual bool IncrementalPropagate(const std::vector< int > &)
Definition integer.h:1071
SatPropagator(const std::string &name)
Definition sat_base.h:535
void AddPropagator(SatPropagator *propagator)
void push_back(const value_type &val)
std::function< std::vector< ValueLiteralPair >(Model *)> FullyEncodeVariable(IntegerVariable var)
Definition integer.h:1659
std::function< IntegerVariable(Model *)> NewIntegerVariableFromLiteral(Literal lit)
Definition integer.h:1532
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
Fix v to a given value.
Definition integer.h:1596
bool operator==(const BoolArgumentProto &lhs, const BoolArgumentProto &rhs)
const LiteralIndex kNoLiteralIndex(-1)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
Definition integer.h:1539
std::function< BooleanVariable(Model *)> NewBooleanVariable()
Definition integer.h:1477
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
Definition integer.h:1582
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
Returns the vector of the negated variables.
Definition integer.cc:52
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
Definition integer.h:1551
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
absl::InlinedVector< std::pair< IntegerVariable, IntegerValue >, 2 > InlinedIntegerValueVector
Definition integer.h:52
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
Definition integer.h:1609
std::function< IntegerVariable(Model *)> ConstantIntegerVariable(int64_t value)
Definition integer.h:1483
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
Definition integer.h:1559
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
Definition integer.h:1545
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
Definition integer.h:1491
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
Definition integer.h:1567
absl::InlinedVector< IntegerLiteral, 2 > InlinedIntegerLiteralVector
Definition integer.h:51
std::function< void(Model *)> ImpliesInInterval(Literal in_interval, IntegerVariable v, int64_t lb, int64_t ub)
in_interval => v in [lb, ub].
Definition integer.h:1637
IntegerVariable CreateNewIntegerVariableFromLiteral(Literal lit, Model *model)
Definition integer.h:1509
In SWIG mode, we don't want anything besides these top-level includes.
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
Definition model.h:51
IntegerValue ValueAt(IntegerValue var_value) const
Returns the value of this affine expression given its variable value.
std::vector< IntegerLiteral > integer_literal_to_fix
Definition integer.h:79
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
bool operator==(const LiteralValueValue &rhs) const
Used for testing.
Definition integer.h:61