OR-Tools  9.6
expressions.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 #include <algorithm>
15 #include <cmath>
16 #include <cstdint>
17 #include <limits>
18 #include <memory>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/container/flat_hash_map.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_format.h"
28 #include "ortools/base/logging.h"
29 #include "ortools/base/map_util.h"
30 #include "ortools/base/mathutil.h"
31 #include "ortools/base/stl_util.h"
34 #include "ortools/util/bitset.h"
37 
38 ABSL_FLAG(bool, cp_disable_expression_optimization, false,
39  "Disable special optimization when creating expressions.");
40 ABSL_FLAG(bool, cp_share_int_consts, true,
41  "Share IntConst's with the same value.");
42 
43 #if defined(_MSC_VER)
44 #pragma warning(disable : 4351 4355)
45 #endif
46 
47 namespace operations_research {
48 
49 // ---------- IntExpr ----------
50 
51 IntVar* IntExpr::VarWithName(const std::string& name) {
52  IntVar* const var = Var();
53  var->set_name(name);
54  return var;
55 }
56 
57 // ---------- IntVar ----------
58 
59 IntVar::IntVar(Solver* const s) : IntExpr(s), index_(s->GetNewIntVarIndex()) {}
60 
61 IntVar::IntVar(Solver* const s, const std::string& name)
62  : IntExpr(s), index_(s->GetNewIntVarIndex()) {
63  set_name(name);
64 }
65 
66 // ----- Boolean variable -----
67 
69 
70 void BooleanVar::SetMin(int64_t m) {
71  if (m <= 0) return;
72  if (m > 1) solver()->Fail();
73  SetValue(1);
74 }
75 
76 void BooleanVar::SetMax(int64_t m) {
77  if (m >= 1) return;
78  if (m < 0) solver()->Fail();
79  SetValue(0);
80 }
81 
82 void BooleanVar::SetRange(int64_t mi, int64_t ma) {
83  if (mi > 1 || ma < 0 || mi > ma) {
84  solver()->Fail();
85  }
86  if (mi == 1) {
87  SetValue(1);
88  } else if (ma == 0) {
89  SetValue(0);
90  }
91 }
92 
93 void BooleanVar::RemoveValue(int64_t v) {
95  if (v == 0) {
96  SetValue(1);
97  } else if (v == 1) {
98  SetValue(0);
99  }
100  } else if (v == value_) {
101  solver()->Fail();
102  }
103 }
104 
105 void BooleanVar::RemoveInterval(int64_t l, int64_t u) {
106  if (u < l) return;
107  if (l <= 0 && u >= 1) {
108  solver()->Fail();
109  } else if (l == 1) {
110  SetValue(0);
111  } else if (u == 0) {
112  SetValue(1);
113  }
114 }
115 
118  if (d->priority() == Solver::DELAYED_PRIORITY) {
119  delayed_bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
120  } else {
121  bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
122  }
123  }
124 }
125 
126 uint64_t BooleanVar::Size() const {
127  return (1 + (value_ == kUnboundBooleanVarValue));
128 }
129 
130 bool BooleanVar::Contains(int64_t v) const {
131  return ((v == 0 && value_ != 1) || (v == 1 && value_ != 0));
132 }
133 
134 IntVar* BooleanVar::IsEqual(int64_t constant) {
135  if (constant > 1 || constant < 0) {
136  return solver()->MakeIntConst(0);
137  }
138  if (constant == 1) {
139  return this;
140  } else { // constant == 0.
141  return solver()->MakeDifference(1, this)->Var();
142  }
143 }
144 
145 IntVar* BooleanVar::IsDifferent(int64_t constant) {
146  if (constant > 1 || constant < 0) {
147  return solver()->MakeIntConst(1);
148  }
149  if (constant == 1) {
150  return solver()->MakeDifference(1, this)->Var();
151  } else { // constant == 0.
152  return this;
153  }
154 }
155 
157  if (constant > 1) {
158  return solver()->MakeIntConst(0);
159  } else if (constant <= 0) {
160  return solver()->MakeIntConst(1);
161  } else {
162  return this;
163  }
164 }
165 
166 IntVar* BooleanVar::IsLessOrEqual(int64_t constant) {
167  if (constant < 0) {
168  return solver()->MakeIntConst(0);
169  } else if (constant >= 1) {
170  return solver()->MakeIntConst(1);
171  } else {
172  return IsEqual(0);
173  }
174 }
175 
176 std::string BooleanVar::DebugString() const {
177  std::string out;
178  const std::string& var_name = name();
179  if (!var_name.empty()) {
180  out = var_name + "(";
181  } else {
182  out = "BooleanVar(";
183  }
184  switch (value_) {
185  case 0:
186  out += "0";
187  break;
188  case 1:
189  out += "1";
190  break;
192  out += "0 .. 1";
193  break;
194  }
195  out += ")";
196  return out;
197 }
198 
199 namespace {
200 // ---------- Subclasses of IntVar ----------
201 
202 // ----- Domain Int Var: base class for variables -----
203 // It Contains bounds and a bitset representation of possible values.
204 class DomainIntVar : public IntVar {
205  public:
206  // Utility classes
207  class BitSetIterator : public BaseObject {
208  public:
209  BitSetIterator(uint64_t* const bitset, int64_t omin)
210  : bitset_(bitset),
211  omin_(omin),
212  max_(std::numeric_limits<int64_t>::min()),
213  current_(std::numeric_limits<int64_t>::max()) {}
214 
215  ~BitSetIterator() override {}
216 
217  void Init(int64_t min, int64_t max) {
218  max_ = max;
219  current_ = min;
220  }
221 
222  bool Ok() const { return current_ <= max_; }
223 
224  int64_t Value() const { return current_; }
225 
226  void Next() {
227  if (++current_ <= max_) {
229  bitset_, current_ - omin_, max_ - omin_) +
230  omin_;
231  }
232  }
233 
234  std::string DebugString() const override { return "BitSetIterator"; }
235 
236  private:
237  uint64_t* const bitset_;
238  const int64_t omin_;
239  int64_t max_;
240  int64_t current_;
241  };
242 
243  class BitSet : public BaseObject {
244  public:
245  explicit BitSet(Solver* const s) : solver_(s), holes_stamp_(0) {}
246  ~BitSet() override {}
247 
248  virtual int64_t ComputeNewMin(int64_t nmin, int64_t cmin, int64_t cmax) = 0;
249  virtual int64_t ComputeNewMax(int64_t nmax, int64_t cmin, int64_t cmax) = 0;
250  virtual bool Contains(int64_t val) const = 0;
251  virtual bool SetValue(int64_t val) = 0;
252  virtual bool RemoveValue(int64_t val) = 0;
253  virtual uint64_t Size() const = 0;
254  virtual void DelayRemoveValue(int64_t val) = 0;
255  virtual void ApplyRemovedValues(DomainIntVar* var) = 0;
256  virtual void ClearRemovedValues() = 0;
257  virtual std::string pretty_DebugString(int64_t min, int64_t max) const = 0;
258  virtual BitSetIterator* MakeIterator() = 0;
259 
260  void InitHoles() {
261  const uint64_t current_stamp = solver_->stamp();
262  if (holes_stamp_ < current_stamp) {
263  holes_.clear();
264  holes_stamp_ = current_stamp;
265  }
266  }
267 
268  virtual void ClearHoles() { holes_.clear(); }
269 
270  const std::vector<int64_t>& Holes() { return holes_; }
271 
272  void AddHole(int64_t value) { holes_.push_back(value); }
273 
274  int NumHoles() const {
275  return holes_stamp_ < solver_->stamp() ? 0 : holes_.size();
276  }
277 
278  protected:
279  Solver* const solver_;
280 
281  private:
282  std::vector<int64_t> holes_;
283  uint64_t holes_stamp_;
284  };
285 
286  class QueueHandler : public Demon {
287  public:
288  explicit QueueHandler(DomainIntVar* const var) : var_(var) {}
289  ~QueueHandler() override {}
290  void Run(Solver* const s) override {
291  s->GetPropagationMonitor()->StartProcessingIntegerVariable(var_);
292  var_->Process();
293  s->GetPropagationMonitor()->EndProcessingIntegerVariable(var_);
294  }
295  Solver::DemonPriority priority() const override {
296  return Solver::VAR_PRIORITY;
297  }
298  std::string DebugString() const override {
299  return absl::StrFormat("Handler(%s)", var_->DebugString());
300  }
301 
302  private:
303  DomainIntVar* const var_;
304  };
305 
306  // Bounds and Value watchers
307 
308  // This class stores the watchers variables attached to values. It is
309  // reversible and it helps maintaining the set of 'active' watchers
310  // (variables not bound to a single value).
311  template <class T>
312  class RevIntPtrMap {
313  public:
314  RevIntPtrMap(Solver* const solver, int64_t rmin, int64_t rmax)
315  : solver_(solver), range_min_(rmin), start_(0) {}
316 
317  ~RevIntPtrMap() {}
318 
319  bool Empty() const { return start_.Value() == elements_.size(); }
320 
321  void SortActive() { std::sort(elements_.begin(), elements_.end()); }
322 
323  // Access with value API.
324 
325  // Add the pointer to the map attached to the given value.
326  void UnsafeRevInsert(int64_t value, T* elem) {
327  elements_.push_back(std::make_pair(value, elem));
328  if (solver_->state() != Solver::OUTSIDE_SEARCH) {
329  solver_->AddBacktrackAction(
330  [this, value](Solver* s) { Uninsert(value); }, false);
331  }
332  }
333 
334  T* FindPtrOrNull(int64_t value, int* position) {
335  for (int pos = start_.Value(); pos < elements_.size(); ++pos) {
336  if (elements_[pos].first == value) {
337  if (position != nullptr) *position = pos;
338  return At(pos).second;
339  }
340  }
341  return nullptr;
342  }
343 
344  // Access map through the underlying vector.
345  void RemoveAt(int position) {
346  const int start = start_.Value();
347  DCHECK_GE(position, start);
348  DCHECK_LT(position, elements_.size());
349  if (position > start) {
350  // Swap the current element with the one at the start position, and
351  // increase start.
352  const std::pair<int64_t, T*> copy = elements_[start];
353  elements_[start] = elements_[position];
354  elements_[position] = copy;
355  }
356  start_.Incr(solver_);
357  }
358 
359  const std::pair<int64_t, T*>& At(int position) const {
360  DCHECK_GE(position, start_.Value());
361  DCHECK_LT(position, elements_.size());
362  return elements_[position];
363  }
364 
365  void RemoveAll() { start_.SetValue(solver_, elements_.size()); }
366 
367  int start() const { return start_.Value(); }
368  int end() const { return elements_.size(); }
369  // Number of active elements.
370  int Size() const { return elements_.size() - start_.Value(); }
371 
372  // Removes the object permanently from the map.
373  void Uninsert(int64_t value) {
374  for (int pos = 0; pos < elements_.size(); ++pos) {
375  if (elements_[pos].first == value) {
376  DCHECK_GE(pos, start_.Value());
377  const int last = elements_.size() - 1;
378  if (pos != last) { // Swap the current with the last.
379  elements_[pos] = elements_.back();
380  }
381  elements_.pop_back();
382  return;
383  }
384  }
385  LOG(FATAL) << "The element should have been removed";
386  }
387 
388  private:
389  Solver* const solver_;
390  const int64_t range_min_;
391  NumericalRev<int> start_;
392  std::vector<std::pair<int64_t, T*>> elements_;
393  };
394 
395  // Base class for value watchers
396  class BaseValueWatcher : public Constraint {
397  public:
398  explicit BaseValueWatcher(Solver* const solver) : Constraint(solver) {}
399 
400  ~BaseValueWatcher() override {}
401 
402  virtual IntVar* GetOrMakeValueWatcher(int64_t value) = 0;
403 
404  virtual void SetValueWatcher(IntVar* const boolvar, int64_t value) = 0;
405  };
406 
407  // This class monitors the domain of the variable and updates the
408  // IsEqual/IsDifferent boolean variables accordingly.
409  class ValueWatcher : public BaseValueWatcher {
410  public:
411  class WatchDemon : public Demon {
412  public:
413  WatchDemon(ValueWatcher* const watcher, int64_t value, IntVar* var)
414  : value_watcher_(watcher), value_(value), var_(var) {}
415  ~WatchDemon() override {}
416 
417  void Run(Solver* const solver) override {
418  value_watcher_->ProcessValueWatcher(value_, var_);
419  }
420 
421  private:
422  ValueWatcher* const value_watcher_;
423  const int64_t value_;
424  IntVar* const var_;
425  };
426 
427  class VarDemon : public Demon {
428  public:
429  explicit VarDemon(ValueWatcher* const watcher)
430  : value_watcher_(watcher) {}
431 
432  ~VarDemon() override {}
433 
434  void Run(Solver* const solver) override { value_watcher_->ProcessVar(); }
435 
436  private:
437  ValueWatcher* const value_watcher_;
438  };
439 
440  ValueWatcher(Solver* const solver, DomainIntVar* const variable)
441  : BaseValueWatcher(solver),
442  variable_(variable),
443  hole_iterator_(variable_->MakeHoleIterator(true)),
444  var_demon_(nullptr),
445  watchers_(solver, variable->Min(), variable->Max()) {}
446 
447  ~ValueWatcher() override {}
448 
449  IntVar* GetOrMakeValueWatcher(int64_t value) override {
450  IntVar* const watcher = watchers_.FindPtrOrNull(value, nullptr);
451  if (watcher != nullptr) return watcher;
452  if (variable_->Contains(value)) {
453  if (variable_->Bound()) {
454  return solver()->MakeIntConst(1);
455  } else {
456  const std::string vname = variable_->HasName()
457  ? variable_->name()
458  : variable_->DebugString();
459  const std::string bname =
460  absl::StrFormat("Watch<%s == %d>", vname, value);
461  IntVar* const boolvar = solver()->MakeBoolVar(bname);
462  watchers_.UnsafeRevInsert(value, boolvar);
463  if (posted_.Switched()) {
464  boolvar->WhenBound(
465  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
466  var_demon_->desinhibit(solver());
467  }
468  return boolvar;
469  }
470  } else {
471  return variable_->solver()->MakeIntConst(0);
472  }
473  }
474 
475  void SetValueWatcher(IntVar* const boolvar, int64_t value) override {
476  CHECK(watchers_.FindPtrOrNull(value, nullptr) == nullptr);
477  if (!boolvar->Bound()) {
478  watchers_.UnsafeRevInsert(value, boolvar);
479  if (posted_.Switched() && !boolvar->Bound()) {
480  boolvar->WhenBound(
481  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
482  var_demon_->desinhibit(solver());
483  }
484  }
485  }
486 
487  void Post() override {
488  var_demon_ = solver()->RevAlloc(new VarDemon(this));
489  variable_->WhenDomain(var_demon_);
490  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
491  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
492  const int64_t value = w.first;
493  IntVar* const boolvar = w.second;
494  if (!boolvar->Bound() && variable_->Contains(value)) {
495  boolvar->WhenBound(
496  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
497  }
498  }
499  posted_.Switch(solver());
500  }
501 
502  void InitialPropagate() override {
503  if (variable_->Bound()) {
504  VariableBound();
505  } else {
506  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
507  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
508  const int64_t value = w.first;
509  IntVar* const boolvar = w.second;
510  if (!variable_->Contains(value)) {
511  boolvar->SetValue(0);
512  watchers_.RemoveAt(pos);
513  } else {
514  if (boolvar->Bound()) {
515  ProcessValueWatcher(value, boolvar);
516  watchers_.RemoveAt(pos);
517  }
518  }
519  }
520  CheckInhibit();
521  }
522  }
523 
524  void ProcessValueWatcher(int64_t value, IntVar* boolvar) {
525  if (boolvar->Min() == 0) {
526  if (variable_->Size() < 0xFFFFFF) {
527  variable_->RemoveValue(value);
528  } else {
529  // Delay removal.
530  solver()->AddConstraint(solver()->MakeNonEquality(variable_, value));
531  }
532  } else {
533  variable_->SetValue(value);
534  }
535  }
536 
537  void ProcessVar() {
538  const int kSmallList = 16;
539  if (variable_->Bound()) {
540  VariableBound();
541  } else if (watchers_.Size() <= kSmallList ||
542  variable_->Min() != variable_->OldMin() ||
543  variable_->Max() != variable_->OldMax()) {
544  // Brute force loop for small numbers of watchers, or if the bounds have
545  // changed, which would have required a sort (n log(n)) anyway to take
546  // advantage of.
547  ScanWatchers();
548  CheckInhibit();
549  } else {
550  // If there is no bitset, then there are no holes.
551  // In that case, the two loops above should have performed all
552  // propagation. Otherwise, scan the remaining watchers.
553  BitSet* const bitset = variable_->bitset();
554  if (bitset != nullptr && !watchers_.Empty()) {
555  if (bitset->NumHoles() * 2 < watchers_.Size()) {
556  for (const int64_t hole : InitAndGetValues(hole_iterator_)) {
557  int pos = 0;
558  IntVar* const boolvar = watchers_.FindPtrOrNull(hole, &pos);
559  if (boolvar != nullptr) {
560  boolvar->SetValue(0);
561  watchers_.RemoveAt(pos);
562  }
563  }
564  } else {
565  ScanWatchers();
566  }
567  }
568  CheckInhibit();
569  }
570  }
571 
572  // Optimized case if the variable is bound.
573  void VariableBound() {
574  DCHECK(variable_->Bound());
575  const int64_t value = variable_->Min();
576  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
577  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
578  w.second->SetValue(w.first == value);
579  }
580  watchers_.RemoveAll();
581  var_demon_->inhibit(solver());
582  }
583 
584  // Scans all the watchers to check and assign them.
585  void ScanWatchers() {
586  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
587  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
588  if (!variable_->Contains(w.first)) {
589  IntVar* const boolvar = w.second;
590  boolvar->SetValue(0);
591  watchers_.RemoveAt(pos);
592  }
593  }
594  }
595 
596  // If the set of active watchers is empty, we can inhibit the demon on the
597  // main variable.
598  void CheckInhibit() {
599  if (watchers_.Empty()) {
600  var_demon_->inhibit(solver());
601  }
602  }
603 
604  void Accept(ModelVisitor* const visitor) const override {
605  visitor->BeginVisitConstraint(ModelVisitor::kVarValueWatcher, this);
606  visitor->VisitIntegerExpressionArgument(ModelVisitor::kVariableArgument,
607  variable_);
608  std::vector<int64_t> all_coefficients;
609  std::vector<IntVar*> all_bool_vars;
610  for (int position = watchers_.start(); position < watchers_.end();
611  ++position) {
612  const std::pair<int64_t, IntVar*>& w = watchers_.At(position);
613  all_coefficients.push_back(w.first);
614  all_bool_vars.push_back(w.second);
615  }
616  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
617  all_bool_vars);
618  visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
619  all_coefficients);
620  visitor->EndVisitConstraint(ModelVisitor::kVarValueWatcher, this);
621  }
622 
623  std::string DebugString() const override {
624  return absl::StrFormat("ValueWatcher(%s)", variable_->DebugString());
625  }
626 
627  private:
628  DomainIntVar* const variable_;
629  IntVarIterator* const hole_iterator_;
630  RevSwitch posted_;
631  Demon* var_demon_;
632  RevIntPtrMap<IntVar> watchers_;
633  };
634 
635  // Optimized case for small maps.
636  class DenseValueWatcher : public BaseValueWatcher {
637  public:
638  class WatchDemon : public Demon {
639  public:
640  WatchDemon(DenseValueWatcher* const watcher, int64_t value, IntVar* var)
641  : value_watcher_(watcher), value_(value), var_(var) {}
642  ~WatchDemon() override {}
643 
644  void Run(Solver* const solver) override {
645  value_watcher_->ProcessValueWatcher(value_, var_);
646  }
647 
648  private:
649  DenseValueWatcher* const value_watcher_;
650  const int64_t value_;
651  IntVar* const var_;
652  };
653 
654  class VarDemon : public Demon {
655  public:
656  explicit VarDemon(DenseValueWatcher* const watcher)
657  : value_watcher_(watcher) {}
658 
659  ~VarDemon() override {}
660 
661  void Run(Solver* const solver) override { value_watcher_->ProcessVar(); }
662 
663  private:
664  DenseValueWatcher* const value_watcher_;
665  };
666 
667  DenseValueWatcher(Solver* const solver, DomainIntVar* const variable)
668  : BaseValueWatcher(solver),
669  variable_(variable),
670  hole_iterator_(variable_->MakeHoleIterator(true)),
671  var_demon_(nullptr),
672  offset_(variable->Min()),
673  watchers_(variable->Max() - variable->Min() + 1, nullptr),
674  active_watchers_(0) {}
675 
676  ~DenseValueWatcher() override {}
677 
678  IntVar* GetOrMakeValueWatcher(int64_t value) override {
679  const int64_t var_max = offset_ + watchers_.size() - 1; // Bad cast.
680  if (value < offset_ || value > var_max) {
681  return solver()->MakeIntConst(0);
682  }
683  const int index = value - offset_;
684  IntVar* const watcher = watchers_[index];
685  if (watcher != nullptr) return watcher;
686  if (variable_->Contains(value)) {
687  if (variable_->Bound()) {
688  return solver()->MakeIntConst(1);
689  } else {
690  const std::string vname = variable_->HasName()
691  ? variable_->name()
692  : variable_->DebugString();
693  const std::string bname =
694  absl::StrFormat("Watch<%s == %d>", vname, value);
695  IntVar* const boolvar = solver()->MakeBoolVar(bname);
696  RevInsert(index, boolvar);
697  if (posted_.Switched()) {
698  boolvar->WhenBound(
699  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
700  var_demon_->desinhibit(solver());
701  }
702  return boolvar;
703  }
704  } else {
705  return variable_->solver()->MakeIntConst(0);
706  }
707  }
708 
709  void SetValueWatcher(IntVar* const boolvar, int64_t value) override {
710  const int index = value - offset_;
711  CHECK(watchers_[index] == nullptr);
712  if (!boolvar->Bound()) {
713  RevInsert(index, boolvar);
714  if (posted_.Switched() && !boolvar->Bound()) {
715  boolvar->WhenBound(
716  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
717  var_demon_->desinhibit(solver());
718  }
719  }
720  }
721 
722  void Post() override {
723  var_demon_ = solver()->RevAlloc(new VarDemon(this));
724  variable_->WhenDomain(var_demon_);
725  for (int pos = 0; pos < watchers_.size(); ++pos) {
726  const int64_t value = pos + offset_;
727  IntVar* const boolvar = watchers_[pos];
728  if (boolvar != nullptr && !boolvar->Bound() &&
729  variable_->Contains(value)) {
730  boolvar->WhenBound(
731  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
732  }
733  }
734  posted_.Switch(solver());
735  }
736 
737  void InitialPropagate() override {
738  if (variable_->Bound()) {
739  VariableBound();
740  } else {
741  for (int pos = 0; pos < watchers_.size(); ++pos) {
742  IntVar* const boolvar = watchers_[pos];
743  if (boolvar == nullptr) continue;
744  const int64_t value = pos + offset_;
745  if (!variable_->Contains(value)) {
746  boolvar->SetValue(0);
747  RevRemove(pos);
748  } else if (boolvar->Bound()) {
749  ProcessValueWatcher(value, boolvar);
750  RevRemove(pos);
751  }
752  }
753  if (active_watchers_.Value() == 0) {
754  var_demon_->inhibit(solver());
755  }
756  }
757  }
758 
759  void ProcessValueWatcher(int64_t value, IntVar* boolvar) {
760  if (boolvar->Min() == 0) {
761  variable_->RemoveValue(value);
762  } else {
763  variable_->SetValue(value);
764  }
765  }
766 
767  void ProcessVar() {
768  if (variable_->Bound()) {
769  VariableBound();
770  } else {
771  // Brute force loop for small numbers of watchers.
772  ScanWatchers();
773  if (active_watchers_.Value() == 0) {
774  var_demon_->inhibit(solver());
775  }
776  }
777  }
778 
779  // Optimized case if the variable is bound.
780  void VariableBound() {
781  DCHECK(variable_->Bound());
782  const int64_t value = variable_->Min();
783  for (int pos = 0; pos < watchers_.size(); ++pos) {
784  IntVar* const boolvar = watchers_[pos];
785  if (boolvar != nullptr) {
786  boolvar->SetValue(pos + offset_ == value);
787  RevRemove(pos);
788  }
789  }
790  var_demon_->inhibit(solver());
791  }
792 
793  // Scans all the watchers to check and assign them.
794  void ScanWatchers() {
795  const int64_t old_min_index = variable_->OldMin() - offset_;
796  const int64_t old_max_index = variable_->OldMax() - offset_;
797  const int64_t min_index = variable_->Min() - offset_;
798  const int64_t max_index = variable_->Max() - offset_;
799  for (int pos = old_min_index; pos < min_index; ++pos) {
800  IntVar* const boolvar = watchers_[pos];
801  if (boolvar != nullptr) {
802  boolvar->SetValue(0);
803  RevRemove(pos);
804  }
805  }
806  for (int pos = max_index + 1; pos <= old_max_index; ++pos) {
807  IntVar* const boolvar = watchers_[pos];
808  if (boolvar != nullptr) {
809  boolvar->SetValue(0);
810  RevRemove(pos);
811  }
812  }
813  BitSet* const bitset = variable_->bitset();
814  if (bitset != nullptr) {
815  if (bitset->NumHoles() * 2 < active_watchers_.Value()) {
816  for (const int64_t hole : InitAndGetValues(hole_iterator_)) {
817  IntVar* const boolvar = watchers_[hole - offset_];
818  if (boolvar != nullptr) {
819  boolvar->SetValue(0);
820  RevRemove(hole - offset_);
821  }
822  }
823  } else {
824  for (int pos = min_index + 1; pos < max_index; ++pos) {
825  IntVar* const boolvar = watchers_[pos];
826  if (boolvar != nullptr && !variable_->Contains(offset_ + pos)) {
827  boolvar->SetValue(0);
828  RevRemove(pos);
829  }
830  }
831  }
832  }
833  }
834 
835  void RevRemove(int pos) {
836  solver()->SaveValue(reinterpret_cast<void**>(&watchers_[pos]));
837  watchers_[pos] = nullptr;
838  active_watchers_.Decr(solver());
839  }
840 
841  void RevInsert(int pos, IntVar* boolvar) {
842  solver()->SaveValue(reinterpret_cast<void**>(&watchers_[pos]));
843  watchers_[pos] = boolvar;
844  active_watchers_.Incr(solver());
845  }
846 
847  void Accept(ModelVisitor* const visitor) const override {
848  visitor->BeginVisitConstraint(ModelVisitor::kVarValueWatcher, this);
849  visitor->VisitIntegerExpressionArgument(ModelVisitor::kVariableArgument,
850  variable_);
851  std::vector<int64_t> all_coefficients;
852  std::vector<IntVar*> all_bool_vars;
853  for (int position = 0; position < watchers_.size(); ++position) {
854  if (watchers_[position] != nullptr) {
855  all_coefficients.push_back(position + offset_);
856  all_bool_vars.push_back(watchers_[position]);
857  }
858  }
859  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
860  all_bool_vars);
861  visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
862  all_coefficients);
863  visitor->EndVisitConstraint(ModelVisitor::kVarValueWatcher, this);
864  }
865 
866  std::string DebugString() const override {
867  return absl::StrFormat("DenseValueWatcher(%s)", variable_->DebugString());
868  }
869 
870  private:
871  DomainIntVar* const variable_;
872  IntVarIterator* const hole_iterator_;
873  RevSwitch posted_;
874  Demon* var_demon_;
875  const int64_t offset_;
876  std::vector<IntVar*> watchers_;
877  NumericalRev<int> active_watchers_;
878  };
879 
880  class BaseUpperBoundWatcher : public Constraint {
881  public:
882  explicit BaseUpperBoundWatcher(Solver* const solver) : Constraint(solver) {}
883 
884  ~BaseUpperBoundWatcher() override {}
885 
886  virtual IntVar* GetOrMakeUpperBoundWatcher(int64_t value) = 0;
887 
888  virtual void SetUpperBoundWatcher(IntVar* const boolvar, int64_t value) = 0;
889  };
890 
891  // This class watches the bounds of the variable and updates the
892  // IsGreater/IsGreaterOrEqual/IsLess/IsLessOrEqual demons
893  // accordingly.
894  class UpperBoundWatcher : public BaseUpperBoundWatcher {
895  public:
896  class WatchDemon : public Demon {
897  public:
898  WatchDemon(UpperBoundWatcher* const watcher, int64_t index,
899  IntVar* const var)
900  : value_watcher_(watcher), index_(index), var_(var) {}
901  ~WatchDemon() override {}
902 
903  void Run(Solver* const solver) override {
904  value_watcher_->ProcessUpperBoundWatcher(index_, var_);
905  }
906 
907  private:
908  UpperBoundWatcher* const value_watcher_;
909  const int64_t index_;
910  IntVar* const var_;
911  };
912 
913  class VarDemon : public Demon {
914  public:
915  explicit VarDemon(UpperBoundWatcher* const watcher)
916  : value_watcher_(watcher) {}
917  ~VarDemon() override {}
918 
919  void Run(Solver* const solver) override { value_watcher_->ProcessVar(); }
920 
921  private:
922  UpperBoundWatcher* const value_watcher_;
923  };
924 
925  UpperBoundWatcher(Solver* const solver, DomainIntVar* const variable)
926  : BaseUpperBoundWatcher(solver),
927  variable_(variable),
928  var_demon_(nullptr),
929  watchers_(solver, variable->Min(), variable->Max()),
930  start_(0),
931  end_(0),
932  sorted_(false) {}
933 
934  ~UpperBoundWatcher() override {}
935 
936  IntVar* GetOrMakeUpperBoundWatcher(int64_t value) override {
937  IntVar* const watcher = watchers_.FindPtrOrNull(value, nullptr);
938  if (watcher != nullptr) {
939  return watcher;
940  }
941  if (variable_->Max() >= value) {
942  if (variable_->Min() >= value) {
943  return solver()->MakeIntConst(1);
944  } else {
945  const std::string vname = variable_->HasName()
946  ? variable_->name()
947  : variable_->DebugString();
948  const std::string bname =
949  absl::StrFormat("Watch<%s >= %d>", vname, value);
950  IntVar* const boolvar = solver()->MakeBoolVar(bname);
951  watchers_.UnsafeRevInsert(value, boolvar);
952  if (posted_.Switched()) {
953  boolvar->WhenBound(
954  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
955  var_demon_->desinhibit(solver());
956  sorted_ = false;
957  }
958  return boolvar;
959  }
960  } else {
961  return variable_->solver()->MakeIntConst(0);
962  }
963  }
964 
965  void SetUpperBoundWatcher(IntVar* const boolvar, int64_t value) override {
966  CHECK(watchers_.FindPtrOrNull(value, nullptr) == nullptr);
967  watchers_.UnsafeRevInsert(value, boolvar);
968  if (posted_.Switched() && !boolvar->Bound()) {
969  boolvar->WhenBound(
970  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
971  var_demon_->desinhibit(solver());
972  sorted_ = false;
973  }
974  }
975 
976  void Post() override {
977  const int kTooSmallToSort = 8;
978  var_demon_ = solver()->RevAlloc(new VarDemon(this));
979  variable_->WhenRange(var_demon_);
980 
981  if (watchers_.Size() > kTooSmallToSort) {
982  watchers_.SortActive();
983  sorted_ = true;
984  start_.SetValue(solver(), watchers_.start());
985  end_.SetValue(solver(), watchers_.end() - 1);
986  }
987 
988  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
989  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
990  IntVar* const boolvar = w.second;
991  const int64_t value = w.first;
992  if (!boolvar->Bound() && value > variable_->Min() &&
993  value <= variable_->Max()) {
994  boolvar->WhenBound(
995  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
996  }
997  }
998  posted_.Switch(solver());
999  }
1000 
1001  void InitialPropagate() override {
1002  const int64_t var_min = variable_->Min();
1003  const int64_t var_max = variable_->Max();
1004  if (sorted_) {
1005  while (start_.Value() <= end_.Value()) {
1006  const std::pair<int64_t, IntVar*>& w = watchers_.At(start_.Value());
1007  if (w.first <= var_min) {
1008  w.second->SetValue(1);
1009  start_.Incr(solver());
1010  } else {
1011  break;
1012  }
1013  }
1014  while (end_.Value() >= start_.Value()) {
1015  const std::pair<int64_t, IntVar*>& w = watchers_.At(end_.Value());
1016  if (w.first > var_max) {
1017  w.second->SetValue(0);
1018  end_.Decr(solver());
1019  } else {
1020  break;
1021  }
1022  }
1023  for (int i = start_.Value(); i <= end_.Value(); ++i) {
1024  const std::pair<int64_t, IntVar*>& w = watchers_.At(i);
1025  if (w.second->Bound()) {
1026  ProcessUpperBoundWatcher(w.first, w.second);
1027  }
1028  }
1029  if (start_.Value() > end_.Value()) {
1030  var_demon_->inhibit(solver());
1031  }
1032  } else {
1033  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
1034  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
1035  const int64_t value = w.first;
1036  IntVar* const boolvar = w.second;
1037 
1038  if (value <= var_min) {
1039  boolvar->SetValue(1);
1040  watchers_.RemoveAt(pos);
1041  } else if (value > var_max) {
1042  boolvar->SetValue(0);
1043  watchers_.RemoveAt(pos);
1044  } else if (boolvar->Bound()) {
1045  ProcessUpperBoundWatcher(value, boolvar);
1046  watchers_.RemoveAt(pos);
1047  }
1048  }
1049  }
1050  }
1051 
1052  void Accept(ModelVisitor* const visitor) const override {
1053  visitor->BeginVisitConstraint(ModelVisitor::kVarBoundWatcher, this);
1054  visitor->VisitIntegerExpressionArgument(ModelVisitor::kVariableArgument,
1055  variable_);
1056  std::vector<int64_t> all_coefficients;
1057  std::vector<IntVar*> all_bool_vars;
1058  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
1059  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
1060  all_coefficients.push_back(w.first);
1061  all_bool_vars.push_back(w.second);
1062  }
1063  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1064  all_bool_vars);
1065  visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
1066  all_coefficients);
1067  visitor->EndVisitConstraint(ModelVisitor::kVarBoundWatcher, this);
1068  }
1069 
1070  std::string DebugString() const override {
1071  return absl::StrFormat("UpperBoundWatcher(%s)", variable_->DebugString());
1072  }
1073 
1074  private:
1075  void ProcessUpperBoundWatcher(int64_t value, IntVar* const boolvar) {
1076  if (boolvar->Min() == 0) {
1077  variable_->SetMax(value - 1);
1078  } else {
1079  variable_->SetMin(value);
1080  }
1081  }
1082 
1083  void ProcessVar() {
1084  const int64_t var_min = variable_->Min();
1085  const int64_t var_max = variable_->Max();
1086  if (sorted_) {
1087  while (start_.Value() <= end_.Value()) {
1088  const std::pair<int64_t, IntVar*>& w = watchers_.At(start_.Value());
1089  if (w.first <= var_min) {
1090  w.second->SetValue(1);
1091  start_.Incr(solver());
1092  } else {
1093  break;
1094  }
1095  }
1096  while (end_.Value() >= start_.Value()) {
1097  const std::pair<int64_t, IntVar*>& w = watchers_.At(end_.Value());
1098  if (w.first > var_max) {
1099  w.second->SetValue(0);
1100  end_.Decr(solver());
1101  } else {
1102  break;
1103  }
1104  }
1105  if (start_.Value() > end_.Value()) {
1106  var_demon_->inhibit(solver());
1107  }
1108  } else {
1109  for (int pos = watchers_.start(); pos < watchers_.end(); ++pos) {
1110  const std::pair<int64_t, IntVar*>& w = watchers_.At(pos);
1111  const int64_t value = w.first;
1112  IntVar* const boolvar = w.second;
1113 
1114  if (value <= var_min) {
1115  boolvar->SetValue(1);
1116  watchers_.RemoveAt(pos);
1117  } else if (value > var_max) {
1118  boolvar->SetValue(0);
1119  watchers_.RemoveAt(pos);
1120  }
1121  }
1122  if (watchers_.Empty()) {
1123  var_demon_->inhibit(solver());
1124  }
1125  }
1126  }
1127 
1128  DomainIntVar* const variable_;
1129  RevSwitch posted_;
1130  Demon* var_demon_;
1131  RevIntPtrMap<IntVar> watchers_;
1132  NumericalRev<int> start_;
1133  NumericalRev<int> end_;
1134  bool sorted_;
1135  };
1136 
1137  // Optimized case for small maps.
1138  class DenseUpperBoundWatcher : public BaseUpperBoundWatcher {
1139  public:
1140  class WatchDemon : public Demon {
1141  public:
1142  WatchDemon(DenseUpperBoundWatcher* const watcher, int64_t value,
1143  IntVar* var)
1144  : value_watcher_(watcher), value_(value), var_(var) {}
1145  ~WatchDemon() override {}
1146 
1147  void Run(Solver* const solver) override {
1148  value_watcher_->ProcessUpperBoundWatcher(value_, var_);
1149  }
1150 
1151  private:
1152  DenseUpperBoundWatcher* const value_watcher_;
1153  const int64_t value_;
1154  IntVar* const var_;
1155  };
1156 
1157  class VarDemon : public Demon {
1158  public:
1159  explicit VarDemon(DenseUpperBoundWatcher* const watcher)
1160  : value_watcher_(watcher) {}
1161 
1162  ~VarDemon() override {}
1163 
1164  void Run(Solver* const solver) override { value_watcher_->ProcessVar(); }
1165 
1166  private:
1167  DenseUpperBoundWatcher* const value_watcher_;
1168  };
1169 
1170  DenseUpperBoundWatcher(Solver* const solver, DomainIntVar* const variable)
1171  : BaseUpperBoundWatcher(solver),
1172  variable_(variable),
1173  var_demon_(nullptr),
1174  offset_(variable->Min()),
1175  watchers_(variable->Max() - variable->Min() + 1, nullptr),
1176  active_watchers_(0) {}
1177 
1178  ~DenseUpperBoundWatcher() override {}
1179 
1180  IntVar* GetOrMakeUpperBoundWatcher(int64_t value) override {
1181  if (variable_->Max() >= value) {
1182  if (variable_->Min() >= value) {
1183  return solver()->MakeIntConst(1);
1184  } else {
1185  const std::string vname = variable_->HasName()
1186  ? variable_->name()
1187  : variable_->DebugString();
1188  const std::string bname =
1189  absl::StrFormat("Watch<%s >= %d>", vname, value);
1190  IntVar* const boolvar = solver()->MakeBoolVar(bname);
1191  RevInsert(value - offset_, boolvar);
1192  if (posted_.Switched()) {
1193  boolvar->WhenBound(
1194  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
1195  var_demon_->desinhibit(solver());
1196  }
1197  return boolvar;
1198  }
1199  } else {
1200  return variable_->solver()->MakeIntConst(0);
1201  }
1202  }
1203 
1204  void SetUpperBoundWatcher(IntVar* const boolvar, int64_t value) override {
1205  const int index = value - offset_;
1206  CHECK(watchers_[index] == nullptr);
1207  if (!boolvar->Bound()) {
1208  RevInsert(index, boolvar);
1209  if (posted_.Switched() && !boolvar->Bound()) {
1210  boolvar->WhenBound(
1211  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
1212  var_demon_->desinhibit(solver());
1213  }
1214  }
1215  }
1216 
1217  void Post() override {
1218  var_demon_ = solver()->RevAlloc(new VarDemon(this));
1219  variable_->WhenRange(var_demon_);
1220  for (int pos = 0; pos < watchers_.size(); ++pos) {
1221  const int64_t value = pos + offset_;
1222  IntVar* const boolvar = watchers_[pos];
1223  if (boolvar != nullptr && !boolvar->Bound() &&
1224  value > variable_->Min() && value <= variable_->Max()) {
1225  boolvar->WhenBound(
1226  solver()->RevAlloc(new WatchDemon(this, value, boolvar)));
1227  }
1228  }
1229  posted_.Switch(solver());
1230  }
1231 
1232  void InitialPropagate() override {
1233  for (int pos = 0; pos < watchers_.size(); ++pos) {
1234  IntVar* const boolvar = watchers_[pos];
1235  if (boolvar == nullptr) continue;
1236  const int64_t value = pos + offset_;
1237  if (value <= variable_->Min()) {
1238  boolvar->SetValue(1);
1239  RevRemove(pos);
1240  } else if (value > variable_->Max()) {
1241  boolvar->SetValue(0);
1242  RevRemove(pos);
1243  } else if (boolvar->Bound()) {
1244  ProcessUpperBoundWatcher(value, boolvar);
1245  RevRemove(pos);
1246  }
1247  }
1248  if (active_watchers_.Value() == 0) {
1249  var_demon_->inhibit(solver());
1250  }
1251  }
1252 
1253  void ProcessUpperBoundWatcher(int64_t value, IntVar* boolvar) {
1254  if (boolvar->Min() == 0) {
1255  variable_->SetMax(value - 1);
1256  } else {
1257  variable_->SetMin(value);
1258  }
1259  }
1260 
1261  void ProcessVar() {
1262  const int64_t old_min_index = variable_->OldMin() - offset_;
1263  const int64_t old_max_index = variable_->OldMax() - offset_;
1264  const int64_t min_index = variable_->Min() - offset_;
1265  const int64_t max_index = variable_->Max() - offset_;
1266  for (int pos = old_min_index; pos <= min_index; ++pos) {
1267  IntVar* const boolvar = watchers_[pos];
1268  if (boolvar != nullptr) {
1269  boolvar->SetValue(1);
1270  RevRemove(pos);
1271  }
1272  }
1273 
1274  for (int pos = max_index + 1; pos <= old_max_index; ++pos) {
1275  IntVar* const boolvar = watchers_[pos];
1276  if (boolvar != nullptr) {
1277  boolvar->SetValue(0);
1278  RevRemove(pos);
1279  }
1280  }
1281  if (active_watchers_.Value() == 0) {
1282  var_demon_->inhibit(solver());
1283  }
1284  }
1285 
1286  void RevRemove(int pos) {
1287  solver()->SaveValue(reinterpret_cast<void**>(&watchers_[pos]));
1288  watchers_[pos] = nullptr;
1289  active_watchers_.Decr(solver());
1290  }
1291 
1292  void RevInsert(int pos, IntVar* boolvar) {
1293  solver()->SaveValue(reinterpret_cast<void**>(&watchers_[pos]));
1294  watchers_[pos] = boolvar;
1295  active_watchers_.Incr(solver());
1296  }
1297 
1298  void Accept(ModelVisitor* const visitor) const override {
1299  visitor->BeginVisitConstraint(ModelVisitor::kVarBoundWatcher, this);
1300  visitor->VisitIntegerExpressionArgument(ModelVisitor::kVariableArgument,
1301  variable_);
1302  std::vector<int64_t> all_coefficients;
1303  std::vector<IntVar*> all_bool_vars;
1304  for (int position = 0; position < watchers_.size(); ++position) {
1305  if (watchers_[position] != nullptr) {
1306  all_coefficients.push_back(position + offset_);
1307  all_bool_vars.push_back(watchers_[position]);
1308  }
1309  }
1310  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1311  all_bool_vars);
1312  visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
1313  all_coefficients);
1314  visitor->EndVisitConstraint(ModelVisitor::kVarBoundWatcher, this);
1315  }
1316 
1317  std::string DebugString() const override {
1318  return absl::StrFormat("DenseUpperBoundWatcher(%s)",
1319  variable_->DebugString());
1320  }
1321 
1322  private:
1323  DomainIntVar* const variable_;
1324  RevSwitch posted_;
1325  Demon* var_demon_;
1326  const int64_t offset_;
1327  std::vector<IntVar*> watchers_;
1328  NumericalRev<int> active_watchers_;
1329  };
1330 
1331  // ----- Main Class -----
1332  DomainIntVar(Solver* const s, int64_t vmin, int64_t vmax,
1333  const std::string& name);
1334  DomainIntVar(Solver* const s, const std::vector<int64_t>& sorted_values,
1335  const std::string& name);
1336  ~DomainIntVar() override;
1337 
1338  int64_t Min() const override { return min_.Value(); }
1339  void SetMin(int64_t m) override;
1340  int64_t Max() const override { return max_.Value(); }
1341  void SetMax(int64_t m) override;
1342  void SetRange(int64_t mi, int64_t ma) override;
1343  void SetValue(int64_t v) override;
1344  bool Bound() const override { return (min_.Value() == max_.Value()); }
1345  int64_t Value() const override {
1346  CHECK_EQ(min_.Value(), max_.Value())
1347  << " variable " << DebugString() << " is not bound.";
1348  return min_.Value();
1349  }
1350  void RemoveValue(int64_t v) override;
1351  void RemoveInterval(int64_t l, int64_t u) override;
1352  void CreateBits();
1353  void WhenBound(Demon* d) override {
1354  if (min_.Value() != max_.Value()) {
1355  if (d->priority() == Solver::DELAYED_PRIORITY) {
1356  delayed_bound_demons_.PushIfNotTop(solver(),
1357  solver()->RegisterDemon(d));
1358  } else {
1359  bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
1360  }
1361  }
1362  }
1363  void WhenRange(Demon* d) override {
1364  if (min_.Value() != max_.Value()) {
1365  if (d->priority() == Solver::DELAYED_PRIORITY) {
1366  delayed_range_demons_.PushIfNotTop(solver(),
1367  solver()->RegisterDemon(d));
1368  } else {
1369  range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
1370  }
1371  }
1372  }
1373  void WhenDomain(Demon* d) override {
1374  if (min_.Value() != max_.Value()) {
1375  if (d->priority() == Solver::DELAYED_PRIORITY) {
1376  delayed_domain_demons_.PushIfNotTop(solver(),
1377  solver()->RegisterDemon(d));
1378  } else {
1379  domain_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
1380  }
1381  }
1382  }
1383 
1384  IntVar* IsEqual(int64_t constant) override {
1385  Solver* const s = solver();
1386  if (constant == min_.Value() && value_watcher_ == nullptr) {
1387  return s->MakeIsLessOrEqualCstVar(this, constant);
1388  }
1389  if (constant == max_.Value() && value_watcher_ == nullptr) {
1390  return s->MakeIsGreaterOrEqualCstVar(this, constant);
1391  }
1392  if (!Contains(constant)) {
1393  return s->MakeIntConst(int64_t{0});
1394  }
1395  if (Bound() && min_.Value() == constant) {
1396  return s->MakeIntConst(int64_t{1});
1397  }
1398  IntExpr* const cache = s->Cache()->FindExprConstantExpression(
1399  this, constant, ModelCache::EXPR_CONSTANT_IS_EQUAL);
1400  if (cache != nullptr) {
1401  return cache->Var();
1402  } else {
1403  if (value_watcher_ == nullptr) {
1404  if (CapSub(Max(), Min()) <= 256) {
1405  solver()->SaveAndSetValue(
1406  reinterpret_cast<void**>(&value_watcher_),
1407  reinterpret_cast<void*>(
1408  solver()->RevAlloc(new DenseValueWatcher(solver(), this))));
1409 
1410  } else {
1411  solver()->SaveAndSetValue(reinterpret_cast<void**>(&value_watcher_),
1412  reinterpret_cast<void*>(solver()->RevAlloc(
1413  new ValueWatcher(solver(), this))));
1414  }
1415  solver()->AddConstraint(value_watcher_);
1416  }
1417  IntVar* const boolvar = value_watcher_->GetOrMakeValueWatcher(constant);
1418  s->Cache()->InsertExprConstantExpression(
1419  boolvar, this, constant, ModelCache::EXPR_CONSTANT_IS_EQUAL);
1420  return boolvar;
1421  }
1422  }
1423 
1424  Constraint* SetIsEqual(const std::vector<int64_t>& values,
1425  const std::vector<IntVar*>& vars) {
1426  if (value_watcher_ == nullptr) {
1427  solver()->SaveAndSetValue(reinterpret_cast<void**>(&value_watcher_),
1428  reinterpret_cast<void*>(solver()->RevAlloc(
1429  new ValueWatcher(solver(), this))));
1430  for (int i = 0; i < vars.size(); ++i) {
1431  value_watcher_->SetValueWatcher(vars[i], values[i]);
1432  }
1433  }
1434  return value_watcher_;
1435  }
1436 
1437  IntVar* IsDifferent(int64_t constant) override {
1438  Solver* const s = solver();
1439  if (constant == min_.Value() && value_watcher_ == nullptr) {
1440  return s->MakeIsGreaterOrEqualCstVar(this, constant + 1);
1441  }
1442  if (constant == max_.Value() && value_watcher_ == nullptr) {
1443  return s->MakeIsLessOrEqualCstVar(this, constant - 1);
1444  }
1445  if (!Contains(constant)) {
1446  return s->MakeIntConst(int64_t{1});
1447  }
1448  if (Bound() && min_.Value() == constant) {
1449  return s->MakeIntConst(int64_t{0});
1450  }
1451  IntExpr* const cache = s->Cache()->FindExprConstantExpression(
1452  this, constant, ModelCache::EXPR_CONSTANT_IS_NOT_EQUAL);
1453  if (cache != nullptr) {
1454  return cache->Var();
1455  } else {
1456  IntVar* const boolvar = s->MakeDifference(1, IsEqual(constant))->Var();
1457  s->Cache()->InsertExprConstantExpression(
1458  boolvar, this, constant, ModelCache::EXPR_CONSTANT_IS_NOT_EQUAL);
1459  return boolvar;
1460  }
1461  }
1462 
1463  IntVar* IsGreaterOrEqual(int64_t constant) override {
1464  Solver* const s = solver();
1465  if (max_.Value() < constant) {
1466  return s->MakeIntConst(int64_t{0});
1467  }
1468  if (min_.Value() >= constant) {
1469  return s->MakeIntConst(int64_t{1});
1470  }
1471  IntExpr* const cache = s->Cache()->FindExprConstantExpression(
1473  if (cache != nullptr) {
1474  return cache->Var();
1475  } else {
1476  if (bound_watcher_ == nullptr) {
1477  if (CapSub(Max(), Min()) <= 256) {
1478  solver()->SaveAndSetValue(
1479  reinterpret_cast<void**>(&bound_watcher_),
1480  reinterpret_cast<void*>(solver()->RevAlloc(
1481  new DenseUpperBoundWatcher(solver(), this))));
1482  solver()->AddConstraint(bound_watcher_);
1483  } else {
1484  solver()->SaveAndSetValue(
1485  reinterpret_cast<void**>(&bound_watcher_),
1486  reinterpret_cast<void*>(
1487  solver()->RevAlloc(new UpperBoundWatcher(solver(), this))));
1488  solver()->AddConstraint(bound_watcher_);
1489  }
1490  }
1491  IntVar* const boolvar =
1492  bound_watcher_->GetOrMakeUpperBoundWatcher(constant);
1493  s->Cache()->InsertExprConstantExpression(
1494  boolvar, this, constant,
1496  return boolvar;
1497  }
1498  }
1499 
1500  Constraint* SetIsGreaterOrEqual(const std::vector<int64_t>& values,
1501  const std::vector<IntVar*>& vars) {
1502  if (bound_watcher_ == nullptr) {
1503  if (CapSub(Max(), Min()) <= 256) {
1504  solver()->SaveAndSetValue(
1505  reinterpret_cast<void**>(&bound_watcher_),
1506  reinterpret_cast<void*>(solver()->RevAlloc(
1507  new DenseUpperBoundWatcher(solver(), this))));
1508  solver()->AddConstraint(bound_watcher_);
1509  } else {
1510  solver()->SaveAndSetValue(reinterpret_cast<void**>(&bound_watcher_),
1511  reinterpret_cast<void*>(solver()->RevAlloc(
1512  new UpperBoundWatcher(solver(), this))));
1513  solver()->AddConstraint(bound_watcher_);
1514  }
1515  for (int i = 0; i < values.size(); ++i) {
1516  bound_watcher_->SetUpperBoundWatcher(vars[i], values[i]);
1517  }
1518  }
1519  return bound_watcher_;
1520  }
1521 
1522  IntVar* IsLessOrEqual(int64_t constant) override {
1523  Solver* const s = solver();
1524  IntExpr* const cache = s->Cache()->FindExprConstantExpression(
1526  if (cache != nullptr) {
1527  return cache->Var();
1528  } else {
1529  IntVar* const boolvar =
1530  s->MakeDifference(1, IsGreaterOrEqual(constant + 1))->Var();
1531  s->Cache()->InsertExprConstantExpression(
1532  boolvar, this, constant, ModelCache::EXPR_CONSTANT_IS_LESS_OR_EQUAL);
1533  return boolvar;
1534  }
1535  }
1536 
1537  void Process();
1538  void Push();
1539  void CleanInProcess();
1540  uint64_t Size() const override {
1541  if (bits_ != nullptr) return bits_->Size();
1542  return (static_cast<uint64_t>(max_.Value()) -
1543  static_cast<uint64_t>(min_.Value()) + 1);
1544  }
1545  bool Contains(int64_t v) const override {
1546  if (v < min_.Value() || v > max_.Value()) return false;
1547  return (bits_ == nullptr ? true : bits_->Contains(v));
1548  }
1549  IntVarIterator* MakeHoleIterator(bool reversible) const override;
1550  IntVarIterator* MakeDomainIterator(bool reversible) const override;
1551  int64_t OldMin() const override { return std::min(old_min_, min_.Value()); }
1552  int64_t OldMax() const override { return std::max(old_max_, max_.Value()); }
1553 
1554  std::string DebugString() const override;
1555  BitSet* bitset() const { return bits_; }
1556  int VarType() const override { return DOMAIN_INT_VAR; }
1557  std::string BaseName() const override { return "IntegerVar"; }
1558 
1559  friend class PlusCstDomainIntVar;
1560  friend class LinkExprAndDomainIntVar;
1561 
1562  private:
1563  void CheckOldMin() {
1564  if (old_min_ > min_.Value()) {
1565  old_min_ = min_.Value();
1566  }
1567  }
1568  void CheckOldMax() {
1569  if (old_max_ < max_.Value()) {
1570  old_max_ = max_.Value();
1571  }
1572  }
1573  Rev<int64_t> min_;
1574  Rev<int64_t> max_;
1575  int64_t old_min_;
1576  int64_t old_max_;
1577  int64_t new_min_;
1578  int64_t new_max_;
1579  SimpleRevFIFO<Demon*> bound_demons_;
1580  SimpleRevFIFO<Demon*> range_demons_;
1581  SimpleRevFIFO<Demon*> domain_demons_;
1582  SimpleRevFIFO<Demon*> delayed_bound_demons_;
1583  SimpleRevFIFO<Demon*> delayed_range_demons_;
1584  SimpleRevFIFO<Demon*> delayed_domain_demons_;
1585  QueueHandler handler_;
1586  bool in_process_;
1587  BitSet* bits_;
1588  BaseValueWatcher* value_watcher_;
1589  BaseUpperBoundWatcher* bound_watcher_;
1590 };
1591 
1592 // ----- BitSet -----
1593 
1594 // Return whether an integer interval [a..b] (inclusive) contains at most
1595 // K values, i.e. b - a < K, in a way that's robust to overflows.
1596 // For performance reasons, in opt mode it doesn't check that [a, b] is a
1597 // valid interval, nor that K is nonnegative.
1598 inline bool ClosedIntervalNoLargerThan(int64_t a, int64_t b, int64_t K) {
1599  DCHECK_LE(a, b);
1600  DCHECK_GE(K, 0);
1601  if (a > 0) {
1602  return a > b - K;
1603  } else {
1604  return a + K > b;
1605  }
1606 }
1607 
1608 class SimpleBitSet : public DomainIntVar::BitSet {
1609  public:
1610  SimpleBitSet(Solver* const s, int64_t vmin, int64_t vmax)
1611  : BitSet(s),
1612  bits_(nullptr),
1613  stamps_(nullptr),
1614  omin_(vmin),
1615  omax_(vmax),
1616  size_(vmax - vmin + 1),
1617  bsize_(BitLength64(size_.Value())) {
1618  CHECK(ClosedIntervalNoLargerThan(vmin, vmax, 0xFFFFFFFF))
1619  << "Bitset too large: [" << vmin << ", " << vmax << "]";
1620  bits_ = new uint64_t[bsize_];
1621  stamps_ = new uint64_t[bsize_];
1622  for (int i = 0; i < bsize_; ++i) {
1623  const int bs =
1624  (i == size_.Value() - 1) ? 63 - BitPos64(size_.Value()) : 0;
1625  bits_[i] = kAllBits64 >> bs;
1626  stamps_[i] = s->stamp() - 1;
1627  }
1628  }
1629 
1630  SimpleBitSet(Solver* const s, const std::vector<int64_t>& sorted_values,
1631  int64_t vmin, int64_t vmax)
1632  : BitSet(s),
1633  bits_(nullptr),
1634  stamps_(nullptr),
1635  omin_(vmin),
1636  omax_(vmax),
1637  size_(sorted_values.size()),
1638  bsize_(BitLength64(vmax - vmin + 1)) {
1639  CHECK(ClosedIntervalNoLargerThan(vmin, vmax, 0xFFFFFFFF))
1640  << "Bitset too large: [" << vmin << ", " << vmax << "]";
1641  bits_ = new uint64_t[bsize_];
1642  stamps_ = new uint64_t[bsize_];
1643  for (int i = 0; i < bsize_; ++i) {
1644  bits_[i] = uint64_t{0};
1645  stamps_[i] = s->stamp() - 1;
1646  }
1647  for (int i = 0; i < sorted_values.size(); ++i) {
1648  const int64_t val = sorted_values[i];
1649  DCHECK(!bit(val));
1650  const int offset = BitOffset64(val - omin_);
1651  const int pos = BitPos64(val - omin_);
1652  bits_[offset] |= OneBit64(pos);
1653  }
1654  }
1655 
1656  ~SimpleBitSet() override {
1657  delete[] bits_;
1658  delete[] stamps_;
1659  }
1660 
1661  bool bit(int64_t val) const { return IsBitSet64(bits_, val - omin_); }
1662 
1663  int64_t ComputeNewMin(int64_t nmin, int64_t cmin, int64_t cmax) override {
1664  DCHECK_GE(nmin, cmin);
1665  DCHECK_LE(nmin, cmax);
1666  DCHECK_LE(cmin, cmax);
1667  DCHECK_GE(cmin, omin_);
1668  DCHECK_LE(cmax, omax_);
1669  const int64_t new_min =
1670  UnsafeLeastSignificantBitPosition64(bits_, nmin - omin_, cmax - omin_) +
1671  omin_;
1672  const uint64_t removed_bits =
1673  BitCountRange64(bits_, cmin - omin_, new_min - omin_ - 1);
1674  size_.Add(solver_, -removed_bits);
1675  return new_min;
1676  }
1677 
1678  int64_t ComputeNewMax(int64_t nmax, int64_t cmin, int64_t cmax) override {
1679  DCHECK_GE(nmax, cmin);
1680  DCHECK_LE(nmax, cmax);
1681  DCHECK_LE(cmin, cmax);
1682  DCHECK_GE(cmin, omin_);
1683  DCHECK_LE(cmax, omax_);
1684  const int64_t new_max =
1685  UnsafeMostSignificantBitPosition64(bits_, cmin - omin_, nmax - omin_) +
1686  omin_;
1687  const uint64_t removed_bits =
1688  BitCountRange64(bits_, new_max - omin_ + 1, cmax - omin_);
1689  size_.Add(solver_, -removed_bits);
1690  return new_max;
1691  }
1692 
1693  bool SetValue(int64_t val) override {
1694  DCHECK_GE(val, omin_);
1695  DCHECK_LE(val, omax_);
1696  if (bit(val)) {
1697  size_.SetValue(solver_, 1);
1698  return true;
1699  }
1700  return false;
1701  }
1702 
1703  bool Contains(int64_t val) const override {
1704  DCHECK_GE(val, omin_);
1705  DCHECK_LE(val, omax_);
1706  return bit(val);
1707  }
1708 
1709  bool RemoveValue(int64_t val) override {
1710  if (val < omin_ || val > omax_ || !bit(val)) {
1711  return false;
1712  }
1713  // Bitset.
1714  const int64_t val_offset = val - omin_;
1715  const int offset = BitOffset64(val_offset);
1716  const uint64_t current_stamp = solver_->stamp();
1717  if (stamps_[offset] < current_stamp) {
1718  stamps_[offset] = current_stamp;
1719  solver_->SaveValue(&bits_[offset]);
1720  }
1721  const int pos = BitPos64(val_offset);
1722  bits_[offset] &= ~OneBit64(pos);
1723  // Size.
1724  size_.Decr(solver_);
1725  // Holes.
1726  InitHoles();
1727  AddHole(val);
1728  return true;
1729  }
1730  uint64_t Size() const override { return size_.Value(); }
1731 
1732  std::string DebugString() const override {
1733  std::string out;
1734  absl::StrAppendFormat(&out, "SimpleBitSet(%d..%d : ", omin_, omax_);
1735  for (int i = 0; i < bsize_; ++i) {
1736  absl::StrAppendFormat(&out, "%x", bits_[i]);
1737  }
1738  out += ")";
1739  return out;
1740  }
1741 
1742  void DelayRemoveValue(int64_t val) override { removed_.push_back(val); }
1743 
1744  void ApplyRemovedValues(DomainIntVar* var) override {
1745  std::sort(removed_.begin(), removed_.end());
1746  for (std::vector<int64_t>::iterator it = removed_.begin();
1747  it != removed_.end(); ++it) {
1748  var->RemoveValue(*it);
1749  }
1750  }
1751 
1752  void ClearRemovedValues() override { removed_.clear(); }
1753 
1754  std::string pretty_DebugString(int64_t min, int64_t max) const override {
1755  std::string out;
1756  DCHECK(bit(min));
1757  DCHECK(bit(max));
1758  if (max != min) {
1759  int cumul = true;
1760  int64_t start_cumul = min;
1761  for (int64_t v = min + 1; v < max; ++v) {
1762  if (bit(v)) {
1763  if (!cumul) {
1764  cumul = true;
1765  start_cumul = v;
1766  }
1767  } else {
1768  if (cumul) {
1769  if (v == start_cumul + 1) {
1770  absl::StrAppendFormat(&out, "%d ", start_cumul);
1771  } else if (v == start_cumul + 2) {
1772  absl::StrAppendFormat(&out, "%d %d ", start_cumul, v - 1);
1773  } else {
1774  absl::StrAppendFormat(&out, "%d..%d ", start_cumul, v - 1);
1775  }
1776  cumul = false;
1777  }
1778  }
1779  }
1780  if (cumul) {
1781  if (max == start_cumul + 1) {
1782  absl::StrAppendFormat(&out, "%d %d", start_cumul, max);
1783  } else {
1784  absl::StrAppendFormat(&out, "%d..%d", start_cumul, max);
1785  }
1786  } else {
1787  absl::StrAppendFormat(&out, "%d", max);
1788  }
1789  } else {
1790  absl::StrAppendFormat(&out, "%d", min);
1791  }
1792  return out;
1793  }
1794 
1795  DomainIntVar::BitSetIterator* MakeIterator() override {
1796  return new DomainIntVar::BitSetIterator(bits_, omin_);
1797  }
1798 
1799  private:
1800  uint64_t* bits_;
1801  uint64_t* stamps_;
1802  const int64_t omin_;
1803  const int64_t omax_;
1804  NumericalRev<int64_t> size_;
1805  const int bsize_;
1806  std::vector<int64_t> removed_;
1807 };
1808 
1809 // This is a special case where the bitset fits into one 64 bit integer.
1810 // In that case, there are no offset to compute.
1811 // Overflows are caught by the robust ClosedIntervalNoLargerThan() method.
1812 class SmallBitSet : public DomainIntVar::BitSet {
1813  public:
1814  SmallBitSet(Solver* const s, int64_t vmin, int64_t vmax)
1815  : BitSet(s),
1816  bits_(uint64_t{0}),
1817  stamp_(s->stamp() - 1),
1818  omin_(vmin),
1819  omax_(vmax),
1820  size_(vmax - vmin + 1) {
1821  CHECK(ClosedIntervalNoLargerThan(vmin, vmax, 64)) << vmin << ", " << vmax;
1822  bits_ = OneRange64(0, size_.Value() - 1);
1823  }
1824 
1825  SmallBitSet(Solver* const s, const std::vector<int64_t>& sorted_values,
1826  int64_t vmin, int64_t vmax)
1827  : BitSet(s),
1828  bits_(uint64_t{0}),
1829  stamp_(s->stamp() - 1),
1830  omin_(vmin),
1831  omax_(vmax),
1832  size_(sorted_values.size()) {
1833  CHECK(ClosedIntervalNoLargerThan(vmin, vmax, 64)) << vmin << ", " << vmax;
1834  // We know the array is sorted and does not contains duplicate values.
1835  for (int i = 0; i < sorted_values.size(); ++i) {
1836  const int64_t val = sorted_values[i];
1837  DCHECK_GE(val, vmin);
1838  DCHECK_LE(val, vmax);
1839  DCHECK(!IsBitSet64(&bits_, val - omin_));
1840  bits_ |= OneBit64(val - omin_);
1841  }
1842  }
1843 
1844  ~SmallBitSet() override {}
1845 
1846  bool bit(int64_t val) const {
1847  DCHECK_GE(val, omin_);
1848  DCHECK_LE(val, omax_);
1849  return (bits_ & OneBit64(val - omin_)) != 0;
1850  }
1851 
1852  int64_t ComputeNewMin(int64_t nmin, int64_t cmin, int64_t cmax) override {
1853  DCHECK_GE(nmin, cmin);
1854  DCHECK_LE(nmin, cmax);
1855  DCHECK_LE(cmin, cmax);
1856  DCHECK_GE(cmin, omin_);
1857  DCHECK_LE(cmax, omax_);
1858  // We do not clean the bits between cmin and nmin.
1859  // But we use mask to look only at 'active' bits.
1860 
1861  // Create the mask and compute new bits
1862  const uint64_t new_bits = bits_ & OneRange64(nmin - omin_, cmax - omin_);
1863  if (new_bits != uint64_t{0}) {
1864  // Compute new size and new min
1865  size_.SetValue(solver_, BitCount64(new_bits));
1866  if (bit(nmin)) { // Common case, the new min is inside the bitset
1867  return nmin;
1868  }
1869  return LeastSignificantBitPosition64(new_bits) + omin_;
1870  } else { // == 0 -> Fail()
1871  solver_->Fail();
1873  }
1874  }
1875 
1876  int64_t ComputeNewMax(int64_t nmax, int64_t cmin, int64_t cmax) override {
1877  DCHECK_GE(nmax, cmin);
1878  DCHECK_LE(nmax, cmax);
1879  DCHECK_LE(cmin, cmax);
1880  DCHECK_GE(cmin, omin_);
1881  DCHECK_LE(cmax, omax_);
1882  // We do not clean the bits between nmax and cmax.
1883  // But we use mask to look only at 'active' bits.
1884 
1885  // Create the mask and compute new_bits
1886  const uint64_t new_bits = bits_ & OneRange64(cmin - omin_, nmax - omin_);
1887  if (new_bits != uint64_t{0}) {
1888  // Compute new size and new min
1889  size_.SetValue(solver_, BitCount64(new_bits));
1890  if (bit(nmax)) { // Common case, the new max is inside the bitset
1891  return nmax;
1892  }
1893  return MostSignificantBitPosition64(new_bits) + omin_;
1894  } else { // == 0 -> Fail()
1895  solver_->Fail();
1897  }
1898  }
1899 
1900  bool SetValue(int64_t val) override {
1901  DCHECK_GE(val, omin_);
1902  DCHECK_LE(val, omax_);
1903  // We do not clean the bits. We will use masks to ignore the bits
1904  // that should have been cleaned.
1905  if (bit(val)) {
1906  size_.SetValue(solver_, 1);
1907  return true;
1908  }
1909  return false;
1910  }
1911 
1912  bool Contains(int64_t val) const override {
1913  DCHECK_GE(val, omin_);
1914  DCHECK_LE(val, omax_);
1915  return bit(val);
1916  }
1917 
1918  bool RemoveValue(int64_t val) override {
1919  DCHECK_GE(val, omin_);
1920  DCHECK_LE(val, omax_);
1921  if (bit(val)) {
1922  // Bitset.
1923  const uint64_t current_stamp = solver_->stamp();
1924  if (stamp_ < current_stamp) {
1925  stamp_ = current_stamp;
1926  solver_->SaveValue(&bits_);
1927  }
1928  bits_ &= ~OneBit64(val - omin_);
1929  DCHECK(!bit(val));
1930  // Size.
1931  size_.Decr(solver_);
1932  // Holes.
1933  InitHoles();
1934  AddHole(val);
1935  return true;
1936  } else {
1937  return false;
1938  }
1939  }
1940 
1941  uint64_t Size() const override { return size_.Value(); }
1942 
1943  std::string DebugString() const override {
1944  return absl::StrFormat("SmallBitSet(%d..%d : %llx)", omin_, omax_, bits_);
1945  }
1946 
1947  void DelayRemoveValue(int64_t val) override {
1948  DCHECK_GE(val, omin_);
1949  DCHECK_LE(val, omax_);
1950  removed_.push_back(val);
1951  }
1952 
1953  void ApplyRemovedValues(DomainIntVar* var) override {
1954  std::sort(removed_.begin(), removed_.end());
1955  for (std::vector<int64_t>::iterator it = removed_.begin();
1956  it != removed_.end(); ++it) {
1957  var->RemoveValue(*it);
1958  }
1959  }
1960 
1961  void ClearRemovedValues() override { removed_.clear(); }
1962 
1963  std::string pretty_DebugString(int64_t min, int64_t max) const override {
1964  std::string out;
1965  DCHECK(bit(min));
1966  DCHECK(bit(max));
1967  if (max != min) {
1968  int cumul = true;
1969  int64_t start_cumul = min;
1970  for (int64_t v = min + 1; v < max; ++v) {
1971  if (bit(v)) {
1972  if (!cumul) {
1973  cumul = true;
1974  start_cumul = v;
1975  }
1976  } else {
1977  if (cumul) {
1978  if (v == start_cumul + 1) {
1979  absl::StrAppendFormat(&out, "%d ", start_cumul);
1980  } else if (v == start_cumul + 2) {
1981  absl::StrAppendFormat(&out, "%d %d ", start_cumul, v - 1);
1982  } else {
1983  absl::StrAppendFormat(&out, "%d..%d ", start_cumul, v - 1);
1984  }
1985  cumul = false;
1986  }
1987  }
1988  }
1989  if (cumul) {
1990  if (max == start_cumul + 1) {
1991  absl::StrAppendFormat(&out, "%d %d", start_cumul, max);
1992  } else {
1993  absl::StrAppendFormat(&out, "%d..%d", start_cumul, max);
1994  }
1995  } else {
1996  absl::StrAppendFormat(&out, "%d", max);
1997  }
1998  } else {
1999  absl::StrAppendFormat(&out, "%d", min);
2000  }
2001  return out;
2002  }
2003 
2004  DomainIntVar::BitSetIterator* MakeIterator() override {
2005  return new DomainIntVar::BitSetIterator(&bits_, omin_);
2006  }
2007 
2008  private:
2009  uint64_t bits_;
2010  uint64_t stamp_;
2011  const int64_t omin_;
2012  const int64_t omax_;
2013  NumericalRev<int64_t> size_;
2014  std::vector<int64_t> removed_;
2015 };
2016 
2017 class EmptyIterator : public IntVarIterator {
2018  public:
2019  ~EmptyIterator() override {}
2020  void Init() override {}
2021  bool Ok() const override { return false; }
2022  int64_t Value() const override {
2023  LOG(FATAL) << "Should not be called";
2024  return 0LL;
2025  }
2026  void Next() override {}
2027 };
2028 
2029 class RangeIterator : public IntVarIterator {
2030  public:
2031  explicit RangeIterator(const IntVar* const var)
2032  : var_(var),
2033  min_(std::numeric_limits<int64_t>::max()),
2034  max_(std::numeric_limits<int64_t>::min()),
2035  current_(-1) {}
2036 
2037  ~RangeIterator() override {}
2038 
2039  void Init() override {
2040  min_ = var_->Min();
2041  max_ = var_->Max();
2042  current_ = min_;
2043  }
2044 
2045  bool Ok() const override { return current_ <= max_; }
2046 
2047  int64_t Value() const override { return current_; }
2048 
2049  void Next() override { current_++; }
2050 
2051  private:
2052  const IntVar* const var_;
2053  int64_t min_;
2054  int64_t max_;
2055  int64_t current_;
2056 };
2057 
2058 class DomainIntVarHoleIterator : public IntVarIterator {
2059  public:
2060  explicit DomainIntVarHoleIterator(const DomainIntVar* const v)
2061  : var_(v), bits_(nullptr), values_(nullptr), size_(0), index_(0) {}
2062 
2063  ~DomainIntVarHoleIterator() override {}
2064 
2065  void Init() override {
2066  bits_ = var_->bitset();
2067  if (bits_ != nullptr) {
2068  bits_->InitHoles();
2069  values_ = bits_->Holes().data();
2070  size_ = bits_->Holes().size();
2071  } else {
2072  values_ = nullptr;
2073  size_ = 0;
2074  }
2075  index_ = 0;
2076  }
2077 
2078  bool Ok() const override { return index_ < size_; }
2079 
2080  int64_t Value() const override {
2081  DCHECK(bits_ != nullptr);
2082  DCHECK(index_ < size_);
2083  return values_[index_];
2084  }
2085 
2086  void Next() override { index_++; }
2087 
2088  private:
2089  const DomainIntVar* const var_;
2090  DomainIntVar::BitSet* bits_;
2091  const int64_t* values_;
2092  int size_;
2093  int index_;
2094 };
2095 
2096 class DomainIntVarDomainIterator : public IntVarIterator {
2097  public:
2098  explicit DomainIntVarDomainIterator(const DomainIntVar* const v,
2099  bool reversible)
2100  : var_(v),
2101  bitset_iterator_(nullptr),
2102  min_(std::numeric_limits<int64_t>::max()),
2103  max_(std::numeric_limits<int64_t>::min()),
2104  current_(-1),
2105  reversible_(reversible) {}
2106 
2107  ~DomainIntVarDomainIterator() override {
2108  if (!reversible_ && bitset_iterator_) {
2109  delete bitset_iterator_;
2110  }
2111  }
2112 
2113  void Init() override {
2114  if (var_->bitset() != nullptr && !var_->Bound()) {
2115  if (reversible_) {
2116  if (!bitset_iterator_) {
2117  Solver* const solver = var_->solver();
2118  solver->SaveValue(reinterpret_cast<void**>(&bitset_iterator_));
2119  bitset_iterator_ = solver->RevAlloc(var_->bitset()->MakeIterator());
2120  }
2121  } else {
2122  if (bitset_iterator_) {
2123  delete bitset_iterator_;
2124  }
2125  bitset_iterator_ = var_->bitset()->MakeIterator();
2126  }
2127  bitset_iterator_->Init(var_->Min(), var_->Max());
2128  } else {
2129  if (bitset_iterator_) {
2130  if (reversible_) {
2131  Solver* const solver = var_->solver();
2132  solver->SaveValue(reinterpret_cast<void**>(&bitset_iterator_));
2133  } else {
2134  delete bitset_iterator_;
2135  }
2136  bitset_iterator_ = nullptr;
2137  }
2138  min_ = var_->Min();
2139  max_ = var_->Max();
2140  current_ = min_;
2141  }
2142  }
2143 
2144  bool Ok() const override {
2145  return bitset_iterator_ ? bitset_iterator_->Ok() : (current_ <= max_);
2146  }
2147 
2148  int64_t Value() const override {
2149  return bitset_iterator_ ? bitset_iterator_->Value() : current_;
2150  }
2151 
2152  void Next() override {
2153  if (bitset_iterator_) {
2154  bitset_iterator_->Next();
2155  } else {
2156  current_++;
2157  }
2158  }
2159 
2160  private:
2161  const DomainIntVar* const var_;
2162  DomainIntVar::BitSetIterator* bitset_iterator_;
2163  int64_t min_;
2164  int64_t max_;
2165  int64_t current_;
2166  const bool reversible_;
2167 };
2168 
2169 class UnaryIterator : public IntVarIterator {
2170  public:
2171  UnaryIterator(const IntVar* const v, bool hole, bool reversible)
2172  : iterator_(hole ? v->MakeHoleIterator(reversible)
2173  : v->MakeDomainIterator(reversible)),
2174  reversible_(reversible) {}
2175 
2176  ~UnaryIterator() override {
2177  if (!reversible_) {
2178  delete iterator_;
2179  }
2180  }
2181 
2182  void Init() override { iterator_->Init(); }
2183 
2184  bool Ok() const override { return iterator_->Ok(); }
2185 
2186  void Next() override { iterator_->Next(); }
2187 
2188  protected:
2189  IntVarIterator* const iterator_;
2190  const bool reversible_;
2191 };
2192 
2193 DomainIntVar::DomainIntVar(Solver* const s, int64_t vmin, int64_t vmax,
2194  const std::string& name)
2195  : IntVar(s, name),
2196  min_(vmin),
2197  max_(vmax),
2198  old_min_(vmin),
2199  old_max_(vmax),
2200  new_min_(vmin),
2201  new_max_(vmax),
2202  handler_(this),
2203  in_process_(false),
2204  bits_(nullptr),
2205  value_watcher_(nullptr),
2206  bound_watcher_(nullptr) {}
2207 
2208 DomainIntVar::DomainIntVar(Solver* const s,
2209  const std::vector<int64_t>& sorted_values,
2210  const std::string& name)
2211  : IntVar(s, name),
2212  min_(std::numeric_limits<int64_t>::max()),
2213  max_(std::numeric_limits<int64_t>::min()),
2214  old_min_(std::numeric_limits<int64_t>::max()),
2215  old_max_(std::numeric_limits<int64_t>::min()),
2216  new_min_(std::numeric_limits<int64_t>::max()),
2217  new_max_(std::numeric_limits<int64_t>::min()),
2218  handler_(this),
2219  in_process_(false),
2220  bits_(nullptr),
2221  value_watcher_(nullptr),
2222  bound_watcher_(nullptr) {
2223  CHECK_GE(sorted_values.size(), 1);
2224  // We know that the vector is sorted and does not have duplicate values.
2225  const int64_t vmin = sorted_values.front();
2226  const int64_t vmax = sorted_values.back();
2227  const bool contiguous = vmax - vmin + 1 == sorted_values.size();
2228 
2229  min_.SetValue(solver(), vmin);
2230  old_min_ = vmin;
2231  new_min_ = vmin;
2232  max_.SetValue(solver(), vmax);
2233  old_max_ = vmax;
2234  new_max_ = vmax;
2235 
2236  if (!contiguous) {
2237  if (vmax - vmin + 1 < 65) {
2238  bits_ = solver()->RevAlloc(
2239  new SmallBitSet(solver(), sorted_values, vmin, vmax));
2240  } else {
2241  bits_ = solver()->RevAlloc(
2242  new SimpleBitSet(solver(), sorted_values, vmin, vmax));
2243  }
2244  }
2245 }
2246 
2247 DomainIntVar::~DomainIntVar() {}
2248 
2249 void DomainIntVar::SetMin(int64_t m) {
2250  if (m <= min_.Value()) return;
2251  if (m > max_.Value()) solver()->Fail();
2252  if (in_process_) {
2253  if (m > new_min_) {
2254  new_min_ = m;
2255  if (new_min_ > new_max_) {
2256  solver()->Fail();
2257  }
2258  }
2259  } else {
2260  CheckOldMin();
2261  const int64_t new_min =
2262  (bits_ == nullptr
2263  ? m
2264  : bits_->ComputeNewMin(m, min_.Value(), max_.Value()));
2265  min_.SetValue(solver(), new_min);
2266  if (min_.Value() > max_.Value()) {
2267  solver()->Fail();
2268  }
2269  Push();
2270  }
2271 }
2272 
2273 void DomainIntVar::SetMax(int64_t m) {
2274  if (m >= max_.Value()) return;
2275  if (m < min_.Value()) solver()->Fail();
2276  if (in_process_) {
2277  if (m < new_max_) {
2278  new_max_ = m;
2279  if (new_max_ < new_min_) {
2280  solver()->Fail();
2281  }
2282  }
2283  } else {
2284  CheckOldMax();
2285  const int64_t new_max =
2286  (bits_ == nullptr
2287  ? m
2288  : bits_->ComputeNewMax(m, min_.Value(), max_.Value()));
2289  max_.SetValue(solver(), new_max);
2290  if (min_.Value() > max_.Value()) {
2291  solver()->Fail();
2292  }
2293  Push();
2294  }
2295 }
2296 
2297 void DomainIntVar::SetRange(int64_t mi, int64_t ma) {
2298  if (mi == ma) {
2299  SetValue(mi);
2300  } else {
2301  if (mi > ma || mi > max_.Value() || ma < min_.Value()) solver()->Fail();
2302  if (mi <= min_.Value() && ma >= max_.Value()) return;
2303  if (in_process_) {
2304  if (ma < new_max_) {
2305  new_max_ = ma;
2306  }
2307  if (mi > new_min_) {
2308  new_min_ = mi;
2309  }
2310  if (new_min_ > new_max_) {
2311  solver()->Fail();
2312  }
2313  } else {
2314  if (mi > min_.Value()) {
2315  CheckOldMin();
2316  const int64_t new_min =
2317  (bits_ == nullptr
2318  ? mi
2319  : bits_->ComputeNewMin(mi, min_.Value(), max_.Value()));
2320  min_.SetValue(solver(), new_min);
2321  }
2322  if (min_.Value() > ma) {
2323  solver()->Fail();
2324  }
2325  if (ma < max_.Value()) {
2326  CheckOldMax();
2327  const int64_t new_max =
2328  (bits_ == nullptr
2329  ? ma
2330  : bits_->ComputeNewMax(ma, min_.Value(), max_.Value()));
2331  max_.SetValue(solver(), new_max);
2332  }
2333  if (min_.Value() > max_.Value()) {
2334  solver()->Fail();
2335  }
2336  Push();
2337  }
2338  }
2339 }
2340 
2341 void DomainIntVar::SetValue(int64_t v) {
2342  if (v != min_.Value() || v != max_.Value()) {
2343  if (v < min_.Value() || v > max_.Value()) {
2344  solver()->Fail();
2345  }
2346  if (in_process_) {
2347  if (v > new_max_ || v < new_min_) {
2348  solver()->Fail();
2349  }
2350  new_min_ = v;
2351  new_max_ = v;
2352  } else {
2353  if (bits_ && !bits_->SetValue(v)) {
2354  solver()->Fail();
2355  }
2356  CheckOldMin();
2357  CheckOldMax();
2358  min_.SetValue(solver(), v);
2359  max_.SetValue(solver(), v);
2360  Push();
2361  }
2362  }
2363 }
2364 
2365 void DomainIntVar::RemoveValue(int64_t v) {
2366  if (v < min_.Value() || v > max_.Value()) return;
2367  if (v == min_.Value()) {
2368  SetMin(v + 1);
2369  } else if (v == max_.Value()) {
2370  SetMax(v - 1);
2371  } else {
2372  if (bits_ == nullptr) {
2373  CreateBits();
2374  }
2375  if (in_process_) {
2376  if (v >= new_min_ && v <= new_max_ && bits_->Contains(v)) {
2377  bits_->DelayRemoveValue(v);
2378  }
2379  } else {
2380  if (bits_->RemoveValue(v)) {
2381  Push();
2382  }
2383  }
2384  }
2385 }
2386 
2387 void DomainIntVar::RemoveInterval(int64_t l, int64_t u) {
2388  if (l <= min_.Value()) {
2389  SetMin(u + 1);
2390  } else if (u >= max_.Value()) {
2391  SetMax(l - 1);
2392  } else {
2393  for (int64_t v = l; v <= u; ++v) {
2394  RemoveValue(v);
2395  }
2396  }
2397 }
2398 
2399 void DomainIntVar::CreateBits() {
2400  solver()->SaveValue(reinterpret_cast<void**>(&bits_));
2401  if (max_.Value() - min_.Value() < 64) {
2402  bits_ = solver()->RevAlloc(
2403  new SmallBitSet(solver(), min_.Value(), max_.Value()));
2404  } else {
2405  bits_ = solver()->RevAlloc(
2406  new SimpleBitSet(solver(), min_.Value(), max_.Value()));
2407  }
2408 }
2409 
2410 void DomainIntVar::CleanInProcess() {
2411  in_process_ = false;
2412  if (bits_ != nullptr) {
2413  bits_->ClearHoles();
2414  }
2415 }
2416 
2417 void DomainIntVar::Push() {
2418  const bool in_process = in_process_;
2419  EnqueueVar(&handler_);
2420  CHECK_EQ(in_process, in_process_);
2421 }
2422 
2423 void DomainIntVar::Process() {
2424  CHECK(!in_process_);
2425  in_process_ = true;
2426  if (bits_ != nullptr) {
2427  bits_->ClearRemovedValues();
2428  }
2429  set_variable_to_clean_on_fail(this);
2430  new_min_ = min_.Value();
2431  new_max_ = max_.Value();
2432  const bool is_bound = min_.Value() == max_.Value();
2433  const bool range_changed =
2434  min_.Value() != OldMin() || max_.Value() != OldMax();
2435  // Process immediate demons.
2436  if (is_bound) {
2437  ExecuteAll(bound_demons_);
2438  }
2439  if (range_changed) {
2440  ExecuteAll(range_demons_);
2441  }
2442  ExecuteAll(domain_demons_);
2443 
2444  // Process delayed demons.
2445  if (is_bound) {
2446  EnqueueAll(delayed_bound_demons_);
2447  }
2448  if (range_changed) {
2449  EnqueueAll(delayed_range_demons_);
2450  }
2451  EnqueueAll(delayed_domain_demons_);
2452 
2453  // Everything went well if we arrive here. Let's clean the variable.
2454  set_variable_to_clean_on_fail(nullptr);
2455  CleanInProcess();
2456  old_min_ = min_.Value();
2457  old_max_ = max_.Value();
2458  if (min_.Value() < new_min_) {
2459  SetMin(new_min_);
2460  }
2461  if (max_.Value() > new_max_) {
2462  SetMax(new_max_);
2463  }
2464  if (bits_ != nullptr) {
2465  bits_->ApplyRemovedValues(this);
2466  }
2467 }
2468 
2469 template <typename T>
2470 T* CondRevAlloc(Solver* solver, bool reversible, T* object) {
2471  return reversible ? solver->RevAlloc(object) : object;
2472 }
2473 
2474 IntVarIterator* DomainIntVar::MakeHoleIterator(bool reversible) const {
2475  return CondRevAlloc(solver(), reversible, new DomainIntVarHoleIterator(this));
2476 }
2477 
2478 IntVarIterator* DomainIntVar::MakeDomainIterator(bool reversible) const {
2479  return CondRevAlloc(solver(), reversible,
2480  new DomainIntVarDomainIterator(this, reversible));
2481 }
2482 
2483 std::string DomainIntVar::DebugString() const {
2484  std::string out;
2485  const std::string& var_name = name();
2486  if (!var_name.empty()) {
2487  out = var_name + "(";
2488  } else {
2489  out = "DomainIntVar(";
2490  }
2491  if (min_.Value() == max_.Value()) {
2492  absl::StrAppendFormat(&out, "%d", min_.Value());
2493  } else if (bits_ != nullptr) {
2494  out.append(bits_->pretty_DebugString(min_.Value(), max_.Value()));
2495  } else {
2496  absl::StrAppendFormat(&out, "%d..%d", min_.Value(), max_.Value());
2497  }
2498  out += ")";
2499  return out;
2500 }
2501 
2502 // ----- Real Boolean Var -----
2503 
2504 class ConcreteBooleanVar : public BooleanVar {
2505  public:
2506  // Utility classes
2507  class Handler : public Demon {
2508  public:
2509  explicit Handler(ConcreteBooleanVar* const var) : Demon(), var_(var) {}
2510  ~Handler() override {}
2511  void Run(Solver* const s) override {
2512  s->GetPropagationMonitor()->StartProcessingIntegerVariable(var_);
2513  var_->Process();
2514  s->GetPropagationMonitor()->EndProcessingIntegerVariable(var_);
2515  }
2516  Solver::DemonPriority priority() const override {
2517  return Solver::VAR_PRIORITY;
2518  }
2519  std::string DebugString() const override {
2520  return absl::StrFormat("Handler(%s)", var_->DebugString());
2521  }
2522 
2523  private:
2524  ConcreteBooleanVar* const var_;
2525  };
2526 
2527  ConcreteBooleanVar(Solver* const s, const std::string& name)
2528  : BooleanVar(s, name), handler_(this) {}
2529 
2530  ~ConcreteBooleanVar() override {}
2531 
2532  void SetValue(int64_t v) override {
2533  if (value_ == kUnboundBooleanVarValue) {
2534  if ((v & 0xfffffffffffffffe) == 0) {
2535  InternalSaveBooleanVarValue(solver(), this);
2536  value_ = static_cast<int>(v);
2537  EnqueueVar(&handler_);
2538  return;
2539  }
2540  } else if (v == value_) {
2541  return;
2542  }
2543  solver()->Fail();
2544  }
2545 
2546  void Process() {
2547  DCHECK_NE(value_, kUnboundBooleanVarValue);
2548  ExecuteAll(bound_demons_);
2549  for (SimpleRevFIFO<Demon*>::Iterator it(&delayed_bound_demons_); it.ok();
2550  ++it) {
2551  EnqueueDelayedDemon(*it);
2552  }
2553  }
2554 
2555  int64_t OldMin() const override { return 0LL; }
2556  int64_t OldMax() const override { return 1LL; }
2557  void RestoreValue() override { value_ = kUnboundBooleanVarValue; }
2558 
2559  private:
2560  Handler handler_;
2561 };
2562 
2563 // ----- IntConst -----
2564 
2565 class IntConst : public IntVar {
2566  public:
2567  IntConst(Solver* const s, int64_t value, const std::string& name = "")
2568  : IntVar(s, name), value_(value) {}
2569  ~IntConst() override {}
2570 
2571  int64_t Min() const override { return value_; }
2572  void SetMin(int64_t m) override {
2573  if (m > value_) {
2574  solver()->Fail();
2575  }
2576  }
2577  int64_t Max() const override { return value_; }
2578  void SetMax(int64_t m) override {
2579  if (m < value_) {
2580  solver()->Fail();
2581  }
2582  }
2583  void SetRange(int64_t l, int64_t u) override {
2584  if (l > value_ || u < value_) {
2585  solver()->Fail();
2586  }
2587  }
2588  void SetValue(int64_t v) override {
2589  if (v != value_) {
2590  solver()->Fail();
2591  }
2592  }
2593  bool Bound() const override { return true; }
2594  int64_t Value() const override { return value_; }
2595  void RemoveValue(int64_t v) override {
2596  if (v == value_) {
2597  solver()->Fail();
2598  }
2599  }
2600  void RemoveInterval(int64_t l, int64_t u) override {
2601  if (l <= value_ && value_ <= u) {
2602  solver()->Fail();
2603  }
2604  }
2605  void WhenBound(Demon* d) override {}
2606  void WhenRange(Demon* d) override {}
2607  void WhenDomain(Demon* d) override {}
2608  uint64_t Size() const override { return 1; }
2609  bool Contains(int64_t v) const override { return (v == value_); }
2610  IntVarIterator* MakeHoleIterator(bool reversible) const override {
2611  return CondRevAlloc(solver(), reversible, new EmptyIterator());
2612  }
2613  IntVarIterator* MakeDomainIterator(bool reversible) const override {
2614  return CondRevAlloc(solver(), reversible, new RangeIterator(this));
2615  }
2616  int64_t OldMin() const override { return value_; }
2617  int64_t OldMax() const override { return value_; }
2618  std::string DebugString() const override {
2619  std::string out;
2620  if (solver()->HasName(this)) {
2621  const std::string& var_name = name();
2622  absl::StrAppendFormat(&out, "%s(%d)", var_name, value_);
2623  } else {
2624  absl::StrAppendFormat(&out, "IntConst(%d)", value_);
2625  }
2626  return out;
2627  }
2628 
2629  int VarType() const override { return CONST_VAR; }
2630 
2631  IntVar* IsEqual(int64_t constant) override {
2632  if (constant == value_) {
2633  return solver()->MakeIntConst(1);
2634  } else {
2635  return solver()->MakeIntConst(0);
2636  }
2637  }
2638 
2639  IntVar* IsDifferent(int64_t constant) override {
2640  if (constant == value_) {
2641  return solver()->MakeIntConst(0);
2642  } else {
2643  return solver()->MakeIntConst(1);
2644  }
2645  }
2646 
2647  IntVar* IsGreaterOrEqual(int64_t constant) override {
2648  return solver()->MakeIntConst(value_ >= constant);
2649  }
2650 
2651  IntVar* IsLessOrEqual(int64_t constant) override {
2652  return solver()->MakeIntConst(value_ <= constant);
2653  }
2654 
2655  std::string name() const override {
2656  if (solver()->HasName(this)) {
2657  return PropagationBaseObject::name();
2658  } else {
2659  return absl::StrCat(value_);
2660  }
2661  }
2662 
2663  private:
2664  int64_t value_;
2665 };
2666 
2667 // ----- x + c variable, optimized case -----
2668 
2669 class PlusCstVar : public IntVar {
2670  public:
2671  PlusCstVar(Solver* const s, IntVar* v, int64_t c)
2672  : IntVar(s), var_(v), cst_(c) {}
2673 
2674  ~PlusCstVar() override {}
2675 
2676  void WhenRange(Demon* d) override { var_->WhenRange(d); }
2677 
2678  void WhenBound(Demon* d) override { var_->WhenBound(d); }
2679 
2680  void WhenDomain(Demon* d) override { var_->WhenDomain(d); }
2681 
2682  int64_t OldMin() const override { return CapAdd(var_->OldMin(), cst_); }
2683 
2684  int64_t OldMax() const override { return CapAdd(var_->OldMax(), cst_); }
2685 
2686  std::string DebugString() const override {
2687  if (HasName()) {
2688  return absl::StrFormat("%s(%s + %d)", name(), var_->DebugString(), cst_);
2689  } else {
2690  return absl::StrFormat("(%s + %d)", var_->DebugString(), cst_);
2691  }
2692  }
2693 
2694  int VarType() const override { return VAR_ADD_CST; }
2695 
2696  void Accept(ModelVisitor* const visitor) const override {
2697  visitor->VisitIntegerVariable(this, ModelVisitor::kSumOperation, cst_,
2698  var_);
2699  }
2700 
2701  IntVar* IsEqual(int64_t constant) override {
2702  return var_->IsEqual(constant - cst_);
2703  }
2704 
2705  IntVar* IsDifferent(int64_t constant) override {
2706  return var_->IsDifferent(constant - cst_);
2707  }
2708 
2709  IntVar* IsGreaterOrEqual(int64_t constant) override {
2710  return var_->IsGreaterOrEqual(constant - cst_);
2711  }
2712 
2713  IntVar* IsLessOrEqual(int64_t constant) override {
2714  return var_->IsLessOrEqual(constant - cst_);
2715  }
2716 
2717  IntVar* SubVar() const { return var_; }
2718 
2719  int64_t Constant() const { return cst_; }
2720 
2721  protected:
2722  IntVar* const var_;
2723  const int64_t cst_;
2724 };
2725 
2726 class PlusCstIntVar : public PlusCstVar {
2727  public:
2728  class PlusCstIntVarIterator : public UnaryIterator {
2729  public:
2730  PlusCstIntVarIterator(const IntVar* const v, int64_t c, bool hole, bool rev)
2731  : UnaryIterator(v, hole, rev), cst_(c) {}
2732 
2733  ~PlusCstIntVarIterator() override {}
2734 
2735  int64_t Value() const override { return iterator_->Value() + cst_; }
2736 
2737  private:
2738  const int64_t cst_;
2739  };
2740 
2741  PlusCstIntVar(Solver* const s, IntVar* v, int64_t c) : PlusCstVar(s, v, c) {}
2742 
2743  ~PlusCstIntVar() override {}
2744 
2745  int64_t Min() const override { return var_->Min() + cst_; }
2746 
2747  void SetMin(int64_t m) override { var_->SetMin(CapSub(m, cst_)); }
2748 
2749  int64_t Max() const override { return var_->Max() + cst_; }
2750 
2751  void SetMax(int64_t m) override { var_->SetMax(CapSub(m, cst_)); }
2752 
2753  void SetRange(int64_t l, int64_t u) override {
2754  var_->SetRange(CapSub(l, cst_), CapSub(u, cst_));
2755  }
2756 
2757  void SetValue(int64_t v) override { var_->SetValue(v - cst_); }
2758 
2759  int64_t Value() const override { return var_->Value() + cst_; }
2760 
2761  bool Bound() const override { return var_->Bound(); }
2762 
2763  void RemoveValue(int64_t v) override { var_->RemoveValue(v - cst_); }
2764 
2765  void RemoveInterval(int64_t l, int64_t u) override {
2766  var_->RemoveInterval(l - cst_, u - cst_);
2767  }
2768 
2769  uint64_t Size() const override { return var_->Size(); }
2770 
2771  bool Contains(int64_t v) const override { return var_->Contains(v - cst_); }
2772 
2773  IntVarIterator* MakeHoleIterator(bool reversible) const override {
2774  return CondRevAlloc(
2775  solver(), reversible,
2776  new PlusCstIntVarIterator(var_, cst_, true, reversible));
2777  }
2778  IntVarIterator* MakeDomainIterator(bool reversible) const override {
2779  return CondRevAlloc(
2780  solver(), reversible,
2781  new PlusCstIntVarIterator(var_, cst_, false, reversible));
2782  }
2783 };
2784 
2785 class PlusCstDomainIntVar : public PlusCstVar {
2786  public:
2787  class PlusCstDomainIntVarIterator : public UnaryIterator {
2788  public:
2789  PlusCstDomainIntVarIterator(const IntVar* const v, int64_t c, bool hole,
2790  bool reversible)
2791  : UnaryIterator(v, hole, reversible), cst_(c) {}
2792 
2793  ~PlusCstDomainIntVarIterator() override {}
2794 
2795  int64_t Value() const override { return iterator_->Value() + cst_; }
2796 
2797  private:
2798  const int64_t cst_;
2799  };
2800 
2801  PlusCstDomainIntVar(Solver* const s, DomainIntVar* v, int64_t c)
2802  : PlusCstVar(s, v, c) {}
2803 
2804  ~PlusCstDomainIntVar() override {}
2805 
2806  int64_t Min() const override;
2807  void SetMin(int64_t m) override;
2808  int64_t Max() const override;
2809  void SetMax(int64_t m) override;
2810  void SetRange(int64_t l, int64_t u) override;
2811  void SetValue(int64_t v) override;
2812  bool Bound() const override;
2813  int64_t Value() const override;
2814  void RemoveValue(int64_t v) override;
2815  void RemoveInterval(int64_t l, int64_t u) override;
2816  uint64_t Size() const override;
2817  bool Contains(int64_t v) const override;
2818 
2819  DomainIntVar* domain_int_var() const {
2820  return reinterpret_cast<DomainIntVar*>(var_);
2821  }
2822 
2823  IntVarIterator* MakeHoleIterator(bool reversible) const override {
2824  return CondRevAlloc(
2825  solver(), reversible,
2826  new PlusCstDomainIntVarIterator(var_, cst_, true, reversible));
2827  }
2828  IntVarIterator* MakeDomainIterator(bool reversible) const override {
2829  return CondRevAlloc(
2830  solver(), reversible,
2831  new PlusCstDomainIntVarIterator(var_, cst_, false, reversible));
2832  }
2833 };
2834 
2835 int64_t PlusCstDomainIntVar::Min() const {
2836  return domain_int_var()->min_.Value() + cst_;
2837 }
2838 
2839 void PlusCstDomainIntVar::SetMin(int64_t m) {
2840  domain_int_var()->DomainIntVar::SetMin(CapSub(m, cst_));
2841 }
2842 
2843 int64_t PlusCstDomainIntVar::Max() const {
2844  return domain_int_var()->max_.Value() + cst_;
2845 }
2846 
2847 void PlusCstDomainIntVar::SetMax(int64_t m) {
2848  domain_int_var()->DomainIntVar::SetMax(CapSub(m, cst_));
2849 }
2850 
2851 void PlusCstDomainIntVar::SetRange(int64_t l, int64_t u) {
2852  domain_int_var()->DomainIntVar::SetRange(l - cst_, u - cst_);
2853 }
2854 
2855 void PlusCstDomainIntVar::SetValue(int64_t v) {
2856  domain_int_var()->DomainIntVar::SetValue(v - cst_);
2857 }
2858 
2859 bool PlusCstDomainIntVar::Bound() const {
2860  return domain_int_var()->min_.Value() == domain_int_var()->max_.Value();
2861 }
2862 
2863 int64_t PlusCstDomainIntVar::Value() const {
2864  CHECK_EQ(domain_int_var()->min_.Value(), domain_int_var()->max_.Value())
2865  << " variable is not bound";
2866  return domain_int_var()->min_.Value() + cst_;
2867 }
2868 
2869 void PlusCstDomainIntVar::RemoveValue(int64_t v) {
2870  domain_int_var()->DomainIntVar::RemoveValue(v - cst_);
2871 }
2872 
2873 void PlusCstDomainIntVar::RemoveInterval(int64_t l, int64_t u) {
2874  domain_int_var()->DomainIntVar::RemoveInterval(l - cst_, u - cst_);
2875 }
2876 
2877 uint64_t PlusCstDomainIntVar::Size() const {
2878  return domain_int_var()->DomainIntVar::Size();
2879 }
2880 
2881 bool PlusCstDomainIntVar::Contains(int64_t v) const {
2882  return domain_int_var()->DomainIntVar::Contains(v - cst_);
2883 }
2884 
2885 // c - x variable, optimized case
2886 
2887 class SubCstIntVar : public IntVar {
2888  public:
2889  class SubCstIntVarIterator : public UnaryIterator {
2890  public:
2891  SubCstIntVarIterator(const IntVar* const v, int64_t c, bool hole, bool rev)
2892  : UnaryIterator(v, hole, rev), cst_(c) {}
2893  ~SubCstIntVarIterator() override {}
2894 
2895  int64_t Value() const override { return cst_ - iterator_->Value(); }
2896 
2897  private:
2898  const int64_t cst_;
2899  };
2900 
2901  SubCstIntVar(Solver* const s, IntVar* v, int64_t c);
2902  ~SubCstIntVar() override;
2903 
2904  int64_t Min() const override;
2905  void SetMin(int64_t m) override;
2906  int64_t Max() const override;
2907  void SetMax(int64_t m) override;
2908  void SetRange(int64_t l, int64_t u) override;
2909  void SetValue(int64_t v) override;
2910  bool Bound() const override;
2911  int64_t Value() const override;
2912  void RemoveValue(int64_t v) override;
2913  void RemoveInterval(int64_t l, int64_t u) override;
2914  uint64_t Size() const override;
2915  bool Contains(int64_t v) const override;
2916  void WhenRange(Demon* d) override;
2917  void WhenBound(Demon* d) override;
2918  void WhenDomain(Demon* d) override;
2919  IntVarIterator* MakeHoleIterator(bool reversible) const override {
2920  return CondRevAlloc(solver(), reversible,
2921  new SubCstIntVarIterator(var_, cst_, true, reversible));
2922  }
2923  IntVarIterator* MakeDomainIterator(bool reversible) const override {
2924  return CondRevAlloc(
2925  solver(), reversible,
2926  new SubCstIntVarIterator(var_, cst_, false, reversible));
2927  }
2928  int64_t OldMin() const override { return CapSub(cst_, var_->OldMax()); }
2929  int64_t OldMax() const override { return CapSub(cst_, var_->OldMin()); }
2930  std::string DebugString() const override;
2931  std::string name() const override;
2932  int VarType() const override { return CST_SUB_VAR; }
2933 
2934  void Accept(ModelVisitor* const visitor) const override {
2935  visitor->VisitIntegerVariable(this, ModelVisitor::kDifferenceOperation,
2936  cst_, var_);
2937  }
2938 
2939  IntVar* IsEqual(int64_t constant) override {
2940  return var_->IsEqual(cst_ - constant);
2941  }
2942 
2943  IntVar* IsDifferent(int64_t constant) override {
2944  return var_->IsDifferent(cst_ - constant);
2945  }
2946 
2947  IntVar* IsGreaterOrEqual(int64_t constant) override {
2948  return var_->IsLessOrEqual(cst_ - constant);
2949  }
2950 
2951  IntVar* IsLessOrEqual(int64_t constant) override {
2952  return var_->IsGreaterOrEqual(cst_ - constant);
2953  }
2954 
2955  IntVar* SubVar() const { return var_; }
2956  int64_t Constant() const { return cst_; }
2957 
2958  private:
2959  IntVar* const var_;
2960  const int64_t cst_;
2961 };
2962 
2963 SubCstIntVar::SubCstIntVar(Solver* const s, IntVar* v, int64_t c)
2964  : IntVar(s), var_(v), cst_(c) {}
2965 
2966 SubCstIntVar::~SubCstIntVar() {}
2967 
2968 int64_t SubCstIntVar::Min() const { return cst_ - var_->Max(); }
2969 
2970 void SubCstIntVar::SetMin(int64_t m) { var_->SetMax(CapSub(cst_, m)); }
2971 
2972 int64_t SubCstIntVar::Max() const { return cst_ - var_->Min(); }
2973 
2974 void SubCstIntVar::SetMax(int64_t m) { var_->SetMin(CapSub(cst_, m)); }
2975 
2976 void SubCstIntVar::SetRange(int64_t l, int64_t u) {
2977  var_->SetRange(CapSub(cst_, u), CapSub(cst_, l));
2978 }
2979 
2980 void SubCstIntVar::SetValue(int64_t v) { var_->SetValue(cst_ - v); }
2981 
2982 bool SubCstIntVar::Bound() const { return var_->Bound(); }
2983 
2984 void SubCstIntVar::WhenRange(Demon* d) { var_->WhenRange(d); }
2985 
2986 int64_t SubCstIntVar::Value() const { return cst_ - var_->Value(); }
2987 
2988 void SubCstIntVar::RemoveValue(int64_t v) { var_->RemoveValue(cst_ - v); }
2989 
2990 void SubCstIntVar::RemoveInterval(int64_t l, int64_t u) {
2991  var_->RemoveInterval(cst_ - u, cst_ - l);
2992 }
2993 
2994 void SubCstIntVar::WhenBound(Demon* d) { var_->WhenBound(d); }
2995 
2996 void SubCstIntVar::WhenDomain(Demon* d) { var_->WhenDomain(d); }
2997 
2998 uint64_t SubCstIntVar::Size() const { return var_->Size(); }
2999 
3000 bool SubCstIntVar::Contains(int64_t v) const {
3001  return var_->Contains(cst_ - v);
3002 }
3003 
3004 std::string SubCstIntVar::DebugString() const {
3005  if (cst_ == 1 && var_->VarType() == BOOLEAN_VAR) {
3006  return absl::StrFormat("Not(%s)", var_->DebugString());
3007  } else {
3008  return absl::StrFormat("(%d - %s)", cst_, var_->DebugString());
3009  }
3010 }
3011 
3012 std::string SubCstIntVar::name() const {
3013  if (solver()->HasName(this)) {
3014  return PropagationBaseObject::name();
3015  } else if (cst_ == 1 && var_->VarType() == BOOLEAN_VAR) {
3016  return absl::StrFormat("Not(%s)", var_->name());
3017  } else {
3018  return absl::StrFormat("(%d - %s)", cst_, var_->name());
3019  }
3020 }
3021 
3022 // -x variable, optimized case
3023 
3024 class OppIntVar : public IntVar {
3025  public:
3026  class OppIntVarIterator : public UnaryIterator {
3027  public:
3028  OppIntVarIterator(const IntVar* const v, bool hole, bool reversible)
3029  : UnaryIterator(v, hole, reversible) {}
3030  ~OppIntVarIterator() override {}
3031 
3032  int64_t Value() const override { return -iterator_->Value(); }
3033  };
3034 
3035  OppIntVar(Solver* const s, IntVar* v);
3036  ~OppIntVar() override;
3037 
3038  int64_t Min() const override;
3039  void SetMin(int64_t m) override;
3040  int64_t Max() const override;
3041  void SetMax(int64_t m) override;
3042  void SetRange(int64_t l, int64_t u) override;
3043  void SetValue(int64_t v) override;
3044  bool Bound() const override;
3045  int64_t Value() const override;
3046  void RemoveValue(int64_t v) override;
3047  void RemoveInterval(int64_t l, int64_t u) override;
3048  uint64_t Size() const override;
3049  bool Contains(int64_t v) const override;
3050  void WhenRange(Demon* d) override;
3051  void WhenBound(Demon* d) override;
3052  void WhenDomain(Demon* d) override;
3053  IntVarIterator* MakeHoleIterator(bool reversible) const override {
3054  return CondRevAlloc(solver(), reversible,
3055  new OppIntVarIterator(var_, true, reversible));
3056  }
3057  IntVarIterator* MakeDomainIterator(bool reversible) const override {
3058  return CondRevAlloc(solver(), reversible,
3059  new OppIntVarIterator(var_, false, reversible));
3060  }
3061  int64_t OldMin() const override { return CapOpp(var_->OldMax()); }
3062  int64_t OldMax() const override { return CapOpp(var_->OldMin()); }
3063  std::string DebugString() const override;
3064  int VarType() const override { return OPP_VAR; }
3065 
3066  void Accept(ModelVisitor* const visitor) const override {
3067  visitor->VisitIntegerVariable(this, ModelVisitor::kDifferenceOperation, 0,
3068  var_);
3069  }
3070 
3071  IntVar* IsEqual(int64_t constant) override {
3072  return var_->IsEqual(-constant);
3073  }
3074 
3075  IntVar* IsDifferent(int64_t constant) override {
3076  return var_->IsDifferent(-constant);
3077  }
3078 
3079  IntVar* IsGreaterOrEqual(int64_t constant) override {
3080  return var_->IsLessOrEqual(-constant);
3081  }
3082 
3083  IntVar* IsLessOrEqual(int64_t constant) override {
3084  return var_->IsGreaterOrEqual(-constant);
3085  }
3086 
3087  IntVar* SubVar() const { return var_; }
3088 
3089  private:
3090  IntVar* const var_;
3091 };
3092 
3093 OppIntVar::OppIntVar(Solver* const s, IntVar* v) : IntVar(s), var_(v) {}
3094 
3095 OppIntVar::~OppIntVar() {}
3096 
3097 int64_t OppIntVar::Min() const { return -var_->Max(); }
3098 
3099 void OppIntVar::SetMin(int64_t m) { var_->SetMax(CapOpp(m)); }
3100 
3101 int64_t OppIntVar::Max() const { return -var_->Min(); }
3102 
3103 void OppIntVar::SetMax(int64_t m) { var_->SetMin(CapOpp(m)); }
3104 
3105 void OppIntVar::SetRange(int64_t l, int64_t u) {
3106  var_->SetRange(CapOpp(u), CapOpp(l));
3107 }
3108 
3109 void OppIntVar::SetValue(int64_t v) { var_->SetValue(CapOpp(v)); }
3110 
3111 bool OppIntVar::Bound() const { return var_->Bound(); }
3112 
3113 void OppIntVar::WhenRange(Demon* d) { var_->WhenRange(d); }
3114 
3115 int64_t OppIntVar::Value() const { return -var_->Value(); }
3116 
3117 void OppIntVar::RemoveValue(int64_t v) { var_->RemoveValue(-v); }
3118 
3119 void OppIntVar::RemoveInterval(int64_t l, int64_t u) {
3120  var_->RemoveInterval(-u, -l);
3121 }
3122 
3123 void OppIntVar::WhenBound(Demon* d) { var_->WhenBound(d); }
3124 
3125 void OppIntVar::WhenDomain(Demon* d) { var_->WhenDomain(d); }
3126 
3127 uint64_t OppIntVar::Size() const { return var_->Size(); }
3128 
3129 bool OppIntVar::Contains(int64_t v) const { return var_->Contains(-v); }
3130 
3131 std::string OppIntVar::DebugString() const {
3132  return absl::StrFormat("-(%s)", var_->DebugString());
3133 }
3134 
3135 // ----- Utility functions -----
3136 
3137 // x * c variable, optimized case
3138 
3139 class TimesCstIntVar : public IntVar {
3140  public:
3141  TimesCstIntVar(Solver* const s, IntVar* v, int64_t c)
3142  : IntVar(s), var_(v), cst_(c) {}
3143  ~TimesCstIntVar() override {}
3144 
3145  IntVar* SubVar() const { return var_; }
3146  int64_t Constant() const { return cst_; }
3147 
3148  void Accept(ModelVisitor* const visitor) const override {
3149  visitor->VisitIntegerVariable(this, ModelVisitor::kProductOperation, cst_,
3150  var_);
3151  }
3152 
3153  IntVar* IsEqual(int64_t constant) override {
3154  if (constant % cst_ == 0) {
3155  return var_->IsEqual(constant / cst_);
3156  } else {
3157  return solver()->MakeIntConst(0);
3158  }
3159  }
3160 
3161  IntVar* IsDifferent(int64_t constant) override {
3162  if (constant % cst_ == 0) {
3163  return var_->IsDifferent(constant / cst_);
3164  } else {
3165  return solver()->MakeIntConst(1);
3166  }
3167  }
3168 
3169  IntVar* IsGreaterOrEqual(int64_t constant) override {
3170  if (cst_ > 0) {
3171  return var_->IsGreaterOrEqual(PosIntDivUp(constant, cst_));
3172  } else {
3173  return var_->IsLessOrEqual(PosIntDivDown(-constant, -cst_));
3174  }
3175  }
3176 
3177  IntVar* IsLessOrEqual(int64_t constant) override {
3178  if (cst_ > 0) {
3179  return var_->IsLessOrEqual(PosIntDivDown(constant, cst_));
3180  } else {
3181  return var_->IsGreaterOrEqual(PosIntDivUp(-constant, -cst_));
3182  }
3183  }
3184 
3185  std::string DebugString() const override {
3186  return absl::StrFormat("(%s * %d)", var_->DebugString(), cst_);
3187  }
3188 
3189  int VarType() const override { return VAR_TIMES_CST; }
3190 
3191  protected:
3192  IntVar* const var_;
3193  const int64_t cst_;
3194 };
3195 
3196 class TimesPosCstIntVar : public TimesCstIntVar {
3197  public:
3198  class TimesPosCstIntVarIterator : public UnaryIterator {
3199  public:
3200  TimesPosCstIntVarIterator(const IntVar* const v, int64_t c, bool hole,
3201  bool reversible)
3202  : UnaryIterator(v, hole, reversible), cst_(c) {}
3203  ~TimesPosCstIntVarIterator() override {}
3204 
3205  int64_t Value() const override { return iterator_->Value() * cst_; }
3206 
3207  private:
3208  const int64_t cst_;
3209  };
3210 
3211  TimesPosCstIntVar(Solver* const s, IntVar* v, int64_t c);
3212  ~TimesPosCstIntVar() override;
3213 
3214  int64_t Min() const override;
3215  void SetMin(int64_t m) override;
3216  int64_t Max() const override;
3217  void SetMax(int64_t m) override;
3218  void SetRange(int64_t l, int64_t u) override;
3219  void SetValue(int64_t v) override;
3220  bool Bound() const override;
3221  int64_t Value() const override;
3222  void RemoveValue(int64_t v) override;
3223  void RemoveInterval(int64_t l, int64_t u) override;
3224  uint64_t Size() const override;
3225  bool Contains(int64_t v) const override;
3226  void WhenRange(Demon* d) override;
3227  void WhenBound(Demon* d) override;
3228  void WhenDomain(Demon* d) override;
3229  IntVarIterator* MakeHoleIterator(bool reversible) const override {
3230  return CondRevAlloc(
3231  solver(), reversible,
3232  new TimesPosCstIntVarIterator(var_, cst_, true, reversible));
3233  }
3234  IntVarIterator* MakeDomainIterator(bool reversible) const override {
3235  return CondRevAlloc(
3236  solver(), reversible,
3237  new TimesPosCstIntVarIterator(var_, cst_, false, reversible));
3238  }
3239  int64_t OldMin() const override { return CapProd(var_->OldMin(), cst_); }
3240  int64_t OldMax() const override { return CapProd(var_->OldMax(), cst_); }
3241 };
3242 
3243 // ----- TimesPosCstIntVar -----
3244 
3245 TimesPosCstIntVar::TimesPosCstIntVar(Solver* const s, IntVar* v, int64_t c)
3246  : TimesCstIntVar(s, v, c) {}
3247 
3248 TimesPosCstIntVar::~TimesPosCstIntVar() {}
3249 
3250 int64_t TimesPosCstIntVar::Min() const { return CapProd(var_->Min(), cst_); }
3251 
3252 void TimesPosCstIntVar::SetMin(int64_t m) {
3253  if (m != std::numeric_limits<int64_t>::min()) {
3254  var_->SetMin(PosIntDivUp(m, cst_));
3255  }
3256 }
3257 
3258 int64_t TimesPosCstIntVar::Max() const { return CapProd(var_->Max(), cst_); }
3259 
3260 void TimesPosCstIntVar::SetMax(int64_t m) {
3261  if (m != std::numeric_limits<int64_t>::max()) {
3262  var_->SetMax(PosIntDivDown(m, cst_));
3263  }
3264 }
3265 
3266 void TimesPosCstIntVar::SetRange(int64_t l, int64_t u) {
3267  var_->SetRange(PosIntDivUp(l, cst_), PosIntDivDown(u, cst_));
3268 }
3269 
3270 void TimesPosCstIntVar::SetValue(int64_t v) {
3271  if (v % cst_ != 0) {
3272  solver()->Fail();
3273  }
3274  var_->SetValue(v / cst_);
3275 }
3276 
3277 bool TimesPosCstIntVar::Bound() const { return var_->Bound(); }
3278 
3279 void TimesPosCstIntVar::WhenRange(Demon* d) { var_->WhenRange(d); }
3280 
3281 int64_t TimesPosCstIntVar::Value() const {
3282  return CapProd(var_->Value(), cst_);
3283 }
3284 
3285 void TimesPosCstIntVar::RemoveValue(int64_t v) {
3286  if (v % cst_ == 0) {
3287  var_->RemoveValue(v / cst_);
3288  }
3289 }
3290 
3291 void TimesPosCstIntVar::RemoveInterval(int64_t l, int64_t u) {
3292  for (int64_t v = l; v <= u; ++v) {
3293  RemoveValue(v);
3294  }
3295  // TODO(user) : Improve me
3296 }
3297 
3298 void TimesPosCstIntVar::WhenBound(Demon* d) { var_->WhenBound(d); }
3299 
3300 void TimesPosCstIntVar::WhenDomain(Demon* d) { var_->WhenDomain(d); }
3301 
3302 uint64_t TimesPosCstIntVar::Size() const { return var_->Size(); }
3303 
3304 bool TimesPosCstIntVar::Contains(int64_t v) const {
3305  return (v % cst_ == 0 && var_->Contains(v / cst_));
3306 }
3307 
3308 // b * c variable, optimized case
3309 
3310 class TimesPosCstBoolVar : public TimesCstIntVar {
3311  public:
3312  class TimesPosCstBoolVarIterator : public UnaryIterator {
3313  public:
3314  // TODO(user) : optimize this.
3315  TimesPosCstBoolVarIterator(const IntVar* const v, int64_t c, bool hole,
3316  bool reversible)
3317  : UnaryIterator(v, hole, reversible), cst_(c) {}
3318  ~TimesPosCstBoolVarIterator() override {}
3319 
3320  int64_t Value() const override { return iterator_->Value() * cst_; }
3321 
3322  private:
3323  const int64_t cst_;
3324  };
3325 
3326  TimesPosCstBoolVar(Solver* const s, BooleanVar* v, int64_t c);
3327  ~TimesPosCstBoolVar() override;
3328 
3329  int64_t Min() const override;
3330  void SetMin(int64_t m) override;
3331  int64_t Max() const override;
3332  void SetMax(int64_t m) override;
3333  void SetRange(int64_t l, int64_t u) override;
3334  void SetValue(int64_t v) override;
3335  bool Bound() const override;
3336  int64_t Value() const override;
3337  void RemoveValue(int64_t v) override;
3338  void RemoveInterval(int64_t l, int64_t u) override;
3339  uint64_t Size() const override;
3340  bool Contains(int64_t v) const override;
3341  void WhenRange(Demon* d) override;
3342  void WhenBound(Demon* d) override;
3343  void WhenDomain(Demon* d) override;
3344  IntVarIterator* MakeHoleIterator(bool reversible) const override {
3345  return CondRevAlloc(solver(), reversible, new EmptyIterator());
3346  }
3347  IntVarIterator* MakeDomainIterator(bool reversible) const override {
3348  return CondRevAlloc(
3349  solver(), reversible,
3350  new TimesPosCstBoolVarIterator(boolean_var(), cst_, false, reversible));
3351  }
3352  int64_t OldMin() const override { return 0; }
3353  int64_t OldMax() const override { return cst_; }
3354 
3355  BooleanVar* boolean_var() const {
3356  return reinterpret_cast<BooleanVar*>(var_);
3357  }
3358 };
3359 
3360 // ----- TimesPosCstBoolVar -----
3361 
3362 TimesPosCstBoolVar::TimesPosCstBoolVar(Solver* const s, BooleanVar* v,
3363  int64_t c)
3364  : TimesCstIntVar(s, v, c) {}
3365 
3366 TimesPosCstBoolVar::~TimesPosCstBoolVar() {}
3367 
3368 int64_t TimesPosCstBoolVar::Min() const {
3369  return (boolean_var()->RawValue() == 1) * cst_;
3370 }
3371 
3372 void TimesPosCstBoolVar::SetMin(int64_t m) {
3373  if (m > cst_) {
3374  solver()->Fail();
3375  } else if (m > 0) {
3376  boolean_var()->SetMin(1);
3377  }
3378 }
3379 
3380 int64_t TimesPosCstBoolVar::Max() const {
3381  return (boolean_var()->RawValue() != 0) * cst_;
3382 }
3383 
3384 void TimesPosCstBoolVar::SetMax(int64_t m) {
3385  if (m < 0) {
3386  solver()->Fail();
3387  } else if (m < cst_) {
3388  boolean_var()->SetMax(0);
3389  }
3390 }
3391 
3392 void TimesPosCstBoolVar::SetRange(int64_t l, int64_t u) {
3393  if (u < 0 || l > cst_ || l > u) {
3394  solver()->Fail();
3395  }
3396  if (l > 0) {
3397  boolean_var()->SetMin(1);
3398  } else if (u < cst_) {
3399  boolean_var()->SetMax(0);
3400  }
3401 }
3402 
3403 void TimesPosCstBoolVar::SetValue(int64_t v) {
3404  if (v == 0) {
3405  boolean_var()->SetValue(0);
3406  } else if (v == cst_) {
3407  boolean_var()->SetValue(1);
3408  } else {
3409  solver()->Fail();
3410  }
3411 }
3412 
3413 bool TimesPosCstBoolVar::Bound() const {
3414  return boolean_var()->RawValue() != BooleanVar::kUnboundBooleanVarValue;
3415 }
3416 
3417 void TimesPosCstBoolVar::WhenRange(Demon* d) { boolean_var()->WhenRange(d); }
3418 
3419 int64_t TimesPosCstBoolVar::Value() const {
3420  CHECK_NE(boolean_var()->RawValue(), BooleanVar::kUnboundBooleanVarValue)
3421  << " variable is not bound";
3422  return boolean_var()->RawValue() * cst_;
3423 }
3424 
3425 void TimesPosCstBoolVar::RemoveValue(int64_t v) {
3426  if (v == 0) {
3427  boolean_var()->RemoveValue(0);
3428  } else if (v == cst_) {
3429  boolean_var()->RemoveValue(1);
3430  }
3431 }
3432 
3433 void TimesPosCstBoolVar::RemoveInterval(int64_t l, int64_t u) {
3434  if (l <= 0 && u >= 0) {
3435  boolean_var()->RemoveValue(0);
3436  }
3437  if (l <= cst_ && u >= cst_) {
3438  boolean_var()->RemoveValue(1);
3439  }
3440 }
3441 
3442 void TimesPosCstBoolVar::WhenBound(Demon* d) { boolean_var()->WhenBound(d); }
3443 
3444 void TimesPosCstBoolVar::WhenDomain(Demon* d) { boolean_var()->WhenDomain(d); }
3445 
3446 uint64_t TimesPosCstBoolVar::Size() const {
3447  return (1 +
3448  (boolean_var()->RawValue() == BooleanVar::kUnboundBooleanVarValue));
3449 }
3450 
3451 bool TimesPosCstBoolVar::Contains(int64_t v) const {
3452  if (v == 0) {
3453  return boolean_var()->RawValue() != 1;
3454  } else if (v == cst_) {
3455  return boolean_var()->RawValue() != 0;
3456  }
3457  return false;
3458 }
3459 
3460 // TimesNegCstIntVar
3461 
3462 class TimesNegCstIntVar : public TimesCstIntVar {
3463  public:
3464  class TimesNegCstIntVarIterator : public UnaryIterator {
3465  public:
3466  TimesNegCstIntVarIterator(const IntVar* const v, int64_t c, bool hole,
3467  bool reversible)
3468  : UnaryIterator(v, hole, reversible), cst_(c) {}
3469  ~TimesNegCstIntVarIterator() override {}
3470 
3471  int64_t Value() const override { return iterator_->Value() * cst_; }
3472 
3473  private:
3474  const int64_t cst_;
3475  };
3476 
3477  TimesNegCstIntVar(Solver* const s, IntVar* v, int64_t c);
3478  ~TimesNegCstIntVar() override;
3479 
3480  int64_t Min() const override;
3481  void SetMin(int64_t m) override;
3482  int64_t Max() const override;
3483  void SetMax(int64_t m) override;
3484  void SetRange(int64_t l, int64_t u) override;
3485  void SetValue(int64_t v) override;
3486  bool Bound() const override;
3487  int64_t Value() const override;
3488  void RemoveValue(int64_t v) override;
3489  void RemoveInterval(int64_t l, int64_t u) override;
3490  uint64_t Size() const override;
3491  bool Contains(int64_t v) const override;
3492  void WhenRange(Demon* d) override;
3493  void WhenBound(Demon* d) override;
3494  void WhenDomain(Demon* d) override;
3495  IntVarIterator* MakeHoleIterator(bool reversible) const override {
3496  return CondRevAlloc(
3497  solver(), reversible,
3498  new TimesNegCstIntVarIterator(var_, cst_, true, reversible));
3499  }
3500  IntVarIterator* MakeDomainIterator(bool reversible) const override {
3501  return CondRevAlloc(
3502  solver(), reversible,
3503  new TimesNegCstIntVarIterator(var_, cst_, false, reversible));
3504  }
3505  int64_t OldMin() const override { return CapProd(var_->OldMax(), cst_); }
3506  int64_t OldMax() const override { return CapProd(var_->OldMin(), cst_); }
3507 };
3508 
3509 // ----- TimesNegCstIntVar -----
3510 
3511 TimesNegCstIntVar::TimesNegCstIntVar(Solver* const s, IntVar* v, int64_t c)
3512  : TimesCstIntVar(s, v, c) {}
3513 
3514 TimesNegCstIntVar::~TimesNegCstIntVar() {}
3515 
3516 int64_t TimesNegCstIntVar::Min() const { return CapProd(var_->Max(), cst_); }
3517 
3518 void TimesNegCstIntVar::SetMin(int64_t m) {
3519  if (m != std::numeric_limits<int64_t>::min()) {
3520  var_->SetMax(PosIntDivDown(-m, -cst_));
3521  }
3522 }
3523 
3524 int64_t TimesNegCstIntVar::Max() const { return CapProd(var_->Min(), cst_); }
3525 
3526 void TimesNegCstIntVar::SetMax(int64_t m) {
3527  if (m != std::numeric_limits<int64_t>::max()) {
3528  var_->SetMin(PosIntDivUp(-m, -cst_));
3529  }
3530 }
3531 
3532 void TimesNegCstIntVar::SetRange(int64_t l, int64_t u) {
3533  var_->SetRange(PosIntDivUp(CapOpp(u), CapOpp(cst_)),
3535 }
3536 
3537 void TimesNegCstIntVar::SetValue(int64_t v) {
3538  if (v % cst_ != 0) {
3539  solver()->Fail();
3540  }
3541  var_->SetValue(v / cst_);
3542 }
3543 
3544 bool TimesNegCstIntVar::Bound() const { return var_->Bound(); }
3545 
3546 void TimesNegCstIntVar::WhenRange(Demon* d) { var_->WhenRange(d); }
3547 
3548 int64_t TimesNegCstIntVar::Value() const {
3549  return CapProd(var_->Value(), cst_);
3550 }
3551 
3552 void TimesNegCstIntVar::RemoveValue(int64_t v) {
3553  if (v % cst_ == 0) {
3554  var_->RemoveValue(v / cst_);
3555  }
3556 }
3557 
3558 void TimesNegCstIntVar::RemoveInterval(int64_t l, int64_t u) {
3559  for (int64_t v = l; v <= u; ++v) {
3560  RemoveValue(v);
3561  }
3562  // TODO(user) : Improve me
3563 }
3564 
3565 void TimesNegCstIntVar::WhenBound(Demon* d) { var_->WhenBound(d); }
3566 
3567 void TimesNegCstIntVar::WhenDomain(Demon* d) { var_->WhenDomain(d); }
3568 
3569 uint64_t TimesNegCstIntVar::Size() const { return var_->Size(); }
3570 
3571 bool TimesNegCstIntVar::Contains(int64_t v) const {
3572  return (v % cst_ == 0 && var_->Contains(v / cst_));
3573 }
3574 
3575 // ---------- arithmetic expressions ----------
3576 
3577 // ----- PlusIntExpr -----
3578 
3579 class PlusIntExpr : public BaseIntExpr {
3580  public:
3581  PlusIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
3582  : BaseIntExpr(s), left_(l), right_(r) {}
3583 
3584  ~PlusIntExpr() override {}
3585 
3586  int64_t Min() const override { return left_->Min() + right_->Min(); }
3587 
3588  void SetMin(int64_t m) override {
3589  if (m > left_->Min() + right_->Min()) {
3590  // Catching potential overflow.
3591  if (m > right_->Max() + left_->Max()) solver()->Fail();
3592  left_->SetMin(m - right_->Max());
3593  right_->SetMin(m - left_->Max());
3594  }
3595  }
3596 
3597  void SetRange(int64_t l, int64_t u) override {
3598  const int64_t left_min = left_->Min();
3599  const int64_t right_min = right_->Min();
3600  const int64_t left_max = left_->Max();
3601  const int64_t right_max = right_->Max();
3602  if (l > left_min + right_min) {
3603  // Catching potential overflow.
3604  if (l > right_max + left_max) solver()->Fail();
3605  left_->SetMin(l - right_max);
3606  right_->SetMin(l - left_max);
3607  }
3608  if (u < left_max + right_max) {
3609  // Catching potential overflow.
3610  if (u < right_min + left_min) solver()->Fail();
3611  left_->SetMax(u - right_min);
3612  right_->SetMax(u - left_min);
3613  }
3614  }
3615 
3616  int64_t Max() const override { return left_->Max() + right_->Max(); }
3617 
3618  void SetMax(int64_t m) override {
3619  if (m < left_->Max() + right_->Max()) {
3620  // Catching potential overflow.
3621  if (m < right_->Min() + left_->Min()) solver()->Fail();
3622  left_->SetMax(m - right_->Min());
3623  right_->SetMax(m - left_->Min());
3624  }
3625  }
3626 
3627  bool Bound() const override { return (left_->Bound() && right_->Bound()); }
3628 
3629  void Range(int64_t* const mi, int64_t* const ma) override {
3630  *mi = left_->Min() + right_->Min();
3631  *ma = left_->Max() + right_->Max();
3632  }
3633 
3634  std::string name() const override {
3635  return absl::StrFormat("(%s + %s)", left_->name(), right_->name());
3636  }
3637 
3638  std::string DebugString() const override {
3639  return absl::StrFormat("(%s + %s)", left_->DebugString(),
3640  right_->DebugString());
3641  }
3642 
3643  void WhenRange(Demon* d) override {
3644  left_->WhenRange(d);
3645  right_->WhenRange(d);
3646  }
3647 
3648  void ExpandPlusIntExpr(IntExpr* const expr, std::vector<IntExpr*>* subs) {
3649  PlusIntExpr* const casted = dynamic_cast<PlusIntExpr*>(expr);
3650  if (casted != nullptr) {
3651  ExpandPlusIntExpr(casted->left_, subs);
3652  ExpandPlusIntExpr(casted->right_, subs);
3653  } else {
3654  subs->push_back(expr);
3655  }
3656  }
3657 
3658  IntVar* CastToVar() override {
3659  if (dynamic_cast<PlusIntExpr*>(left_) != nullptr ||
3660  dynamic_cast<PlusIntExpr*>(right_) != nullptr) {
3661  std::vector<IntExpr*> sub_exprs;
3662  ExpandPlusIntExpr(left_, &sub_exprs);
3663  ExpandPlusIntExpr(right_, &sub_exprs);
3664  if (sub_exprs.size() >= 3) {
3665  std::vector<IntVar*> sub_vars(sub_exprs.size());
3666  for (int i = 0; i < sub_exprs.size(); ++i) {
3667  sub_vars[i] = sub_exprs[i]->Var();
3668  }
3669  return solver()->MakeSum(sub_vars)->Var();
3670  }
3671  }
3672  return BaseIntExpr::CastToVar();
3673  }
3674 
3675  void Accept(ModelVisitor* const visitor) const override {
3676  visitor->BeginVisitIntegerExpression(ModelVisitor::kSum, this);
3677  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
3678  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
3679  right_);
3680  visitor->EndVisitIntegerExpression(ModelVisitor::kSum, this);
3681  }
3682 
3683  private:
3684  IntExpr* const left_;
3685  IntExpr* const right_;
3686 };
3687 
3688 class SafePlusIntExpr : public BaseIntExpr {
3689  public:
3690  SafePlusIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
3691  : BaseIntExpr(s), left_(l), right_(r) {}
3692 
3693  ~SafePlusIntExpr() override {}
3694 
3695  int64_t Min() const override { return CapAdd(left_->Min(), right_->Min()); }
3696 
3697  void SetMin(int64_t m) override {
3698  left_->SetMin(CapSub(m, right_->Max()));
3699  right_->SetMin(CapSub(m, left_->Max()));
3700  }
3701 
3702  void SetRange(int64_t l, int64_t u) override {
3703  const int64_t left_min = left_->Min();
3704  const int64_t right_min = right_->Min();
3705  const int64_t left_max = left_->Max();
3706  const int64_t right_max = right_->Max();
3707  if (l > CapAdd(left_min, right_min)) {
3708  left_->SetMin(CapSub(l, right_max));
3709  right_->SetMin(CapSub(l, left_max));
3710  }
3711  if (u < CapAdd(left_max, right_max)) {
3712  left_->SetMax(CapSub(u, right_min));
3713  right_->SetMax(CapSub(u, left_min));
3714  }
3715  }
3716 
3717  int64_t Max() const override { return CapAdd(left_->Max(), right_->Max()); }
3718 
3719  void SetMax(int64_t m) override {
3720  left_->SetMax(CapSub(m, right_->Min()));
3721  right_->SetMax(CapSub(m, left_->Min()));
3722  }
3723 
3724  bool Bound() const override { return (left_->Bound() && right_->Bound()); }
3725 
3726  std::string name() const override {
3727  return absl::StrFormat("(%s + %s)", left_->name(), right_->name());
3728  }
3729 
3730  std::string DebugString() const override {
3731  return absl::StrFormat("(%s + %s)", left_->DebugString(),
3732  right_->DebugString());
3733  }
3734 
3735  void WhenRange(Demon* d) override {
3736  left_->WhenRange(d);
3737  right_->WhenRange(d);
3738  }
3739 
3740  void Accept(ModelVisitor* const visitor) const override {
3741  visitor->BeginVisitIntegerExpression(ModelVisitor::kSum, this);
3742  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
3743  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
3744  right_);
3745  visitor->EndVisitIntegerExpression(ModelVisitor::kSum, this);
3746  }
3747 
3748  private:
3749  IntExpr* const left_;
3750  IntExpr* const right_;
3751 };
3752 
3753 // ----- PlusIntCstExpr -----
3754 
3755 class PlusIntCstExpr : public BaseIntExpr {
3756  public:
3757  PlusIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
3758  : BaseIntExpr(s), expr_(e), value_(v) {}
3759  ~PlusIntCstExpr() override {}
3760  int64_t Min() const override { return CapAdd(expr_->Min(), value_); }
3761  void SetMin(int64_t m) override { expr_->SetMin(CapSub(m, value_)); }
3762  int64_t Max() const override { return CapAdd(expr_->Max(), value_); }
3763  void SetMax(int64_t m) override { expr_->SetMax(CapSub(m, value_)); }
3764  bool Bound() const override { return (expr_->Bound()); }
3765  std::string name() const override {
3766  return absl::StrFormat("(%s + %d)", expr_->name(), value_);
3767  }
3768  std::string DebugString() const override {
3769  return absl::StrFormat("(%s + %d)", expr_->DebugString(), value_);
3770  }
3771  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
3772  IntVar* CastToVar() override;
3773  void Accept(ModelVisitor* const visitor) const override {
3774  visitor->BeginVisitIntegerExpression(ModelVisitor::kSum, this);
3775  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
3776  expr_);
3777  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
3778  visitor->EndVisitIntegerExpression(ModelVisitor::kSum, this);
3779  }
3780 
3781  private:
3782  IntExpr* const expr_;
3783  const int64_t value_;
3784 };
3785 
3786 IntVar* PlusIntCstExpr::CastToVar() {
3787  Solver* const s = solver();
3788  IntVar* const var = expr_->Var();
3789  IntVar* cast = nullptr;
3790  if (AddOverflows(value_, expr_->Max()) ||
3791  AddOverflows(value_, expr_->Min())) {
3792  return BaseIntExpr::CastToVar();
3793  }
3794  switch (var->VarType()) {
3795  case DOMAIN_INT_VAR:
3796  cast = s->RegisterIntVar(s->RevAlloc(new PlusCstDomainIntVar(
3797  s, reinterpret_cast<DomainIntVar*>(var), value_)));
3798  // FIXME: Break was inserted during fallthrough cleanup. Please check.
3799  break;
3800  default:
3801  cast = s->RegisterIntVar(s->RevAlloc(new PlusCstIntVar(s, var, value_)));
3802  break;
3803  }
3804  return cast;
3805 }
3806 
3807 // ----- SubIntExpr -----
3808 
3809 class SubIntExpr : public BaseIntExpr {
3810  public:
3811  SubIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
3812  : BaseIntExpr(s), left_(l), right_(r) {}
3813 
3814  ~SubIntExpr() override {}
3815 
3816  int64_t Min() const override { return left_->Min() - right_->Max(); }
3817 
3818  void SetMin(int64_t m) override {
3819  left_->SetMin(CapAdd(m, right_->Min()));
3820  right_->SetMax(CapSub(left_->Max(), m));
3821  }
3822 
3823  int64_t Max() const override { return left_->Max() - right_->Min(); }
3824 
3825  void SetMax(int64_t m) override {
3826  left_->SetMax(CapAdd(m, right_->Max()));
3827  right_->SetMin(CapSub(left_->Min(), m));
3828  }
3829 
3830  void Range(int64_t* mi, int64_t* ma) override {
3831  *mi = left_->Min() - right_->Max();
3832  *ma = left_->Max() - right_->Min();
3833  }
3834 
3835  void SetRange(int64_t l, int64_t u) override {
3836  const int64_t left_min = left_->Min();
3837  const int64_t right_min = right_->Min();
3838  const int64_t left_max = left_->Max();
3839  const int64_t right_max = right_->Max();
3840  if (l > left_min - right_max) {
3841  left_->SetMin(CapAdd(l, right_min));
3842  right_->SetMax(CapSub(left_max, l));
3843  }
3844  if (u < left_max - right_min) {
3845  left_->SetMax(CapAdd(u, right_max));
3846  right_->SetMin(CapSub(left_min, u));
3847  }
3848  }
3849 
3850  bool Bound() const override { return (left_->Bound() && right_->Bound()); }
3851 
3852  std::string name() const override {
3853  return absl::StrFormat("(%s - %s)", left_->name(), right_->name());
3854  }
3855 
3856  std::string DebugString() const override {
3857  return absl::StrFormat("(%s - %s)", left_->DebugString(),
3858  right_->DebugString());
3859  }
3860 
3861  void WhenRange(Demon* d) override {
3862  left_->WhenRange(d);
3863  right_->WhenRange(d);
3864  }
3865 
3866  void Accept(ModelVisitor* const visitor) const override {
3867  visitor->BeginVisitIntegerExpression(ModelVisitor::kDifference, this);
3868  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
3869  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
3870  right_);
3871  visitor->EndVisitIntegerExpression(ModelVisitor::kDifference, this);
3872  }
3873 
3874  IntExpr* left() const { return left_; }
3875  IntExpr* right() const { return right_; }
3876 
3877  protected:
3878  IntExpr* const left_;
3879  IntExpr* const right_;
3880 };
3881 
3882 class SafeSubIntExpr : public SubIntExpr {
3883  public:
3884  SafeSubIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
3885  : SubIntExpr(s, l, r) {}
3886 
3887  ~SafeSubIntExpr() override {}
3888 
3889  int64_t Min() const override { return CapSub(left_->Min(), right_->Max()); }
3890 
3891  void SetMin(int64_t m) override {
3892  left_->SetMin(CapAdd(m, right_->Min()));
3893  right_->SetMax(CapSub(left_->Max(), m));
3894  }
3895 
3896  void SetRange(int64_t l, int64_t u) override {
3897  const int64_t left_min = left_->Min();
3898  const int64_t right_min = right_->Min();
3899  const int64_t left_max = left_->Max();
3900  const int64_t right_max = right_->Max();
3901  if (l > CapSub(left_min, right_max)) {
3902  left_->SetMin(CapAdd(l, right_min));
3903  right_->SetMax(CapSub(left_max, l));
3904  }
3905  if (u < CapSub(left_max, right_min)) {
3906  left_->SetMax(CapAdd(u, right_max));
3907  right_->SetMin(CapSub(left_min, u));
3908  }
3909  }
3910 
3911  void Range(int64_t* mi, int64_t* ma) override {
3912  *mi = CapSub(left_->Min(), right_->Max());
3913  *ma = CapSub(left_->Max(), right_->Min());
3914  }
3915 
3916  int64_t Max() const override { return CapSub(left_->Max(), right_->Min()); }
3917 
3918  void SetMax(int64_t m) override {
3919  left_->SetMax(CapAdd(m, right_->Max()));
3920  right_->SetMin(CapSub(left_->Min(), m));
3921  }
3922 };
3923 
3924 // l - r
3925 
3926 // ----- SubIntCstExpr -----
3927 
3928 class SubIntCstExpr : public BaseIntExpr {
3929  public:
3930  SubIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
3931  : BaseIntExpr(s), expr_(e), value_(v) {}
3932  ~SubIntCstExpr() override {}
3933  int64_t Min() const override { return CapSub(value_, expr_->Max()); }
3934  void SetMin(int64_t m) override { expr_->SetMax(CapSub(value_, m)); }
3935  int64_t Max() const override { return CapSub(value_, expr_->Min()); }
3936  void SetMax(int64_t m) override { expr_->SetMin(CapSub(value_, m)); }
3937  bool Bound() const override { return (expr_->Bound()); }
3938  std::string name() const override {
3939  return absl::StrFormat("(%d - %s)", value_, expr_->name());
3940  }
3941  std::string DebugString() const override {
3942  return absl::StrFormat("(%d - %s)", value_, expr_->DebugString());
3943  }
3944  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
3945  IntVar* CastToVar() override;
3946 
3947  void Accept(ModelVisitor* const visitor) const override {
3948  visitor->BeginVisitIntegerExpression(ModelVisitor::kDifference, this);
3949  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
3950  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
3951  expr_);
3952  visitor->EndVisitIntegerExpression(ModelVisitor::kDifference, this);
3953  }
3954 
3955  private:
3956  IntExpr* const expr_;
3957  const int64_t value_;
3958 };
3959 
3960 IntVar* SubIntCstExpr::CastToVar() {
3961  if (SubOverflows(value_, expr_->Min()) ||
3962  SubOverflows(value_, expr_->Max())) {
3963  return BaseIntExpr::CastToVar();
3964  }
3965  Solver* const s = solver();
3966  IntVar* const var =
3967  s->RegisterIntVar(s->RevAlloc(new SubCstIntVar(s, expr_->Var(), value_)));
3968  return var;
3969 }
3970 
3971 // ----- OppIntExpr -----
3972 
3973 class OppIntExpr : public BaseIntExpr {
3974  public:
3975  OppIntExpr(Solver* const s, IntExpr* const e) : BaseIntExpr(s), expr_(e) {}
3976  ~OppIntExpr() override {}
3977  int64_t Min() const override { return (CapOpp(expr_->Max())); }
3978  void SetMin(int64_t m) override { expr_->SetMax(CapOpp(m)); }
3979  int64_t Max() const override { return (CapOpp(expr_->Min())); }
3980  void SetMax(int64_t m) override { expr_->SetMin(CapOpp(m)); }
3981  bool Bound() const override { return (expr_->Bound()); }
3982  std::string name() const override {
3983  return absl::StrFormat("(-%s)", expr_->name());
3984  }
3985  std::string DebugString() const override {
3986  return absl::StrFormat("(-%s)", expr_->DebugString());
3987  }
3988  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
3989  IntVar* CastToVar() override;
3990 
3991  void Accept(ModelVisitor* const visitor) const override {
3992  visitor->BeginVisitIntegerExpression(ModelVisitor::kOpposite, this);
3993  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
3994  expr_);
3995  visitor->EndVisitIntegerExpression(ModelVisitor::kOpposite, this);
3996  }
3997 
3998  private:
3999  IntExpr* const expr_;
4000 };
4001 
4002 IntVar* OppIntExpr::CastToVar() {
4003  Solver* const s = solver();
4004  IntVar* const var =
4005  s->RegisterIntVar(s->RevAlloc(new OppIntVar(s, expr_->Var())));
4006  return var;
4007 }
4008 
4009 // ----- TimesIntCstExpr -----
4010 
4011 class TimesIntCstExpr : public BaseIntExpr {
4012  public:
4013  TimesIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
4014  : BaseIntExpr(s), expr_(e), value_(v) {}
4015 
4016  ~TimesIntCstExpr() override {}
4017 
4018  bool Bound() const override { return (expr_->Bound()); }
4019 
4020  std::string name() const override {
4021  return absl::StrFormat("(%s * %d)", expr_->name(), value_);
4022  }
4023 
4024  std::string DebugString() const override {
4025  return absl::StrFormat("(%s * %d)", expr_->DebugString(), value_);
4026  }
4027 
4028  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
4029 
4030  IntExpr* Expr() const { return expr_; }
4031 
4032  int64_t Constant() const { return value_; }
4033 
4034  void Accept(ModelVisitor* const visitor) const override {
4035  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4036  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
4037  expr_);
4038  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
4039  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4040  }
4041 
4042  protected:
4043  IntExpr* const expr_;
4044  const int64_t value_;
4045 };
4046 
4047 // ----- TimesPosIntCstExpr -----
4048 
4049 class TimesPosIntCstExpr : public TimesIntCstExpr {
4050  public:
4051  TimesPosIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
4052  : TimesIntCstExpr(s, e, v) {
4053  CHECK_GT(v, 0);
4054  }
4055 
4056  ~TimesPosIntCstExpr() override {}
4057 
4058  int64_t Min() const override { return expr_->Min() * value_; }
4059 
4060  void SetMin(int64_t m) override { expr_->SetMin(PosIntDivUp(m, value_)); }
4061 
4062  int64_t Max() const override { return expr_->Max() * value_; }
4063 
4064  void SetMax(int64_t m) override { expr_->SetMax(PosIntDivDown(m, value_)); }
4065 
4066  IntVar* CastToVar() override {
4067  Solver* const s = solver();
4068  IntVar* var = nullptr;
4069  if (expr_->IsVar() &&
4070  reinterpret_cast<IntVar*>(expr_)->VarType() == BOOLEAN_VAR) {
4071  var = s->RegisterIntVar(s->RevAlloc(new TimesPosCstBoolVar(
4072  s, reinterpret_cast<BooleanVar*>(expr_), value_)));
4073  } else {
4074  var = s->RegisterIntVar(
4075  s->RevAlloc(new TimesPosCstIntVar(s, expr_->Var(), value_)));
4076  }
4077  return var;
4078  }
4079 };
4080 
4081 // This expressions adds safe arithmetic (w.r.t. overflows) compared
4082 // to the previous one.
4083 class SafeTimesPosIntCstExpr : public TimesIntCstExpr {
4084  public:
4085  SafeTimesPosIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
4086  : TimesIntCstExpr(s, e, v) {
4087  CHECK_GT(v, 0);
4088  }
4089 
4090  ~SafeTimesPosIntCstExpr() override {}
4091 
4092  int64_t Min() const override { return CapProd(expr_->Min(), value_); }
4093 
4094  void SetMin(int64_t m) override {
4095  if (m != std::numeric_limits<int64_t>::min()) {
4096  expr_->SetMin(PosIntDivUp(m, value_));
4097  }
4098  }
4099 
4100  int64_t Max() const override { return CapProd(expr_->Max(), value_); }
4101 
4102  void SetMax(int64_t m) override {
4103  if (m != std::numeric_limits<int64_t>::max()) {
4104  expr_->SetMax(PosIntDivDown(m, value_));
4105  }
4106  }
4107 
4108  IntVar* CastToVar() override {
4109  Solver* const s = solver();
4110  IntVar* var = nullptr;
4111  if (expr_->IsVar() &&
4112  reinterpret_cast<IntVar*>(expr_)->VarType() == BOOLEAN_VAR) {
4113  var = s->RegisterIntVar(s->RevAlloc(new TimesPosCstBoolVar(
4114  s, reinterpret_cast<BooleanVar*>(expr_), value_)));
4115  } else {
4116  // TODO(user): Check overflows.
4117  var = s->RegisterIntVar(
4118  s->RevAlloc(new TimesPosCstIntVar(s, expr_->Var(), value_)));
4119  }
4120  return var;
4121  }
4122 };
4123 
4124 // ----- TimesIntNegCstExpr -----
4125 
4126 class TimesIntNegCstExpr : public TimesIntCstExpr {
4127  public:
4128  TimesIntNegCstExpr(Solver* const s, IntExpr* const e, int64_t v)
4129  : TimesIntCstExpr(s, e, v) {
4130  CHECK_LT(v, 0);
4131  }
4132 
4133  ~TimesIntNegCstExpr() override {}
4134 
4135  int64_t Min() const override { return CapProd(expr_->Max(), value_); }
4136 
4137  void SetMin(int64_t m) override {
4138  if (m != std::numeric_limits<int64_t>::min()) {
4139  expr_->SetMax(PosIntDivDown(-m, -value_));
4140  }
4141  }
4142 
4143  int64_t Max() const override { return CapProd(expr_->Min(), value_); }
4144 
4145  void SetMax(int64_t m) override {
4146  if (m != std::numeric_limits<int64_t>::max()) {
4147  expr_->SetMin(PosIntDivUp(-m, -value_));
4148  }
4149  }
4150 
4151  IntVar* CastToVar() override {
4152  Solver* const s = solver();
4153  IntVar* var = nullptr;
4154  var = s->RegisterIntVar(
4155  s->RevAlloc(new TimesNegCstIntVar(s, expr_->Var(), value_)));
4156  return var;
4157  }
4158 };
4159 
4160 // ----- Utilities for product expression -----
4161 
4162 // Propagates set_min on left * right, left and right >= 0.
4163 void SetPosPosMinExpr(IntExpr* const left, IntExpr* const right, int64_t m) {
4164  DCHECK_GE(left->Min(), 0);
4165  DCHECK_GE(right->Min(), 0);
4166  const int64_t lmax = left->Max();
4167  const int64_t rmax = right->Max();
4168  if (m > CapProd(lmax, rmax)) {
4169  left->solver()->Fail();
4170  }
4171  if (m > CapProd(left->Min(), right->Min())) {
4172  // Ok for m == 0 due to left and right being positive
4173  if (0 != rmax) {
4174  left->SetMin(PosIntDivUp(m, rmax));
4175  }
4176  if (0 != lmax) {
4177  right->SetMin(PosIntDivUp(m, lmax));
4178  }
4179  }
4180 }
4181 
4182 // Propagates set_max on left * right, left and right >= 0.
4183 void SetPosPosMaxExpr(IntExpr* const left, IntExpr* const right, int64_t m) {
4184  DCHECK_GE(left->Min(), 0);
4185  DCHECK_GE(right->Min(), 0);
4186  const int64_t lmin = left->Min();
4187  const int64_t rmin = right->Min();
4188  if (m < CapProd(lmin, rmin)) {
4189  left->solver()->Fail();
4190  }
4191  if (m < CapProd(left->Max(), right->Max())) {
4192  if (0 != lmin) {
4193  right->SetMax(PosIntDivDown(m, lmin));
4194  }
4195  if (0 != rmin) {
4196  left->SetMax(PosIntDivDown(m, rmin));
4197  }
4198  // else do nothing: 0 is supporting any value from other expr.
4199  }
4200 }
4201 
4202 // Propagates set_min on left * right, left >= 0, right across 0.
4203 void SetPosGenMinExpr(IntExpr* const left, IntExpr* const right, int64_t m) {
4204  DCHECK_GE(left->Min(), 0);
4205  DCHECK_GT(right->Max(), 0);
4206  DCHECK_LT(right->Min(), 0);
4207  const int64_t lmax = left->Max();
4208  const int64_t rmax = right->Max();
4209  if (m > CapProd(lmax, rmax)) {
4210  left->solver()->Fail();
4211  }
4212  if (left->Max() == 0) { // left is bound to 0, product is bound to 0.
4213  DCHECK_EQ(0, left->Min());
4214  DCHECK_LE(m, 0);
4215  } else {
4216  if (m > 0) { // We deduce right > 0.
4217  left->SetMin(PosIntDivUp(m, rmax));
4218  right->SetMin(PosIntDivUp(m, lmax));
4219  } else if (m == 0) {
4220  const int64_t lmin = left->Min();
4221  if (lmin > 0) {
4222  right->SetMin(0);
4223  }
4224  } else { // m < 0
4225  const int64_t lmin = left->Min();
4226  if (0 != lmin) { // We cannot deduce anything if 0 is in the domain.
4227  right->SetMin(-PosIntDivDown(-m, lmin));
4228  }
4229  }
4230  }
4231 }
4232 
4233 // Propagates set_min on left * right, left and right across 0.
4234 void SetGenGenMinExpr(IntExpr* const left, IntExpr* const right, int64_t m) {
4235  DCHECK_LT(left->Min(), 0);
4236  DCHECK_GT(left->Max(), 0);
4237  DCHECK_GT(right->Max(), 0);
4238  DCHECK_LT(right->Min(), 0);
4239  const int64_t lmin = left->Min();
4240  const int64_t lmax = left->Max();
4241  const int64_t rmin = right->Min();
4242  const int64_t rmax = right->Max();
4243  if (m > std::max(CapProd(lmin, rmin), CapProd(lmax, rmax))) {
4244  left->solver()->Fail();
4245  }
4246  if (m >
4247  CapProd(lmin, rmin)) { // Must be positive section * positive section.
4248  left->SetMin(PosIntDivUp(m, rmax));
4249  right->SetMin(PosIntDivUp(m, lmax));
4250  } else if (m > CapProd(lmax, rmax)) { // Negative section * negative section.
4251  left->SetMax(CapOpp(PosIntDivUp(m, CapOpp(rmin))));
4252  right->SetMax(CapOpp(PosIntDivUp(m, CapOpp(lmin))));
4253  }
4254 }
4255 
4256 void TimesSetMin(IntExpr* const left, IntExpr* const right,
4257  IntExpr* const minus_left, IntExpr* const minus_right,
4258  int64_t m) {
4259  if (left->Min() >= 0) {
4260  if (right->Min() >= 0) {
4261  SetPosPosMinExpr(left, right, m);
4262  } else if (right->Max() <= 0) {
4263  SetPosPosMaxExpr(left, minus_right, -m);
4264  } else { // right->Min() < 0 && right->Max() > 0
4265  SetPosGenMinExpr(left, right, m);
4266  }
4267  } else if (left->Max() <= 0) {
4268  if (right->Min() >= 0) {
4269  SetPosPosMaxExpr(right, minus_left, -m);
4270  } else if (right->Max() <= 0) {
4271  SetPosPosMinExpr(minus_left, minus_right, m);
4272  } else { // right->Min() < 0 && right->Max() > 0
4273  SetPosGenMinExpr(minus_left, minus_right, m);
4274  }
4275  } else if (right->Min() >= 0) { // left->Min() < 0 && left->Max() > 0
4276  SetPosGenMinExpr(right, left, m);
4277  } else if (right->Max() <= 0) { // left->Min() < 0 && left->Max() > 0
4278  SetPosGenMinExpr(minus_right, minus_left, m);
4279  } else { // left->Min() < 0 && left->Max() > 0 &&
4280  // right->Min() < 0 && right->Max() > 0
4281  SetGenGenMinExpr(left, right, m);
4282  }
4283 }
4284 
4285 class TimesIntExpr : public BaseIntExpr {
4286  public:
4287  TimesIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
4288  : BaseIntExpr(s),
4289  left_(l),
4290  right_(r),
4291  minus_left_(s->MakeOpposite(left_)),
4292  minus_right_(s->MakeOpposite(right_)) {}
4293  ~TimesIntExpr() override {}
4294  int64_t Min() const override {
4295  const int64_t lmin = left_->Min();
4296  const int64_t lmax = left_->Max();
4297  const int64_t rmin = right_->Min();
4298  const int64_t rmax = right_->Max();
4299  return std::min(std::min(CapProd(lmin, rmin), CapProd(lmax, rmax)),
4300  std::min(CapProd(lmax, rmin), CapProd(lmin, rmax)));
4301  }
4302  void SetMin(int64_t m) override;
4303  int64_t Max() const override {
4304  const int64_t lmin = left_->Min();
4305  const int64_t lmax = left_->Max();
4306  const int64_t rmin = right_->Min();
4307  const int64_t rmax = right_->Max();
4308  return std::max(std::max(CapProd(lmin, rmin), CapProd(lmax, rmax)),
4309  std::max(CapProd(lmax, rmin), CapProd(lmin, rmax)));
4310  }
4311  void SetMax(int64_t m) override;
4312  bool Bound() const override;
4313  std::string name() const override {
4314  return absl::StrFormat("(%s * %s)", left_->name(), right_->name());
4315  }
4316  std::string DebugString() const override {
4317  return absl::StrFormat("(%s * %s)", left_->DebugString(),
4318  right_->DebugString());
4319  }
4320  void WhenRange(Demon* d) override {
4321  left_->WhenRange(d);
4322  right_->WhenRange(d);
4323  }
4324 
4325  void Accept(ModelVisitor* const visitor) const override {
4326  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4327  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
4328  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4329  right_);
4330  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4331  }
4332 
4333  private:
4334  IntExpr* const left_;
4335  IntExpr* const right_;
4336  IntExpr* const minus_left_;
4337  IntExpr* const minus_right_;
4338 };
4339 
4340 void TimesIntExpr::SetMin(int64_t m) {
4341  if (m != std::numeric_limits<int64_t>::min()) {
4342  TimesSetMin(left_, right_, minus_left_, minus_right_, m);
4343  }
4344 }
4345 
4346 void TimesIntExpr::SetMax(int64_t m) {
4347  if (m != std::numeric_limits<int64_t>::max()) {
4348  TimesSetMin(left_, minus_right_, minus_left_, right_, CapOpp(m));
4349  }
4350 }
4351 
4352 bool TimesIntExpr::Bound() const {
4353  const bool left_bound = left_->Bound();
4354  const bool right_bound = right_->Bound();
4355  return ((left_bound && left_->Max() == 0) ||
4356  (right_bound && right_->Max() == 0) || (left_bound && right_bound));
4357 }
4358 
4359 // ----- TimesPosIntExpr -----
4360 
4361 class TimesPosIntExpr : public BaseIntExpr {
4362  public:
4363  TimesPosIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
4364  : BaseIntExpr(s), left_(l), right_(r) {}
4365  ~TimesPosIntExpr() override {}
4366  int64_t Min() const override { return (left_->Min() * right_->Min()); }
4367  void SetMin(int64_t m) override;
4368  int64_t Max() const override { return (left_->Max() * right_->Max()); }
4369  void SetMax(int64_t m) override;
4370  bool Bound() const override;
4371  std::string name() const override {
4372  return absl::StrFormat("(%s * %s)", left_->name(), right_->name());
4373  }
4374  std::string DebugString() const override {
4375  return absl::StrFormat("(%s * %s)", left_->DebugString(),
4376  right_->DebugString());
4377  }
4378  void WhenRange(Demon* d) override {
4379  left_->WhenRange(d);
4380  right_->WhenRange(d);
4381  }
4382 
4383  void Accept(ModelVisitor* const visitor) const override {
4384  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4385  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
4386  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4387  right_);
4388  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4389  }
4390 
4391  private:
4392  IntExpr* const left_;
4393  IntExpr* const right_;
4394 };
4395 
4396 void TimesPosIntExpr::SetMin(int64_t m) { SetPosPosMinExpr(left_, right_, m); }
4397 
4398 void TimesPosIntExpr::SetMax(int64_t m) { SetPosPosMaxExpr(left_, right_, m); }
4399 
4400 bool TimesPosIntExpr::Bound() const {
4401  return (left_->Max() == 0 || right_->Max() == 0 ||
4402  (left_->Bound() && right_->Bound()));
4403 }
4404 
4405 // ----- SafeTimesPosIntExpr -----
4406 
4407 class SafeTimesPosIntExpr : public BaseIntExpr {
4408  public:
4409  SafeTimesPosIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
4410  : BaseIntExpr(s), left_(l), right_(r) {}
4411  ~SafeTimesPosIntExpr() override {}
4412  int64_t Min() const override { return CapProd(left_->Min(), right_->Min()); }
4413  void SetMin(int64_t m) override {
4414  if (m != std::numeric_limits<int64_t>::min()) {
4415  SetPosPosMinExpr(left_, right_, m);
4416  }
4417  }
4418  int64_t Max() const override { return CapProd(left_->Max(), right_->Max()); }
4419  void SetMax(int64_t m) override {
4420  if (m != std::numeric_limits<int64_t>::max()) {
4421  SetPosPosMaxExpr(left_, right_, m);
4422  }
4423  }
4424  bool Bound() const override {
4425  return (left_->Max() == 0 || right_->Max() == 0 ||
4426  (left_->Bound() && right_->Bound()));
4427  }
4428  std::string name() const override {
4429  return absl::StrFormat("(%s * %s)", left_->name(), right_->name());
4430  }
4431  std::string DebugString() const override {
4432  return absl::StrFormat("(%s * %s)", left_->DebugString(),
4433  right_->DebugString());
4434  }
4435  void WhenRange(Demon* d) override {
4436  left_->WhenRange(d);
4437  right_->WhenRange(d);
4438  }
4439 
4440  void Accept(ModelVisitor* const visitor) const override {
4441  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4442  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
4443  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4444  right_);
4445  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4446  }
4447 
4448  private:
4449  IntExpr* const left_;
4450  IntExpr* const right_;
4451 };
4452 
4453 // ----- TimesBooleanPosIntExpr -----
4454 
4455 class TimesBooleanPosIntExpr : public BaseIntExpr {
4456  public:
4457  TimesBooleanPosIntExpr(Solver* const s, BooleanVar* const b, IntExpr* const e)
4458  : BaseIntExpr(s), boolvar_(b), expr_(e) {}
4459  ~TimesBooleanPosIntExpr() override {}
4460  int64_t Min() const override {
4461  return (boolvar_->RawValue() == 1 ? expr_->Min() : 0);
4462  }
4463  void SetMin(int64_t m) override;
4464  int64_t Max() const override {
4465  return (boolvar_->RawValue() == 0 ? 0 : expr_->Max());
4466  }
4467  void SetMax(int64_t m) override;
4468  void Range(int64_t* mi, int64_t* ma) override;
4469  void SetRange(int64_t mi, int64_t ma) override;
4470  bool Bound() const override;
4471  std::string name() const override {
4472  return absl::StrFormat("(%s * %s)", boolvar_->name(), expr_->name());
4473  }
4474  std::string DebugString() const override {
4475  return absl::StrFormat("(%s * %s)", boolvar_->DebugString(),
4476  expr_->DebugString());
4477  }
4478  void WhenRange(Demon* d) override {
4479  boolvar_->WhenRange(d);
4480  expr_->WhenRange(d);
4481  }
4482 
4483  void Accept(ModelVisitor* const visitor) const override {
4484  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4485  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument,
4486  boolvar_);
4487  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4488  expr_);
4489  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4490  }
4491 
4492  private:
4493  BooleanVar* const boolvar_;
4494  IntExpr* const expr_;
4495 };
4496 
4497 void TimesBooleanPosIntExpr::SetMin(int64_t m) {
4498  if (m > 0) {
4499  boolvar_->SetValue(1);
4500  expr_->SetMin(m);
4501  }
4502 }
4503 
4504 void TimesBooleanPosIntExpr::SetMax(int64_t m) {
4505  if (m < 0) {
4506  solver()->Fail();
4507  }
4508  if (m < expr_->Min()) {
4509  boolvar_->SetValue(0);
4510  }
4511  if (boolvar_->RawValue() == 1) {
4512  expr_->SetMax(m);
4513  }
4514 }
4515 
4516 void TimesBooleanPosIntExpr::Range(int64_t* mi, int64_t* ma) {
4517  const int value = boolvar_->RawValue();
4518  if (value == 0) {
4519  *mi = 0;
4520  *ma = 0;
4521  } else if (value == 1) {
4522  expr_->Range(mi, ma);
4523  } else {
4524  *mi = 0;
4525  *ma = expr_->Max();
4526  }
4527 }
4528 
4529 void TimesBooleanPosIntExpr::SetRange(int64_t mi, int64_t ma) {
4530  if (ma < 0 || mi > ma) {
4531  solver()->Fail();
4532  }
4533  if (mi > 0) {
4534  boolvar_->SetValue(1);
4535  expr_->SetMin(mi);
4536  }
4537  if (ma < expr_->Min()) {
4538  boolvar_->SetValue(0);
4539  }
4540  if (boolvar_->RawValue() == 1) {
4541  expr_->SetMax(ma);
4542  }
4543 }
4544 
4545 bool TimesBooleanPosIntExpr::Bound() const {
4546  return (boolvar_->RawValue() == 0 || expr_->Max() == 0 ||
4547  (boolvar_->RawValue() != BooleanVar::kUnboundBooleanVarValue &&
4548  expr_->Bound()));
4549 }
4550 
4551 // ----- TimesBooleanIntExpr -----
4552 
4553 class TimesBooleanIntExpr : public BaseIntExpr {
4554  public:
4555  TimesBooleanIntExpr(Solver* const s, BooleanVar* const b, IntExpr* const e)
4556  : BaseIntExpr(s), boolvar_(b), expr_(e) {}
4557  ~TimesBooleanIntExpr() override {}
4558  int64_t Min() const override {
4559  switch (boolvar_->RawValue()) {
4560  case 0: {
4561  return 0LL;
4562  }
4563  case 1: {
4564  return expr_->Min();
4565  }
4566  default: {
4567  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4568  return std::min(int64_t{0}, expr_->Min());
4569  }
4570  }
4571  }
4572  void SetMin(int64_t m) override;
4573  int64_t Max() const override {
4574  switch (boolvar_->RawValue()) {
4575  case 0: {
4576  return 0LL;
4577  }
4578  case 1: {
4579  return expr_->Max();
4580  }
4581  default: {
4582  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4583  return std::max(int64_t{0}, expr_->Max());
4584  }
4585  }
4586  }
4587  void SetMax(int64_t m) override;
4588  void Range(int64_t* mi, int64_t* ma) override;
4589  void SetRange(int64_t mi, int64_t ma) override;
4590  bool Bound() const override;
4591  std::string name() const override {
4592  return absl::StrFormat("(%s * %s)", boolvar_->name(), expr_->name());
4593  }
4594  std::string DebugString() const override {
4595  return absl::StrFormat("(%s * %s)", boolvar_->DebugString(),
4596  expr_->DebugString());
4597  }
4598  void WhenRange(Demon* d) override {
4599  boolvar_->WhenRange(d);
4600  expr_->WhenRange(d);
4601  }
4602 
4603  void Accept(ModelVisitor* const visitor) const override {
4604  visitor->BeginVisitIntegerExpression(ModelVisitor::kProduct, this);
4605  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument,
4606  boolvar_);
4607  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4608  expr_);
4609  visitor->EndVisitIntegerExpression(ModelVisitor::kProduct, this);
4610  }
4611 
4612  private:
4613  BooleanVar* const boolvar_;
4614  IntExpr* const expr_;
4615 };
4616 
4617 void TimesBooleanIntExpr::SetMin(int64_t m) {
4618  switch (boolvar_->RawValue()) {
4619  case 0: {
4620  if (m > 0) {
4621  solver()->Fail();
4622  }
4623  break;
4624  }
4625  case 1: {
4626  expr_->SetMin(m);
4627  break;
4628  }
4629  default: {
4630  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4631  if (m > 0) { // 0 is no longer possible for boolvar because min > 0.
4632  boolvar_->SetValue(1);
4633  expr_->SetMin(m);
4634  } else if (m <= 0 && expr_->Max() < m) {
4635  boolvar_->SetValue(0);
4636  }
4637  }
4638  }
4639 }
4640 
4641 void TimesBooleanIntExpr::SetMax(int64_t m) {
4642  switch (boolvar_->RawValue()) {
4643  case 0: {
4644  if (m < 0) {
4645  solver()->Fail();
4646  }
4647  break;
4648  }
4649  case 1: {
4650  expr_->SetMax(m);
4651  break;
4652  }
4653  default: {
4654  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4655  if (m < 0) { // 0 is no longer possible for boolvar because max < 0.
4656  boolvar_->SetValue(1);
4657  expr_->SetMax(m);
4658  } else if (m >= 0 && expr_->Min() > m) {
4659  boolvar_->SetValue(0);
4660  }
4661  }
4662  }
4663 }
4664 
4665 void TimesBooleanIntExpr::Range(int64_t* mi, int64_t* ma) {
4666  switch (boolvar_->RawValue()) {
4667  case 0: {
4668  *mi = 0;
4669  *ma = 0;
4670  break;
4671  }
4672  case 1: {
4673  *mi = expr_->Min();
4674  *ma = expr_->Max();
4675  break;
4676  }
4677  default: {
4678  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4679  *mi = std::min(int64_t{0}, expr_->Min());
4680  *ma = std::max(int64_t{0}, expr_->Max());
4681  break;
4682  }
4683  }
4684 }
4685 
4686 void TimesBooleanIntExpr::SetRange(int64_t mi, int64_t ma) {
4687  if (mi > ma) {
4688  solver()->Fail();
4689  }
4690  switch (boolvar_->RawValue()) {
4691  case 0: {
4692  if (mi > 0 || ma < 0) {
4693  solver()->Fail();
4694  }
4695  break;
4696  }
4697  case 1: {
4698  expr_->SetRange(mi, ma);
4699  break;
4700  }
4701  default: {
4702  DCHECK_EQ(BooleanVar::kUnboundBooleanVarValue, boolvar_->RawValue());
4703  if (mi > 0) {
4704  boolvar_->SetValue(1);
4705  expr_->SetMin(mi);
4706  } else if (mi == 0 && expr_->Max() < 0) {
4707  boolvar_->SetValue(0);
4708  }
4709  if (ma < 0) {
4710  boolvar_->SetValue(1);
4711  expr_->SetMax(ma);
4712  } else if (ma == 0 && expr_->Min() > 0) {
4713  boolvar_->SetValue(0);
4714  }
4715  break;
4716  }
4717  }
4718 }
4719 
4720 bool TimesBooleanIntExpr::Bound() const {
4721  return (boolvar_->RawValue() == 0 ||
4722  (expr_->Bound() &&
4723  (boolvar_->RawValue() != BooleanVar::kUnboundBooleanVarValue ||
4724  expr_->Max() == 0)));
4725 }
4726 
4727 // ----- DivPosIntCstExpr -----
4728 
4729 class DivPosIntCstExpr : public BaseIntExpr {
4730  public:
4731  DivPosIntCstExpr(Solver* const s, IntExpr* const e, int64_t v)
4732  : BaseIntExpr(s), expr_(e), value_(v) {
4733  CHECK_GE(v, 0);
4734  }
4735  ~DivPosIntCstExpr() override {}
4736 
4737  int64_t Min() const override { return expr_->Min() / value_; }
4738 
4739  void SetMin(int64_t m) override {
4740  if (m > 0) {
4741  expr_->SetMin(m * value_);
4742  } else {
4743  expr_->SetMin((m - 1) * value_ + 1);
4744  }
4745  }
4746  int64_t Max() const override { return expr_->Max() / value_; }
4747 
4748  void SetMax(int64_t m) override {
4749  if (m >= 0) {
4750  expr_->SetMax((m + 1) * value_ - 1);
4751  } else {
4752  expr_->SetMax(m * value_);
4753  }
4754  }
4755 
4756  std::string name() const override {
4757  return absl::StrFormat("(%s div %d)", expr_->name(), value_);
4758  }
4759 
4760  std::string DebugString() const override {
4761  return absl::StrFormat("(%s div %d)", expr_->DebugString(), value_);
4762  }
4763 
4764  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
4765 
4766  void Accept(ModelVisitor* const visitor) const override {
4767  visitor->BeginVisitIntegerExpression(ModelVisitor::kDivide, this);
4768  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
4769  expr_);
4770  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
4771  visitor->EndVisitIntegerExpression(ModelVisitor::kDivide, this);
4772  }
4773 
4774  private:
4775  IntExpr* const expr_;
4776  const int64_t value_;
4777 };
4778 
4779 // DivPosIntExpr
4780 
4781 class DivPosIntExpr : public BaseIntExpr {
4782  public:
4783  DivPosIntExpr(Solver* const s, IntExpr* const num, IntExpr* const denom)
4784  : BaseIntExpr(s),
4785  num_(num),
4786  denom_(denom),
4787  opp_num_(s->MakeOpposite(num)) {}
4788 
4789  ~DivPosIntExpr() override {}
4790 
4791  int64_t Min() const override {
4792  return num_->Min() >= 0
4793  ? num_->Min() / denom_->Max()
4794  : (denom_->Min() == 0 ? num_->Min()
4795  : num_->Min() / denom_->Min());
4796  }
4797 
4798  int64_t Max() const override {
4799  return num_->Max() >= 0 ? (denom_->Min() == 0 ? num_->Max()
4800  : num_->Max() / denom_->Min())
4801  : num_->Max() / denom_->Max();
4802  }
4803 
4804  static void SetPosMin(IntExpr* const num, IntExpr* const denom, int64_t m) {
4805  num->SetMin(m * denom->Min());
4806  denom->SetMax(num->Max() / m);
4807  }
4808 
4809  static void SetPosMax(IntExpr* const num, IntExpr* const denom, int64_t m) {
4810  num->SetMax((m + 1) * denom->Max() - 1);
4811  denom->SetMin(num->Min() / (m + 1) + 1);
4812  }
4813 
4814  void SetMin(int64_t m) override {
4815  if (m > 0) {
4816  SetPosMin(num_, denom_, m);
4817  } else {
4818  SetPosMax(opp_num_, denom_, -m);
4819  }
4820  }
4821 
4822  void SetMax(int64_t m) override {
4823  if (m >= 0) {
4824  SetPosMax(num_, denom_, m);
4825  } else {
4826  SetPosMin(opp_num_, denom_, -m);
4827  }
4828  }
4829 
4830  std::string name() const override {
4831  return absl::StrFormat("(%s div %s)", num_->name(), denom_->name());
4832  }
4833  std::string DebugString() const override {
4834  return absl::StrFormat("(%s div %s)", num_->DebugString(),
4835  denom_->DebugString());
4836  }
4837  void WhenRange(Demon* d) override {
4838  num_->WhenRange(d);
4839  denom_->WhenRange(d);
4840  }
4841 
4842  void Accept(ModelVisitor* const visitor) const override {
4843  visitor->BeginVisitIntegerExpression(ModelVisitor::kDivide, this);
4844  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, num_);
4845  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4846  denom_);
4847  visitor->EndVisitIntegerExpression(ModelVisitor::kDivide, this);
4848  }
4849 
4850  private:
4851  IntExpr* const num_;
4852  IntExpr* const denom_;
4853  IntExpr* const opp_num_;
4854 };
4855 
4856 class DivPosPosIntExpr : public BaseIntExpr {
4857  public:
4858  DivPosPosIntExpr(Solver* const s, IntExpr* const num, IntExpr* const denom)
4859  : BaseIntExpr(s), num_(num), denom_(denom) {}
4860 
4861  ~DivPosPosIntExpr() override {}
4862 
4863  int64_t Min() const override {
4864  if (denom_->Max() == 0) {
4865  solver()->Fail();
4866  }
4867  return num_->Min() / denom_->Max();
4868  }
4869 
4870  int64_t Max() const override {
4871  if (denom_->Min() == 0) {
4872  return num_->Max();
4873  } else {
4874  return num_->Max() / denom_->Min();
4875  }
4876  }
4877 
4878  void SetMin(int64_t m) override {
4879  if (m > 0) {
4880  num_->SetMin(m * denom_->Min());
4881  denom_->SetMax(num_->Max() / m);
4882  }
4883  }
4884 
4885  void SetMax(int64_t m) override {
4886  if (m >= 0) {
4887  num_->SetMax((m + 1) * denom_->Max() - 1);
4888  denom_->SetMin(num_->Min() / (m + 1) + 1);
4889  } else {
4890  solver()->Fail();
4891  }
4892  }
4893 
4894  std::string name() const override {
4895  return absl::StrFormat("(%s div %s)", num_->name(), denom_->name());
4896  }
4897 
4898  std::string DebugString() const override {
4899  return absl::StrFormat("(%s div %s)", num_->DebugString(),
4900  denom_->DebugString());
4901  }
4902 
4903  void WhenRange(Demon* d) override {
4904  num_->WhenRange(d);
4905  denom_->WhenRange(d);
4906  }
4907 
4908  void Accept(ModelVisitor* const visitor) const override {
4909  visitor->BeginVisitIntegerExpression(ModelVisitor::kDivide, this);
4910  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, num_);
4911  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
4912  denom_);
4913  visitor->EndVisitIntegerExpression(ModelVisitor::kDivide, this);
4914  }
4915 
4916  private:
4917  IntExpr* const num_;
4918  IntExpr* const denom_;
4919 };
4920 
4921 // DivIntExpr
4922 
4923 class DivIntExpr : public BaseIntExpr {
4924  public:
4925  DivIntExpr(Solver* const s, IntExpr* const num, IntExpr* const denom)
4926  : BaseIntExpr(s),
4927  num_(num),
4928  denom_(denom),
4929  opp_num_(s->MakeOpposite(num)) {}
4930 
4931  ~DivIntExpr() override {}
4932 
4933  int64_t Min() const override {
4934  const int64_t num_min = num_->Min();
4935  const int64_t num_max = num_->Max();
4936  const int64_t denom_min = denom_->Min();
4937  const int64_t denom_max = denom_->Max();
4938 
4939  if (denom_min == 0 && denom_max == 0) {
4940  return std::numeric_limits<int64_t>::max(); // TODO(user): Check this
4941  // convention.
4942  }
4943 
4944  if (denom_min >= 0) { // Denominator strictly positive.
4945  DCHECK_GT(denom_max, 0);
4946  const int64_t adjusted_denom_min = denom_min == 0 ? 1 : denom_min;
4947  return num_min >= 0 ? num_min / denom_max : num_min / adjusted_denom_min;
4948  } else if (denom_max <= 0) { // Denominator strictly negative.
4949  DCHECK_LT(denom_min, 0);
4950  const int64_t adjusted_denom_max = denom_max == 0 ? -1 : denom_max;
4951  return num_max >= 0 ? num_max / adjusted_denom_max : num_max / denom_min;
4952  } else { // Denominator across 0.
4953  return std::min(num_min, -num_max);
4954  }
4955  }
4956 
4957  int64_t Max() const override {
4958  const int64_t num_min = num_->Min();
4959  const int64_t num_max = num_->Max();
4960  const int64_t denom_min = denom_->Min();
4961  const int64_t denom_max = denom_->Max();
4962 
4963  if (denom_min == 0 && denom_max == 0) {
4964  return std::numeric_limits<int64_t>::min(); // TODO(user): Check this
4965  // convention.
4966  }
4967 
4968  if (denom_min >= 0) { // Denominator strictly positive.
4969  DCHECK_GT(denom_max, 0);
4970  const int64_t adjusted_denom_min = denom_min == 0 ? 1 : denom_min;
4971  return num_max >= 0 ? num_max / adjusted_denom_min : num_max / denom_max;
4972  } else if (denom_max <= 0) { // Denominator strictly negative.
4973  DCHECK_LT(denom_min, 0);
4974  const int64_t adjusted_denom_max = denom_max == 0 ? -1 : denom_max;
4975  return num_min >= 0 ? num_min / denom_min
4976  : -num_min / -adjusted_denom_max;
4977  } else { // Denominator across 0.
4978  return std::max(num_max, -num_min);
4979  }
4980  }
4981 
4982  void AdjustDenominator() {
4983  if (denom_->Min() == 0) {
4984  denom_->SetMin(1);
4985  } else if (denom_->Max() == 0) {
4986  denom_->SetMax(-1);
4987  }
4988  }
4989 
4990  // m > 0.
4991  static void SetPosMin(IntExpr* const num, IntExpr* const denom, int64_t m) {
4992  DCHECK_GT(m, 0);
4993  const int64_t num_min = num->Min();
4994  const int64_t num_max = num->Max();
4995  const int64_t denom_min = denom->Min();
4996  const int64_t denom_max = denom->Max();
4997  DCHECK_NE(denom_min, 0);
4998  DCHECK_NE(denom_max, 0);
4999  if (denom_min > 0) { // Denominator strictly positive.
5000  num->SetMin(m * denom_min);
5001  denom->SetMax(num_max / m);
5002  } else if (denom_max < 0) { // Denominator strictly negative.
5003  num->SetMax(m * denom_max);
5004  denom->SetMin(num_min / m);
5005  } else { // Denominator across 0.
5006  if (num_min >= 0) {
5007  num->SetMin(m);
5008  denom->SetRange(1, num_max / m);
5009  } else if (num_max <= 0) {
5010  num->SetMax(-m);
5011  denom->SetRange(num_min / m, -1);
5012  } else {
5013  if (m > -num_min) { // Denominator is forced positive.
5014  num->SetMin(m);
5015  denom->SetRange(1, num_max / m);
5016  } else if (m > num_max) { // Denominator is forced negative.
5017  num->SetMax(-m);
5018  denom->SetRange(num_min / m, -1);
5019  } else {
5020  denom->SetRange(num_min / m, num_max / m);
5021  }
5022  }
5023  }
5024  }
5025 
5026  // m >= 0.
5027  static void SetPosMax(IntExpr* const num, IntExpr* const denom, int64_t m) {
5028  DCHECK_GE(m, 0);
5029  const int64_t num_min = num->Min();
5030  const int64_t num_max = num->Max();
5031  const int64_t denom_min = denom->Min();
5032  const int64_t denom_max = denom->Max();
5033  DCHECK_NE(denom_min, 0);
5034  DCHECK_NE(denom_max, 0);
5035  if (denom_min > 0) { // Denominator strictly positive.
5036  num->SetMax((m + 1) * denom_max - 1);
5037  denom->SetMin((num_min / (m + 1)) + 1);
5038  } else if (denom_max < 0) {
5039  num->SetMin((m + 1) * denom_min + 1);
5040  denom->SetMax(num_max / (m + 1) - 1);
5041  } else if (num_min > (m + 1) * denom_max - 1) {
5042  denom->SetMax(-1);
5043  } else if (num_max < (m + 1) * denom_min + 1) {
5044  denom->SetMin(1);
5045  }
5046  }
5047 
5048  void SetMin(int64_t m) override {
5049  AdjustDenominator();
5050  if (m > 0) {
5051  SetPosMin(num_, denom_, m);
5052  } else {
5053  SetPosMax(opp_num_, denom_, -m);
5054  }
5055  }
5056 
5057  void SetMax(int64_t m) override {
5058  AdjustDenominator();
5059  if (m >= 0) {
5060  SetPosMax(num_, denom_, m);
5061  } else {
5062  SetPosMin(opp_num_, denom_, -m);
5063  }
5064  }
5065 
5066  std::string name() const override {
5067  return absl::StrFormat("(%s div %s)", num_->name(), denom_->name());
5068  }
5069  std::string DebugString() const override {
5070  return absl::StrFormat("(%s div %s)", num_->DebugString(),
5071  denom_->DebugString());
5072  }
5073  void WhenRange(Demon* d) override {
5074  num_->WhenRange(d);
5075  denom_->WhenRange(d);
5076  }
5077 
5078  void Accept(ModelVisitor* const visitor) const override {
5079  visitor->BeginVisitIntegerExpression(ModelVisitor::kDivide, this);
5080  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, num_);
5081  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
5082  denom_);
5083  visitor->EndVisitIntegerExpression(ModelVisitor::kDivide, this);
5084  }
5085 
5086  private:
5087  IntExpr* const num_;
5088  IntExpr* const denom_;
5089  IntExpr* const opp_num_;
5090 };
5091 
5092 // ----- IntAbs And IntAbsConstraint ------
5093 
5094 class IntAbsConstraint : public CastConstraint {
5095  public:
5096  IntAbsConstraint(Solver* const s, IntVar* const sub, IntVar* const target)
5097  : CastConstraint(s, target), sub_(sub) {}
5098 
5099  ~IntAbsConstraint() override {}
5100 
5101  void Post() override {
5102  Demon* const sub_demon = MakeConstraintDemon0(
5103  solver(), this, &IntAbsConstraint::PropagateSub, "PropagateSub");
5104  sub_->WhenRange(sub_demon);
5105  Demon* const target_demon = MakeConstraintDemon0(
5106  solver(), this, &IntAbsConstraint::PropagateTarget, "PropagateTarget");
5107  target_var_->WhenRange(target_demon);
5108  }
5109 
5110  void InitialPropagate() override {
5111  PropagateSub();
5112  PropagateTarget();
5113  }
5114 
5115  void PropagateSub() {
5116  const int64_t smin = sub_->Min();
5117  const int64_t smax = sub_->Max();
5118  if (smax <= 0) {
5119  target_var_->SetRange(-smax, -smin);
5120  } else if (smin >= 0) {
5121  target_var_->SetRange(smin, smax);
5122  } else {
5123  target_var_->SetRange(0, std::max(-smin, smax));
5124  }
5125  }
5126 
5127  void PropagateTarget() {
5128  const int64_t target_max = target_var_->Max();
5129  sub_->SetRange(-target_max, target_max);
5130  const int64_t target_min = target_var_->Min();
5131  if (target_min > 0) {
5132  if (sub_->Min() > -target_min) {
5133  sub_->SetMin(target_min);
5134  } else if (sub_->Max() < target_min) {
5135  sub_->SetMax(-target_min);
5136  }
5137  }
5138  }
5139 
5140  std::string DebugString() const override {
5141  return absl::StrFormat("IntAbsConstraint(%s, %s)", sub_->DebugString(),
5142  target_var_->DebugString());
5143  }
5144 
5145  void Accept(ModelVisitor* const visitor) const override {
5146  visitor->BeginVisitConstraint(ModelVisitor::kAbsEqual, this);
5147  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5148  sub_);
5149  visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
5150  target_var_);
5151  visitor->EndVisitConstraint(ModelVisitor::kAbsEqual, this);
5152  }
5153 
5154  private:
5155  IntVar* const sub_;
5156 };
5157 
5158 class IntAbs : public BaseIntExpr {
5159  public:
5160  IntAbs(Solver* const s, IntExpr* const e) : BaseIntExpr(s), expr_(e) {}
5161 
5162  ~IntAbs() override {}
5163 
5164  int64_t Min() const override {
5165  int64_t emin = 0;
5166  int64_t emax = 0;
5167  expr_->Range(&emin, &emax);
5168  if (emin >= 0) {
5169  return emin;
5170  }
5171  if (emax <= 0) {
5172  return -emax;
5173  }
5174  return 0;
5175  }
5176 
5177  void SetMin(int64_t m) override {
5178  if (m > 0) {
5179  int64_t emin = 0;
5180  int64_t emax = 0;
5181  expr_->Range(&emin, &emax);
5182  if (emin > -m) {
5183  expr_->SetMin(m);
5184  } else if (emax < m) {
5185  expr_->SetMax(-m);
5186  }
5187  }
5188  }
5189 
5190  int64_t Max() const override {
5191  int64_t emin = 0;
5192  int64_t emax = 0;
5193  expr_->Range(&emin, &emax);
5194  return std::max(-emin, emax);
5195  }
5196 
5197  void SetMax(int64_t m) override { expr_->SetRange(-m, m); }
5198 
5199  void SetRange(int64_t mi, int64_t ma) override {
5200  expr_->SetRange(-ma, ma);
5201  if (mi > 0) {
5202  int64_t emin = 0;
5203  int64_t emax = 0;
5204  expr_->Range(&emin, &emax);
5205  if (emin > -mi) {
5206  expr_->SetMin(mi);
5207  } else if (emax < mi) {
5208  expr_->SetMax(-mi);
5209  }
5210  }
5211  }
5212 
5213  void Range(int64_t* mi, int64_t* ma) override {
5214  int64_t emin = 0;
5215  int64_t emax = 0;
5216  expr_->Range(&emin, &emax);
5217  if (emin >= 0) {
5218  *mi = emin;
5219  *ma = emax;
5220  } else if (emax <= 0) {
5221  *mi = -emax;
5222  *ma = -emin;
5223  } else {
5224  *mi = 0;
5225  *ma = std::max(-emin, emax);
5226  }
5227  }
5228 
5229  bool Bound() const override { return expr_->Bound(); }
5230 
5231  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5232 
5233  std::string name() const override {
5234  return absl::StrFormat("IntAbs(%s)", expr_->name());
5235  }
5236 
5237  std::string DebugString() const override {
5238  return absl::StrFormat("IntAbs(%s)", expr_->DebugString());
5239  }
5240 
5241  void Accept(ModelVisitor* const visitor) const override {
5242  visitor->BeginVisitIntegerExpression(ModelVisitor::kAbs, this);
5243  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5244  expr_);
5245  visitor->EndVisitIntegerExpression(ModelVisitor::kAbs, this);
5246  }
5247 
5248  IntVar* CastToVar() override {
5249  int64_t min_value = 0;
5250  int64_t max_value = 0;
5251  Range(&min_value, &max_value);
5252  Solver* const s = solver();
5253  const std::string name = absl::StrFormat("AbsVar(%s)", expr_->name());
5254  IntVar* const target = s->MakeIntVar(min_value, max_value, name);
5255  CastConstraint* const ct =
5256  s->RevAlloc(new IntAbsConstraint(s, expr_->Var(), target));
5257  s->AddCastConstraint(ct, target, this);
5258  return target;
5259  }
5260 
5261  private:
5262  IntExpr* const expr_;
5263 };
5264 
5265 // ----- Square -----
5266 
5267 // TODO(user): shouldn't we compare to kint32max^2 instead of kint64max?
5268 class IntSquare : public BaseIntExpr {
5269  public:
5270  IntSquare(Solver* const s, IntExpr* const e) : BaseIntExpr(s), expr_(e) {}
5271  ~IntSquare() override {}
5272 
5273  int64_t Min() const override {
5274  const int64_t emin = expr_->Min();
5275  if (emin >= 0) {
5276  return emin >= std::numeric_limits<int32_t>::max()
5278  : emin * emin;
5279  }
5280  const int64_t emax = expr_->Max();
5281  if (emax < 0) {
5282  return emax <= -std::numeric_limits<int32_t>::max()
5284  : emax * emax;
5285  }
5286  return 0LL;
5287  }
5288  void SetMin(int64_t m) override {
5289  if (m <= 0) {
5290  return;
5291  }
5292  // TODO(user): What happens if m is kint64max?
5293  const int64_t emin = expr_->Min();
5294  const int64_t emax = expr_->Max();
5295  const int64_t root =
5296  static_cast<int64_t>(ceil(sqrt(static_cast<double>(m))));
5297  if (emin >= 0) {
5298  expr_->SetMin(root);
5299  } else if (emax <= 0) {
5300  expr_->SetMax(-root);
5301  } else if (expr_->IsVar()) {
5302  reinterpret_cast<IntVar*>(expr_)->RemoveInterval(-root + 1, root - 1);
5303  }
5304  }
5305  int64_t Max() const override {
5306  const int64_t emax = expr_->Max();
5307  const int64_t emin = expr_->Min();
5308  if (emax >= std::numeric_limits<int32_t>::max() ||
5309  emin <= -std::numeric_limits<int32_t>::max()) {
5311  }
5312  return std::max(emin * emin, emax * emax);
5313  }
5314  void SetMax(int64_t m) override {
5315  if (m < 0) {
5316  solver()->Fail();
5317  }
5318  if (m == std::numeric_limits<int64_t>::max()) {
5319  return;
5320  }
5321  const int64_t root =
5322  static_cast<int64_t>(floor(sqrt(static_cast<double>(m))));
5323  expr_->SetRange(-root, root);
5324  }
5325  bool Bound() const override { return expr_->Bound(); }
5326  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5327  std::string name() const override {
5328  return absl::StrFormat("IntSquare(%s)", expr_->name());
5329  }
5330  std::string DebugString() const override {
5331  return absl::StrFormat("IntSquare(%s)", expr_->DebugString());
5332  }
5333 
5334  void Accept(ModelVisitor* const visitor) const override {
5335  visitor->BeginVisitIntegerExpression(ModelVisitor::kSquare, this);
5336  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5337  expr_);
5338  visitor->EndVisitIntegerExpression(ModelVisitor::kSquare, this);
5339  }
5340 
5341  IntExpr* expr() const { return expr_; }
5342 
5343  protected:
5344  IntExpr* const expr_;
5345 };
5346 
5347 class PosIntSquare : public IntSquare {
5348  public:
5349  PosIntSquare(Solver* const s, IntExpr* const e) : IntSquare(s, e) {}
5350  ~PosIntSquare() override {}
5351 
5352  int64_t Min() const override {
5353  const int64_t emin = expr_->Min();
5354  return emin >= std::numeric_limits<int32_t>::max()
5356  : emin * emin;
5357  }
5358  void SetMin(int64_t m) override {
5359  if (m <= 0) {
5360  return;
5361  }
5362  const int64_t root =
5363  static_cast<int64_t>(ceil(sqrt(static_cast<double>(m))));
5364  expr_->SetMin(root);
5365  }
5366  int64_t Max() const override {
5367  const int64_t emax = expr_->Max();
5368  return emax >= std::numeric_limits<int32_t>::max()
5370  : emax * emax;
5371  }
5372  void SetMax(int64_t m) override {
5373  if (m < 0) {
5374  solver()->Fail();
5375  }
5376  if (m == std::numeric_limits<int64_t>::max()) {
5377  return;
5378  }
5379  const int64_t root =
5380  static_cast<int64_t>(floor(sqrt(static_cast<double>(m))));
5381  expr_->SetMax(root);
5382  }
5383 };
5384 
5385 // ----- EvenPower -----
5386 
5387 int64_t IntPower(int64_t value, int64_t power) {
5388  int64_t result = value;
5389  // TODO(user): Speed that up.
5390  for (int i = 1; i < power; ++i) {
5391  result *= value;
5392  }
5393  return result;
5394 }
5395 
5396 int64_t OverflowLimit(int64_t power) {
5397  return static_cast<int64_t>(floor(exp(
5398  log(static_cast<double>(std::numeric_limits<int64_t>::max())) / power)));
5399 }
5400 
5401 class BasePower : public BaseIntExpr {
5402  public:
5403  BasePower(Solver* const s, IntExpr* const e, int64_t n)
5404  : BaseIntExpr(s), expr_(e), pow_(n), limit_(OverflowLimit(n)) {
5405  CHECK_GT(n, 0);
5406  }
5407 
5408  ~BasePower() override {}
5409 
5410  bool Bound() const override { return expr_->Bound(); }
5411 
5412  IntExpr* expr() const { return expr_; }
5413 
5414  int64_t exponant() const { return pow_; }
5415 
5416  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5417 
5418  std::string name() const override {
5419  return absl::StrFormat("IntPower(%s, %d)", expr_->name(), pow_);
5420  }
5421 
5422  std::string DebugString() const override {
5423  return absl::StrFormat("IntPower(%s, %d)", expr_->DebugString(), pow_);
5424  }
5425 
5426  void Accept(ModelVisitor* const visitor) const override {
5427  visitor->BeginVisitIntegerExpression(ModelVisitor::kPower, this);
5428  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5429  expr_);
5430  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, pow_);
5431  visitor->EndVisitIntegerExpression(ModelVisitor::kPower, this);
5432  }
5433 
5434  protected:
5435  int64_t Pown(int64_t value) const {
5436  if (value >= limit_) {
5438  }
5439  if (value <= -limit_) {
5440  if (pow_ % 2 == 0) {
5442  } else {
5444  }
5445  }
5446  return IntPower(value, pow_);
5447  }
5448 
5449  int64_t SqrnDown(int64_t value) const {
5452  }
5455  }
5456  int64_t res = 0;
5457  const double d_value = static_cast<double>(value);
5458  if (value >= 0) {
5459  const double sq = exp(log(d_value) / pow_);
5460  res = static_cast<int64_t>(floor(sq));
5461  } else {
5462  CHECK_EQ(1, pow_ % 2);
5463  const double sq = exp(log(-d_value) / pow_);
5464  res = -static_cast<int64_t>(ceil(sq));
5465  }
5466  const int64_t pow_res = Pown(res + 1);
5467  if (pow_res <= value) {
5468  return res + 1;
5469  } else {
5470  return res;
5471  }
5472  }
5473 
5474  int64_t SqrnUp(int64_t value) const {
5477  }
5480  }
5481  int64_t res = 0;
5482  const double d_value = static_cast<double>(value);
5483  if (value >= 0) {
5484  const double sq = exp(log(d_value) / pow_);
5485  res = static_cast<int64_t>(ceil(sq));
5486  } else {
5487  CHECK_EQ(1, pow_ % 2);
5488  const double sq = exp(log(-d_value) / pow_);
5489  res = -static_cast<int64_t>(floor(sq));
5490  }
5491  const int64_t pow_res = Pown(res - 1);
5492  if (pow_res >= value) {
5493  return res - 1;
5494  } else {
5495  return res;
5496  }
5497  }
5498 
5499  IntExpr* const expr_;
5500  const int64_t pow_;
5501  const int64_t limit_;
5502 };
5503 
5504 class IntEvenPower : public BasePower {
5505  public:
5506  IntEvenPower(Solver* const s, IntExpr* const e, int64_t n)
5507  : BasePower(s, e, n) {
5508  CHECK_EQ(0, n % 2);
5509  }
5510 
5511  ~IntEvenPower() override {}
5512 
5513  int64_t Min() const override {
5514  int64_t emin = 0;
5515  int64_t emax = 0;
5516  expr_->Range(&emin, &emax);
5517  if (emin >= 0) {
5518  return Pown(emin);
5519  }
5520  if (emax < 0) {
5521  return Pown(emax);
5522  }
5523  return 0LL;
5524  }
5525  void SetMin(int64_t m) override {
5526  if (m <= 0) {
5527  return;
5528  }
5529  int64_t emin = 0;
5530  int64_t emax = 0;
5531  expr_->Range(&emin, &emax);
5532  const int64_t root = SqrnUp(m);
5533  if (emin > -root) {
5534  expr_->SetMin(root);
5535  } else if (emax < root) {
5536  expr_->SetMax(-root);
5537  } else if (expr_->IsVar()) {
5538  reinterpret_cast<IntVar*>(expr_)->RemoveInterval(-root + 1, root - 1);
5539  }
5540  }
5541 
5542  int64_t Max() const override {
5543  return std::max(Pown(expr_->Min()), Pown(expr_->Max()));
5544  }
5545 
5546  void SetMax(int64_t m) override {
5547  if (m < 0) {
5548  solver()->Fail();
5549  }
5550  if (m == std::numeric_limits<int64_t>::max()) {
5551  return;
5552  }
5553  const int64_t root = SqrnDown(m);
5554  expr_->SetRange(-root, root);
5555  }
5556 };
5557 
5558 class PosIntEvenPower : public BasePower {
5559  public:
5560  PosIntEvenPower(Solver* const s, IntExpr* const e, int64_t pow)
5561  : BasePower(s, e, pow) {
5562  CHECK_EQ(0, pow % 2);
5563  }
5564 
5565  ~PosIntEvenPower() override {}
5566 
5567  int64_t Min() const override { return Pown(expr_->Min()); }
5568 
5569  void SetMin(int64_t m) override {
5570  if (m <= 0) {
5571  return;
5572  }
5573  expr_->SetMin(SqrnUp(m));
5574  }
5575  int64_t Max() const override { return Pown(expr_->Max()); }
5576 
5577  void SetMax(int64_t m) override {
5578  if (m < 0) {
5579  solver()->Fail();
5580  }
5581  if (m == std::numeric_limits<int64_t>::max()) {
5582  return;
5583  }
5584  expr_->SetMax(SqrnDown(m));
5585  }
5586 };
5587 
5588 class IntOddPower : public BasePower {
5589  public:
5590  IntOddPower(Solver* const s, IntExpr* const e, int64_t n)
5591  : BasePower(s, e, n) {
5592  CHECK_EQ(1, n % 2);
5593  }
5594 
5595  ~IntOddPower() override {}
5596 
5597  int64_t Min() const override { return Pown(expr_->Min()); }
5598 
5599  void SetMin(int64_t m) override { expr_->SetMin(SqrnUp(m)); }
5600 
5601  int64_t Max() const override { return Pown(expr_->Max()); }
5602 
5603  void SetMax(int64_t m) override { expr_->SetMax(SqrnDown(m)); }
5604 };
5605 
5606 // ----- Min(expr, expr) -----
5607 
5608 class MinIntExpr : public BaseIntExpr {
5609  public:
5610  MinIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
5611  : BaseIntExpr(s), left_(l), right_(r) {}
5612  ~MinIntExpr() override {}
5613  int64_t Min() const override {
5614  const int64_t lmin = left_->Min();
5615  const int64_t rmin = right_->Min();
5616  return std::min(lmin, rmin);
5617  }
5618  void SetMin(int64_t m) override {
5619  left_->SetMin(m);
5620  right_->SetMin(m);
5621  }
5622  int64_t Max() const override {
5623  const int64_t lmax = left_->Max();
5624  const int64_t rmax = right_->Max();
5625  return std::min(lmax, rmax);
5626  }
5627  void SetMax(int64_t m) override {
5628  if (left_->Min() > m) {
5629  right_->SetMax(m);
5630  }
5631  if (right_->Min() > m) {
5632  left_->SetMax(m);
5633  }
5634  }
5635  std::string name() const override {
5636  return absl::StrFormat("MinIntExpr(%s, %s)", left_->name(), right_->name());
5637  }
5638  std::string DebugString() const override {
5639  return absl::StrFormat("MinIntExpr(%s, %s)", left_->DebugString(),
5640  right_->DebugString());
5641  }
5642  void WhenRange(Demon* d) override {
5643  left_->WhenRange(d);
5644  right_->WhenRange(d);
5645  }
5646 
5647  void Accept(ModelVisitor* const visitor) const override {
5648  visitor->BeginVisitIntegerExpression(ModelVisitor::kMin, this);
5649  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
5650  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
5651  right_);
5652  visitor->EndVisitIntegerExpression(ModelVisitor::kMin, this);
5653  }
5654 
5655  private:
5656  IntExpr* const left_;
5657  IntExpr* const right_;
5658 };
5659 
5660 // ----- Min(expr, constant) -----
5661 
5662 class MinCstIntExpr : public BaseIntExpr {
5663  public:
5664  MinCstIntExpr(Solver* const s, IntExpr* const e, int64_t v)
5665  : BaseIntExpr(s), expr_(e), value_(v) {}
5666 
5667  ~MinCstIntExpr() override {}
5668 
5669  int64_t Min() const override { return std::min(expr_->Min(), value_); }
5670 
5671  void SetMin(int64_t m) override {
5672  if (m > value_) {
5673  solver()->Fail();
5674  }
5675  expr_->SetMin(m);
5676  }
5677 
5678  int64_t Max() const override { return std::min(expr_->Max(), value_); }
5679 
5680  void SetMax(int64_t m) override {
5681  if (value_ > m) {
5682  expr_->SetMax(m);
5683  }
5684  }
5685 
5686  bool Bound() const override {
5687  return (expr_->Bound() || expr_->Min() >= value_);
5688  }
5689 
5690  std::string name() const override {
5691  return absl::StrFormat("MinCstIntExpr(%s, %d)", expr_->name(), value_);
5692  }
5693 
5694  std::string DebugString() const override {
5695  return absl::StrFormat("MinCstIntExpr(%s, %d)", expr_->DebugString(),
5696  value_);
5697  }
5698 
5699  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5700 
5701  void Accept(ModelVisitor* const visitor) const override {
5702  visitor->BeginVisitIntegerExpression(ModelVisitor::kMin, this);
5703  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5704  expr_);
5705  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
5706  visitor->EndVisitIntegerExpression(ModelVisitor::kMin, this);
5707  }
5708 
5709  private:
5710  IntExpr* const expr_;
5711  const int64_t value_;
5712 };
5713 
5714 // ----- Max(expr, expr) -----
5715 
5716 class MaxIntExpr : public BaseIntExpr {
5717  public:
5718  MaxIntExpr(Solver* const s, IntExpr* const l, IntExpr* const r)
5719  : BaseIntExpr(s), left_(l), right_(r) {}
5720 
5721  ~MaxIntExpr() override {}
5722 
5723  int64_t Min() const override { return std::max(left_->Min(), right_->Min()); }
5724 
5725  void SetMin(int64_t m) override {
5726  if (left_->Max() < m) {
5727  right_->SetMin(m);
5728  } else {
5729  if (right_->Max() < m) {
5730  left_->SetMin(m);
5731  }
5732  }
5733  }
5734 
5735  int64_t Max() const override { return std::max(left_->Max(), right_->Max()); }
5736 
5737  void SetMax(int64_t m) override {
5738  left_->SetMax(m);
5739  right_->SetMax(m);
5740  }
5741 
5742  std::string name() const override {
5743  return absl::StrFormat("MaxIntExpr(%s, %s)", left_->name(), right_->name());
5744  }
5745 
5746  std::string DebugString() const override {
5747  return absl::StrFormat("MaxIntExpr(%s, %s)", left_->DebugString(),
5748  right_->DebugString());
5749  }
5750 
5751  void WhenRange(Demon* d) override {
5752  left_->WhenRange(d);
5753  right_->WhenRange(d);
5754  }
5755 
5756  void Accept(ModelVisitor* const visitor) const override {
5757  visitor->BeginVisitIntegerExpression(ModelVisitor::kMax, this);
5758  visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
5759  visitor->VisitIntegerExpressionArgument(ModelVisitor::kRightArgument,
5760  right_);
5761  visitor->EndVisitIntegerExpression(ModelVisitor::kMax, this);
5762  }
5763 
5764  private:
5765  IntExpr* const left_;
5766  IntExpr* const right_;
5767 };
5768 
5769 // ----- Max(expr, constant) -----
5770 
5771 class MaxCstIntExpr : public BaseIntExpr {
5772  public:
5773  MaxCstIntExpr(Solver* const s, IntExpr* const e, int64_t v)
5774  : BaseIntExpr(s), expr_(e), value_(v) {}
5775 
5776  ~MaxCstIntExpr() override {}
5777 
5778  int64_t Min() const override { return std::max(expr_->Min(), value_); }
5779 
5780  void SetMin(int64_t m) override {
5781  if (value_ < m) {
5782  expr_->SetMin(m);
5783  }
5784  }
5785 
5786  int64_t Max() const override { return std::max(expr_->Max(), value_); }
5787 
5788  void SetMax(int64_t m) override {
5789  if (m < value_) {
5790  solver()->Fail();
5791  }
5792  expr_->SetMax(m);
5793  }
5794 
5795  bool Bound() const override {
5796  return (expr_->Bound() || expr_->Max() <= value_);
5797  }
5798 
5799  std::string name() const override {
5800  return absl::StrFormat("MaxCstIntExpr(%s, %d)", expr_->name(), value_);
5801  }
5802 
5803  std::string DebugString() const override {
5804  return absl::StrFormat("MaxCstIntExpr(%s, %d)", expr_->DebugString(),
5805  value_);
5806  }
5807 
5808  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5809 
5810  void Accept(ModelVisitor* const visitor) const override {
5811  visitor->BeginVisitIntegerExpression(ModelVisitor::kMax, this);
5812  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5813  expr_);
5814  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
5815  visitor->EndVisitIntegerExpression(ModelVisitor::kMax, this);
5816  }
5817 
5818  private:
5819  IntExpr* const expr_;
5820  const int64_t value_;
5821 };
5822 
5823 // ----- Convex Piecewise -----
5824 
5825 // This class is a very simple convex piecewise linear function. The
5826 // argument of the function is the expression. Between early_date and
5827 // late_date, the value of the function is 0. Before early date, it
5828 // is affine and the cost is early_cost * (early_date - x). After
5829 // late_date, the cost is late_cost * (x - late_date).
5830 
5831 class SimpleConvexPiecewiseExpr : public BaseIntExpr {
5832  public:
5833  SimpleConvexPiecewiseExpr(Solver* const s, IntExpr* const e, int64_t ec,
5834  int64_t ed, int64_t ld, int64_t lc)
5835  : BaseIntExpr(s),
5836  expr_(e),
5837  early_cost_(ec),
5838  early_date_(ec == 0 ? std::numeric_limits<int64_t>::min() : ed),
5839  late_date_(lc == 0 ? std::numeric_limits<int64_t>::max() : ld),
5840  late_cost_(lc) {
5841  DCHECK_GE(ec, int64_t{0});
5842  DCHECK_GE(lc, int64_t{0});
5843  DCHECK_GE(ld, ed);
5844 
5845  // If the penalty is 0, we can push the "confort zone or zone
5846  // of no cost towards infinity.
5847  }
5848 
5849  ~SimpleConvexPiecewiseExpr() override {}
5850 
5851  int64_t Min() const override {
5852  const int64_t vmin = expr_->Min();
5853  const int64_t vmax = expr_->Max();
5854  if (vmin >= late_date_) {
5855  return (vmin - late_date_) * late_cost_;
5856  } else if (vmax <= early_date_) {
5857  return (early_date_ - vmax) * early_cost_;
5858  } else {
5859  return 0LL;
5860  }
5861  }
5862 
5863  void SetMin(int64_t m) override {
5864  if (m <= 0) {
5865  return;
5866  }
5867  int64_t vmin = 0;
5868  int64_t vmax = 0;
5869  expr_->Range(&vmin, &vmax);
5870 
5871  const int64_t rb =
5872  (late_cost_ == 0 ? vmax : late_date_ + PosIntDivUp(m, late_cost_) - 1);
5873  const int64_t lb =
5874  (early_cost_ == 0 ? vmin
5875  : early_date_ - PosIntDivUp(m, early_cost_) + 1);
5876 
5877  if (expr_->IsVar()) {
5878  expr_->Var()->RemoveInterval(lb, rb);
5879  }
5880  }
5881 
5882  int64_t Max() const override {
5883  const int64_t vmin = expr_->Min();
5884  const int64_t vmax = expr_->Max();
5885  const int64_t mr = vmax > late_date_ ? (vmax - late_date_) * late_cost_ : 0;
5886  const int64_t ml =
5887  vmin < early_date_ ? (early_date_ - vmin) * early_cost_ : 0;
5888  return std::max(mr, ml);
5889  }
5890 
5891  void SetMax(int64_t m) override {
5892  if (m < 0) {
5893  solver()->Fail();
5894  }
5895  if (late_cost_ != 0LL) {
5896  const int64_t rb = late_date_ + PosIntDivDown(m, late_cost_);
5897  if (early_cost_ != 0LL) {
5898  const int64_t lb = early_date_ - PosIntDivDown(m, early_cost_);
5899  expr_->SetRange(lb, rb);
5900  } else {
5901  expr_->SetMax(rb);
5902  }
5903  } else {
5904  if (early_cost_ != 0LL) {
5905  const int64_t lb = early_date_ - PosIntDivDown(m, early_cost_);
5906  expr_->SetMin(lb);
5907  }
5908  }
5909  }
5910 
5911  std::string name() const override {
5912  return absl::StrFormat(
5913  "ConvexPiecewiseExpr(%s, ec = %d, ed = %d, ld = %d, lc = %d)",
5914  expr_->name(), early_cost_, early_date_, late_date_, late_cost_);
5915  }
5916 
5917  std::string DebugString() const override {
5918  return absl::StrFormat(
5919  "ConvexPiecewiseExpr(%s, ec = %d, ed = %d, ld = %d, lc = %d)",
5920  expr_->DebugString(), early_cost_, early_date_, late_date_, late_cost_);
5921  }
5922 
5923  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
5924 
5925  void Accept(ModelVisitor* const visitor) const override {
5926  visitor->BeginVisitIntegerExpression(ModelVisitor::kConvexPiecewise, this);
5927  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
5928  expr_);
5929  visitor->VisitIntegerArgument(ModelVisitor::kEarlyCostArgument,
5930  early_cost_);
5931  visitor->VisitIntegerArgument(ModelVisitor::kEarlyDateArgument,
5932  early_date_);
5933  visitor->VisitIntegerArgument(ModelVisitor::kLateCostArgument, late_cost_);
5934  visitor->VisitIntegerArgument(ModelVisitor::kLateDateArgument, late_date_);
5935  visitor->EndVisitIntegerExpression(ModelVisitor::kConvexPiecewise, this);
5936  }
5937 
5938  private:
5939  IntExpr* const expr_;
5940  const int64_t early_cost_;
5941  const int64_t early_date_;
5942  const int64_t late_date_;
5943  const int64_t late_cost_;
5944 };
5945 
5946 // ----- Semi Continuous -----
5947 
5948 class SemiContinuousExpr : public BaseIntExpr {
5949  public:
5950  SemiContinuousExpr(Solver* const s, IntExpr* const e, int64_t fixed_charge,
5951  int64_t step)
5952  : BaseIntExpr(s), expr_(e), fixed_charge_(fixed_charge), step_(step) {
5953  DCHECK_GE(fixed_charge, int64_t{0});
5954  DCHECK_GT(step, int64_t{0});
5955  }
5956 
5957  ~SemiContinuousExpr() override {}
5958 
5959  int64_t Value(int64_t x) const {
5960  if (x <= 0) {
5961  return 0;
5962  } else {
5963  return CapAdd(fixed_charge_, CapProd(x, step_));
5964  }
5965  }
5966 
5967  int64_t Min() const override { return Value(expr_->Min()); }
5968 
5969  void SetMin(int64_t m) override {
5970  if (m >= CapAdd(fixed_charge_, step_)) {
5971  const int64_t y = PosIntDivUp(CapSub(m, fixed_charge_), step_);
5972  expr_->SetMin(y);
5973  } else if (m > 0) {
5974  expr_->SetMin(1);
5975  }
5976  }
5977 
5978  int64_t Max() const override { return Value(expr_->Max()); }
5979 
5980  void SetMax(int64_t m) override {
5981  if (m < 0) {
5982  solver()->Fail();
5983  }
5984  if (m == std::numeric_limits<int64_t>::max()) {
5985  return;
5986  }
5987  if (m < CapAdd(fixed_charge_, step_)) {
5988  expr_->SetMax(0);
5989  } else {
5990  const int64_t y = PosIntDivDown(CapSub(m, fixed_charge_), step_);
5991  expr_->SetMax(y);
5992  }
5993  }
5994 
5995  std::string name() const override {
5996  return absl::StrFormat("SemiContinuous(%s, fixed_charge = %d, step = %d)",
5997  expr_->name(), fixed_charge_, step_);
5998  }
5999 
6000  std::string DebugString() const override {
6001  return absl::StrFormat("SemiContinuous(%s, fixed_charge = %d, step = %d)",
6002  expr_->DebugString(), fixed_charge_, step_);
6003  }
6004 
6005  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
6006 
6007  void Accept(ModelVisitor* const visitor) const override {
6008  visitor->BeginVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6009  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6010  expr_);
6011  visitor->VisitIntegerArgument(ModelVisitor::kFixedChargeArgument,
6012  fixed_charge_);
6013  visitor->VisitIntegerArgument(ModelVisitor::kStepArgument, step_);
6014  visitor->EndVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6015  }
6016 
6017  private:
6018  IntExpr* const expr_;
6019  const int64_t fixed_charge_;
6020  const int64_t step_;
6021 };
6022 
6023 class SemiContinuousStepOneExpr : public BaseIntExpr {
6024  public:
6025  SemiContinuousStepOneExpr(Solver* const s, IntExpr* const e,
6026  int64_t fixed_charge)
6027  : BaseIntExpr(s), expr_(e), fixed_charge_(fixed_charge) {
6028  DCHECK_GE(fixed_charge, int64_t{0});
6029  }
6030 
6031  ~SemiContinuousStepOneExpr() override {}
6032 
6033  int64_t Value(int64_t x) const {
6034  if (x <= 0) {
6035  return 0;
6036  } else {
6037  return fixed_charge_ + x;
6038  }
6039  }
6040 
6041  int64_t Min() const override { return Value(expr_->Min()); }
6042 
6043  void SetMin(int64_t m) override {
6044  if (m >= fixed_charge_ + 1) {
6045  expr_->SetMin(m - fixed_charge_);
6046  } else if (m > 0) {
6047  expr_->SetMin(1);
6048  }
6049  }
6050 
6051  int64_t Max() const override { return Value(expr_->Max()); }
6052 
6053  void SetMax(int64_t m) override {
6054  if (m < 0) {
6055  solver()->Fail();
6056  }
6057  if (m < fixed_charge_ + 1) {
6058  expr_->SetMax(0);
6059  } else {
6060  expr_->SetMax(m - fixed_charge_);
6061  }
6062  }
6063 
6064  std::string name() const override {
6065  return absl::StrFormat("SemiContinuousStepOne(%s, fixed_charge = %d)",
6066  expr_->name(), fixed_charge_);
6067  }
6068 
6069  std::string DebugString() const override {
6070  return absl::StrFormat("SemiContinuousStepOne(%s, fixed_charge = %d)",
6071  expr_->DebugString(), fixed_charge_);
6072  }
6073 
6074  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
6075 
6076  void Accept(ModelVisitor* const visitor) const override {
6077  visitor->BeginVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6078  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6079  expr_);
6080  visitor->VisitIntegerArgument(ModelVisitor::kFixedChargeArgument,
6081  fixed_charge_);
6082  visitor->VisitIntegerArgument(ModelVisitor::kStepArgument, 1);
6083  visitor->EndVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6084  }
6085 
6086  private:
6087  IntExpr* const expr_;
6088  const int64_t fixed_charge_;
6089 };
6090 
6091 class SemiContinuousStepZeroExpr : public BaseIntExpr {
6092  public:
6093  SemiContinuousStepZeroExpr(Solver* const s, IntExpr* const e,
6094  int64_t fixed_charge)
6095  : BaseIntExpr(s), expr_(e), fixed_charge_(fixed_charge) {
6096  DCHECK_GT(fixed_charge, int64_t{0});
6097  }
6098 
6099  ~SemiContinuousStepZeroExpr() override {}
6100 
6101  int64_t Value(int64_t x) const {
6102  if (x <= 0) {
6103  return 0;
6104  } else {
6105  return fixed_charge_;
6106  }
6107  }
6108 
6109  int64_t Min() const override { return Value(expr_->Min()); }
6110 
6111  void SetMin(int64_t m) override {
6112  if (m >= fixed_charge_) {
6113  solver()->Fail();
6114  } else if (m > 0) {
6115  expr_->SetMin(1);
6116  }
6117  }
6118 
6119  int64_t Max() const override { return Value(expr_->Max()); }
6120 
6121  void SetMax(int64_t m) override {
6122  if (m < 0) {
6123  solver()->Fail();
6124  }
6125  if (m < fixed_charge_) {
6126  expr_->SetMax(0);
6127  }
6128  }
6129 
6130  std::string name() const override {
6131  return absl::StrFormat("SemiContinuousStepZero(%s, fixed_charge = %d)",
6132  expr_->name(), fixed_charge_);
6133  }
6134 
6135  std::string DebugString() const override {
6136  return absl::StrFormat("SemiContinuousStepZero(%s, fixed_charge = %d)",
6137  expr_->DebugString(), fixed_charge_);
6138  }
6139 
6140  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
6141 
6142  void Accept(ModelVisitor* const visitor) const override {
6143  visitor->BeginVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6144  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6145  expr_);
6146  visitor->VisitIntegerArgument(ModelVisitor::kFixedChargeArgument,
6147  fixed_charge_);
6148  visitor->VisitIntegerArgument(ModelVisitor::kStepArgument, 0);
6149  visitor->EndVisitIntegerExpression(ModelVisitor::kSemiContinuous, this);
6150  }
6151 
6152  private:
6153  IntExpr* const expr_;
6154  const int64_t fixed_charge_;
6155 };
6156 
6157 // This constraints links an expression and the variable it is casted into
6158 class LinkExprAndVar : public CastConstraint {
6159  public:
6160  LinkExprAndVar(Solver* const s, IntExpr* const expr, IntVar* const var)
6161  : CastConstraint(s, var), expr_(expr) {}
6162 
6163  ~LinkExprAndVar() override {}
6164 
6165  void Post() override {
6166  Solver* const s = solver();
6167  Demon* d = s->MakeConstraintInitialPropagateCallback(this);
6168  expr_->WhenRange(d);
6169  target_var_->WhenRange(d);
6170  }
6171 
6172  void InitialPropagate() override {
6173  expr_->SetRange(target_var_->Min(), target_var_->Max());
6174  int64_t l, u;
6175  expr_->Range(&l, &u);
6176  target_var_->SetRange(l, u);
6177  }
6178 
6179  std::string DebugString() const override {
6180  return absl::StrFormat("cast(%s, %s)", expr_->DebugString(),
6181  target_var_->DebugString());
6182  }
6183 
6184  void Accept(ModelVisitor* const visitor) const override {
6185  visitor->BeginVisitConstraint(ModelVisitor::kLinkExprVar, this);
6186  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6187  expr_);
6188  visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
6189  target_var_);
6190  visitor->EndVisitConstraint(ModelVisitor::kLinkExprVar, this);
6191  }
6192 
6193  private:
6194  IntExpr* const expr_;
6195 };
6196 
6197 // ----- Conditional Expression -----
6198 
6199 class ExprWithEscapeValue : public BaseIntExpr {
6200  public:
6201  ExprWithEscapeValue(Solver* const s, IntVar* const c, IntExpr* const e,
6202  int64_t unperformed_value)
6203  : BaseIntExpr(s),
6204  condition_(c),
6205  expression_(e),
6206  unperformed_value_(unperformed_value) {}
6207 
6208  ~ExprWithEscapeValue() override {}
6209 
6210  int64_t Min() const override {
6211  if (condition_->Min() == 1) {
6212  return expression_->Min();
6213  } else if (condition_->Max() == 1) {
6214  return std::min(unperformed_value_, expression_->Min());
6215  } else {
6216  return unperformed_value_;
6217  }
6218  }
6219 
6220  void SetMin(int64_t m) override {
6221  if (m > unperformed_value_) {
6222  condition_->SetValue(1);
6223  expression_->SetMin(m);
6224  } else if (condition_->Min() == 1) {
6225  expression_->SetMin(m);
6226  } else if (m > expression_->Max()) {
6227  condition_->SetValue(0);
6228  }
6229  }
6230 
6231  int64_t Max() const override {
6232  if (condition_->Min() == 1) {
6233  return expression_->Max();
6234  } else if (condition_->Max() == 1) {
6235  return std::max(unperformed_value_, expression_->Max());
6236  } else {
6237  return unperformed_value_;
6238  }
6239  }
6240 
6241  void SetMax(int64_t m) override {
6242  if (m < unperformed_value_) {
6243  condition_->SetValue(1);
6244  expression_->SetMax(m);
6245  } else if (condition_->Min() == 1) {
6246  expression_->SetMax(m);
6247  } else if (m < expression_->Min()) {
6248  condition_->SetValue(0);
6249  }
6250  }
6251 
6252  void SetRange(int64_t mi, int64_t ma) override {
6253  if (ma < unperformed_value_ || mi > unperformed_value_) {
6254  condition_->SetValue(1);
6255  expression_->SetRange(mi, ma);
6256  } else if (condition_->Min() == 1) {
6257  expression_->SetRange(mi, ma);
6258  } else if (ma < expression_->Min() || mi > expression_->Max()) {
6259  condition_->SetValue(0);
6260  }
6261  }
6262 
6263  void SetValue(int64_t v) override {
6264  if (v != unperformed_value_) {
6265  condition_->SetValue(1);
6266  expression_->SetValue(v);
6267  } else if (condition_->Min() == 1) {
6268  expression_->SetValue(v);
6269  } else if (v < expression_->Min() || v > expression_->Max()) {
6270  condition_->SetValue(0);
6271  }
6272  }
6273 
6274  bool Bound() const override {
6275  return condition_->Max() == 0 || expression_->Bound();
6276  }
6277 
6278  void WhenRange(Demon* d) override {
6279  expression_->WhenRange(d);
6280  condition_->WhenBound(d);
6281  }
6282 
6283  std::string DebugString() const override {
6284  return absl::StrFormat("ConditionExpr(%s, %s, %d)",
6285  condition_->DebugString(),
6286  expression_->DebugString(), unperformed_value_);
6287  }
6288 
6289  void Accept(ModelVisitor* const visitor) const override {
6290  visitor->BeginVisitIntegerExpression(ModelVisitor::kConditionalExpr, this);
6291  visitor->VisitIntegerExpressionArgument(ModelVisitor::kVariableArgument,
6292  condition_);
6293  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6294  expression_);
6295  visitor->VisitIntegerArgument(ModelVisitor::kValueArgument,
6296  unperformed_value_);
6297  visitor->EndVisitIntegerExpression(ModelVisitor::kConditionalExpr, this);
6298  }
6299 
6300  private:
6301  IntVar* const condition_;
6302  IntExpr* const expression_;
6303  const int64_t unperformed_value_;
6304  DISALLOW_COPY_AND_ASSIGN(ExprWithEscapeValue);
6305 };
6306 
6307 // ----- This is a specialized case when the variable exact type is known -----
6308 class LinkExprAndDomainIntVar : public CastConstraint {
6309  public:
6310  LinkExprAndDomainIntVar(Solver* const s, IntExpr* const expr,
6311  DomainIntVar* const var)
6312  : CastConstraint(s, var),
6313  expr_(expr),
6314  cached_min_(std::numeric_limits<int64_t>::min()),
6315  cached_max_(std::numeric_limits<int64_t>::max()),
6316  fail_stamp_(uint64_t{0}) {}
6317 
6318  ~LinkExprAndDomainIntVar() override {}
6319 
6320  DomainIntVar* var() const {
6321  return reinterpret_cast<DomainIntVar*>(target_var_);
6322  }
6323 
6324  void Post() override {
6325  Solver* const s = solver();
6326  Demon* const d = s->MakeConstraintInitialPropagateCallback(this);
6327  expr_->WhenRange(d);
6328  Demon* const target_var_demon = MakeConstraintDemon0(
6329  solver(), this, &LinkExprAndDomainIntVar::Propagate, "Propagate");
6330  target_var_->WhenRange(target_var_demon);
6331  }
6332 
6333  void InitialPropagate() override {
6334  expr_->SetRange(var()->min_.Value(), var()->max_.Value());
6335  expr_->Range(&cached_min_, &cached_max_);
6336  var()->DomainIntVar::SetRange(cached_min_, cached_max_);
6337  }
6338 
6339  void Propagate() {
6340  if (var()->min_.Value() > cached_min_ ||
6341  var()->max_.Value() < cached_max_ ||
6342  solver()->fail_stamp() != fail_stamp_) {
6343  InitialPropagate();
6344  fail_stamp_ = solver()->fail_stamp();
6345  }
6346  }
6347 
6348  std::string DebugString() const override {
6349  return absl::StrFormat("cast(%s, %s)", expr_->DebugString(),
6350  target_var_->DebugString());
6351  }
6352 
6353  void Accept(ModelVisitor* const visitor) const override {
6354  visitor->BeginVisitConstraint(ModelVisitor::kLinkExprVar, this);
6355  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
6356  expr_);
6357  visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
6358  target_var_);
6359  visitor->EndVisitConstraint(ModelVisitor::kLinkExprVar, this);
6360  }
6361 
6362  private:
6363  IntExpr* const expr_;
6364  int64_t cached_min_;
6365  int64_t cached_max_;
6366  uint64_t fail_stamp_;
6367 };
6368 } // namespace
6369 
6370 // ----- Misc -----
6371 
6372 IntVarIterator* BooleanVar::MakeHoleIterator(bool reversible) const {
6373  return CondRevAlloc(solver(), reversible, new EmptyIterator());
6374 }
6375 IntVarIterator* BooleanVar::MakeDomainIterator(bool reversible) const {
6376  return CondRevAlloc(solver(), reversible, new RangeIterator(this));
6377 }
6378 
6379 // ----- API -----
6380 
6382  DCHECK_EQ(DOMAIN_INT_VAR, var->VarType());
6383  DomainIntVar* const dvar = reinterpret_cast<DomainIntVar*>(var);
6384  dvar->CleanInProcess();
6385 }
6386 
6387 Constraint* SetIsEqual(IntVar* const var, const std::vector<int64_t>& values,
6388  const std::vector<IntVar*>& vars) {
6389  DomainIntVar* const dvar = reinterpret_cast<DomainIntVar*>(var);
6390  CHECK(dvar != nullptr);
6391  return dvar->SetIsEqual(values, vars);
6392 }
6393 
6395  const std::vector<int64_t>& values,
6396  const std::vector<IntVar*>& vars) {
6397  DomainIntVar* const dvar = reinterpret_cast<DomainIntVar*>(var);
6398  CHECK(dvar != nullptr);
6399  return dvar->SetIsGreaterOrEqual(values, vars);
6400 }
6401 
6403  DCHECK_EQ(BOOLEAN_VAR, var->VarType());
6404  BooleanVar* const boolean_var = reinterpret_cast<BooleanVar*>(var);
6405  boolean_var->RestoreValue();
6406 }
6407 
6408 // ----- API -----
6409 
6410 IntVar* Solver::MakeIntVar(int64_t min, int64_t max, const std::string& name) {
6411  if (min == max) {
6412  return MakeIntConst(min, name);
6413  }
6414  if (min == 0 && max == 1) {
6415  return RegisterIntVar(RevAlloc(new ConcreteBooleanVar(this, name)));
6416  } else if (CapSub(max, min) == 1) {
6417  const std::string inner_name = "inner_" + name;
6418  return RegisterIntVar(
6419  MakeSum(RevAlloc(new ConcreteBooleanVar(this, inner_name)), min)
6420  ->VarWithName(name));
6421  } else {
6422  return RegisterIntVar(RevAlloc(new DomainIntVar(this, min, max, name)));
6423  }
6424 }
6425 
6426 IntVar* Solver::MakeIntVar(int64_t min, int64_t max) {
6427  return MakeIntVar(min, max, "");
6428 }
6429 
6430 IntVar* Solver::MakeBoolVar(const std::string& name) {
6431  return RegisterIntVar(RevAlloc(new ConcreteBooleanVar(this, name)));
6432 }
6433 
6434 IntVar* Solver::MakeBoolVar() {
6435  return RegisterIntVar(RevAlloc(new ConcreteBooleanVar(this, "")));
6436 }
6437 
6438 IntVar* Solver::MakeIntVar(const std::vector<int64_t>& values,
6439  const std::string& name) {
6440  DCHECK(!values.empty());
6441  // Fast-track the case where we have a single value.
6442  if (values.size() == 1) return MakeIntConst(values[0], name);
6443  // Sort and remove duplicates.
6444  std::vector<int64_t> unique_sorted_values = values;
6445  gtl::STLSortAndRemoveDuplicates(&unique_sorted_values);
6446  // Case when we have a single value, after clean-up.
6447  if (unique_sorted_values.size() == 1) return MakeIntConst(values[0], name);
6448  // Case when the values are a dense interval of integers.
6449  if (unique_sorted_values.size() ==
6450  unique_sorted_values.back() - unique_sorted_values.front() + 1) {
6451  return MakeIntVar(unique_sorted_values.front(), unique_sorted_values.back(),
6452  name);
6453  }
6454  // Compute the GCD: if it's not 1, we can express the variable's domain as
6455  // the product of the GCD and of a domain with smaller values.
6456  int64_t gcd = 0;
6457  for (const int64_t v : unique_sorted_values) {
6458  if (gcd == 0) {
6459  gcd = std::abs(v);
6460  } else {
6461  gcd = MathUtil::GCD64(gcd, std::abs(v)); // Supports v==0.
6462  }
6463  if (gcd == 1) {
6464  // If it's 1, though, we can't do anything special, so we
6465  // immediately return a new DomainIntVar.
6466  return RegisterIntVar(
6467  RevAlloc(new DomainIntVar(this, unique_sorted_values, name)));
6468  }
6469  }
6470  DCHECK_GT(gcd, 1);
6471  for (int64_t& v : unique_sorted_values) {
6472  DCHECK_EQ(0, v % gcd);
6473  v /= gcd;
6474  }
6475  const std::string new_name = name.empty() ? "" : "inner_" + name;
6476  // Catch the case where the divided values are a dense set of integers.
6477  IntVar* inner_intvar = nullptr;
6478  if (unique_sorted_values.size() ==
6479  unique_sorted_values.back() - unique_sorted_values.front() + 1) {
6480  inner_intvar = MakeIntVar(unique_sorted_values.front(),
6481  unique_sorted_values.back(), new_name);
6482  } else {
6483  inner_intvar = RegisterIntVar(
6484  RevAlloc(new DomainIntVar(this, unique_sorted_values, new_name)));
6485  }
6486  return MakeProd(inner_intvar, gcd)->Var();
6487 }
6488 
6489 IntVar* Solver::MakeIntVar(const std::vector<int64_t>& values) {
6490  return MakeIntVar(values, "");
6491 }
6492 
6493 IntVar* Solver::MakeIntVar(const std::vector<int>& values,
6494  const std::string& name) {
6495  return MakeIntVar(ToInt64Vector(values), name);
6496 }
6497 
6498 IntVar* Solver::MakeIntVar(const std::vector<int>& values) {
6499  return MakeIntVar(values, "");
6500 }
6501 
6502 IntVar* Solver::MakeIntConst(int64_t val, const std::string& name) {
6503  // If IntConst is going to be named after its creation,
6504  // cp_share_int_consts should be set to false otherwise names can potentially
6505  // be overwritten.
6506  if (absl::GetFlag(FLAGS_cp_share_int_consts) && name.empty() &&
6507  val >= MIN_CACHED_INT_CONST && val <= MAX_CACHED_INT_CONST) {
6508  return cached_constants_[val - MIN_CACHED_INT_CONST];
6509  }
6510  return RevAlloc(new IntConst(this, val, name));
6511 }
6512 
6513 IntVar* Solver::MakeIntConst(int64_t val) { return MakeIntConst(val, ""); }
6514 
6515 // ----- Int Var and associated methods -----
6516 
6517 namespace {
6518 std::string IndexedName(const std::string& prefix, int index, int max_index) {
6519 #if 0
6520 #if defined(_MSC_VER)
6521  const int digits = max_index > 0 ?
6522  static_cast<int>(log(1.0L * max_index) / log(10.0L)) + 1 :
6523  1;
6524 #else
6525  const int digits = max_index > 0 ? static_cast<int>(log10(max_index)) + 1: 1;
6526 #endif
6527  return absl::StrFormat("%s%0*d", prefix, digits, index);
6528 #else
6529  return absl::StrCat(prefix, index);
6530 #endif
6531 }
6532 } // namespace
6533 
6534 void Solver::MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
6535  const std::string& name,
6536  std::vector<IntVar*>* vars) {
6537  for (int i = 0; i < var_count; ++i) {
6538  vars->push_back(MakeIntVar(vmin, vmax, IndexedName(name, i, var_count)));
6539  }
6540 }
6541 
6542 void Solver::MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
6543  std::vector<IntVar*>* vars) {
6544  for (int i = 0; i < var_count; ++i) {
6545  vars->push_back(MakeIntVar(vmin, vmax));
6546  }
6547 }
6548 
6549 IntVar** Solver::MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
6550  const std::string& name) {
6551  IntVar** vars = new IntVar*[var_count];
6552  for (int i = 0; i < var_count; ++i) {
6553  vars[i] = MakeIntVar(vmin, vmax, IndexedName(name, i, var_count));
6554  }
6555  return vars;
6556 }
6557 
6558 void Solver::MakeBoolVarArray(int var_count, const std::string& name,
6559  std::vector<IntVar*>* vars) {
6560  for (int i = 0; i < var_count; ++i) {
6561  vars->push_back(MakeBoolVar(IndexedName(name, i, var_count)));
6562  }
6563 }
6564 
6565 void Solver::MakeBoolVarArray(int var_count, std::vector<IntVar*>* vars) {
6566  for (int i = 0; i < var_count; ++i) {
6567  vars->push_back(MakeBoolVar());
6568  }
6569 }
6570 
6571 IntVar** Solver::MakeBoolVarArray(int var_count, const std::string& name) {
6572  IntVar** vars = new IntVar*[var_count];
6573  for (int i = 0; i < var_count; ++i) {
6574  vars[i] = MakeBoolVar(IndexedName(name, i, var_count));
6575  }
6576  return vars;
6577 }
6578 
6579 void Solver::InitCachedIntConstants() {
6580  for (int i = MIN_CACHED_INT_CONST; i <= MAX_CACHED_INT_CONST; ++i) {
6581  cached_constants_[i - MIN_CACHED_INT_CONST] =
6582  RevAlloc(new IntConst(this, i, "")); // note the empty name
6583  }
6584 }
6585 
6586 IntExpr* Solver::MakeSum(IntExpr* const left, IntExpr* const right) {
6587  CHECK_EQ(this, left->solver());
6588  CHECK_EQ(this, right->solver());
6589  if (right->Bound()) {
6590  return MakeSum(left, right->Min());
6591  }
6592  if (left->Bound()) {
6593  return MakeSum(right, left->Min());
6594  }
6595  if (left == right) {
6596  return MakeProd(left, 2);
6597  }
6598  IntExpr* cache = model_cache_->FindExprExprExpression(
6599  left, right, ModelCache::EXPR_EXPR_SUM);
6600  if (cache == nullptr) {
6601  cache = model_cache_->FindExprExprExpression(right, left,
6602  ModelCache::EXPR_EXPR_SUM);
6603  }
6604  if (cache != nullptr) {
6605  return cache;
6606  } else {
6607  IntExpr* const result =
6608  AddOverflows(left->Max(), right->Max()) ||
6609  AddOverflows(left->Min(), right->Min())
6610  ? RegisterIntExpr(RevAlloc(new SafePlusIntExpr(this, left, right)))
6611  : RegisterIntExpr(RevAlloc(new PlusIntExpr(this, left, right)));
6612  model_cache_->InsertExprExprExpression(result, left, right,
6613  ModelCache::EXPR_EXPR_SUM);
6614  return result;
6615  }
6616 }
6617 
6618 IntExpr* Solver::MakeSum(IntExpr* const expr, int64_t value) {
6619  CHECK_EQ(this, expr->solver());
6620  if (expr->Bound()) {
6621  return MakeIntConst(CapAdd(expr->Min(), value));
6622  }
6623  if (value == 0) {
6624  return expr;
6625  }
6626  IntExpr* result = Cache()->FindExprConstantExpression(
6627  expr, value, ModelCache::EXPR_CONSTANT_SUM);
6628  if (result == nullptr) {
6629  if (expr->IsVar() && !AddOverflows(value, expr->Max()) &&
6630  !AddOverflows(value, expr->Min())) {
6631  IntVar* const var = expr->Var();
6632  switch (var->VarType()) {
6633  case DOMAIN_INT_VAR: {
6634  result = RegisterIntExpr(RevAlloc(new PlusCstDomainIntVar(
6635  this, reinterpret_cast<DomainIntVar*>(var), value)));
6636  break;
6637  }
6638  case CONST_VAR: {
6639  result = RegisterIntExpr(MakeIntConst(var->Min() + value));
6640  break;
6641  }
6642  case VAR_ADD_CST: {
6643  PlusCstVar* const add_var = reinterpret_cast<PlusCstVar*>(var);
6644  IntVar* const sub_var = add_var->SubVar();
6645  const int64_t new_constant = value + add_var->Constant();
6646  if (new_constant == 0) {
6647  result = sub_var;
6648  } else {
6649  if (sub_var->VarType() == DOMAIN_INT_VAR) {
6650  DomainIntVar* const dvar =
6651  reinterpret_cast<DomainIntVar*>(sub_var);
6652  result = RegisterIntExpr(
6653  RevAlloc(new PlusCstDomainIntVar(this, dvar, new_constant)));
6654  } else {
6655  result = RegisterIntExpr(
6656  RevAlloc(new PlusCstIntVar(this, sub_var, new_constant)));
6657  }
6658  }
6659  break;
6660  }
6661  case CST_SUB_VAR: {
6662  SubCstIntVar* const add_var = reinterpret_cast<SubCstIntVar*>(var);
6663  IntVar* const sub_var = add_var->SubVar();
6664  const int64_t new_constant = value + add_var->Constant();
6665  result = RegisterIntExpr(
6666  RevAlloc(new SubCstIntVar(this, sub_var, new_constant)));
6667  break;
6668  }
6669  case OPP_VAR: {
6670  OppIntVar* const add_var = reinterpret_cast<OppIntVar*>(var);
6671  IntVar* const sub_var = add_var->SubVar();
6672  result =
6673  RegisterIntExpr(RevAlloc(new SubCstIntVar(this, sub_var, value)));
6674  break;
6675  }
6676  default:
6677  result =
6678  RegisterIntExpr(RevAlloc(new PlusCstIntVar(this, var, value)));
6679  }
6680  } else {
6681  result = RegisterIntExpr(RevAlloc(new PlusIntCstExpr(this, expr, value)));
6682  }
6683  Cache()->InsertExprConstantExpression(result, expr, value,
6684  ModelCache::EXPR_CONSTANT_SUM);
6685  }
6686  return result;
6687 }
6688 
6689 IntExpr* Solver::MakeDifference(IntExpr* const left, IntExpr* const right) {
6690  CHECK_EQ(this, left->solver());
6691  CHECK_EQ(this, right->solver());
6692  if (left->Bound()) {
6693  return MakeDifference(left->Min(), right);
6694  }
6695  if (right->Bound()) {
6696  return MakeSum(left, -right->Min());
6697  }
6698  IntExpr* sub_left = nullptr;
6699  IntExpr* sub_right = nullptr;
6700  int64_t left_coef = 1;
6701  int64_t right_coef = 1;
6702  if (IsProduct(left, &sub_left, &left_coef) &&
6703  IsProduct(right, &sub_right, &right_coef)) {
6704  const int64_t abs_gcd =
6705  MathUtil::GCD64(std::abs(left_coef), std::abs(right_coef));
6706  if (abs_gcd != 0 && abs_gcd != 1) {
6707  return MakeProd(MakeDifference(MakeProd(sub_left, left_coef / abs_gcd),
6708  MakeProd(sub_right, right_coef / abs_gcd)),
6709  abs_gcd);
6710  }
6711  }
6712 
6713  IntExpr* result = Cache()->FindExprExprExpression(
6714  left, right, ModelCache::EXPR_EXPR_DIFFERENCE);
6715  if (result == nullptr) {
6716  if (!SubOverflows(left->Min(), right->Max()) &&
6717  !SubOverflows(left->Max(), right->Min())) {
6718  result = RegisterIntExpr(RevAlloc(new SubIntExpr(this, left, right)));
6719  } else {
6720  result = RegisterIntExpr(RevAlloc(new SafeSubIntExpr(this, left, right)));
6721  }
6722  Cache()->InsertExprExprExpression(result, left, right,
6723  ModelCache::EXPR_EXPR_DIFFERENCE);
6724  }
6725  return result;
6726 }
6727 
6728 // warning: this is 'value - expr'.
6729 IntExpr* Solver::MakeDifference(int64_t value, IntExpr* const expr) {
6730  CHECK_EQ(this, expr->solver());
6731  if (expr->Bound()) {
6732  return MakeIntConst(value - expr->Min());
6733  }
6734  if (value == 0) {
6735  return MakeOpposite(expr);
6736  }
6737  IntExpr* result = Cache()->FindExprConstantExpression(
6738  expr, value, ModelCache::EXPR_CONSTANT_DIFFERENCE);
6739  if (result == nullptr) {
6740  if (expr->IsVar() && expr->Min() != std::numeric_limits<int64_t>::min() &&
6741  !SubOverflows(value, expr->Min()) &&
6742  !SubOverflows(value, expr->Max())) {
6743  IntVar* const var = expr->Var();
6744  switch (var->VarType()) {
6745  case VAR_ADD_CST: {
6746  PlusCstVar* const add_var = reinterpret_cast<PlusCstVar*>(var);
6747  IntVar* const sub_var = add_var->SubVar();
6748  const int64_t new_constant = value - add_var->Constant();
6749  if (new_constant == 0) {
6750  result = sub_var;
6751  } else {
6752  result = RegisterIntExpr(
6753  RevAlloc(new SubCstIntVar(this, sub_var, new_constant)));
6754  }
6755  break;
6756  }
6757  case CST_SUB_VAR: {
6758  SubCstIntVar* const add_var = reinterpret_cast<SubCstIntVar*>(var);
6759  IntVar* const sub_var = add_var->SubVar();
6760  const int64_t new_constant = value - add_var->Constant();
6761  result = MakeSum(sub_var, new_constant);
6762  break;
6763  }
6764  case OPP_VAR: {
6765  OppIntVar* const add_var = reinterpret_cast<OppIntVar*>(var);
6766  IntVar* const sub_var = add_var->SubVar();
6767  result = MakeSum(sub_var, value);
6768  break;
6769  }
6770  default:
6771  result =
6772  RegisterIntExpr(RevAlloc(new SubCstIntVar(this, var, value)));
6773  }
6774  } else {
6775  result = RegisterIntExpr(RevAlloc(new SubIntCstExpr(this, expr, value)));
6776  }
6777  Cache()->InsertExprConstantExpression(result, expr, value,
6778  ModelCache::EXPR_CONSTANT_DIFFERENCE);
6779  }
6780  return result;
6781 }
6782 
6783 IntExpr* Solver::MakeOpposite(IntExpr* const expr) {
6784  CHECK_EQ(this, expr->solver());
6785  if (expr->Bound()) {
6786  return MakeIntConst(-expr->Min());
6787  }
6788  IntExpr* result =
6789  Cache()->FindExprExpression(expr, ModelCache::EXPR_OPPOSITE);
6790  if (result == nullptr) {
6791  if (expr->IsVar()) {
6792  result = RegisterIntVar(RevAlloc(new OppIntExpr(this, expr))->Var());
6793  } else {
6794  result = RegisterIntExpr(RevAlloc(new OppIntExpr(this, expr)));
6795  }
6796  Cache()->InsertExprExpression(result, expr, ModelCache::EXPR_OPPOSITE);
6797  }
6798  return result;
6799 }
6800 
6801 IntExpr* Solver::MakeProd(IntExpr* const expr, int64_t value) {
6802  CHECK_EQ(this, expr->solver());
6803  IntExpr* result = Cache()->FindExprConstantExpression(
6804  expr, value, ModelCache::EXPR_CONSTANT_PROD);
6805  if (result != nullptr) {
6806  return result;
6807  } else {
6808  IntExpr* m_expr = nullptr;
6809  int64_t coefficient = 1;
6810  if (IsProduct(expr, &m_expr, &coefficient)) {
6812  } else {
6813  m_expr = expr;
6814  coefficient = value;
6815  }
6816  if (m_expr->Bound()) {
6817  return MakeIntConst(CapProd(coefficient, m_expr->Min()));
6818  } else if (coefficient == 1) {
6819  return m_expr;
6820  } else if (coefficient == -1) {
6821  return MakeOpposite(m_expr);
6822  } else if (coefficient > 0) {
6823  if (m_expr->Max() > std::numeric_limits<int64_t>::max() / coefficient ||
6825  result = RegisterIntExpr(
6826  RevAlloc(new SafeTimesPosIntCstExpr(this, m_expr, coefficient)));
6827  } else {
6828  result = RegisterIntExpr(
6829  RevAlloc(new TimesPosIntCstExpr(this, m_expr, coefficient)));
6830  }
6831  } else if (coefficient == 0) {
6832  result = MakeIntConst(0);
6833  } else { // coefficient < 0.
6834  result = RegisterIntExpr(
6835  RevAlloc(new TimesIntNegCstExpr(this, m_expr, coefficient)));
6836  }
6837  if (m_expr->IsVar() &&
6838  !absl::GetFlag(FLAGS_cp_disable_expression_optimization)) {
6839  result = result->Var();
6840  }
6841  Cache()->InsertExprConstantExpression(result, expr, value,
6842  ModelCache::EXPR_CONSTANT_PROD);
6843  return result;
6844  }
6845 }
6846 
6847 namespace {
6848 void ExtractPower(IntExpr** const expr, int64_t* const exponant) {
6849  if (dynamic_cast<BasePower*>(*expr) != nullptr) {
6850  BasePower* const power = dynamic_cast<BasePower*>(*expr);
6851  *expr = power->expr();
6852  *exponant = power->exponant();
6853  }
6854  if (dynamic_cast<IntSquare*>(*expr) != nullptr) {
6855  IntSquare* const power = dynamic_cast<IntSquare*>(*expr);
6856  *expr = power->expr();
6857  *exponant = 2;
6858  }
6859  if ((*expr)->IsVar()) {
6860  IntVar* const var = (*expr)->Var();
6861  IntExpr* const sub = var->solver()->CastExpression(var);
6862  if (sub != nullptr && dynamic_cast<BasePower*>(sub) != nullptr) {
6863  BasePower* const power = dynamic_cast<BasePower*>(sub);
6864  *expr = power->expr();
6865  *exponant = power->exponant();
6866  }
6867  if (sub != nullptr && dynamic_cast<IntSquare*>(sub) != nullptr) {
6868  IntSquare* const power = dynamic_cast<IntSquare*>(sub);
6869  *expr = power->expr();
6870  *exponant = 2;
6871  }
6872  }
6873 }
6874 
6875 void ExtractProduct(IntExpr** const expr, int64_t* const coefficient,
6876  bool* modified) {
6877  if (dynamic_cast<TimesCstIntVar*>(*expr) != nullptr) {
6878  TimesCstIntVar* const left_prod = dynamic_cast<TimesCstIntVar*>(*expr);
6879  *coefficient *= left_prod->Constant();
6880  *expr = left_prod->SubVar();
6881  *modified = true;
6882  } else if (dynamic_cast<TimesIntCstExpr*>(*expr) != nullptr) {
6883  TimesIntCstExpr* const left_prod = dynamic_cast<TimesIntCstExpr*>(*expr);
6884  *coefficient *= left_prod->Constant();
6885  *expr = left_prod->Expr();
6886  *modified = true;
6887  }
6888 }
6889 } // namespace
6890 
6891 IntExpr* Solver::MakeProd(IntExpr* const left, IntExpr* const right) {
6892  if (left->Bound()) {
6893  return MakeProd(right, left->Min());
6894  }
6895 
6896  if (right->Bound()) {
6897  return MakeProd(left, right->Min());
6898  }
6899 
6900  // ----- Discover squares and powers -----
6901 
6902  IntExpr* m_left = left;
6903  IntExpr* m_right = right;
6904  int64_t left_exponant = 1;
6905  int64_t right_exponant = 1;
6906  ExtractPower(&m_left, &left_exponant);
6907  ExtractPower(&m_right, &right_exponant);
6908 
6909  if (m_left == m_right) {
6910  return MakePower(m_left, left_exponant + right_exponant);
6911  }
6912 
6913  // ----- Discover nested products -----
6914 
6915  m_left = left;
6916  m_right = right;
6917  int64_t coefficient = 1;
6918  bool modified = false;
6919 
6920  ExtractProduct(&m_left, &coefficient, &modified);
6921  ExtractProduct(&m_right, &coefficient, &modified);
6922  if (modified) {
6923  return MakeProd(MakeProd(m_left, m_right), coefficient);
6924  }
6925 
6926  // ----- Standard build -----
6927 
6928  CHECK_EQ(this, left->solver());
6929  CHECK_EQ(this, right->solver());
6930  IntExpr* result = model_cache_->FindExprExprExpression(
6931  left, right, ModelCache::EXPR_EXPR_PROD);
6932  if (result == nullptr) {
6933  result = model_cache_->FindExprExprExpression(right, left,
6934  ModelCache::EXPR_EXPR_PROD);
6935  }
6936  if (result != nullptr) {
6937  return result;
6938  }
6939  if (left->IsVar() && left->Var()->VarType() == BOOLEAN_VAR) {
6940  if (right->Min() >= 0) {
6941  result = RegisterIntExpr(RevAlloc(new TimesBooleanPosIntExpr(
6942  this, reinterpret_cast<BooleanVar*>(left), right)));
6943  } else {
6944  result = RegisterIntExpr(RevAlloc(new TimesBooleanIntExpr(
6945  this, reinterpret_cast<BooleanVar*>(left), right)));
6946  }
6947  } else if (right->IsVar() &&
6948  reinterpret_cast<IntVar*>(right)->VarType() == BOOLEAN_VAR) {
6949  if (left->Min() >= 0) {
6950  result = RegisterIntExpr(RevAlloc(new TimesBooleanPosIntExpr(
6951  this, reinterpret_cast<BooleanVar*>(right), left)));
6952  } else {
6953  result = RegisterIntExpr(RevAlloc(new TimesBooleanIntExpr(
6954  this, reinterpret_cast<BooleanVar*>(right), left)));
6955  }
6956  } else if (left->Min() >= 0 && right->Min() >= 0) {
6957  if (CapProd(left->Max(), right->Max()) ==
6958  std::numeric_limits<int64_t>::max()) { // Potential overflow.
6959  result =
6960  RegisterIntExpr(RevAlloc(new SafeTimesPosIntExpr(this, left, right)));
6961  } else {
6962  result =
6963  RegisterIntExpr(RevAlloc(new TimesPosIntExpr(this, left, right)));
6964  }
6965  } else {
6966  result = RegisterIntExpr(RevAlloc(new TimesIntExpr(this, left, right)));
6967  }
6968  model_cache_->InsertExprExprExpression(result, left, right,
6969  ModelCache::EXPR_EXPR_PROD);
6970  return result;
6971 }
6972 
6973 IntExpr* Solver::MakeDiv(IntExpr* const numerator, IntExpr* const denominator) {
6974  CHECK(numerator != nullptr);
6975  CHECK(denominator != nullptr);
6976  if (denominator->Bound()) {
6977  return MakeDiv(numerator, denominator->Min());
6978  }
6979  IntExpr* result = model_cache_->FindExprExprExpression(
6980  numerator, denominator, ModelCache::EXPR_EXPR_DIV);
6981  if (result != nullptr) {
6982  return result;
6983  }
6984 
6985  if (denominator->Min() <= 0 && denominator->Max() >= 0) {
6986  AddConstraint(MakeNonEquality(denominator, 0));
6987  }
6988 
6989  if (denominator->Min() >= 0) {
6990  if (numerator->Min() >= 0) {
6991  result = RevAlloc(new DivPosPosIntExpr(this, numerator, denominator));
6992  } else {
6993  result = RevAlloc(new DivPosIntExpr(this, numerator, denominator));
6994  }
6995  } else if (denominator->Max() <= 0) {
6996  if (numerator->Max() <= 0) {
6997  result = RevAlloc(new DivPosPosIntExpr(this, MakeOpposite(numerator),
6998  MakeOpposite(denominator)));
6999  } else {
7000  result = MakeOpposite(RevAlloc(
7001  new DivPosIntExpr(this, numerator, MakeOpposite(denominator))));
7002  }
7003  } else {
7004  result = RevAlloc(new DivIntExpr(this, numerator, denominator));
7005  }
7006  model_cache_->InsertExprExprExpression(result, numerator, denominator,
7007  ModelCache::EXPR_EXPR_DIV);
7008  return result;
7009 }
7010 
7011 IntExpr* Solver::MakeDiv(IntExpr* const expr, int64_t value) {
7012  CHECK(expr != nullptr);
7013  CHECK_EQ(this, expr->solver());
7014  if (expr->Bound()) {
7015  return MakeIntConst(expr->Min() / value);
7016  } else if (value == 1) {
7017  return expr;
7018  } else if (value == -1) {
7019  return MakeOpposite(expr);
7020  } else if (value > 0) {
7021  return RegisterIntExpr(RevAlloc(new DivPosIntCstExpr(this, expr, value)));
7022  } else if (value == 0) {
7023  LOG(FATAL) << "Cannot divide by 0";
7024  return nullptr;
7025  } else {
7026  return RegisterIntExpr(
7027  MakeOpposite(RevAlloc(new DivPosIntCstExpr(this, expr, -value))));
7028  // TODO(user) : implement special case.
7029  }
7030 }
7031 
7032 Constraint* Solver::MakeAbsEquality(IntVar* const var, IntVar* const abs_var) {
7033  if (Cache()->FindExprExpression(var, ModelCache::EXPR_ABS) == nullptr) {
7034  Cache()->InsertExprExpression(abs_var, var, ModelCache::EXPR_ABS);
7035  }
7036  return RevAlloc(new IntAbsConstraint(this, var, abs_var));
7037 }
7038 
7039 IntExpr* Solver::MakeAbs(IntExpr* const e) {
7040  CHECK_EQ(this, e->solver());
7041  if (e->Min() >= 0) {
7042  return e;
7043  } else if (e->Max() <= 0) {
7044  return MakeOpposite(e);
7045  }
7046  IntExpr* result = Cache()->FindExprExpression(e, ModelCache::EXPR_ABS);
7047  if (result == nullptr) {
7048  int64_t coefficient = 1;
7049  IntExpr* expr = nullptr;
7050  if (IsProduct(e, &expr, &coefficient)) {
7051  result = MakeProd(MakeAbs(expr), std::abs(coefficient));
7052  } else {
7053  result = RegisterIntExpr(RevAlloc(new IntAbs(this, e)));
7054  }
7055  Cache()->InsertExprExpression(result, e, ModelCache::EXPR_ABS);
7056  }
7057  return result;
7058 }
7059 
7060 IntExpr* Solver::MakeSquare(IntExpr* const expr) {
7061  CHECK_EQ(this, expr->solver());
7062  if (expr->Bound()) {
7063  const int64_t v = expr->Min();
7064  return MakeIntConst(v * v);
7065  }
7066  IntExpr* result = Cache()->FindExprExpression(expr, ModelCache::EXPR_SQUARE);
7067  if (result == nullptr) {
7068  if (expr->Min() >= 0) {
7069  result = RegisterIntExpr(RevAlloc(new PosIntSquare(this, expr)));
7070  } else {
7071  result = RegisterIntExpr(RevAlloc(new IntSquare(this, expr)));
7072  }
7073  Cache()->InsertExprExpression(result, expr, ModelCache::EXPR_SQUARE);
7074  }
7075  return result;
7076 }
7077 
7078 IntExpr* Solver::MakePower(IntExpr* const expr, int64_t n) {
7079  CHECK_EQ(this, expr->solver());
7080  CHECK_GE(n, 0);
7081  if (expr->Bound()) {
7082  const int64_t v = expr->Min();
7083  if (v >= OverflowLimit(n)) { // Overflow.
7084  return MakeIntConst(std::numeric_limits<int64_t>::max());
7085  }
7086  return MakeIntConst(IntPower(v, n));
7087  }
7088  switch (n) {
7089  case 0:
7090  return MakeIntConst(1);
7091  case 1:
7092  return expr;
7093  case 2:
7094  return MakeSquare(expr);
7095  default: {
7096  IntExpr* result = nullptr;
7097  if (n % 2 == 0) { // even.
7098  if (expr->Min() >= 0) {
7099  result =
7100  RegisterIntExpr(RevAlloc(new PosIntEvenPower(this, expr, n)));
7101  } else {
7102  result = RegisterIntExpr(RevAlloc(new IntEvenPower(this, expr, n)));
7103  }
7104  } else {
7105  result = RegisterIntExpr(RevAlloc(new IntOddPower(this, expr, n)));
7106  }
7107  return result;
7108  }
7109  }
7110 }
7111 
7112 IntExpr* Solver::MakeMin(IntExpr* const left, IntExpr* const right) {
7113  CHECK_EQ(this, left->solver());
7114  CHECK_EQ(this, right->solver());
7115  if (left->Bound()) {
7116  return MakeMin(right, left->Min());
7117  }
7118  if (right->Bound()) {
7119  return MakeMin(left, right->Min());
7120  }
7121  if (left->Min() >= right->Max()) {
7122  return right;
7123  }
7124  if (right->Min() >= left->Max()) {
7125  return left;
7126  }
7127  return RegisterIntExpr(RevAlloc(new MinIntExpr(this, left, right)));
7128 }
7129 
7130 IntExpr* Solver::MakeMin(IntExpr* const expr, int64_t value) {
7131  CHECK_EQ(this, expr->solver());
7132  if (value <= expr->Min()) {
7133  return MakeIntConst(value);
7134  }
7135  if (expr->Bound()) {
7136  return MakeIntConst(std::min(expr->Min(), value));
7137  }
7138  if (expr->Max() <= value) {
7139  return expr;
7140  }
7141  return RegisterIntExpr(RevAlloc(new MinCstIntExpr(this, expr, value)));
7142 }
7143 
7144 IntExpr* Solver::MakeMin(IntExpr* const expr, int value) {
7145  return MakeMin(expr, static_cast<int64_t>(value));
7146 }
7147 
7148 IntExpr* Solver::MakeMax(IntExpr* const left, IntExpr* const right) {
7149  CHECK_EQ(this, left->solver());
7150  CHECK_EQ(this, right->solver());
7151  if (left->Bound()) {
7152  return MakeMax(right, left->Min());
7153  }
7154  if (right->Bound()) {
7155  return MakeMax(left, right->Min());
7156  }
7157  if (left->Min() >= right->Max()) {
7158  return left;
7159  }
7160  if (right->Min() >= left->Max()) {
7161  return right;
7162  }
7163  return RegisterIntExpr(RevAlloc(new MaxIntExpr(this, left, right)));
7164 }
7165 
7166 IntExpr* Solver::MakeMax(IntExpr* const expr, int64_t value) {
7167  CHECK_EQ(this, expr->solver());
7168  if (expr->Bound()) {
7169  return MakeIntConst(std::max(expr->Min(), value));
7170  }
7171  if (value <= expr->Min()) {
7172  return expr;
7173  }
7174  if (expr->Max() <= value) {
7175  return MakeIntConst(value);
7176  }
7177  return RegisterIntExpr(RevAlloc(new MaxCstIntExpr(this, expr, value)));
7178 }
7179 
7180 IntExpr* Solver::MakeMax(IntExpr* const expr, int value) {
7181  return MakeMax(expr, static_cast<int64_t>(value));
7182 }
7183 
7184 IntExpr* Solver::MakeConvexPiecewiseExpr(IntExpr* expr, int64_t early_cost,
7185  int64_t early_date, int64_t late_date,
7186  int64_t late_cost) {
7187  return RegisterIntExpr(RevAlloc(new SimpleConvexPiecewiseExpr(
7188  this, expr, early_cost, early_date, late_date, late_cost)));
7189 }
7190 
7191 IntExpr* Solver::MakeSemiContinuousExpr(IntExpr* const expr,
7192  int64_t fixed_charge, int64_t step) {
7193  if (step == 0) {
7194  if (fixed_charge == 0) {
7195  return MakeIntConst(int64_t{0});
7196  } else {
7197  return RegisterIntExpr(
7198  RevAlloc(new SemiContinuousStepZeroExpr(this, expr, fixed_charge)));
7199  }
7200  } else if (step == 1) {
7201  return RegisterIntExpr(
7202  RevAlloc(new SemiContinuousStepOneExpr(this, expr, fixed_charge)));
7203  } else {
7204  return RegisterIntExpr(
7205  RevAlloc(new SemiContinuousExpr(this, expr, fixed_charge, step)));
7206  }
7207  // TODO(user) : benchmark with virtualization of
7208  // PosIntDivDown and PosIntDivUp - or function pointers.
7209 }
7210 
7211 // ----- Piecewise Linear -----
7212 
7214  public:
7216  const PiecewiseLinearFunction& f)
7217  : BaseIntExpr(solver), expr_(expr), f_(f) {}
7218  ~PiecewiseLinearExpr() override {}
7219  int64_t Min() const override {
7220  return f_.GetMinimum(expr_->Min(), expr_->Max());
7221  }
7222  void SetMin(int64_t m) override {
7223  const auto& range =
7224  f_.GetSmallestRangeGreaterThanValue(expr_->Min(), expr_->Max(), m);
7225  expr_->SetRange(range.first, range.second);
7226  }
7227 
7228  int64_t Max() const override {
7229  return f_.GetMaximum(expr_->Min(), expr_->Max());
7230  }
7231 
7232  void SetMax(int64_t m) override {
7233  const auto& range =
7234  f_.GetSmallestRangeLessThanValue(expr_->Min(), expr_->Max(), m);
7235  expr_->SetRange(range.first, range.second);
7236  }
7237 
7238  void SetRange(int64_t l, int64_t u) override {
7239  const auto& range =
7240  f_.GetSmallestRangeInValueRange(expr_->Min(), expr_->Max(), l, u);
7241  expr_->SetRange(range.first, range.second);
7242  }
7243  std::string name() const override {
7244  return absl::StrFormat("PiecewiseLinear(%s, f = %s)", expr_->name(),
7245  f_.DebugString());
7246  }
7247 
7248  std::string DebugString() const override {
7249  return absl::StrFormat("PiecewiseLinear(%s, f = %s)", expr_->DebugString(),
7250  f_.DebugString());
7251  }
7252 
7253  void WhenRange(Demon* d) override { expr_->WhenRange(d); }
7254 
7255  void Accept(ModelVisitor* const visitor) const override {
7256  // TODO(user): Implement visitor.
7257  }
7258 
7259  private:
7260  IntExpr* const expr_;
7261  const PiecewiseLinearFunction f_;
7262 };
7263 
7264 IntExpr* Solver::MakePiecewiseLinearExpr(IntExpr* expr,
7265  const PiecewiseLinearFunction& f) {
7266  return RegisterIntExpr(RevAlloc(new PiecewiseLinearExpr(this, expr, f)));
7267 }
7268 
7269 // ----- Conditional Expression -----
7270 
7271 IntExpr* Solver::MakeConditionalExpression(IntVar* const condition,
7272  IntExpr* const expr,
7273  int64_t unperformed_value) {
7274  if (condition->Min() == 1) {
7275  return expr;
7276  } else if (condition->Max() == 0) {
7277  return MakeIntConst(unperformed_value);
7278  } else {
7279  IntExpr* cache = Cache()->FindExprExprConstantExpression(
7280  condition, expr, unperformed_value,
7281  ModelCache::EXPR_EXPR_CONSTANT_CONDITIONAL);
7282  if (cache == nullptr) {
7283  cache = RevAlloc(
7284  new ExprWithEscapeValue(this, condition, expr, unperformed_value));
7285  Cache()->InsertExprExprConstantExpression(
7286  cache, condition, expr, unperformed_value,
7287  ModelCache::EXPR_EXPR_CONSTANT_CONDITIONAL);
7288  }
7289  return cache;
7290  }
7291 }
7292 
7293 // ----- Modulo -----
7294 
7295 IntExpr* Solver::MakeModulo(IntExpr* const x, int64_t mod) {
7296  IntVar* const result =
7297  MakeDifference(x, MakeProd(MakeDiv(x, mod), mod))->Var();
7298  if (mod >= 0) {
7299  AddConstraint(MakeBetweenCt(result, 0, mod - 1));
7300  } else {
7301  AddConstraint(MakeBetweenCt(result, mod + 1, 0));
7302  }
7303  return result;
7304 }
7305 
7306 IntExpr* Solver::MakeModulo(IntExpr* const x, IntExpr* const mod) {
7307  if (mod->Bound()) {
7308  return MakeModulo(x, mod->Min());
7309  }
7310  IntVar* const result =
7311  MakeDifference(x, MakeProd(MakeDiv(x, mod), mod))->Var();
7312  AddConstraint(MakeLess(result, MakeAbs(mod)));
7313  AddConstraint(MakeGreater(result, MakeOpposite(MakeAbs(mod))));
7314  return result;
7315 }
7316 
7317 // --------- IntVar ---------
7318 
7319 int IntVar::VarType() const { return UNSPECIFIED; }
7320 
7321 void IntVar::RemoveValues(const std::vector<int64_t>& values) {
7322  // TODO(user): Check and maybe inline this code.
7323  const int size = values.size();
7324  DCHECK_GE(size, 0);
7325  switch (size) {
7326  case 0: {
7327  return;
7328  }
7329  case 1: {
7330  RemoveValue(values[0]);
7331  return;
7332  }
7333  case 2: {
7334  RemoveValue(values[0]);
7335  RemoveValue(values[1]);
7336  return;
7337  }
7338  case 3: {
7339  RemoveValue(values[0]);
7340  RemoveValue(values[1]);
7341  RemoveValue(values[2]);
7342  return;
7343  }
7344  default: {
7345  // 4 values, let's start doing some more clever things.
7346  // TODO(user) : Sort values!
7347  int start_index = 0;
7348  int64_t new_min = Min();
7349  if (values[start_index] <= new_min) {
7350  while (start_index < size - 1 &&
7351  values[start_index + 1] == values[start_index] + 1) {
7352  new_min = values[start_index + 1] + 1;
7353  start_index++;
7354  }
7355  }
7356  int end_index = size - 1;
7357  int64_t new_max = Max();
7358  if (values[end_index] >= new_max) {
7359  while (end_index > start_index + 1 &&
7360  values[end_index - 1] == values[end_index] - 1) {
7361  new_max = values[end_index - 1] - 1;
7362  end_index--;
7363  }
7364  }
7365  SetRange(new_min, new_max);
7366  for (int i = start_index; i <= end_index; ++i) {
7367  RemoveValue(values[i]);
7368  }
7369  }
7370  }
7371 }
7372 
7373 void IntVar::Accept(ModelVisitor* const visitor) const {
7374  IntExpr* const casted = solver()->CastExpression(this);
7375  visitor->VisitIntegerVariable(this, casted);
7376 }
7377 
7378 void IntVar::SetValues(const std::vector<int64_t>& values) {
7379  switch (values.size()) {
7380  case 0: {
7381  solver()->Fail();
7382  break;
7383  }
7384  case 1: {
7385  SetValue(values.back());
7386  break;
7387  }
7388  case 2: {
7389  if (Contains(values[0])) {
7390  if (Contains(values[1])) {
7391  const int64_t l = std::min(values[0], values[1]);
7392  const int64_t u = std::max(values[0], values[1]);
7393  SetRange(l, u);
7394  if (u > l + 1) {
7395  RemoveInterval(l + 1, u - 1);
7396  }
7397  } else {
7398  SetValue(values[0]);
7399  }
7400  } else {
7401  SetValue(values[1]);
7402  }
7403  break;
7404  }
7405  default: {
7406  // TODO(user): use a clean and safe SortedUniqueCopy() class
7407  // that uses a global, static shared (and locked) storage.
7408  // TODO(user): [optional] consider porting
7409  // STLSortAndRemoveDuplicates from ortools/base/stl_util.h to the
7410  // existing open_source/base/stl_util.h and using it here.
7411  // TODO(user): We could filter out values not in the var.
7412  std::vector<int64_t>& tmp = solver()->tmp_vector_;
7413  tmp.clear();
7414  tmp.insert(tmp.end(), values.begin(), values.end());
7415  std::sort(tmp.begin(), tmp.end());
7416  tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
7417  const int size = tmp.size();
7418  const int64_t vmin = Min();
7419  const int64_t vmax = Max();
7420  int first = 0;
7421  int last = size - 1;
7422  if (tmp.front() > vmax || tmp.back() < vmin) {
7423  solver()->Fail();
7424  }
7425  // TODO(user) : We could find the first position >= vmin by dichotomy.
7426  while (tmp[first] < vmin || !Contains(tmp[first])) {
7427  ++first;
7428  if (first > last || tmp[first] > vmax) {
7429  solver()->Fail();
7430  }
7431  }
7432  while (last > first && (tmp[last] > vmax || !Contains(tmp[last]))) {
7433  // Note that last >= first implies tmp[last] >= vmin.
7434  --last;
7435  }
7436  DCHECK_GE(last, first);
7437  SetRange(tmp[first], tmp[last]);
7438  while (first < last) {
7439  const int64_t start = tmp[first] + 1;
7440  const int64_t end = tmp[first + 1] - 1;
7441  if (start <= end) {
7442  RemoveInterval(start, end);
7443  }
7444  first++;
7445  }
7446  }
7447  }
7448 }
7449 // ---------- BaseIntExpr ---------
7450 
7451 void LinkVarExpr(Solver* const s, IntExpr* const expr, IntVar* const var) {
7452  if (!var->Bound()) {
7453  if (var->VarType() == DOMAIN_INT_VAR) {
7454  DomainIntVar* dvar = reinterpret_cast<DomainIntVar*>(var);
7455  s->AddCastConstraint(
7456  s->RevAlloc(new LinkExprAndDomainIntVar(s, expr, dvar)), dvar, expr);
7457  } else {
7458  s->AddCastConstraint(s->RevAlloc(new LinkExprAndVar(s, expr, var)), var,
7459  expr);
7460  }
7461  }
7462 }
7463 
7464 IntVar* BaseIntExpr::Var() {
7465  if (var_ == nullptr) {
7466  solver()->SaveValue(reinterpret_cast<void**>(&var_));
7467  var_ = CastToVar();
7468  }
7469  return var_;
7470 }
7471 
7472 IntVar* BaseIntExpr::CastToVar() {
7473  int64_t vmin, vmax;
7474  Range(&vmin, &vmax);
7475  IntVar* const var = solver()->MakeIntVar(vmin, vmax);
7476  LinkVarExpr(solver(), this, var);
7477  return var;
7478 }
7479 
7480 // Discovery methods
7481 bool Solver::IsADifference(IntExpr* expr, IntExpr** const left,
7482  IntExpr** const right) {
7483  if (expr->IsVar()) {
7484  IntVar* const expr_var = expr->Var();
7485  expr = CastExpression(expr_var);
7486  }
7487  // This is a dynamic cast to check the type of expr.
7488  // It returns nullptr is expr is not a subclass of SubIntExpr.
7489  SubIntExpr* const sub_expr = dynamic_cast<SubIntExpr*>(expr);
7490  if (sub_expr != nullptr) {
7491  *left = sub_expr->left();
7492  *right = sub_expr->right();
7493  return true;
7494  }
7495  return false;
7496 }
7497 
7498 bool Solver::IsBooleanVar(IntExpr* const expr, IntVar** inner_var,
7499  bool* is_negated) const {
7500  if (expr->IsVar() && expr->Var()->VarType() == BOOLEAN_VAR) {
7501  *inner_var = expr->Var();
7502  *is_negated = false;
7503  return true;
7504  } else if (expr->IsVar() && expr->Var()->VarType() == CST_SUB_VAR) {
7505  SubCstIntVar* const sub_var = reinterpret_cast<SubCstIntVar*>(expr);
7506  if (sub_var != nullptr && sub_var->Constant() == 1 &&
7507  sub_var->SubVar()->VarType() == BOOLEAN_VAR) {
7508  *is_negated = true;
7509  *inner_var = sub_var->SubVar();
7510  return true;
7511  }
7512  }
7513  return false;
7514 }
7515 
7516 bool Solver::IsProduct(IntExpr* const expr, IntExpr** inner_expr,
7517  int64_t* coefficient) {
7518  if (dynamic_cast<TimesCstIntVar*>(expr) != nullptr) {
7519  TimesCstIntVar* const var = dynamic_cast<TimesCstIntVar*>(expr);
7520  *coefficient = var->Constant();
7521  *inner_expr = var->SubVar();
7522  return true;
7523  } else if (dynamic_cast<TimesIntCstExpr*>(expr) != nullptr) {
7524  TimesIntCstExpr* const prod = dynamic_cast<TimesIntCstExpr*>(expr);
7525  *coefficient = prod->Constant();
7526  *inner_expr = prod->Expr();
7527  return true;
7528  }
7529  *inner_expr = expr;
7530  *coefficient = 1;
7531  return false;
7532 }
7533 
7534 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
A BaseObject is the root of all reversibly allocated objects.
void WhenBound(Demon *d) override
This method attaches a demon that will be awakened when the variable is bound.
Definition: expressions.cc:116
IntVar * IsLessOrEqual(int64_t constant) override
Definition: expressions.cc:166
uint64_t Size() const override
This method returns the number of values in the domain of the variable.
Definition: expressions.cc:126
void SetRange(int64_t mi, int64_t ma) override
This method sets both the min and the max of the expression.
Definition: expressions.cc:82
SimpleRevFIFO< Demon * > delayed_bound_demons_
bool Contains(int64_t v) const override
This method returns whether the value 'v' is in the domain of the variable.
Definition: expressions.cc:130
void RemoveValue(int64_t v) override
This method removes the value 'v' from the domain of the variable.
Definition: expressions.cc:93
IntVar * IsEqual(int64_t constant) override
IsEqual.
Definition: expressions.cc:134
IntVar * IsGreaterOrEqual(int64_t constant) override
Definition: expressions.cc:156
void SetMax(int64_t m) override
Definition: expressions.cc:76
SimpleRevFIFO< Demon * > bound_demons_
void RemoveInterval(int64_t l, int64_t u) override
This method removes the interval 'l' .
Definition: expressions.cc:105
void SetMin(int64_t m) override
Definition: expressions.cc:70
IntVar * IsDifferent(int64_t constant) override
Definition: expressions.cc:145
std::string DebugString() const override
Definition: expressions.cc:176
A constraint is the main modeling object.
A Demon is the base element of a propagation queue.
virtual Solver::DemonPriority priority() const
This method returns the priority of the demon.
The class IntExpr is the base of all integer expressions in constraint programming.
virtual IntVar * Var()=0
Creates a variable from the expression.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual void SetValue(int64_t v)
This method sets the value of the expression.
virtual bool IsVar() const
Returns true if the expression is indeed a variable.
virtual int64_t Min() const =0
IntVar * VarWithName(const std::string &name)
Creates a variable from the expression and set the name of the resulting var.
Definition: expressions.cc:51
virtual int64_t Max() const =0
The class IntVar is a subset of IntExpr.
IntVar * Var() override
Creates a variable from the expression.
IntVar(Solver *const s)
Definition: expressions.cc:59
virtual int VarType() const
The class Iterator has two direct subclasses.
virtual void VisitIntegerVariable(const IntVar *const variable, IntExpr *const delegate)
PiecewiseLinearExpr(Solver *solver, IntExpr *expr, const PiecewiseLinearFunction &f)
void WhenRange(Demon *d) override
Attach a demon that will watch the min or the max of the expression.
void SetRange(int64_t l, int64_t u) override
This method sets both the min and the max of the expression.
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
std::string name() const override
Object naming.
std::string DebugString() const override
virtual std::string name() const
Object naming.
void SetValue(Solver *const s, const T &val)
DemonPriority
This enum represents the three possible priorities for a demon in the Solver queue.
@ VAR_PRIORITY
VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.
@ DELAYED_PRIORITY
DELAYED_PRIORITY is the lowest priority: Demons will be processed after VAR_PRIORITY and NORMAL_PRIOR...
@ OUTSIDE_SEARCH
Before search, after search.
IntExpr * MakeDifference(IntExpr *const left, IntExpr *const right)
left - right
T * RevAlloc(T *object)
Registers the given object as being reversible.
void AddCastConstraint(CastConstraint *const constraint, IntVar *const target_var, IntExpr *const expr)
Adds 'constraint' to the solver and marks it as a cast constraint, that is, a constraint created call...
IntVar * MakeIntConst(int64_t val, const std::string &name)
IntConst will create a constant expression.
void Fail()
Abandon the current branch in the search tree. A backtrack will follow.
int64_t b
std::vector< IntVarIterator * > holes_
int64_t a
const std::string name
const Constraint * ct
int64_t value
IntVar *const expr_
Definition: element.cc:88
IntVar * var
Definition: expr_array.cc:1874
const int64_t limit_
Solver *const solver_
Definition: expressions.cc:279
const int64_t pow_
ABSL_FLAG(bool, cp_disable_expression_optimization, false, "Disable special optimization when creating expressions.")
const int64_t cst_
IntVarIterator *const iterator_
Handler handler_
Definition: interval.cc:430
const int64_t offset_
Definition: interval.cc:2109
bool in_process_
Definition: interval.cc:429
int index
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
int RemoveAt(RepeatedType *array, const IndexContainer &indices)
Definition: protobuf_util.h:50
const Collection::value_type::second_type FindPtrOrNull(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition: map_util.h:89
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
Definition: stl_util.h:58
std::pair< double, double > Range
Definition: statistics.h:27
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1795
Collection of objects used to extend the Constraint Solver library.
int64_t SubOverflows(int64_t x, int64_t y)
static const uint64_t kAllBits64
Definition: bitset.h:34
void InternalSaveBooleanVarValue(Solver *const solver, IntVar *const var)
int64_t CapAdd(int64_t x, int64_t y)
void CleanVariableOnFail(IntVar *const var)
Constraint * SetIsEqual(IntVar *const var, const std::vector< int64_t > &values, const std::vector< IntVar * > &vars)
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
int64_t CapSub(int64_t x, int64_t y)
int64_t UnsafeMostSignificantBitPosition64(const uint64_t *const bitset, uint64_t start, uint64_t end)
uint64_t BitCountRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
int64_t UnsafeLeastSignificantBitPosition64(const uint64_t *const bitset, uint64_t start, uint64_t end)
bool AddOverflows(int64_t x, int64_t y)
void RegisterDemon(Solver *const solver, Demon *const demon, DemonProfiler *const monitor)
void RestoreBoolValue(IntVar *const var)
int64_t CapProd(int64_t x, int64_t y)
uint64_t OneRange64(uint64_t s, uint64_t e)
Definition: bitset.h:286
uint32_t BitPos64(uint64_t pos)
Definition: bitset.h:331
uint64_t BitCount64(uint64_t n)
Definition: bitset.h:43
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:829
void LinkVarExpr(Solver *const s, IntExpr *const expr, IntVar *const var)
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Definition: bitset.h:347
uint64_t OneBit64(int pos)
Definition: bitset.h:39
uint64_t BitOffset64(uint64_t pos)
Definition: bitset.h:335
Constraint * SetIsGreaterOrEqual(IntVar *const var, const std::vector< int64_t > &values, const std::vector< IntVar * > &vars)
int64_t PosIntDivDown(int64_t e, int64_t v)
uint64_t BitLength64(uint64_t size)
Definition: bitset.h:339
int LeastSignificantBitPosition64(uint64_t n)
Definition: bitset.h:128
int64_t CapOpp(int64_t v)
int MostSignificantBitPosition64(uint64_t n)
Definition: bitset.h:232
int64_t PosIntDivUp(int64_t e, int64_t v)
int64_t coefficient
IntervalVar *const target_var_
int64_t step_
Definition: search.cc:3069
int64_t current_
Definition: search.cc:3070
const int64_t stamp
Definition: search.cc:3165
std::optional< int64_t > end
int64_t start
const std::optional< Range > & range
Definition: statistics.cc:36