Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
constraint_solveri.h
Go to the documentation of this file.
1// Copyright 2010-2024 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
48
49#ifndef OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
50#define OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
51
52#include <stdint.h>
53#include <string.h>
54
55#include <algorithm>
56#include <functional>
57#include <initializer_list>
58#include <memory>
59#include <string>
60#include <tuple>
61#include <utility>
62#include <vector>
63
64#include "absl/algorithm/container.h"
65#include "absl/container/flat_hash_map.h"
66#include "absl/strings/str_cat.h"
70#include "ortools/base/timer.h"
71#include "ortools/base/types.h"
73#include "ortools/util/bitset.h"
75
76namespace operations_research {
77
103class LocalSearchMonitor;
104
105class BaseIntExpr : public IntExpr {
106 public:
107 explicit BaseIntExpr(Solver* const s) : IntExpr(s), var_(nullptr) {}
108 ~BaseIntExpr() override {}
109
110 IntVar* Var() override;
111 virtual IntVar* CastToVar();
113 private:
114 IntVar* var_;
116
119enum VarTypes {
123 CONST_VAR,
139#ifndef SWIG
140template <class T>
141class SimpleRevFIFO {
142 private:
143 enum { CHUNK_SIZE = 16 }; // TODO(user): could be an extra template param
144 struct Chunk {
145 T data_[CHUNK_SIZE];
146 const Chunk* const next_;
147 explicit Chunk(const Chunk* next) : next_(next) {}
148 };
149
150 public:
152 class Iterator {
153 public:
154 explicit Iterator(const SimpleRevFIFO<T>* l)
155 : chunk_(l->chunks_), value_(l->Last()) {}
156 bool ok() const { return (value_ != nullptr); }
157 T operator*() const { return *value_; }
158 void operator++() {
159 ++value_;
160 if (value_ == chunk_->data_ + CHUNK_SIZE) {
161 chunk_ = chunk_->next_;
162 value_ = chunk_ ? chunk_->data_ : nullptr;
166 private:
167 const Chunk* chunk_;
168 const T* value_;
169 };
170
171 SimpleRevFIFO() : chunks_(nullptr), pos_(0) {}
172
173 void Push(Solver* const s, T val) {
174 if (pos_.Value() == 0) {
175 Chunk* const chunk = s->UnsafeRevAlloc(new Chunk(chunks_));
176 s->SaveAndSetValue(reinterpret_cast<void**>(&chunks_),
177 reinterpret_cast<void*>(chunk));
178 pos_.SetValue(s, CHUNK_SIZE - 1);
179 } else {
180 pos_.Decr(s);
181 }
182 chunks_->data_[pos_.Value()] = val;
183 }
184
186 void PushIfNotTop(Solver* const s, T val) {
187 if (chunks_ == nullptr || LastValue() != val) {
188 Push(s, val);
189 }
190 }
191
193 const T* Last() const {
194 return chunks_ ? &chunks_->data_[pos_.Value()] : nullptr;
195 }
196
197 T* MutableLast() { return chunks_ ? &chunks_->data_[pos_.Value()] : nullptr; }
198
200 const T& LastValue() const {
201 DCHECK(chunks_);
202 return chunks_->data_[pos_.Value()];
203 }
206 void SetLastValue(const T& v) {
207 DCHECK(Last());
208 chunks_->data_[pos_.Value()] = v;
209 }
210
211 private:
212 Chunk* chunks_;
214};
215
217// TODO(user): use murmurhash.
218inline uint64_t Hash1(uint64_t value) {
219 value = (~value) + (value << 21);
220 value ^= value >> 24;
221 value += (value << 3) + (value << 8);
222 value ^= value >> 14;
223 value += (value << 2) + (value << 4);
224 value ^= value >> 28;
225 value += (value << 31);
226 return value;
227}
228
229inline uint64_t Hash1(uint32_t value) {
230 uint64_t a = value;
231 a = (a + 0x7ed55d16) + (a << 12);
232 a = (a ^ 0xc761c23c) ^ (a >> 19);
233 a = (a + 0x165667b1) + (a << 5);
234 a = (a + 0xd3a2646c) ^ (a << 9);
235 a = (a + 0xfd7046c5) + (a << 3);
236 a = (a ^ 0xb55a4f09) ^ (a >> 16);
237 return a;
238}
239
240inline uint64_t Hash1(int64_t value) {
241 return Hash1(static_cast<uint64_t>(value));
242}
243
244inline uint64_t Hash1(int value) { return Hash1(static_cast<uint32_t>(value)); }
245
246inline uint64_t Hash1(void* const ptr) {
247#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || \
248 defined(__aarch64__) || (defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64))
249 return Hash1(reinterpret_cast<uint64_t>(ptr));
250#else
251 return Hash1(reinterpret_cast<uint32_t>(ptr));
252#endif
254
255template <class T>
256uint64_t Hash1(const std::vector<T*>& ptrs) {
257 if (ptrs.empty()) return 0;
258 if (ptrs.size() == 1) return Hash1(ptrs[0]);
259 uint64_t hash = Hash1(ptrs[0]);
260 for (int i = 1; i < ptrs.size(); ++i) {
261 hash = hash * i + Hash1(ptrs[i]);
262 }
263 return hash;
264}
265
266inline uint64_t Hash1(const std::vector<int64_t>& ptrs) {
267 if (ptrs.empty()) return 0;
268 if (ptrs.size() == 1) return Hash1(ptrs[0]);
269 uint64_t hash = Hash1(ptrs[0]);
270 for (int i = 1; i < ptrs.size(); ++i) {
271 hash = hash * i + Hash1(ptrs[i]);
272 }
273 return hash;
274}
275
278template <class K, class V>
279class RevImmutableMultiMap {
280 public:
281 RevImmutableMultiMap(Solver* const solver, int initial_size)
282 : solver_(solver),
283 array_(solver->UnsafeRevAllocArray(new Cell*[initial_size])),
284 size_(initial_size),
285 num_items_(0) {
286 memset(array_, 0, sizeof(*array_) * size_.Value());
287 }
290
291 int num_items() const { return num_items_.Value(); }
292
294 bool ContainsKey(const K& key) const {
295 uint64_t code = Hash1(key) % size_.Value();
296 Cell* tmp = array_[code];
297 while (tmp) {
298 if (tmp->key() == key) {
299 return true;
300 }
301 tmp = tmp->next();
302 }
303 return false;
304 }
305
309 const V& FindWithDefault(const K& key, const V& default_value) const {
310 uint64_t code = Hash1(key) % size_.Value();
311 Cell* tmp = array_[code];
312 while (tmp) {
313 if (tmp->key() == key) {
314 return tmp->value();
315 }
316 tmp = tmp->next();
317 }
318 return default_value;
319 }
320
322 void Insert(const K& key, const V& value) {
323 const int position = Hash1(key) % size_.Value();
324 Cell* const cell =
325 solver_->UnsafeRevAlloc(new Cell(key, value, array_[position]));
326 solver_->SaveAndSetValue(reinterpret_cast<void**>(&array_[position]),
327 reinterpret_cast<void*>(cell));
328 num_items_.Incr(solver_);
329 if (num_items_.Value() > 2 * size_.Value()) {
330 Double();
331 }
332 }
333
334 private:
335 class Cell {
336 public:
337 Cell(const K& key, const V& value, Cell* const next)
338 : key_(key), value_(value), next_(next) {}
339
340 void SetRevNext(Solver* const solver, Cell* const next) {
341 solver->SaveAndSetValue(reinterpret_cast<void**>(&next_),
342 reinterpret_cast<void*>(next));
343 }
344
345 Cell* next() const { return next_; }
346
347 const K& key() const { return key_; }
348
349 const V& value() const { return value_; }
350
351 private:
352 const K key_;
353 const V value_;
354 Cell* next_;
355 };
356
357 void Double() {
358 Cell** const old_cell_array = array_;
359 const int old_size = size_.Value();
360 size_.SetValue(solver_, size_.Value() * 2);
361 solver_->SaveAndSetValue(
362 reinterpret_cast<void**>(&array_),
363 reinterpret_cast<void*>(
364 solver_->UnsafeRevAllocArray(new Cell*[size_.Value()])));
365 memset(array_, 0, size_.Value() * sizeof(*array_));
366 for (int i = 0; i < old_size; ++i) {
367 Cell* tmp = old_cell_array[i];
368 while (tmp != nullptr) {
369 Cell* const to_reinsert = tmp;
370 tmp = tmp->next();
371 const uint64_t new_position = Hash1(to_reinsert->key()) % size_.Value();
372 to_reinsert->SetRevNext(solver_, array_[new_position]);
373 solver_->SaveAndSetValue(
374 reinterpret_cast<void**>(&array_[new_position]),
375 reinterpret_cast<void*>(to_reinsert));
376 }
377 }
378 }
379
380 Solver* const solver_;
381 Cell** array_;
382 NumericalRev<int> size_;
383 NumericalRev<int> num_items_;
384};
385
387class RevSwitch {
388 public:
389 RevSwitch() : value_(false) {}
390
391 bool Switched() const { return value_; }
392
393 void Switch(Solver* const solver) { solver->SaveAndSetValue(&value_, true); }
395 private:
396 bool value_;
397};
401class SmallRevBitSet {
402 public:
403 explicit SmallRevBitSet(int64_t size);
405 void SetToOne(Solver* solver, int64_t pos);
407 void SetToZero(Solver* solver, int64_t pos);
409 int64_t Cardinality() const;
411 bool IsCardinalityZero() const { return bits_.Value() == uint64_t{0}; }
413 bool IsCardinalityOne() const {
414 return (bits_.Value() != 0) && !(bits_.Value() & (bits_.Value() - 1));
415 }
418 int64_t GetFirstOne() const;
419
420 private:
421 Rev<uint64_t> bits_;
422};
423
426class RevBitSet {
427 public:
428 explicit RevBitSet(int64_t size);
429 ~RevBitSet();
430
432 void SetToOne(Solver* solver, int64_t index);
434 void SetToZero(Solver* solver, int64_t index);
436 bool IsSet(int64_t index) const;
438 int64_t Cardinality() const;
440 bool IsCardinalityZero() const;
442 bool IsCardinalityOne() const;
445 int64_t GetFirstBit(int start) const;
447 void ClearAll(Solver* solver);
448
449 friend class RevBitMatrix;
450
451 private:
453 void Save(Solver* solver, int offset);
454 const int64_t size_;
455 const int64_t length_;
456 uint64_t* bits_;
457 uint64_t* stamps_;
458};
459
461class RevBitMatrix : private RevBitSet {
462 public:
463 RevBitMatrix(int64_t rows, int64_t columns);
465
467 void SetToOne(Solver* solver, int64_t row, int64_t column);
469 void SetToZero(Solver* solver, int64_t row, int64_t column);
471 bool IsSet(int64_t row, int64_t column) const {
472 DCHECK_GE(row, 0);
473 DCHECK_LT(row, rows_);
474 DCHECK_GE(column, 0);
475 DCHECK_LT(column, columns_);
476 return RevBitSet::IsSet(row * columns_ + column);
477 }
479 int64_t Cardinality(int row) const;
481 bool IsCardinalityZero(int row) const;
483 bool IsCardinalityOne(int row) const;
486 int64_t GetFirstBit(int row, int start) const;
488 void ClearAll(Solver* solver);
489
490 private:
491 const int64_t rows_;
492 const int64_t columns_;
493};
494
500
502template <class T>
503class CallMethod0 : public Demon {
504 public:
505 CallMethod0(T* const ct, void (T::*method)(), const std::string& name)
506 : constraint_(ct), method_(method), name_(name) {}
507
508 ~CallMethod0() override {}
509
510 void Run(Solver* const s) override { (constraint_->*method_)(); }
511
512 std::string DebugString() const override {
513 return "CallMethod_" + name_ + "(" + constraint_->DebugString() + ")";
514 }
516 private:
517 T* const constraint_;
518 void (T::*const method_)();
519 const std::string name_;
520};
521
522template <class T>
523Demon* MakeConstraintDemon0(Solver* const s, T* const ct, void (T::*method)(),
524 const std::string& name) {
525 return s->RevAlloc(new CallMethod0<T>(ct, method, name));
526}
527
528template <class P>
529std::string ParameterDebugString(P param) {
530 return absl::StrCat(param);
531}
532
534template <class P>
535std::string ParameterDebugString(P* param) {
536 return param->DebugString();
537}
538
540template <class T, class P>
541class CallMethod1 : public Demon {
542 public:
543 CallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
544 P param1)
545 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
546
547 ~CallMethod1() override {}
549 void Run(Solver* const s) override { (constraint_->*method_)(param1_); }
551 std::string DebugString() const override {
552 return absl::StrCat("CallMethod_", name_, "(", constraint_->DebugString(),
553 ", ", ParameterDebugString(param1_), ")");
555
556 private:
557 T* const constraint_;
558 void (T::*const method_)(P);
559 const std::string name_;
560 P param1_;
561};
562
563template <class T, class P>
564Demon* MakeConstraintDemon1(Solver* const s, T* const ct, void (T::*method)(P),
565 const std::string& name, P param1) {
566 return s->RevAlloc(new CallMethod1<T, P>(ct, method, name, param1));
567}
568
570template <class T, class P, class Q>
571class CallMethod2 : public Demon {
572 public:
573 CallMethod2(T* const ct, void (T::*method)(P, Q), const std::string& name,
574 P param1, Q param2)
575 : constraint_(ct),
576 method_(method),
577 name_(name),
578 param1_(param1),
579 param2_(param2) {}
581 ~CallMethod2() override {}
582
583 void Run(Solver* const s) override {
584 (constraint_->*method_)(param1_, param2_);
585 }
586
587 std::string DebugString() const override {
588 return absl::StrCat(absl::StrCat("CallMethod_", name_),
589 absl::StrCat("(", constraint_->DebugString()),
590 absl::StrCat(", ", ParameterDebugString(param1_)),
591 absl::StrCat(", ", ParameterDebugString(param2_), ")"));
592 }
593
594 private:
595 T* const constraint_;
596 void (T::*const method_)(P, Q);
597 const std::string name_;
598 P param1_;
599 Q param2_;
600};
601
602template <class T, class P, class Q>
603Demon* MakeConstraintDemon2(Solver* const s, T* const ct,
604 void (T::*method)(P, Q), const std::string& name,
605 P param1, Q param2) {
606 return s->RevAlloc(
607 new CallMethod2<T, P, Q>(ct, method, name, param1, param2));
608}
610template <class T, class P, class Q, class R>
611class CallMethod3 : public Demon {
612 public:
613 CallMethod3(T* const ct, void (T::*method)(P, Q, R), const std::string& name,
614 P param1, Q param2, R param3)
615 : constraint_(ct),
616 method_(method),
617 name_(name),
618 param1_(param1),
619 param2_(param2),
620 param3_(param3) {}
621
622 ~CallMethod3() override {}
623
624 void Run(Solver* const s) override {
625 (constraint_->*method_)(param1_, param2_, param3_);
626 }
627
628 std::string DebugString() const override {
629 return absl::StrCat(absl::StrCat("CallMethod_", name_),
630 absl::StrCat("(", constraint_->DebugString()),
631 absl::StrCat(", ", ParameterDebugString(param1_)),
632 absl::StrCat(", ", ParameterDebugString(param2_)),
633 absl::StrCat(", ", ParameterDebugString(param3_), ")"));
634 }
636 private:
637 T* const constraint_;
638 void (T::*const method_)(P, Q, R);
639 const std::string name_;
640 P param1_;
641 Q param2_;
642 R param3_;
643};
644
645template <class T, class P, class Q, class R>
646Demon* MakeConstraintDemon3(Solver* const s, T* const ct,
647 void (T::*method)(P, Q, R), const std::string& name,
648 P param1, Q param2, R param3) {
649 return s->RevAlloc(
650 new CallMethod3<T, P, Q, R>(ct, method, name, param1, param2, param3));
651}
658
660template <class T>
661class DelayedCallMethod0 : public Demon {
662 public:
663 DelayedCallMethod0(T* const ct, void (T::*method)(), const std::string& name)
664 : constraint_(ct), method_(method), name_(name) {}
665
666 ~DelayedCallMethod0() override {}
667
668 void Run(Solver* const s) override { (constraint_->*method_)(); }
669
672 }
674 std::string DebugString() const override {
675 return "DelayedCallMethod_" + name_ + "(" + constraint_->DebugString() +
676 ")";
678
679 private:
680 T* const constraint_;
681 void (T::*const method_)();
682 const std::string name_;
683};
684
685template <class T>
686Demon* MakeDelayedConstraintDemon0(Solver* const s, T* const ct,
687 void (T::*method)(),
688 const std::string& name) {
689 return s->RevAlloc(new DelayedCallMethod0<T>(ct, method, name));
690}
691
693template <class T, class P>
694class DelayedCallMethod1 : public Demon {
695 public:
696 DelayedCallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
697 P param1)
698 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
699
700 ~DelayedCallMethod1() override {}
702 void Run(Solver* const s) override { (constraint_->*method_)(param1_); }
704 Solver::DemonPriority priority() const override {
706 }
708 std::string DebugString() const override {
709 return absl::StrCat("DelayedCallMethod_", name_, "(",
710 constraint_->DebugString(), ", ",
711 ParameterDebugString(param1_), ")");
712 }
713
714 private:
715 T* const constraint_;
716 void (T::*const method_)(P);
717 const std::string name_;
718 P param1_;
719};
720
721template <class T, class P>
722Demon* MakeDelayedConstraintDemon1(Solver* const s, T* const ct,
723 void (T::*method)(P),
724 const std::string& name, P param1) {
725 return s->RevAlloc(new DelayedCallMethod1<T, P>(ct, method, name, param1));
726}
727
729template <class T, class P, class Q>
730class DelayedCallMethod2 : public Demon {
731 public:
732 DelayedCallMethod2(T* const ct, void (T::*method)(P, Q),
733 const std::string& name, P param1, Q param2)
734 : constraint_(ct),
735 method_(method),
736 name_(name),
737 param1_(param1),
738 param2_(param2) {}
740 ~DelayedCallMethod2() override {}
741
742 void Run(Solver* const s) override {
743 (constraint_->*method_)(param1_, param2_);
744 }
745
746 Solver::DemonPriority priority() const override {
748 }
750 std::string DebugString() const override {
751 return absl::StrCat(absl::StrCat("DelayedCallMethod_", name_),
752 absl::StrCat("(", constraint_->DebugString()),
753 absl::StrCat(", ", ParameterDebugString(param1_)),
754 absl::StrCat(", ", ParameterDebugString(param2_), ")"));
755 }
756
757 private:
758 T* const constraint_;
759 void (T::*const method_)(P, Q);
760 const std::string name_;
761 P param1_;
762 Q param2_;
763};
764
765template <class T, class P, class Q>
766Demon* MakeDelayedConstraintDemon2(Solver* const s, T* const ct,
767 void (T::*method)(P, Q),
768 const std::string& name, P param1,
769 Q param2) {
770 return s->RevAlloc(
771 new DelayedCallMethod2<T, P, Q>(ct, method, name, param1, param2));
772}
774
775#endif // !defined(SWIG)
776
777// ----- LightIntFunctionElementCt -----
778
779template <typename F>
780class LightIntFunctionElementCt : public Constraint {
781 public:
782 LightIntFunctionElementCt(Solver* const solver, IntVar* const var,
783 IntVar* const index, F values,
784 std::function<bool()> deep_serialize)
786 var_(var),
787 index_(index),
788 values_(std::move(values)),
789 deep_serialize_(std::move(deep_serialize)) {}
790 ~LightIntFunctionElementCt() override {}
791
792 void Post() override {
793 Demon* demon = MakeConstraintDemon0(
794 solver(), this, &LightIntFunctionElementCt::IndexBound, "IndexBound");
795 index_->WhenBound(demon);
796 }
798 void InitialPropagate() override {
799 if (index_->Bound()) {
800 IndexBound();
801 }
802 }
803
804 std::string DebugString() const override {
805 return absl::StrFormat("LightIntFunctionElementCt(%s, %s)",
806 var_->DebugString(), index_->DebugString());
807 }
808
809 void Accept(ModelVisitor* const visitor) const override {
815 // Warning: This will expand all values into a vector.
816 if (deep_serialize_ == nullptr || deep_serialize_()) {
817 visitor->VisitInt64ToInt64Extension(values_, index_->Min(),
818 index_->Max());
819 }
821 }
822
823 private:
824 void IndexBound() { var_->SetValue(values_(index_->Min())); }
825
826 IntVar* const var_;
827 IntVar* const index_;
828 F values_;
829 std::function<bool()> deep_serialize_;
830};
831
832// ----- LightIntIntFunctionElementCt -----
833
834template <typename F>
835class LightIntIntFunctionElementCt : public Constraint {
836 public:
837 LightIntIntFunctionElementCt(Solver* const solver, IntVar* const var,
838 IntVar* const index1, IntVar* const index2,
839 F values, std::function<bool()> deep_serialize)
841 var_(var),
842 index1_(index1),
843 index2_(index2),
844 values_(std::move(values)),
845 deep_serialize_(std::move(deep_serialize)) {}
847 void Post() override {
848 Demon* demon = MakeConstraintDemon0(
849 solver(), this, &LightIntIntFunctionElementCt::IndexBound,
850 "IndexBound");
851 index1_->WhenBound(demon);
852 index2_->WhenBound(demon);
854 void InitialPropagate() override { IndexBound(); }
855
856 std::string DebugString() const override {
857 return "LightIntIntFunctionElementCt";
858 }
859
860 void Accept(ModelVisitor* const visitor) const override {
861 visitor->BeginVisitConstraint(ModelVisitor::kLightElementEqual, this);
862 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
863 var_);
864 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndexArgument,
865 index1_);
866 visitor->VisitIntegerExpressionArgument(ModelVisitor::kIndex2Argument,
867 index2_);
868 // Warning: This will expand all values into a vector.
869 const int64_t index1_min = index1_->Min();
870 const int64_t index1_max = index1_->Max();
871 visitor->VisitIntegerArgument(ModelVisitor::kMinArgument, index1_min);
872 visitor->VisitIntegerArgument(ModelVisitor::kMaxArgument, index1_max);
873 if (deep_serialize_ == nullptr || deep_serialize_()) {
874 for (int i = index1_min; i <= index1_max; ++i) {
875 visitor->VisitInt64ToInt64Extension(
876 [this, i](int64_t j) { return values_(i, j); }, index2_->Min(),
877 index2_->Max());
878 }
879 }
880 visitor->EndVisitConstraint(ModelVisitor::kLightElementEqual, this);
881 }
882
883 private:
884 void IndexBound() {
885 if (index1_->Bound() && index2_->Bound()) {
886 var_->SetValue(values_(index1_->Min(), index2_->Min()));
887 }
888 }
889
890 IntVar* const var_;
891 IntVar* const index1_;
892 IntVar* const index2_;
894 std::function<bool()> deep_serialize_;
895};
896
914// TODO(user): rename Start to Synchronize ?
915// TODO(user): decouple the iterating from the defining of a neighbor.
916class LocalSearchOperator : public BaseObject {
917 public:
919 ~LocalSearchOperator() override {}
920 virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) = 0;
921 virtual void Start(const Assignment* assignment) = 0;
922 virtual void Reset() {}
923#ifndef SWIG
924 virtual const LocalSearchOperator* Self() const { return this; }
925#endif // SWIG
926 virtual bool HasFragments() const { return false; }
927 virtual bool HoldsDelta() const { return false; }
928};
931 public:
935 max_inversible_index_ = candidate_values_.size();
936 candidate_value_to_index_.resize(max_value + 1, -1);
937 committed_value_to_index_.resize(max_value + 1, -1);
939
942 int64_t CandidateValue(int64_t index) const {
943 DCHECK_LT(index, candidate_values_.size());
944 return candidate_values_[index];
946 int64_t CommittedValue(int64_t index) const {
947 return committed_values_[index];
948 }
949 int64_t CheckPointValue(int64_t index) const {
950 return checkpoint_values_[index];
951 }
952 void SetCandidateValue(int64_t index, int64_t value) {
953 candidate_values_[index] = value;
954 if (index < max_inversible_index_) {
955 candidate_value_to_index_[value] = index;
956 }
957 MarkChange(index);
958 }
959
960 bool CandidateIsActive(int64_t index) const {
961 return candidate_is_active_[index];
962 }
963 void SetCandidateActive(int64_t index, bool active) {
964 if (active) {
965 candidate_is_active_.Set(index);
966 } else {
967 candidate_is_active_.Clear(index);
968 }
969 MarkChange(index);
970 }
972 void Commit() {
973 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
974 const int64_t value = candidate_values_[index];
975 committed_values_[index] = value;
976 if (index < max_inversible_index_) {
977 committed_value_to_index_[value] = index;
978 }
979 committed_is_active_.CopyBucket(candidate_is_active_, index);
980 }
981 changes_.SparseClearAll();
982 incremental_changes_.SparseClearAll();
984
985 void CheckPoint() { checkpoint_values_ = committed_values_; }
986
987 void Revert(bool only_incremental) {
988 incremental_changes_.SparseClearAll();
989 if (only_incremental) return;
990
991 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
992 const int64_t committed_value = committed_values_[index];
993 candidate_values_[index] = committed_value;
994 if (index < max_inversible_index_) {
995 candidate_value_to_index_[committed_value] = index;
997 candidate_is_active_.CopyBucket(committed_is_active_, index);
999 changes_.SparseClearAll();
1000 }
1001
1002 const std::vector<int64_t>& CandidateIndicesChanged() const {
1003 return changes_.PositionsSetAtLeastOnce();
1004 }
1005 const std::vector<int64_t>& IncrementalIndicesChanged() const {
1006 return incremental_changes_.PositionsSetAtLeastOnce();
1007 }
1008
1009 void Resize(int size) {
1010 candidate_values_.resize(size);
1011 committed_values_.resize(size);
1012 checkpoint_values_.resize(size);
1013 candidate_is_active_.Resize(size);
1014 committed_is_active_.Resize(size);
1015 changes_.ClearAndResize(size);
1016 incremental_changes_.ClearAndResize(size);
1017 }
1018
1019 int64_t CandidateInverseValue(int64_t value) const {
1020 return candidate_value_to_index_[value];
1021 }
1022 int64_t CommittedInverseValue(int64_t value) const {
1023 return committed_value_to_index_[value];
1024 }
1025
1026 private:
1027 void MarkChange(int64_t index) {
1028 incremental_changes_.Set(index);
1029 changes_.Set(index);
1031
1032 std::vector<int64_t> candidate_values_;
1033 std::vector<int64_t> committed_values_;
1034 std::vector<int64_t> checkpoint_values_;
1035
1036 Bitset64<> candidate_is_active_;
1037 Bitset64<> committed_is_active_;
1038
1039 SparseBitset<> changes_;
1040 SparseBitset<> incremental_changes_;
1041
1042 int64_t max_inversible_index_ = -1;
1043 std::vector<int64_t> candidate_value_to_index_;
1044 std::vector<int64_t> committed_value_to_index_;
1045};
1046
1053 public:
1054 // If keep_inverse_values is true, assumes that vars models an injective
1055 // function f with domain [0, vars.size()) in which case the operator will
1056 // maintain the inverse function.
1057 explicit IntVarLocalSearchOperator(const std::vector<IntVar*>& vars,
1058 bool keep_inverse_values = false) {
1059 AddVars(vars);
1060 if (keep_inverse_values) {
1061 int64_t max_value = -1;
1062 for (const IntVar* const var : vars) {
1063 max_value = std::max(max_value, var->Max());
1064 }
1066 }
1067 }
1069
1070 bool HoldsDelta() const override { return true; }
1073 void Start(const Assignment* assignment) override {
1074 state_.CheckPoint();
1075 RevertChanges(false);
1076 const int size = Size();
1077 CHECK_LE(size, assignment->Size())
1078 << "Assignment contains fewer variables than operator";
1079 const Assignment::IntContainer& container = assignment->IntVarContainer();
1080 for (int i = 0; i < size; ++i) {
1081 const IntVarElement* element = &(container.Element(i));
1082 if (element->Var() != vars_[i]) {
1083 CHECK(container.Contains(vars_[i]))
1084 << "Assignment does not contain operator variable " << vars_[i];
1085 element = &(container.Element(vars_[i]));
1086 }
1087 state_.SetCandidateValue(i, element->Value());
1088 state_.SetCandidateActive(i, element->Activated());
1089 }
1090 state_.Commit();
1091 OnStart();
1092 }
1093 virtual bool IsIncremental() const { return false; }
1094
1095 int Size() const { return vars_.size(); }
1098 int64_t Value(int64_t index) const {
1099 DCHECK_LT(index, vars_.size());
1100 return state_.CandidateValue(index);
1101 }
1103 IntVar* Var(int64_t index) const { return vars_[index]; }
1104 virtual bool SkipUnchanged(int index) const { return false; }
1105 int64_t OldValue(int64_t index) const { return state_.CommittedValue(index); }
1106 int64_t PrevValue(int64_t index) const {
1107 return state_.CheckPointValue(index);
1108 }
1109 void SetValue(int64_t index, int64_t value) {
1110 state_.SetCandidateValue(index, value);
1111 }
1112 bool Activated(int64_t index) const {
1113 return state_.CandidateIsActive(index);
1115 void Activate(int64_t index) { state_.SetCandidateActive(index, true); }
1116 void Deactivate(int64_t index) { state_.SetCandidateActive(index, false); }
1118 bool ApplyChanges(Assignment* delta, Assignment* deltadelta) const {
1119 if (IsIncremental() && candidate_has_changes_) {
1120 for (const int64_t index : state_.IncrementalIndicesChanged()) {
1121 IntVar* var = Var(index);
1122 const int64_t value = Value(index);
1123 const bool activated = Activated(index);
1124 AddToAssignment(var, value, activated, nullptr, index, deltadelta);
1125 AddToAssignment(var, value, activated, &assignment_indices_, index,
1128 } else {
1129 delta->Clear();
1130 for (const int64_t index : state_.CandidateIndicesChanged()) {
1131 const int64_t value = Value(index);
1132 const bool activated = Activated(index);
1133 if (!activated || value != OldValue(index) || !SkipUnchanged(index)) {
1134 AddToAssignment(Var(index), value, activated, &assignment_indices_,
1135 index, delta);
1136 }
1137 }
1138 }
1139 return true;
1140 }
1141
1142 void RevertChanges(bool change_was_incremental) {
1143 candidate_has_changes_ = change_was_incremental && IsIncremental();
1144
1145 if (!candidate_has_changes_) {
1146 for (const int64_t index : state_.CandidateIndicesChanged()) {
1147 assignment_indices_[index] = -1;
1148 }
1149 }
1150 state_.Revert(candidate_has_changes_);
1151 }
1152
1153 void AddVars(const std::vector<IntVar*>& vars) {
1154 if (!vars.empty()) {
1155 vars_.insert(vars_.end(), vars.begin(), vars.end());
1156 const int64_t size = Size();
1157 assignment_indices_.resize(size, -1);
1158 state_.Resize(size);
1159 }
1160 }
1161
1165 virtual void OnStart() {}
1166
1169
1176 bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
1177
1178 protected:
1181 // TODO(user): make it pure virtual, implies porting all apps overriding
1183 virtual bool MakeOneNeighbor();
1184
1185 int64_t InverseValue(int64_t index) const {
1186 return state_.CandidateInverseValue(index);
1187 }
1188 int64_t OldInverseValue(int64_t index) const {
1189 return state_.CommittedInverseValue(index);
1190 }
1191
1192 void AddToAssignment(IntVar* var, int64_t value, bool active,
1193 std::vector<int>* assignment_indices, int64_t index,
1194 Assignment* assignment) const {
1195 Assignment::IntContainer* const container =
1196 assignment->MutableIntVarContainer();
1197 IntVarElement* element = nullptr;
1198 if (assignment_indices != nullptr) {
1199 if ((*assignment_indices)[index] == -1) {
1200 (*assignment_indices)[index] = container->Size();
1201 element = assignment->FastAdd(var);
1202 } else {
1203 element = container->MutableElement((*assignment_indices)[index]);
1204 }
1205 } else {
1206 element = assignment->FastAdd(var);
1207 }
1208 if (active) {
1209 element->SetValue(value);
1210 element->Activate();
1211 } else {
1212 element->Deactivate();
1213 }
1214 }
1215
1216 private:
1217 std::vector<IntVar*> vars_;
1218 mutable std::vector<int> assignment_indices_;
1219 bool candidate_has_changes_ = false;
1220
1221 LocalSearchOperatorState state_;
1222};
1223
1251class BaseLns : public IntVarLocalSearchOperator {
1252 public:
1253 explicit BaseLns(const std::vector<IntVar*>& vars);
1254 ~BaseLns() override;
1255 virtual void InitFragments();
1256 virtual bool NextFragment() = 0;
1257 void AppendToFragment(int index);
1258 int FragmentSize() const;
1259 bool HasFragments() const override { return true; }
1260
1261 protected:
1263 bool MakeOneNeighbor() override;
1264
1265 private:
1267 void OnStart() override;
1268 std::vector<int> fragment_;
1269};
1276 public:
1277 explicit ChangeValue(const std::vector<IntVar*>& vars);
1278 ~ChangeValue() override;
1279 virtual int64_t ModifyValue(int64_t index, int64_t value) = 0;
1280
1281 protected:
1283 bool MakeOneNeighbor() override;
1284
1285 private:
1286 void OnStart() override;
1287
1288 int index_;
1290
1305 public:
1307 struct IterationParameters {
1325 std::function<int(int64_t)> start_empty_path_class;
1327 std::function<const std::vector<int>&(/*node=*/int, /*start_node=*/int)>
1329 };
1331 PathOperator(const std::vector<IntVar*>& next_vars,
1332 const std::vector<IntVar*>& path_vars,
1333 IterationParameters iteration_parameters);
1334 PathOperator(const std::vector<IntVar*>& next_vars,
1335 const std::vector<IntVar*>& path_vars, int number_of_base_nodes,
1336 bool skip_locally_optimal_paths, bool accept_path_end_base,
1337 std::function<int(int64_t)> start_empty_path_class,
1338 std::function<const std::vector<int>&(int, int)> get_neighbors)
1339 : PathOperator(next_vars, path_vars,
1340 {number_of_base_nodes, skip_locally_optimal_paths,
1341 accept_path_end_base, std::move(start_empty_path_class),
1342 std::move(get_neighbors)}) {}
1343 ~PathOperator() override {}
1344 virtual bool MakeNeighbor() = 0;
1345 void Reset() override;
1346
1347 // TODO(user): Make the following methods protected.
1348 bool SkipUnchanged(int index) const override;
1349
1351 int64_t Next(int64_t node) const {
1352 DCHECK(!IsPathEnd(node));
1353 return Value(node);
1354 }
1355
1357 int64_t Prev(int64_t node) const {
1358 DCHECK(!IsPathStart(node));
1359 DCHECK_EQ(Next(InverseValue(node)), node);
1360 return InverseValue(node);
1361 }
1362
1365 int64_t Path(int64_t node) const {
1366 return ignore_path_vars_ ? 0LL : Value(node + number_of_nexts_);
1367 }
1368
1370 int number_of_nexts() const { return number_of_nexts_; }
1372 protected:
1374 bool MakeOneNeighbor() override;
1378 virtual void OnNodeInitialization() {}
1381 int64_t BaseNode(int i) const { return base_nodes_[i]; }
1383 int BaseAlternative(int i) const { return base_alternatives_[i]; }
1385 int64_t BaseAlternativeNode(int i) const {
1386 if (!ConsiderAlternatives(i)) return BaseNode(i);
1387 const int alternative_index = alternative_index_[BaseNode(i)];
1388 return alternative_index >= 0
1389 ? alternative_sets_[alternative_index][base_alternatives_[i]]
1390 : BaseNode(i);
1391 }
1393 int BaseSiblingAlternative(int i) const {
1394 return base_sibling_alternatives_[i];
1397 int64_t BaseSiblingAlternativeNode(int i) const {
1398 if (!ConsiderAlternatives(i)) return BaseNode(i);
1399 const int sibling_alternative_index =
1401 return sibling_alternative_index >= 0
1402 ? alternative_sets_[sibling_alternative_index]
1403 [base_sibling_alternatives_[i]]
1404 : BaseNode(i);
1405 }
1407 int64_t StartNode(int i) const { return path_starts_[base_paths_[i]]; }
1409 int64_t EndNode(int i) const { return path_ends_[base_paths_[i]]; }
1411 const std::vector<int64_t>& path_starts() const { return path_starts_; }
1413 int PathClass(int i) const { return PathClassFromStartNode(StartNode(i)); }
1414 int PathClassFromStartNode(int64_t start_node) const {
1415 return iteration_parameters_.start_empty_path_class != nullptr
1416 ? iteration_parameters_.start_empty_path_class(start_node)
1417 : start_node;
1418 }
1419
1426 // TODO(user): remove this when automatic detection of such cases in done.
1427 virtual bool RestartAtPathStartOnSynchronize() { return false; }
1431 // TODO(user): ideally this should be OnSamePath(int64_t node1, int64_t
1432 // node2);
1434 virtual bool OnSamePathAsPreviousBase(int64_t base_index) { return false; }
1440 virtual int64_t GetBaseNodeRestartPosition(int base_index) {
1441 return StartNode(base_index);
1442 }
1445 virtual void SetNextBaseToIncrement(int64_t base_index) {
1446 next_base_to_increment_ = base_index;
1447 }
1450 virtual bool ConsiderAlternatives(int64_t base_index) const { return false; }
1451
1452 int64_t OldNext(int64_t node) const {
1453 DCHECK(!IsPathEnd(node));
1454 return OldValue(node);
1455 }
1456
1457 int64_t PrevNext(int64_t node) const {
1458 DCHECK(!IsPathEnd(node));
1459 return PrevValue(node);
1460 }
1461
1462 int64_t OldPrev(int64_t node) const {
1463 DCHECK(!IsPathStart(node));
1464 return OldInverseValue(node);
1465 }
1467 int64_t OldPath(int64_t node) const {
1468 return ignore_path_vars_ ? 0LL : OldValue(node + number_of_nexts_);
1469 }
1470
1471 int CurrentNodePathStart(int64_t node) const {
1472 return node_path_starts_[node];
1473 }
1474
1475 int CurrentNodePathEnd(int64_t node) const { return node_path_ends_[node]; }
1479 bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination);
1480
1483 bool ReverseChain(int64_t before_chain, int64_t after_chain,
1484 int64_t* chain_last);
1487 bool MakeActive(int64_t node, int64_t destination);
1490 bool MakeChainInactive(int64_t before_chain, int64_t chain_end);
1492 bool SwapActiveAndInactive(int64_t active, int64_t inactive);
1493
1495 void SetNext(int64_t from, int64_t to, int64_t path) {
1496 DCHECK_LT(from, number_of_nexts_);
1497 SetValue(from, to);
1498 if (!ignore_path_vars_) {
1499 DCHECK_LT(from + number_of_nexts_, Size());
1500 SetValue(from + number_of_nexts_, path);
1501 }
1502 }
1503
1506 bool IsPathEnd(int64_t node) const { return node >= number_of_nexts_; }
1507
1509 bool IsPathStart(int64_t node) const { return OldInverseValue(node) == -1; }
1510
1512 bool IsInactive(int64_t node) const {
1513 return !IsPathEnd(node) && inactives_[node];
1514 }
1515
1518 virtual bool InitPosition() const { return false; }
1522 void ResetPosition() { just_started_ = true; }
1527 int AddAlternativeSet(const std::vector<int64_t>& alternative_set) {
1528 const int alternative = alternative_sets_.size();
1529 for (int64_t node : alternative_set) {
1530 DCHECK_EQ(-1, alternative_index_[node]);
1531 alternative_index_[node] = alternative;
1533 alternative_sets_.push_back(alternative_set);
1534 sibling_alternative_.push_back(-1);
1535 return alternative;
1537#ifndef SWIG
1540 template <typename PairType>
1542 const std::vector<PairType>& pair_alternative_sets) {
1543 for (const auto& [alternative_set, sibling_alternative_set] :
1544 pair_alternative_sets) {
1545 sibling_alternative_.back() = AddAlternativeSet(alternative_set) + 1;
1546 AddAlternativeSet(sibling_alternative_set);
1547 }
1548 }
1549#endif // SWIG
1551 int64_t GetActiveInAlternativeSet(int alternative_index) const {
1552 return alternative_index >= 0
1553 ? active_in_alternative_set_[alternative_index]
1554 : -1;
1557 int64_t GetActiveAlternativeNode(int node) const {
1558 return GetActiveInAlternativeSet(alternative_index_[node]);
1559 }
1561 int GetSiblingAlternativeIndex(int node) const {
1562 if (node >= alternative_index_.size()) return -1;
1563 const int alternative = alternative_index_[node];
1564 return alternative >= 0 ? sibling_alternative_[alternative] : -1;
1568 int64_t GetActiveAlternativeSibling(int node) const {
1569 if (node >= alternative_index_.size()) return -1;
1570 const int alternative = alternative_index_[node];
1571 const int sibling_alternative =
1572 alternative >= 0 ? sibling_alternative_[alternative] : -1;
1573 return GetActiveInAlternativeSet(sibling_alternative);
1574 }
1577 bool CheckChainValidity(int64_t before_chain, int64_t chain_end,
1578 int64_t exclude) const;
1579
1580 bool HasNeighbors() const {
1581 return iteration_parameters_.get_neighbors != nullptr;
1583
1584 int GetNeighborForBaseNode(int64_t base_index) const {
1585 DCHECK(HasNeighbors());
1586 return iteration_parameters_.get_neighbors(
1587 BaseNode(base_index),
1588 StartNode(base_index))[calls_per_base_node_[base_index]];
1589 }
1590
1591 const int number_of_nexts_;
1592 const bool ignore_path_vars_;
1593
1594 private:
1595 void OnStart() override;
1597 bool OnSamePath(int64_t node1, int64_t node2) const;
1599 bool CheckEnds() const {
1600 const int base_node_size = base_nodes_.size();
1601 for (int i = base_node_size - 1; i >= 0; --i) {
1602 if (base_nodes_[i] != end_nodes_[i] || calls_per_base_node_[0] > 0) {
1603 return true;
1604 }
1606 return false;
1607 }
1608 bool IncrementPosition();
1609 void InitializePathStarts();
1610 void InitializeInactives();
1611 void InitializeBaseNodes();
1612 void InitializeAlternatives();
1613 void Synchronize();
1614
1615 class ActivePaths {
1616 public:
1617 explicit ActivePaths(int num_nodes) : start_to_path_(num_nodes, -1) {}
1618 void Clear() { is_path_pair_active_.clear(); }
1619 template <typename T>
1620 void Initialize(T is_start) {
1621 if (is_path_pair_active_.empty()) {
1622 num_paths_ = 0;
1623 absl::c_fill(start_to_path_, -1);
1624 for (int i = 0; i < start_to_path_.size(); ++i) {
1625 if (is_start(i)) {
1626 start_to_path_[i] = num_paths_;
1627 ++num_paths_;
1628 }
1629 }
1630 is_path_pair_active_.resize(num_paths_ * num_paths_, true);
1631 }
1632 }
1633 void DeactivatePathPair(int start1, int start2) {
1634 is_path_pair_active_[start_to_path_[start1] * num_paths_ +
1635 start_to_path_[start2]] = false;
1636 }
1637 void ActivatePath(int start) {
1638 const int p1 = start_to_path_[start];
1639 const int p1_block = num_paths_ * p1;
1640 for (int p2 = 0; p2 < num_paths_; ++p2) {
1641 is_path_pair_active_[p1_block + p2] = true;
1642 }
1643 for (int p2_block = 0; p2_block < is_path_pair_active_.size();
1644 p2_block += num_paths_) {
1645 is_path_pair_active_[p2_block + p1] = true;
1646 }
1647 }
1648 bool IsPathPairActive(int start1, int start2) const {
1649 return is_path_pair_active_[start_to_path_[start1] * num_paths_ +
1650 start_to_path_[start2]];
1651 }
1652
1653 private:
1654 int num_paths_ = 0;
1655 std::vector<int64_t> start_to_path_;
1656 std::vector<bool> is_path_pair_active_;
1657 };
1658
1659 std::vector<int> base_nodes_;
1660 std::vector<int> base_alternatives_;
1661 std::vector<int> base_sibling_alternatives_;
1662 std::vector<int> end_nodes_;
1663 std::vector<int> base_paths_;
1664 std::vector<int> node_path_starts_;
1665 std::vector<int> node_path_ends_;
1666 std::vector<int> calls_per_base_node_;
1667 std::vector<int64_t> path_starts_;
1668 std::vector<int64_t> path_ends_;
1669 std::vector<bool> inactives_;
1670 bool just_started_;
1671 bool first_start_;
1672 int next_base_to_increment_;
1673 IterationParameters iteration_parameters_;
1674 bool optimal_paths_enabled_;
1675 std::vector<int> path_basis_;
1676 ActivePaths active_paths_;
1678#ifndef SWIG
1679 std::vector<std::vector<int64_t>> alternative_sets_;
1680#endif // SWIG
1681 std::vector<int> alternative_index_;
1682 std::vector<int64_t> active_in_alternative_set_;
1683 std::vector<int> sibling_alternative_;
1684};
1685
1687template <class T>
1688LocalSearchOperator* MakeLocalSearchOperator(
1689 Solver* solver, const std::vector<IntVar*>& vars,
1690 const std::vector<IntVar*>& secondary_vars,
1691 std::function<int(int64_t)> start_empty_path_class);
1692
1693template <class T>
1694LocalSearchOperator* MakeLocalSearchOperatorWithNeighbors(
1695 Solver* solver, const std::vector<IntVar*>& vars,
1696 const std::vector<IntVar*>& secondary_vars,
1697 std::function<int(int64_t)> start_empty_path_class,
1698 std::function<const std::vector<int>&(int, int)> get_neighbors);
1699
1714
1715#if !defined(SWIG)
1716// After building a Directed Acyclic Graph, allows to generate sub-DAGs
1717// reachable from a node.
1718// Workflow:
1719// - Call AddArc() repeatedly to add arcs describing a DAG. Nodes are allocated
1720// on the user side, they must be nonnegative, and it is better but not
1721// mandatory for the set of nodes to be dense.
1722// - Call BuildGraph(). This precomputes all the information needed to make
1723// subsequent requests for sub-DAGs.
1724// - Call ComputeSortedSubDagArcs(node). This returns a view to arcs reachable
1725// from node, in topological order.
1726// All arcs must be added before calling BuildGraph(),
1727// and ComputeSortedSubDagArcs() can only be called after BuildGraph().
1728// If the arcs form a graph that has directed cycles,
1729// - in debug mode, BuildGraph() will crash.
1730// - otherwise, BuildGraph() will not crash, but ComputeSortedSubDagArcs()
1731// will only return a subset of arcs reachable by the given node.
1732class SubDagComputer {
1733 public:
1734 DEFINE_STRONG_INT_TYPE(ArcId, int);
1735 DEFINE_STRONG_INT_TYPE(NodeId, int);
1736 SubDagComputer() = default;
1737 // Adds an arc between node 'tail' and node 'head'. Nodes must be nonnegative.
1738 // Returns the index of the new arc, those are used to identify arcs when
1739 // calling ComputeSortedSubDagArcs().
1740 ArcId AddArc(NodeId tail, NodeId head) {
1741 DCHECK(!graph_was_built_);
1742 num_nodes_ = std::max(num_nodes_, std::max(tail.value(), head.value()) + 1);
1743 const ArcId arc_id(arcs_.size());
1744 arcs_.push_back({.tail = tail, .head = head, .arc_id = arc_id});
1745 return arc_id;
1747 // Finishes the construction of the DAG. 'num_nodes' is the number of nodes
1748 // in the DAG and must be greater than all node indices passed to AddArc().
1749 void BuildGraph(int num_nodes);
1750 // Computes the arcs of the sub-DAG reachable from node returns a view of
1751 // those arcs in topological order.
1752 const std::vector<ArcId>& ComputeSortedSubDagArcs(NodeId node);
1753
1754 private:
1755 // Checks whether the underlying graph has a directed cycle.
1756 // Should be called after the graph has been built.
1757 bool HasDirectedCycle() const;
1758
1759 struct Arc {
1760 NodeId tail;
1761 NodeId head;
1762 ArcId arc_id;
1763 bool operator<(const Arc& other) const {
1764 return std::tie(tail, arc_id) < std::tie(other.tail, other.arc_id);
1765 }
1766 };
1767 int num_nodes_ = 0;
1768 std::vector<Arc> arcs_;
1769 // Initialized by BuildGraph(), after which the outgoing arcs of node n are
1770 // the range from arcs_[arcs_of_node_[n]] included to
1771 // arcs_[arcs_of_node_[n+1]] excluded.
1773 // Must be false before BuildGraph() is called, true afterwards.
1774 bool graph_was_built_ = false;
1775 // Used by ComputeSortedSubDagArcs.
1777 // Used by ComputeSortedSubDagArcs.
1778 std::vector<NodeId> nodes_to_visit_;
1779 // Used as output, set up as a member to allow reuse.
1780 std::vector<ArcId> sorted_arcs_;
1781};
1782
1783// A LocalSearchState is a container for variables with domains that can be
1784// relaxed and tightened, saved and restored. It represents the solution state
1785// of a local search engine, and allows it to go from solution to solution by
1786// relaxing some variables to form a new subproblem, then tightening those
1787// variables to move to a new solution representation. That state may be saved
1788// to an internal copy, or reverted to the last saved internal copy.
1789// Relaxing a variable returns its bounds to their initial state.
1790// Tightening a variable's bounds may make its min larger than its max,
1791// in that case, the tightening function will return false, and the state will
1792// be marked as invalid. No other operations than Revert() can be called on an
1793// invalid state: in particular, an invalid state cannot be saved.
1794class LocalSearchState {
1795 public:
1796 class Variable;
1797 DEFINE_STRONG_INT_TYPE(VariableDomainId, int);
1798 DEFINE_STRONG_INT_TYPE(ConstraintId, int);
1799 // Adds a variable domain to this state, returns a handler to the new domain.
1800 VariableDomainId AddVariableDomain(int64_t relaxed_min, int64_t relaxed_max);
1801 void RelaxVariableDomain(VariableDomainId domain_id);
1802 bool TightenVariableDomainMin(VariableDomainId domain_id, int64_t value);
1803 bool TightenVariableDomainMax(VariableDomainId domain_id, int64_t value);
1804 int64_t VariableDomainMin(VariableDomainId domain_id) const;
1805 int64_t VariableDomainMax(VariableDomainId domain_id) const;
1806 void ChangeRelaxedVariableDomain(VariableDomainId domain_id, int64_t min,
1807 int64_t max);
1809 // Propagation of all events.
1810 void PropagateRelax(VariableDomainId domain_id);
1811 bool PropagateTighten(VariableDomainId domain_id);
1812 // Makes a variable, an object with restricted operations on the underlying
1813 // domain identified by domain_id: only Relax, Tighten and Min/Max read
1814 // operations are available.
1815 Variable MakeVariable(VariableDomainId domain_id);
1816 void Commit();
1817 void Revert();
1818 bool StateIsFeasible() const {
1819 return state_domains_are_all_nonempty_ && num_committed_empty_domains_ == 0;
1820 }
1821 // Adds a constraint that output = input_offset + sum_i weight_i * input_i.
1822 void AddWeightedSumConstraint(
1823 const std::vector<VariableDomainId>& input_domain_ids,
1824 const std::vector<int64_t>& input_weights, int64_t input_offset,
1825 VariableDomainId output_domain_id);
1826 // Precomputes which domain change triggers which constraint(s).
1827 // Should be run after adding all constraints, before any Relax()/Tighten().
1828 void CompileConstraints();
1829
1830 private:
1831 // VariableDomains implement the domain of Variables.
1832 // Those are trailed, meaning they are saved on their first modification,
1833 // and can be reverted or committed in O(1) per modification.
1834 struct VariableDomain {
1835 int64_t min;
1836 int64_t max;
1837 };
1838 bool IntersectionIsEmpty(const VariableDomain& d1,
1839 const VariableDomain& d2) const {
1840 return d1.max < d2.min || d2.max < d1.min;
1841 }
1844 struct TrailedVariableDomain {
1845 VariableDomain committed_domain;
1846 VariableDomainId domain_id;
1847 };
1848 std::vector<TrailedVariableDomain> trailed_domains_;
1850 // True iff all domains have their min <= max.
1851 bool state_domains_are_all_nonempty_ = true;
1852 bool state_has_relaxed_domains_ = false;
1853 // Number of domains d for which the intersection of
1854 // current_domains_[d] and relaxed_domains_[d] is empty.
1855 int num_committed_empty_domains_ = 0;
1856 int trailed_num_committed_empty_domains_ = 0;
1857
1858 // Constraints may be trailed too, they decide how to track their internal
1859 // structure.
1860 class Constraint;
1861 void TrailConstraint(Constraint* constraint) {
1862 trailed_constraints_.push_back(constraint);
1863 }
1864 std::vector<Constraint*> trailed_constraints_;
1865
1866 // Stores domain-constraint dependencies, allows to generate topological
1867 // orderings of dependency arcs reachable from nodes.
1868 class DependencyGraph {
1869 public:
1870 DependencyGraph() {}
1871 // There are two kinds of domain-constraint dependencies:
1872 // - domain -> constraint when the domain is an input to the constraint.
1873 // Then the label is the index of the domain in the input tuple.
1874 // - constraint -> domain when the domain is the output of the constraint.
1875 // Then, the label is -1.
1876 struct Dependency {
1877 VariableDomainId domain_id;
1878 int input_index;
1879 ConstraintId constraint_id;
1880 };
1881 // Adds all dependencies domains[i] -> constraint labelled by i.
1882 void AddDomainsConstraintDependencies(
1883 const std::vector<VariableDomainId>& domain_ids,
1884 ConstraintId constraint_id);
1885 // Adds a dependency domain -> constraint labelled by -1.
1886 void AddConstraintDomainDependency(ConstraintId constraint_id,
1887 VariableDomainId domain_id);
1888 // After all dependencies have been added,
1889 // builds the DAG representation that allows to compute sorted dependencies.
1890 void BuildDependencyDAG(int num_domains);
1891 // Returns a view on the list of arc dependencies reachable by given domain,
1892 // in some topological order of the overall DAG. Modifying the graph or
1893 // calling ComputeSortedDependencies() again invalidates the view.
1894 const std::vector<Dependency>& ComputeSortedDependencies(
1895 VariableDomainId domain_id);
1896
1897 private:
1898 using ArcId = SubDagComputer::ArcId;
1899 using NodeId = SubDagComputer::NodeId;
1900 // Returns dag_node_of_domain_[domain_id] if already defined,
1901 // or makes a node for domain_id, possibly extending dag_node_of_domain_.
1902 NodeId GetOrCreateNodeOfDomainId(VariableDomainId domain_id);
1903 // Returns dag_node_of_constraint_[constraint_id] if already defined,
1904 // or makes a node for constraint_id, possibly extending
1905 // dag_node_of_constraint_.
1906 NodeId GetOrCreateNodeOfConstraintId(ConstraintId constraint_id);
1907 // Structure of the expression DAG, used to buffer propagation storage.
1908 SubDagComputer dag_;
1909 // Maps arcs of dag_ to domain/constraint dependencies.
1910 util_intops::StrongVector<ArcId, Dependency> dependency_of_dag_arc_;
1911 // Maps domain ids to dag_ nodes.
1913 // Maps constraint ids to dag_ nodes.
1915 // Number of nodes currently allocated in dag_.
1916 // Reserve node 0 as a default dummy node with no dependencies.
1917 int num_dag_nodes_ = 1;
1918 // Used as reusable output of ComputeSortedDependencies().
1919 std::vector<Dependency> sorted_dependencies_;
1920 };
1921 DependencyGraph dependency_graph_;
1922
1923 // Propagation order storage: each domain change triggers constraints.
1924 // Each trigger tells a constraint that a domain changed, and identifies
1925 // the domain by the index in the list of the constraint's inputs.
1926 struct Trigger {
1927 Constraint* constraint;
1928 int input_index;
1929 };
1930 // Triggers of all constraints, concatenated.
1931 // The triggers of domain i are stored from triggers_of_domain_[i]
1932 // to triggers_of_domain_[i+1] excluded.
1933 std::vector<Trigger> triggers_;
1935
1936 // Constraints are used to form expressions that make up the objective.
1937 // Constraints are directed: they have inputs and an output, moreover the
1938 // constraint-domain graph must not have directed cycles.
1939 class Constraint {
1940 public:
1941 virtual ~Constraint() = default;
1942 virtual LocalSearchState::VariableDomain Propagate(int input_index) = 0;
1943 virtual VariableDomainId Output() const = 0;
1944 virtual void Commit() = 0;
1945 virtual void Revert() = 0;
1946 };
1947 // WeightedSum constraints enforces the equation:
1948 // output = offset + sum_i input_weights[i] * input_domain_ids[i]
1949 class WeightedSum final : public Constraint {
1950 public:
1951 WeightedSum(LocalSearchState* state,
1952 const std::vector<VariableDomainId>& input_domain_ids,
1953 const std::vector<int64_t>& input_weights, int64_t input_offset,
1954 VariableDomainId output);
1955 ~WeightedSum() override = default;
1956 LocalSearchState::VariableDomain Propagate(int input_index) override;
1957 void Commit() override;
1958 void Revert() override;
1959 VariableDomainId Output() const override { return output_; }
1960
1961 private:
1962 // Weighted variable holds a variable's domain, an associated weight,
1963 // and the variable's last known min and max.
1964 struct WeightedVariable {
1965 int64_t min;
1966 int64_t max;
1967 int64_t committed_min;
1968 int64_t committed_max;
1969 int64_t weight;
1970 VariableDomainId domain;
1971 bool is_trailed;
1972 void Commit() {
1973 committed_min = min;
1974 committed_max = max;
1975 is_trailed = false;
1976 }
1977 void Revert() {
1978 min = committed_min;
1979 max = committed_max;
1980 is_trailed = false;
1981 }
1982 };
1983 std::vector<WeightedVariable> inputs_;
1984 std::vector<WeightedVariable*> trailed_inputs_;
1985 // Invariants held by this constraint to allow O(1) propagation.
1986 struct Invariants {
1987 // Number of inputs_[i].min equal to kint64min.
1988 int64_t num_neg_inf;
1989 // Sum of inputs_[i].min that are different from kint64min.
1990 int64_t wsum_mins;
1991 // Number of inputs_[i].max equal to kint64max.
1992 int64_t num_pos_inf;
1993 // Sum of inputs_[i].max that are different from kint64max.
1994 int64_t wsum_maxs;
1995 };
1996 Invariants invariants_;
1997 Invariants committed_invariants_;
1998
1999 const VariableDomainId output_;
2000 LocalSearchState* const state_;
2001 bool constraint_is_trailed_ = false;
2002 };
2003 // Used to identify constraints and hold ownership.
2005};
2006
2007// A LocalSearchState Variable can only be created by a LocalSearchState,
2008// then it is meant to be passed by copy. If at some point the duplication of
2009// LocalSearchState pointers is too expensive, we could switch to index only,
2010// and the user would have to know the relevant state. The present setup allows
2011// to ensure that variable users will not misuse the state.
2012class LocalSearchState::Variable {
2013 public:
2014 int64_t Min() const { return state_->VariableDomainMin(domain_id_); }
2015 int64_t Max() const { return state_->VariableDomainMax(domain_id_); }
2016 bool SetMin(int64_t new_min) {
2017 return state_->TightenVariableDomainMin(domain_id_, new_min) &&
2018 state_->PropagateTighten(domain_id_);
2019 }
2020 bool SetMax(int64_t new_max) {
2021 return state_->TightenVariableDomainMax(domain_id_, new_max) &&
2022 state_->PropagateTighten(domain_id_);
2023 }
2024 void Relax() {
2025 state_->RelaxVariableDomain(domain_id_);
2026 state_->PropagateRelax(domain_id_);
2027 }
2029 private:
2030 // Only LocalSearchState can construct LocalSearchVariables.
2031 friend class LocalSearchState;
2032
2033 Variable(LocalSearchState* state, VariableDomainId domain_id)
2034 : state_(state), domain_id_(domain_id) {}
2035
2036 LocalSearchState* const state_;
2037 const VariableDomainId domain_id_;
2039#endif // !defined(SWIG)
2040
2057class LocalSearchFilter : public BaseObject {
2058 public:
2061 virtual void Relax(const Assignment* delta, const Assignment* deltadelta) {}
2063 virtual void Commit(const Assignment* delta, const Assignment* deltadelta) {}
2064
2074 virtual bool Accept(const Assignment* delta, const Assignment* deltadelta,
2075 int64_t objective_min, int64_t objective_max) = 0;
2076 virtual bool IsIncremental() const { return false; }
2083 virtual void Synchronize(const Assignment* assignment,
2084 const Assignment* delta) = 0;
2086 virtual void Revert() {}
2087
2089 virtual void Reset() {}
2092 virtual int64_t GetSynchronizedObjectiveValue() const { return 0LL; }
2094 // If the last Accept() call returned false, returns an undefined value.
2095 virtual int64_t GetAcceptedObjectiveValue() const { return 0LL; }
2096};
2101class LocalSearchFilterManager : public BaseObject {
2102 public:
2103 // This class is responsible for calling filters methods in a correct order.
2104 // For now, an order is specified explicitly by the user.
2105 enum FilterEventType { kAccept, kRelax };
2106 struct FilterEvent {
2107 LocalSearchFilter* filter;
2108 FilterEventType event_type;
2109 int priority;
2110 };
2111
2112 std::string DebugString() const override {
2113 return "LocalSearchFilterManager";
2114 }
2115 // Builds a manager that calls filter methods ordered by increasing priority.
2116 // Note that some filters might appear only once, if their Relax() or Accept()
2117 // are trivial.
2118 explicit LocalSearchFilterManager(std::vector<FilterEvent> filter_events);
2119 // Builds a manager that calls filter methods using the following ordering:
2120 // first Relax() in vector order, then Accept() in vector order.
2121 explicit LocalSearchFilterManager(std::vector<LocalSearchFilter*> filters);
2123 // Calls Revert() of filters, in reverse order of Relax events.
2124 void Revert();
2128 bool Accept(LocalSearchMonitor* monitor, const Assignment* delta,
2129 const Assignment* deltadelta, int64_t objective_min,
2130 int64_t objective_max);
2132 void Synchronize(const Assignment* assignment, const Assignment* delta);
2133 int64_t GetSynchronizedObjectiveValue() const { return synchronized_value_; }
2134 int64_t GetAcceptedObjectiveValue() const { return accepted_value_; }
2135
2136 private:
2137 // Finds the last event (incremental -itself- or not) with the same priority
2138 // as the last incremental event.
2139 void FindIncrementalEventEnd();
2140
2141 std::vector<FilterEvent> events_;
2142 int last_event_called_ = -1;
2143 // If a filter is incremental, its Relax() and Accept() must be called for
2144 // every candidate, even if the Accept() of a prior filter rejected it.
2145 // To ensure that those incremental filters have consistent inputs, all
2146 // intermediate events with Relax() must also be called.
2147 int incremental_events_end_ = 0;
2148 int64_t synchronized_value_;
2149 int64_t accepted_value_;
2150};
2151
2153 public:
2154 explicit IntVarLocalSearchFilter(const std::vector<IntVar*>& vars);
2155 ~IntVarLocalSearchFilter() override;
2158 void Synchronize(const Assignment* assignment,
2159 const Assignment* delta) override;
2160
2161 bool FindIndex(IntVar* const var, int64_t* index) const {
2162 DCHECK(index != nullptr);
2163 const int var_index = var->index();
2164 *index = (var_index < var_index_to_index_.size())
2165 ? var_index_to_index_[var_index]
2166 : kUnassigned;
2167 return *index != kUnassigned;
2168 }
2169
2171 void AddVars(const std::vector<IntVar*>& vars);
2172 int Size() const { return vars_.size(); }
2173 IntVar* Var(int index) const { return vars_[index]; }
2174 int64_t Value(int index) const {
2175 DCHECK(IsVarSynced(index));
2176 return values_[index];
2177 }
2178 bool IsVarSynced(int index) const { return var_synced_[index]; }
2179
2180 protected:
2181 virtual void OnSynchronize(const Assignment* delta) {}
2182 void SynchronizeOnAssignment(const Assignment* assignment);
2183
2184 private:
2185 std::vector<IntVar*> vars_;
2186 std::vector<int64_t> values_;
2187 std::vector<bool> var_synced_;
2188 std::vector<int> var_index_to_index_;
2189 static const int kUnassigned;
2190};
2191
2193 public:
2194 explicit PropagationMonitor(Solver* solver);
2196 std::string DebugString() const override { return "PropagationMonitor"; }
2197
2199 virtual void BeginConstraintInitialPropagation(Constraint* constraint) = 0;
2200 virtual void EndConstraintInitialPropagation(Constraint* constraint) = 0;
2201 virtual void BeginNestedConstraintInitialPropagation(Constraint* parent,
2202 Constraint* nested) = 0;
2203 virtual void EndNestedConstraintInitialPropagation(Constraint* parent,
2204 Constraint* nested) = 0;
2205 virtual void RegisterDemon(Demon* demon) = 0;
2206 virtual void BeginDemonRun(Demon* demon) = 0;
2207 virtual void EndDemonRun(Demon* demon) = 0;
2208 virtual void StartProcessingIntegerVariable(IntVar* var) = 0;
2209 virtual void EndProcessingIntegerVariable(IntVar* var) = 0;
2210 virtual void PushContext(const std::string& context) = 0;
2211 virtual void PopContext() = 0;
2213 virtual void SetMin(IntExpr* expr, int64_t new_min) = 0;
2214 virtual void SetMax(IntExpr* expr, int64_t new_max) = 0;
2215 virtual void SetRange(IntExpr* expr, int64_t new_min, int64_t new_max) = 0;
2217 virtual void SetMin(IntVar* var, int64_t new_min) = 0;
2218 virtual void SetMax(IntVar* var, int64_t new_max) = 0;
2219 virtual void SetRange(IntVar* var, int64_t new_min, int64_t new_max) = 0;
2220 virtual void RemoveValue(IntVar* var, int64_t value) = 0;
2221 virtual void SetValue(IntVar* var, int64_t value) = 0;
2222 virtual void RemoveInterval(IntVar* var, int64_t imin, int64_t imax) = 0;
2223 virtual void SetValues(IntVar* var, const std::vector<int64_t>& values) = 0;
2224 virtual void RemoveValues(IntVar* var,
2225 const std::vector<int64_t>& values) = 0;
2227 virtual void SetStartMin(IntervalVar* var, int64_t new_min) = 0;
2228 virtual void SetStartMax(IntervalVar* var, int64_t new_max) = 0;
2229 virtual void SetStartRange(IntervalVar* var, int64_t new_min,
2230 int64_t new_max) = 0;
2231 virtual void SetEndMin(IntervalVar* var, int64_t new_min) = 0;
2232 virtual void SetEndMax(IntervalVar* var, int64_t new_max) = 0;
2233 virtual void SetEndRange(IntervalVar* var, int64_t new_min,
2234 int64_t new_max) = 0;
2235 virtual void SetDurationMin(IntervalVar* var, int64_t new_min) = 0;
2236 virtual void SetDurationMax(IntervalVar* var, int64_t new_max) = 0;
2237 virtual void SetDurationRange(IntervalVar* var, int64_t new_min,
2238 int64_t new_max) = 0;
2239 virtual void SetPerformed(IntervalVar* var, bool value) = 0;
2241 virtual void RankFirst(SequenceVar* var, int index) = 0;
2242 virtual void RankNotFirst(SequenceVar* var, int index) = 0;
2243 virtual void RankLast(SequenceVar* var, int index) = 0;
2244 virtual void RankNotLast(SequenceVar* var, int index) = 0;
2245 virtual void RankSequence(SequenceVar* var,
2246 const std::vector<int>& rank_first,
2247 const std::vector<int>& rank_last,
2248 const std::vector<int>& unperformed) = 0;
2250 void Install() override;
2252
2254 // TODO(user): Add monitoring of local search filters.
2255 public:
2256 explicit LocalSearchMonitor(Solver* solver);
2258 std::string DebugString() const override { return "LocalSearchMonitor"; }
2261 virtual void BeginOperatorStart() = 0;
2262 virtual void EndOperatorStart() = 0;
2263 virtual void BeginMakeNextNeighbor(const LocalSearchOperator* op) = 0;
2264 virtual void EndMakeNextNeighbor(const LocalSearchOperator* op,
2265 bool neighbor_found, const Assignment* delta,
2266 const Assignment* deltadelta) = 0;
2267 virtual void BeginFilterNeighbor(const LocalSearchOperator* op) = 0;
2268 virtual void EndFilterNeighbor(const LocalSearchOperator* op,
2269 bool neighbor_found) = 0;
2270 virtual void BeginAcceptNeighbor(const LocalSearchOperator* op) = 0;
2271 virtual void EndAcceptNeighbor(const LocalSearchOperator* op,
2272 bool neighbor_found) = 0;
2273 virtual void BeginFiltering(const LocalSearchFilter* filter) = 0;
2274 virtual void EndFiltering(const LocalSearchFilter* filter, bool reject) = 0;
2276 virtual bool IsActive() const = 0;
2279 void Install() override;
2280};
2282class BooleanVar : public IntVar {
2283 public:
2284 static const int kUnboundBooleanVarValue;
2286 explicit BooleanVar(Solver* const s, const std::string& name = "")
2287 : IntVar(s, name), value_(kUnboundBooleanVarValue) {}
2289 ~BooleanVar() override {}
2291 int64_t Min() const override { return (value_ == 1); }
2292 void SetMin(int64_t m) override;
2293 int64_t Max() const override { return (value_ != 0); }
2294 void SetMax(int64_t m) override;
2295 void SetRange(int64_t mi, int64_t ma) override;
2296 bool Bound() const override { return (value_ != kUnboundBooleanVarValue); }
2297 int64_t Value() const override {
2298 CHECK_NE(value_, kUnboundBooleanVarValue) << "variable is not bound";
2299 return value_;
2301 void RemoveValue(int64_t v) override;
2302 void RemoveInterval(int64_t l, int64_t u) override;
2303 void WhenBound(Demon* d) override;
2304 void WhenRange(Demon* d) override { WhenBound(d); }
2305 void WhenDomain(Demon* d) override { WhenBound(d); }
2306 uint64_t Size() const override;
2307 bool Contains(int64_t v) const override;
2308 IntVarIterator* MakeHoleIterator(bool reversible) const override;
2309 IntVarIterator* MakeDomainIterator(bool reversible) const override;
2310 std::string DebugString() const override;
2311 int VarType() const override { return BOOLEAN_VAR; }
2312
2313 IntVar* IsEqual(int64_t constant) override;
2314 IntVar* IsDifferent(int64_t constant) override;
2315 IntVar* IsGreaterOrEqual(int64_t constant) override;
2316 IntVar* IsLessOrEqual(int64_t constant) override;
2317
2318 virtual void RestoreValue() = 0;
2319 std::string BaseName() const override { return "BooleanVar"; }
2320
2321 int RawValue() const { return value_; }
2322
2323 protected:
2324 int value_;
2326 SimpleRevFIFO<Demon*> delayed_bound_demons_;
2327};
2328
2329class SymmetryManager;
2330
2334class SymmetryBreaker : public DecisionVisitor {
2335 public:
2337 : symmetry_manager_(nullptr), index_in_symmetry_manager_(-1) {}
2338 ~SymmetryBreaker() override {}
2340 void AddIntegerVariableEqualValueClause(IntVar* var, int64_t value);
2341 void AddIntegerVariableGreaterOrEqualValueClause(IntVar* var, int64_t value);
2342 void AddIntegerVariableLessOrEqualValueClause(IntVar* var, int64_t value);
2343
2344 private:
2345 friend class SymmetryManager;
2346 void set_symmetry_manager_and_index(SymmetryManager* manager, int index) {
2347 CHECK(symmetry_manager_ == nullptr);
2348 CHECK_EQ(-1, index_in_symmetry_manager_);
2349 symmetry_manager_ = manager;
2350 index_in_symmetry_manager_ = index;
2351 }
2352 SymmetryManager* symmetry_manager() const { return symmetry_manager_; }
2353 int index_in_symmetry_manager() const { return index_in_symmetry_manager_; }
2354
2355 SymmetryManager* symmetry_manager_;
2357 int index_in_symmetry_manager_;
2358};
2362class SearchLog : public SearchMonitor {
2363 public:
2364 SearchLog(Solver* solver, std::vector<IntVar*> vars, std::string vars_name,
2365 std::vector<double> scaling_factors, std::vector<double> offsets,
2366 std::function<std::string()> display_callback,
2367 bool display_on_new_solutions_only, int period);
2368 ~SearchLog() override;
2369 void EnterSearch() override;
2370 void ExitSearch() override;
2371 bool AtSolution() override;
2372 void BeginFail() override;
2373 void NoMoreSolutions() override;
2374 void AcceptUncheckedNeighbor() override;
2375 void ApplyDecision(Decision* decision) override;
2376 void RefuteDecision(Decision* decision) override;
2377 void OutputDecision();
2378 void Maintain();
2379 void BeginInitialPropagation() override;
2380 void EndInitialPropagation() override;
2381 std::string DebugString() const override;
2382
2383 protected:
2384 /* Bottleneck function used for all UI related output. */
2385 virtual void OutputLine(const std::string& line);
2386
2387 private:
2388 static std::string MemoryUsage();
2389
2390 const int period_;
2391 std::unique_ptr<WallTimer> timer_;
2392 const std::vector<IntVar*> vars_;
2393 const std::string vars_name_;
2394 const std::vector<double> scaling_factors_;
2395 const std::vector<double> offsets_;
2396 std::function<std::string()> display_callback_;
2397 const bool display_on_new_solutions_only_;
2398 int nsol_;
2399 int64_t tick_;
2400 std::vector<int64_t> objective_min_;
2401 std::vector<int64_t> objective_max_;
2402 int min_right_depth_;
2403 int max_depth_;
2404 int sliding_min_depth_;
2405 int sliding_max_depth_;
2406 int neighbors_offset_ = 0;
2407};
2408
2413class ModelCache {
2414 public:
2415 enum VoidConstraintType {
2416 VOID_FALSE_CONSTRAINT = 0,
2417 VOID_TRUE_CONSTRAINT,
2418 VOID_CONSTRAINT_MAX,
2419 };
2420
2421 enum VarConstantConstraintType {
2422 VAR_CONSTANT_EQUALITY = 0,
2423 VAR_CONSTANT_GREATER_OR_EQUAL,
2424 VAR_CONSTANT_LESS_OR_EQUAL,
2425 VAR_CONSTANT_NON_EQUALITY,
2426 VAR_CONSTANT_CONSTRAINT_MAX,
2428
2430 VAR_CONSTANT_CONSTANT_BETWEEN = 0,
2431 VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX,
2433
2434 enum ExprExprConstraintType {
2435 EXPR_EXPR_EQUALITY = 0,
2436 EXPR_EXPR_GREATER,
2437 EXPR_EXPR_GREATER_OR_EQUAL,
2438 EXPR_EXPR_LESS,
2439 EXPR_EXPR_LESS_OR_EQUAL,
2440 EXPR_EXPR_NON_EQUALITY,
2441 EXPR_EXPR_CONSTRAINT_MAX,
2442 };
2445 EXPR_OPPOSITE = 0,
2446 EXPR_ABS,
2447 EXPR_SQUARE,
2448 EXPR_EXPRESSION_MAX,
2452 EXPR_EXPR_DIFFERENCE = 0,
2453 EXPR_EXPR_PROD,
2454 EXPR_EXPR_DIV,
2455 EXPR_EXPR_MAX,
2456 EXPR_EXPR_MIN,
2457 EXPR_EXPR_SUM,
2458 EXPR_EXPR_IS_LESS,
2459 EXPR_EXPR_IS_LESS_OR_EQUAL,
2460 EXPR_EXPR_IS_EQUAL,
2461 EXPR_EXPR_IS_NOT_EQUAL,
2462 EXPR_EXPR_EXPRESSION_MAX,
2463 };
2464
2466 EXPR_EXPR_CONSTANT_CONDITIONAL = 0,
2467 EXPR_EXPR_CONSTANT_EXPRESSION_MAX,
2471 EXPR_CONSTANT_DIFFERENCE = 0,
2472 EXPR_CONSTANT_DIVIDE,
2473 EXPR_CONSTANT_PROD,
2474 EXPR_CONSTANT_MAX,
2475 EXPR_CONSTANT_MIN,
2476 EXPR_CONSTANT_SUM,
2477 EXPR_CONSTANT_IS_EQUAL,
2478 EXPR_CONSTANT_IS_NOT_EQUAL,
2479 EXPR_CONSTANT_IS_GREATER_OR_EQUAL,
2480 EXPR_CONSTANT_IS_LESS_OR_EQUAL,
2481 EXPR_CONSTANT_EXPRESSION_MAX,
2482 };
2483 enum VarConstantConstantExpressionType {
2484 VAR_CONSTANT_CONSTANT_SEMI_CONTINUOUS = 0,
2485 VAR_CONSTANT_CONSTANT_EXPRESSION_MAX,
2489 VAR_CONSTANT_ARRAY_ELEMENT = 0,
2490 VAR_CONSTANT_ARRAY_EXPRESSION_MAX,
2494 VAR_ARRAY_CONSTANT_ARRAY_SCAL_PROD = 0,
2495 VAR_ARRAY_CONSTANT_ARRAY_EXPRESSION_MAX,
2496 };
2499 VAR_ARRAY_MAX = 0,
2500 VAR_ARRAY_MIN,
2501 VAR_ARRAY_SUM,
2502 VAR_ARRAY_EXPRESSION_MAX,
2506 VAR_ARRAY_CONSTANT_INDEX = 0,
2507 VAR_ARRAY_CONSTANT_EXPRESSION_MAX,
2510 explicit ModelCache(Solver* solver);
2511 virtual ~ModelCache();
2513 virtual void Clear() = 0;
2517 virtual Constraint* FindVoidConstraint(VoidConstraintType type) const = 0;
2518
2519 virtual void InsertVoidConstraint(Constraint* ct,
2523 virtual Constraint* FindVarConstantConstraint(
2524 IntVar* var, int64_t value, VarConstantConstraintType type) const = 0;
2525
2526 virtual void InsertVarConstantConstraint(Constraint* ct, IntVar* var,
2527 int64_t value,
2528 VarConstantConstraintType type) = 0;
2529
2532 virtual Constraint* FindVarConstantConstantConstraint(
2533 IntVar* var, int64_t value1, int64_t value2,
2534 VarConstantConstantConstraintType type) const = 0;
2535
2536 virtual void InsertVarConstantConstantConstraint(
2537 Constraint* ct, IntVar* var, int64_t value1, int64_t value2,
2539
2541
2542 virtual Constraint* FindExprExprConstraint(
2543 IntExpr* expr1, IntExpr* expr2, ExprExprConstraintType type) const = 0;
2544
2545 virtual void InsertExprExprConstraint(Constraint* ct, IntExpr* expr1,
2546 IntExpr* expr2,
2547 ExprExprConstraintType type) = 0;
2548
2551 virtual IntExpr* FindExprExpression(IntExpr* expr,
2552 ExprExpressionType type) const = 0;
2553
2554 virtual void InsertExprExpression(IntExpr* expression, IntExpr* expr,
2555 ExprExpressionType type) = 0;
2558
2559 virtual IntExpr* FindExprConstantExpression(
2560 IntExpr* expr, int64_t value, ExprConstantExpressionType type) const = 0;
2561
2562 virtual void InsertExprConstantExpression(
2563 IntExpr* expression, IntExpr* var, int64_t value,
2567
2568 virtual IntExpr* FindExprExprExpression(
2569 IntExpr* var1, IntExpr* var2, ExprExprExpressionType type) const = 0;
2570
2571 virtual void InsertExprExprExpression(IntExpr* expression, IntExpr* var1,
2572 IntExpr* var2,
2574
2577 virtual IntExpr* FindExprExprConstantExpression(
2578 IntExpr* var1, IntExpr* var2, int64_t constant,
2579 ExprExprConstantExpressionType type) const = 0;
2580
2581 virtual void InsertExprExprConstantExpression(
2582 IntExpr* expression, IntExpr* var1, IntExpr* var2, int64_t constant,
2584
2586
2587 virtual IntExpr* FindVarConstantConstantExpression(
2588 IntVar* var, int64_t value1, int64_t value2,
2589 VarConstantConstantExpressionType type) const = 0;
2590
2591 virtual void InsertVarConstantConstantExpression(
2592 IntExpr* expression, IntVar* var, int64_t value1, int64_t value2,
2594
2596
2597 virtual IntExpr* FindVarConstantArrayExpression(
2598 IntVar* var, const std::vector<int64_t>& values,
2599 VarConstantArrayExpressionType type) const = 0;
2600
2601 virtual void InsertVarConstantArrayExpression(
2602 IntExpr* expression, IntVar* var, const std::vector<int64_t>& values,
2604
2606
2607 virtual IntExpr* FindVarArrayExpression(
2608 const std::vector<IntVar*>& vars, VarArrayExpressionType type) const = 0;
2609
2610 virtual void InsertVarArrayExpression(IntExpr* expression,
2611 const std::vector<IntVar*>& vars,
2612 VarArrayExpressionType type) = 0;
2613
2616 virtual IntExpr* FindVarArrayConstantArrayExpression(
2617 const std::vector<IntVar*>& vars, const std::vector<int64_t>& values,
2619
2620 virtual void InsertVarArrayConstantArrayExpression(
2621 IntExpr* expression, const std::vector<IntVar*>& var,
2622 const std::vector<int64_t>& values,
2626
2627 virtual IntExpr* FindVarArrayConstantExpression(
2628 const std::vector<IntVar*>& vars, int64_t value,
2629 VarArrayConstantExpressionType type) const = 0;
2631 virtual void InsertVarArrayConstantExpression(
2632 IntExpr* expression, const std::vector<IntVar*>& var, int64_t value,
2635 Solver* solver() const;
2636
2637 private:
2638 Solver* const solver_;
2639};
2640
2642#if !defined(SWIG)
2643class ArgumentHolder {
2644 public:
2646 const std::string& TypeName() const;
2647 void SetTypeName(const std::string& type_name);
2648
2650 void SetIntegerArgument(const std::string& arg_name, int64_t value);
2651 void SetIntegerArrayArgument(const std::string& arg_name,
2652 const std::vector<int64_t>& values);
2653 void SetIntegerMatrixArgument(const std::string& arg_name,
2654 const IntTupleSet& values);
2655 void SetIntegerExpressionArgument(const std::string& arg_name, IntExpr* expr);
2656 void SetIntegerVariableArrayArgument(const std::string& arg_name,
2657 const std::vector<IntVar*>& vars);
2658 void SetIntervalArgument(const std::string& arg_name, IntervalVar* var);
2659 void SetIntervalArrayArgument(const std::string& arg_name,
2660 const std::vector<IntervalVar*>& vars);
2661 void SetSequenceArgument(const std::string& arg_name, SequenceVar* var);
2662 void SetSequenceArrayArgument(const std::string& arg_name,
2663 const std::vector<SequenceVar*>& vars);
2664
2666 bool HasIntegerExpressionArgument(const std::string& arg_name) const;
2667 bool HasIntegerVariableArrayArgument(const std::string& arg_name) const;
2668
2670 int64_t FindIntegerArgumentWithDefault(const std::string& arg_name,
2671 int64_t def) const;
2672 int64_t FindIntegerArgumentOrDie(const std::string& arg_name) const;
2673 const std::vector<int64_t>& FindIntegerArrayArgumentOrDie(
2674 const std::string& arg_name) const;
2675 const IntTupleSet& FindIntegerMatrixArgumentOrDie(
2676 const std::string& arg_name) const;
2677
2678 IntExpr* FindIntegerExpressionArgumentOrDie(
2679 const std::string& arg_name) const;
2680 const std::vector<IntVar*>& FindIntegerVariableArrayArgumentOrDie(
2681 const std::string& arg_name) const;
2682
2683 private:
2684 std::string type_name_;
2685 absl::flat_hash_map<std::string, int64_t> integer_argument_;
2686 absl::flat_hash_map<std::string, std::vector<int64_t>>
2687 integer_array_argument_;
2688 absl::flat_hash_map<std::string, IntTupleSet> matrix_argument_;
2689 absl::flat_hash_map<std::string, IntExpr*> integer_expression_argument_;
2690 absl::flat_hash_map<std::string, IntervalVar*> interval_argument_;
2691 absl::flat_hash_map<std::string, SequenceVar*> sequence_argument_;
2692 absl::flat_hash_map<std::string, std::vector<IntVar*>>
2693 integer_variable_array_argument_;
2694 absl::flat_hash_map<std::string, std::vector<IntervalVar*>>
2695 interval_array_argument_;
2696 absl::flat_hash_map<std::string, std::vector<SequenceVar*>>
2697 sequence_array_argument_;
2698};
2699
2701class ModelParser : public ModelVisitor {
2702 public:
2703 ModelParser();
2704
2705 ~ModelParser() override;
2706
2708 void BeginVisitModel(const std::string& solver_name) override;
2709 void EndVisitModel(const std::string& solver_name) override;
2710 void BeginVisitConstraint(const std::string& type_name,
2711 const Constraint* constraint) override;
2712 void EndVisitConstraint(const std::string& type_name,
2713 const Constraint* constraint) override;
2714 void BeginVisitIntegerExpression(const std::string& type_name,
2715 const IntExpr* expr) override;
2716 void EndVisitIntegerExpression(const std::string& type_name,
2717 const IntExpr* expr) override;
2718 void VisitIntegerVariable(const IntVar* variable, IntExpr* delegate) override;
2719 void VisitIntegerVariable(const IntVar* variable,
2720 const std::string& operation, int64_t value,
2721 IntVar* delegate) override;
2722 void VisitIntervalVariable(const IntervalVar* variable,
2723 const std::string& operation, int64_t value,
2724 IntervalVar* delegate) override;
2725 void VisitSequenceVariable(const SequenceVar* variable) override;
2727 void VisitIntegerArgument(const std::string& arg_name,
2728 int64_t value) override;
2729 void VisitIntegerArrayArgument(const std::string& arg_name,
2730 const std::vector<int64_t>& values) override;
2731 void VisitIntegerMatrixArgument(const std::string& arg_name,
2732 const IntTupleSet& values) override;
2734 void VisitIntegerExpressionArgument(const std::string& arg_name,
2735 IntExpr* argument) override;
2736 void VisitIntegerVariableArrayArgument(
2737 const std::string& arg_name,
2738 const std::vector<IntVar*>& arguments) override;
2740 void VisitIntervalArgument(const std::string& arg_name,
2741 IntervalVar* argument) override;
2742 void VisitIntervalArrayArgument(
2743 const std::string& arg_name,
2744 const std::vector<IntervalVar*>& arguments) override;
2746 void VisitSequenceArgument(const std::string& arg_name,
2747 SequenceVar* argument) override;
2748 void VisitSequenceArrayArgument(
2749 const std::string& arg_name,
2750 const std::vector<SequenceVar*>& arguments) override;
2751
2752 protected:
2753 void PushArgumentHolder();
2754 void PopArgumentHolder();
2755 ArgumentHolder* Top() const;
2756
2757 private:
2758 std::vector<ArgumentHolder*> holders_;
2759};
2760
2761template <class T>
2762class ArrayWithOffset : public BaseObject {
2763 public:
2764 ArrayWithOffset(int64_t index_min, int64_t index_max)
2765 : index_min_(index_min),
2766 index_max_(index_max),
2767 values_(new T[index_max - index_min + 1]) {
2768 DCHECK_LE(index_min, index_max);
2769 }
2770
2771 ~ArrayWithOffset() override {}
2772
2773 virtual T Evaluate(int64_t index) const {
2774 DCHECK_GE(index, index_min_);
2775 DCHECK_LE(index, index_max_);
2776 return values_[index - index_min_];
2777 }
2779 void SetValue(int64_t index, T value) {
2780 DCHECK_GE(index, index_min_);
2781 DCHECK_LE(index, index_max_);
2782 values_[index - index_min_] = value;
2783 }
2784
2785 std::string DebugString() const override { return "ArrayWithOffset"; }
2786
2787 private:
2788 const int64_t index_min_;
2789 const int64_t index_max_;
2790 std::unique_ptr<T[]> values_;
2791};
2792#endif // SWIG
2798template <class T, class C>
2800 public:
2801 explicit RevGrowingArray(int64_t block_size)
2802 : block_size_(block_size), block_offset_(0) {
2803 CHECK_GT(block_size, 0);
2804 }
2805
2807 for (int i = 0; i < elements_.size(); ++i) {
2808 delete[] elements_[i];
2809 }
2810 }
2811
2812 T At(int64_t index) const {
2813 const int64_t block_index = ComputeBlockIndex(index);
2814 const int64_t relative_index = block_index - block_offset_;
2815 if (relative_index < 0 || relative_index >= elements_.size()) {
2816 return T();
2817 }
2818 const T* block = elements_[relative_index];
2819 return block != nullptr ? block[index - block_index * block_size_] : T();
2821
2822 void RevInsert(Solver* const solver, int64_t index, T value) {
2823 const int64_t block_index = ComputeBlockIndex(index);
2824 T* const block = GetOrCreateBlock(block_index);
2825 const int64_t residual = index - block_index * block_size_;
2826 solver->SaveAndSetValue(reinterpret_cast<C*>(&block[residual]),
2827 reinterpret_cast<C>(value));
2828 }
2829
2830 private:
2831 T* NewBlock() const {
2832 T* const result = new T[block_size_];
2833 for (int i = 0; i < block_size_; ++i) {
2834 result[i] = T();
2835 }
2836 return result;
2837 }
2838
2839 T* GetOrCreateBlock(int block_index) {
2840 if (elements_.size() == 0) {
2841 block_offset_ = block_index;
2842 GrowUp(block_index);
2843 } else if (block_index < block_offset_) {
2844 GrowDown(block_index);
2845 } else if (block_index - block_offset_ >= elements_.size()) {
2846 GrowUp(block_index);
2847 }
2848 T* block = elements_[block_index - block_offset_];
2849 if (block == nullptr) {
2850 block = NewBlock();
2851 elements_[block_index - block_offset_] = block;
2852 }
2853 return block;
2854 }
2855
2856 int64_t ComputeBlockIndex(int64_t value) const {
2857 return value >= 0 ? value / block_size_
2858 : (value - block_size_ + 1) / block_size_;
2859 }
2860
2861 void GrowUp(int64_t block_index) {
2862 elements_.resize(block_index - block_offset_ + 1);
2863 }
2864
2865 void GrowDown(int64_t block_index) {
2866 const int64_t delta = block_offset_ - block_index;
2867 block_offset_ = block_index;
2868 DCHECK_GT(delta, 0);
2869 elements_.insert(elements_.begin(), delta, nullptr);
2870 }
2871
2872 const int64_t block_size_;
2873 std::vector<T*> elements_;
2874 int block_offset_;
2875};
2876
2881template <class T>
2882class RevIntSet {
2883 public:
2884 static constexpr int kNoInserted = -1;
2885
2887 explicit RevIntSet(int capacity)
2888 : elements_(new T[capacity]),
2889 num_elements_(0),
2890 capacity_(capacity),
2891 position_(new int[capacity]),
2892 delete_position_(true) {
2893 for (int i = 0; i < capacity; ++i) {
2894 position_[i] = kNoInserted;
2895 }
2897
2899 RevIntSet(int capacity, int* shared_positions, int shared_positions_size)
2900 : elements_(new T[capacity]),
2901 num_elements_(0),
2902 capacity_(capacity),
2903 position_(shared_positions),
2904 delete_position_(false) {
2905 for (int i = 0; i < shared_positions_size; ++i) {
2906 position_[i] = kNoInserted;
2907 }
2908 }
2909
2910 ~RevIntSet() {
2911 if (delete_position_) {
2912 delete[] position_;
2914 }
2915
2916 int Size() const { return num_elements_.Value(); }
2917
2918 int Capacity() const { return capacity_; }
2919
2920 T Element(int i) const {
2921 DCHECK_GE(i, 0);
2922 DCHECK_LT(i, num_elements_.Value());
2923 return elements_[i];
2925
2926 T RemovedElement(int i) const {
2927 DCHECK_GE(i, 0);
2928 DCHECK_LT(i + num_elements_.Value(), capacity_);
2929 return elements_[i + num_elements_.Value()];
2931
2932 void Insert(Solver* const solver, const T& elt) {
2933 const int position = num_elements_.Value();
2934 DCHECK_LT(position, capacity_);
2935 DCHECK(NotAlreadyInserted(elt));
2936 elements_[position] = elt;
2937 position_[elt] = position;
2938 num_elements_.Incr(solver);
2939 }
2941 void Remove(Solver* const solver, const T& value_index) {
2942 num_elements_.Decr(solver);
2943 SwapTo(value_index, num_elements_.Value());
2944 }
2945
2946 void Restore(Solver* const solver, const T& value_index) {
2947 SwapTo(value_index, num_elements_.Value());
2948 num_elements_.Incr(solver);
2949 }
2950
2951 void Clear(Solver* const solver) { num_elements_.SetValue(solver, 0); }
2952
2954 typedef const T* const_iterator;
2955 const_iterator begin() const { return elements_.get(); }
2956 const_iterator end() const { return elements_.get() + num_elements_.Value(); }
2957
2958 private:
2960 bool NotAlreadyInserted(const T& elt) {
2961 for (int i = 0; i < num_elements_.Value(); ++i) {
2962 if (elt == elements_[i]) {
2963 return false;
2964 }
2966 return true;
2967 }
2969 void SwapTo(T value_index, int next_position) {
2970 const int current_position = position_[value_index];
2971 if (current_position != next_position) {
2972 const T next_value_index = elements_[next_position];
2973 elements_[current_position] = next_value_index;
2974 elements_[next_position] = value_index;
2975 position_[value_index] = next_position;
2976 position_[next_value_index] = current_position;
2977 }
2978 }
2979
2981 std::unique_ptr<T[]> elements_;
2983 NumericalRev<int> num_elements_;
2985 const int capacity_;
2987 int* position_;
2989 const bool delete_position_;
2990};
2991
2993
2994class RevPartialSequence {
2995 public:
2996 explicit RevPartialSequence(const std::vector<int>& items)
2997 : elements_(items),
2998 first_ranked_(0),
2999 last_ranked_(items.size() - 1),
3000 size_(items.size()),
3001 position_(new int[size_]) {
3002 for (int i = 0; i < size_; ++i) {
3003 elements_[i] = items[i];
3004 position_[i] = i;
3005 }
3006 }
3007
3009 : elements_(size),
3010 first_ranked_(0),
3011 last_ranked_(size - 1),
3012 size_(size),
3013 position_(new int[size_]) {
3014 for (int i = 0; i < size_; ++i) {
3015 elements_[i] = i;
3016 position_[i] = i;
3017 }
3018 }
3019
3021
3022 int NumFirstRanked() const { return first_ranked_.Value(); }
3023
3024 int NumLastRanked() const { return size_ - 1 - last_ranked_.Value(); }
3025
3026 int Size() const { return size_; }
3027
3028#if !defined(SWIG)
3029 const int& operator[](int index) const {
3030 DCHECK_GE(index, 0);
3031 DCHECK_LT(index, size_);
3032 return elements_[index];
3033 }
3034#endif
3035
3036 void RankFirst(Solver* const solver, int elt) {
3037 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
3038 SwapTo(elt, first_ranked_.Value());
3039 first_ranked_.Incr(solver);
3041
3042 void RankLast(Solver* const solver, int elt) {
3043 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
3044 SwapTo(elt, last_ranked_.Value());
3045 last_ranked_.Decr(solver);
3046 }
3047
3048 bool IsRanked(int elt) const {
3049 const int position = position_[elt];
3050 return (position < first_ranked_.Value() ||
3051 position > last_ranked_.Value());
3052 }
3053
3054 std::string DebugString() const {
3055 std::string result = "[";
3056 for (int i = 0; i < first_ranked_.Value(); ++i) {
3057 absl::StrAppend(&result, elements_[i]);
3058 if (i != first_ranked_.Value() - 1) {
3059 result.append("-");
3060 }
3061 }
3062 result.append("|");
3063 for (int i = first_ranked_.Value(); i <= last_ranked_.Value(); ++i) {
3064 absl::StrAppend(&result, elements_[i]);
3065 if (i != last_ranked_.Value()) {
3066 result.append("-");
3067 }
3069 result.append("|");
3070 for (int i = last_ranked_.Value() + 1; i < size_; ++i) {
3071 absl::StrAppend(&result, elements_[i]);
3072 if (i != size_ - 1) {
3073 result.append("-");
3074 }
3075 }
3076 result.append("]");
3077 return result;
3078 }
3079
3080 private:
3081 void SwapTo(int elt, int next_position) {
3082 const int current_position = position_[elt];
3083 if (current_position != next_position) {
3084 const int next_elt = elements_[next_position];
3085 elements_[current_position] = next_elt;
3086 elements_[next_position] = elt;
3087 position_[elt] = next_position;
3088 position_[next_elt] = current_position;
3089 }
3090 }
3091
3093 std::vector<int> elements_;
3095 NumericalRev<int> first_ranked_;
3097 NumericalRev<int> last_ranked_;
3099 const int size_;
3101 std::unique_ptr<int[]> position_;
3102};
3103
3108class UnsortedNullableRevBitset {
3109 public:
3111 explicit UnsortedNullableRevBitset(int bit_size);
3112
3113 ~UnsortedNullableRevBitset() {}
3114
3117 void Init(Solver* solver, const std::vector<uint64_t>& mask);
3118
3121 bool RevSubtract(Solver* solver, const std::vector<uint64_t>& mask);
3125 bool RevAnd(Solver* solver, const std::vector<uint64_t>& mask);
3126
3129 int ActiveWordSize() const { return active_words_.Size(); }
3130
3132 bool Empty() const { return active_words_.Size() == 0; }
3133
3141 bool Intersects(const std::vector<uint64_t>& mask, int* support_index);
3142
3144 int64_t bit_size() const { return bit_size_; }
3146 int64_t word_size() const { return word_size_; }
3148 const RevIntSet<int>& active_words() const { return active_words_; }
3149
3150 private:
3151 void CleanUpActives(Solver* solver);
3152
3153 const int64_t bit_size_;
3154 const int64_t word_size_;
3155 RevArray<uint64_t> bits_;
3156 RevIntSet<int> active_words_;
3157 std::vector<int> to_remove_;
3159
3160template <class T>
3161bool IsArrayConstant(const std::vector<T>& values, const T& value) {
3162 for (int i = 0; i < values.size(); ++i) {
3163 if (values[i] != value) {
3164 return false;
3165 }
3166 }
3167 return true;
3168}
3169
3170template <class T>
3171bool IsArrayBoolean(const std::vector<T>& values) {
3172 for (int i = 0; i < values.size(); ++i) {
3173 if (values[i] != 0 && values[i] != 1) {
3174 return false;
3176 }
3177 return true;
3178}
3179
3180template <class T>
3181bool AreAllOnes(const std::vector<T>& values) {
3182 return IsArrayConstant(values, T(1));
3183}
3184
3185template <class T>
3186bool AreAllNull(const std::vector<T>& values) {
3187 return IsArrayConstant(values, T(0));
3188}
3189
3190template <class T>
3191bool AreAllGreaterOrEqual(const std::vector<T>& values, const T& value) {
3192 for (const T& current_value : values) {
3193 if (current_value < value) {
3194 return false;
3196 }
3197 return true;
3198}
3199
3200template <class T>
3201bool AreAllLessOrEqual(const std::vector<T>& values, const T& value) {
3202 for (const T& current_value : values) {
3203 if (current_value > value) {
3204 return false;
3206 }
3207 return true;
3208}
3209
3210template <class T>
3211bool AreAllPositive(const std::vector<T>& values) {
3212 return AreAllGreaterOrEqual(values, T(0));
3213}
3214
3215template <class T>
3216bool AreAllNegative(const std::vector<T>& values) {
3217 return AreAllLessOrEqual(values, T(0));
3218}
3219
3220template <class T>
3221bool AreAllStrictlyPositive(const std::vector<T>& values) {
3222 return AreAllGreaterOrEqual(values, T(1));
3223}
3224
3225template <class T>
3226bool AreAllStrictlyNegative(const std::vector<T>& values) {
3227 return AreAllLessOrEqual(values, T(-1));
3228}
3229
3230template <class T>
3231bool IsIncreasingContiguous(const std::vector<T>& values) {
3232 for (int i = 0; i < values.size() - 1; ++i) {
3233 if (values[i + 1] != values[i] + 1) {
3234 return false;
3236 }
3237 return true;
3238}
3239
3240template <class T>
3241bool IsIncreasing(const std::vector<T>& values) {
3242 for (int i = 0; i < values.size() - 1; ++i) {
3243 if (values[i + 1] < values[i]) {
3244 return false;
3246 }
3247 return true;
3248}
3249
3250template <class T>
3251bool IsArrayInRange(const std::vector<IntVar*>& vars, T range_min,
3252 T range_max) {
3253 for (int i = 0; i < vars.size(); ++i) {
3254 if (vars[i]->Min() < range_min || vars[i]->Max() > range_max) {
3255 return false;
3256 }
3257 }
3258 return true;
3259}
3260
3261inline bool AreAllBound(const std::vector<IntVar*>& vars) {
3262 for (int i = 0; i < vars.size(); ++i) {
3263 if (!vars[i]->Bound()) {
3264 return false;
3266 }
3267 return true;
3268}
3269
3270inline bool AreAllBooleans(const std::vector<IntVar*>& vars) {
3271 return IsArrayInRange(vars, 0, 1);
3272}
3273
3276template <class T>
3277bool AreAllBoundOrNull(const std::vector<IntVar*>& vars,
3278 const std::vector<T>& values) {
3279 for (int i = 0; i < vars.size(); ++i) {
3280 if (values[i] != 0 && !vars[i]->Bound()) {
3281 return false;
3282 }
3283 }
3284 return true;
3285}
3286
3288inline bool AreAllBoundTo(const std::vector<IntVar*>& vars, int64_t value) {
3289 for (int i = 0; i < vars.size(); ++i) {
3290 if (!vars[i]->Bound() || vars[i]->Min() != value) {
3291 return false;
3292 }
3293 }
3294 return true;
3295}
3296
3297inline int64_t MaxVarArray(const std::vector<IntVar*>& vars) {
3298 DCHECK(!vars.empty());
3299 int64_t result = kint64min;
3300 for (int i = 0; i < vars.size(); ++i) {
3302 result = std::max<int64_t>(result, vars[i]->Max());
3303 }
3304 return result;
3305}
3306
3307inline int64_t MinVarArray(const std::vector<IntVar*>& vars) {
3308 DCHECK(!vars.empty());
3309 int64_t result = kint64max;
3310 for (int i = 0; i < vars.size(); ++i) {
3312 result = std::min<int64_t>(result, vars[i]->Min());
3313 }
3314 return result;
3315}
3316
3317inline void FillValues(const std::vector<IntVar*>& vars,
3318 std::vector<int64_t>* const values) {
3319 values->clear();
3320 values->resize(vars.size());
3321 for (int i = 0; i < vars.size(); ++i) {
3322 (*values)[i] = vars[i]->Value();
3323 }
3324}
3325
3326inline int64_t PosIntDivUp(int64_t e, int64_t v) {
3327 DCHECK_GT(v, 0);
3328 return (e < 0 || e % v == 0) ? e / v : e / v + 1;
3329}
3330
3331inline int64_t PosIntDivDown(int64_t e, int64_t v) {
3332 DCHECK_GT(v, 0);
3333 return (e >= 0 || e % v == 0) ? e / v : e / v - 1;
3334}
3335
3336std::vector<int64_t> ToInt64Vector(const std::vector<int>& input);
3337
3338#if !defined(SWIG)
3339// A PathState represents a set of paths and changes made on it.
3341// More accurately, let us define P_{num_nodes, starts, ends}-graphs the set of
3342// directed graphs with nodes [0, num_nodes) whose connected components are
3343// paths from starts[i] to ends[i] (for the same i) and loops.
3344// Let us fix num_nodes, starts and ends, so we call these P-graphs.
3346// A P-graph can be described by the sequence of nodes of each of its paths,
3347// and its set of loops. To describe a change made on a given P-graph G0 that
3348// yields another P-graph G1, we choose to describe G1 in terms of G0. When
3349// the difference between G0 and G1 is small, as is almost always the case in a
3350// local search setting, the description is compact, allowing for incremental
3351// filters to be efficient.
3352//
3353// In order to describe G1 in terms of G0 succintly, we describe each path of
3354// G1 as a sequence of chains of G0. A chain of G0 is either a nonempty sequence
3355// of consecutive nodes of a path of G0, or a node that was a loop in G0.
3356// For instance, a path that was not modified from G0 to G1 has one chain,
3357// the sequence of all nodes in the path. Typically, local search operators
3358// modify one or two paths, and the resulting paths can described as sequences
3359// of two to four chains of G0. Paths that were modified are listed explicitly,
3360// allowing to iterate only on changed paths.
3361// The loops of G1 are described more implicitly: the loops of G1 not in G0
3362// are listed explicitly, but those in both G1 and G0 are not listed.
3363//
3364// A PathState object can be in two states: committed or changed.
3365// At construction, the object is committed, G0.
3366// To enter a changed state G1, one can pass modifications with ChangePath() and
3367// ChangeLoops(). For reasons of efficiency, a chain is described as a range of
3368// node indices in the representation of the committed graph G0. To that effect,
3369// the nodes of a path of G0 are guaranteed to have consecutive indices.
3370//
3371// Filters can then browse the change efficiently using ChangedPaths(),
3372// Chains(), Nodes() and ChangedLoops().
3373//
3374// Then Commit() or Revert() can be called: Commit() sets the changed state G1
3375// as the new committed state, Revert() erases all changes.
3376class PathState {
3377 public:
3378 // A Chain allows to iterate on all nodes of a chain, and access some data:
3379 // first node, last node, number of nodes in the chain.
3380 // Chain is a range, its iterator ChainNodeIterator, its value type int.
3381 // Chains are returned by PathChainIterator's operator*().
3382 class Chain;
3383 // A ChainRange allows to iterate on all chains of a path.
3384 // ChainRange is a range, its iterator Chain*, its value type Chain.
3385 class ChainRange;
3386 // A NodeRange allows to iterate on all nodes of a path.
3387 // NodeRange is a range, its iterator PathNodeIterator, its value type int.
3388 class NodeRange;
3389
3391 ChainBounds() {}
3392 ChainBounds(int begin_index, int end_index)
3393 : begin_index(begin_index), end_index(end_index) {}
3394 int begin_index;
3395 int end_index;
3396 };
3397 int CommittedIndex(int node) const { return committed_index_[node]; }
3398 ChainBounds CommittedPathRange(int path) const { return chains_[path]; }
3399
3400 // Path constructor: path_start and path_end must be disjoint,
3401 // their values in [0, num_nodes).
3402 PathState(int num_nodes, std::vector<int> path_start,
3403 std::vector<int> path_end);
3405 // Instance-constant accessors.
3407 // Returns the number of nodes in the underlying graph.
3408 int NumNodes() const { return num_nodes_; }
3409 // Returns the number of paths (empty paths included).
3410 int NumPaths() const { return num_paths_; }
3411 // Returns the start of a path.
3412 int Start(int path) const { return path_start_end_[path].start; }
3413 // Returns the end of a path.
3414 int End(int path) const { return path_start_end_[path].end; }
3415
3416 // State-dependent accessors.
3417
3418 // Returns the committed path of a given node, -1 if it is a loop.
3419 int Path(int node) const { return committed_paths_[node]; }
3420 // Returns the set of paths that actually changed,
3421 // i.e. that have more than one chain.
3422 const std::vector<int>& ChangedPaths() const { return changed_paths_; }
3423 // Returns the set of loops that were added by the change.
3424 const std::vector<int>& ChangedLoops() const { return changed_loops_; }
3425 // Returns the current range of chains of path.
3426 ChainRange Chains(int path) const;
3427 // Returns the current range of nodes of path.
3428 NodeRange Nodes(int path) const;
3429
3430 // State modifiers.
3431
3432 // Changes the path to the given sequence of chains of the committed state.
3433 // Chains are described by semi-open intervals. No optimization is made in
3434 // case two consecutive chains are actually already consecutive in the
3435 // committed state: they are not merged into one chain, and Chains(path) will
3436 // report the two chains.
3437 void ChangePath(int path, const std::vector<ChainBounds>& chains);
3438 // Same as above, but the initializer_list interface avoids the need to pass
3439 // a vector.
3440 void ChangePath(int path, const std::initializer_list<ChainBounds>& chains) {
3441 changed_paths_.push_back(path);
3442 const int path_begin_index = chains_.size();
3443 chains_.insert(chains_.end(), chains.begin(), chains.end());
3444 const int path_end_index = chains_.size();
3445 paths_[path] = {path_begin_index, path_end_index};
3446 // Always add sentinel, in case this is the last path change.
3447 chains_.emplace_back(0, 0);
3448 }
3449
3450 // Describes the nodes that are newly loops in this change.
3451 void ChangeLoops(const std::vector<int>& new_loops);
3452
3453 // Set the current state G1 as committed. See class comment for details.
3454 void Commit();
3455 // Erase incremental changes. See class comment for details.
3456 void Revert();
3457
3458 // LNS Operators may not fix variables,
3459 // in which case we mark the candidate invalid.
3460 void SetInvalid() { is_invalid_ = true; }
3461 bool IsInvalid() const { return is_invalid_; }
3462
3463 private:
3464 // Most structs below are named pairs of ints, for typing purposes.
3465
3466 // Start and end are stored together to optimize (likely) simultaneous access.
3467 struct PathStartEnd {
3468 PathStartEnd(int start, int end) : start(start), end(end) {}
3469 int start;
3470 int end;
3471 };
3472 // Paths are ranges of chains, which are ranges of committed nodes, see below.
3473 struct PathBounds {
3474 int begin_index;
3475 int end_index;
3476 };
3477
3478 // Copies nodes in chains of path at the end of nodes,
3479 // and sets those nodes' path member to value path.
3480 void CopyNewPathAtEndOfNodes(int path);
3481 // Commits paths in O(#{changed paths' nodes}) time,
3482 // increasing this object's space usage by O(|changed path nodes|).
3483 void IncrementalCommit();
3484 // Commits paths in O(num_nodes + num_paths) time,
3485 // reducing this object's space usage to O(num_nodes + num_paths).
3486 void FullCommit();
3487
3488 // Instance-constant data.
3489 const int num_nodes_;
3490 const int num_paths_;
3491 std::vector<PathStartEnd> path_start_end_;
3492
3493 // Representation of the committed and changed paths.
3494 // A path is a range of chains, which is a range of nodes.
3495 // Ranges are represented internally by indices in vectors:
3496 // ChainBounds are indices in committed_nodes_. PathBounds are indices in
3497 // chains_. When committed (after construction, Revert() or Commit()):
3498 // - path ranges are [path, path+1): they have one chain.
3499 // - chain ranges don't overlap, chains_ has an empty sentinel at the end.
3500 // The sentinel allows the Nodes() iterator to maintain its current pointer
3501 // to committed nodes on NodeRange::operator++().
3502 // - committed_nodes_ contains all nodes, both paths and loops.
3503 // Actually, old duplicates will likely appear,
3504 // the current version of a node is at the index given by
3505 // committed_index_[node]. A Commit() can add nodes at the end of
3506 // committed_nodes_ in a space/time tradeoff, but if committed_nodes_' size
3507 // is above num_nodes_threshold_, Commit() must reclaim useless duplicates'
3508 // space by rewriting the path/chain/nodes structure.
3509 // When changed (after ChangePaths() and ChangeLoops()),
3510 // the structure is updated accordingly:
3511 // - path ranges that were changed have nonoverlapping values [begin, end)
3512 // where begin is >= num_paths_ + 1, i.e. new chains are stored after
3513 // the committed state.
3514 // - additional chain ranges are stored after the committed chains and its
3515 // sentinel to represent the new chains resulting from the changes.
3516 // Those chains do not overlap with one another or with committed chains.
3517 // - committed_nodes_ are not modified, and still represent the committed
3518 // paths. committed_index_ is not modified either.
3519 std::vector<int> committed_nodes_;
3520 // Maps nodes to their path in the latest committed state.
3521 std::vector<int> committed_paths_;
3522 // Maps nodes to their index in the latest committed state.
3523 std::vector<int> committed_index_;
3524 const int num_nodes_threshold_;
3525 std::vector<ChainBounds> chains_;
3526 std::vector<PathBounds> paths_;
3527
3528 // Incremental information.
3529 std::vector<int> changed_paths_;
3530 std::vector<int> changed_loops_;
3531
3532 // See IsInvalid() and SetInvalid().
3533 bool is_invalid_ = false;
3534};
3535
3536// A Chain is a range of committed nodes.
3537class PathState::Chain {
3538 public:
3539 class Iterator {
3540 public:
3541 Iterator& operator++() {
3542 ++current_node_;
3543 return *this;
3544 }
3545 int operator*() const { return *current_node_; }
3546 bool operator!=(Iterator other) const {
3547 return current_node_ != other.current_node_;
3548 }
3549
3550 private:
3551 // Only a Chain can construct its iterator.
3552 friend class PathState::Chain;
3553 explicit Iterator(const int* node) : current_node_(node) {}
3554 const int* current_node_;
3556
3557 // Chains hold CommittedNode* values, a Chain may be invalidated
3558 // if the underlying vector is modified.
3559 Chain(const int* begin_node, const int* end_node)
3560 : begin_(begin_node), end_(end_node) {}
3561
3562 int NumNodes() const { return end_ - begin_; }
3563 int First() const { return *begin_; }
3564 int Last() const { return *(end_ - 1); }
3565 Iterator begin() const { return Iterator(begin_); }
3566 Iterator end() const { return Iterator(end_); }
3567
3568 Chain WithoutFirstNode() const { return Chain(begin_ + 1, end_); }
3569
3570 private:
3571 const int* const begin_;
3572 const int* const end_;
3574
3575// A ChainRange is a range of Chains, committed or not.
3577 public:
3578 class Iterator {
3579 public:
3580 Iterator& operator++() {
3581 ++current_chain_;
3582 return *this;
3583 }
3584 Chain operator*() const {
3585 return {first_node_ + current_chain_->begin_index,
3586 first_node_ + current_chain_->end_index};
3587 }
3588 bool operator!=(Iterator other) const {
3589 return current_chain_ != other.current_chain_;
3591
3592 private:
3593 // Only a ChainRange can construct its Iterator.
3594 friend class ChainRange;
3595 Iterator(const ChainBounds* chain, const int* const first_node)
3596 : current_chain_(chain), first_node_(first_node) {}
3597 const ChainBounds* current_chain_;
3598 const int* const first_node_;
3599 };
3600
3601 // ChainRanges hold ChainBounds* and CommittedNode*,
3602 // a ChainRange may be invalidated if on of the underlying vector is modified.
3603 ChainRange(const ChainBounds* const begin_chain,
3604 const ChainBounds* const end_chain, const int* const first_node)
3605 : begin_(begin_chain), end_(end_chain), first_node_(first_node) {}
3606
3607 Iterator begin() const { return {begin_, first_node_}; }
3608 Iterator end() const { return {end_, first_node_}; }
3609
3610 private:
3611 const ChainBounds* const begin_;
3612 const ChainBounds* const end_;
3613 const int* const first_node_;
3614};
3615
3616// A NodeRange allows to iterate on all nodes of a path,
3617// by a two-level iteration on ChainBounds* and CommittedNode* of a PathState.
3619 public:
3620 class Iterator {
3621 public:
3622 Iterator& operator++() {
3623 ++current_node_;
3624 if (current_node_ == end_node_) {
3625 ++current_chain_;
3626 // Note: dereferencing bounds is valid because there is a sentinel
3627 // value at the end of PathState::chains_ to that intent.
3628 const ChainBounds bounds = *current_chain_;
3629 current_node_ = first_node_ + bounds.begin_index;
3630 end_node_ = first_node_ + bounds.end_index;
3631 }
3632 return *this;
3633 }
3634 int operator*() const { return *current_node_; }
3635 bool operator!=(Iterator other) const {
3636 return current_chain_ != other.current_chain_;
3637 }
3638
3639 private:
3640 // Only a NodeRange can construct its Iterator.
3641 friend class NodeRange;
3642 Iterator(const ChainBounds* current_chain, const int* const first_node)
3643 : current_node_(first_node + current_chain->begin_index),
3644 end_node_(first_node + current_chain->end_index),
3645 current_chain_(current_chain),
3646 first_node_(first_node) {}
3647 const int* current_node_;
3648 const int* end_node_;
3649 const ChainBounds* current_chain_;
3650 const int* const first_node_;
3651 };
3652
3653 // NodeRanges hold ChainBounds* and int* (first committed node),
3654 // a NodeRange may be invalidated if on of the underlying vector is modified.
3655 NodeRange(const ChainBounds* begin_chain, const ChainBounds* end_chain,
3656 const int* first_node)
3657 : begin_chain_(begin_chain),
3658 end_chain_(end_chain),
3659 first_node_(first_node) {}
3660 Iterator begin() const { return {begin_chain_, first_node_}; }
3661 // Note: there is a sentinel value at the end of PathState::chains_,
3662 // so dereferencing chain_range_.end()->begin_ is always valid.
3663 Iterator end() const { return {end_chain_, first_node_}; }
3664
3665 private:
3666 const ChainBounds* begin_chain_;
3667 const ChainBounds* end_chain_;
3668 const int* const first_node_;
3670
3671// This checker enforces dimension requirements.
3672// A dimension requires that there is some valuation of
3673// cumul and demand such that for all paths:
3674// - cumul[A] is in interval node_capacity[A]
3675// - if arc A -> B is on a path of path_class p,
3676// then cumul[A] + demand[p](A, B) = cumul[B].
3677// - if A is on a path of class p, then
3678// cumul[A] must be inside interval path_capacity[path].
3679class DimensionChecker {
3680 public:
3681 struct Interval {
3682 int64_t min;
3683 int64_t max;
3684 };
3685
3686 struct ExtendedInterval {
3687 int64_t min;
3688 int64_t max;
3689 int64_t num_negative_infinity;
3690 int64_t num_positive_infinity;
3691 };
3692
3693 // TODO(user): the addition of kMinRangeSizeForRIQ slowed down Check().
3694 // See if using a template parameter makes it faster.
3695 DimensionChecker(const PathState* path_state,
3696 std::vector<Interval> path_capacity,
3697 std::vector<int> path_class,
3698 std::vector<std::function<Interval(int64_t, int64_t)>>
3699 demand_per_path_class,
3700 std::vector<Interval> node_capacity,
3701 int min_range_size_for_riq = kOptimalMinRangeSizeForRIQ);
3703 // Given the change made in PathState, checks that the dimension
3704 // constraint is still feasible.
3705 bool Check() const;
3706
3707 // Commits to the changes made in PathState,
3708 // must be called before PathState::Commit().
3709 void Commit();
3710
3711 static constexpr int kOptimalMinRangeSizeForRIQ = 4;
3712
3713 private:
3714 inline void UpdateCumulUsingChainRIQ(int first_index, int last_index,
3715 const ExtendedInterval& path_capacity,
3716 ExtendedInterval& cumul) const;
3717
3718 // Commits to the current solution and rebuilds structures from scratch.
3719 void FullCommit();
3720 // Commits to the current solution and only build structures for paths that
3721 // changed, using additional space to do so in a time-memory tradeoff.
3722 void IncrementalCommit();
3723 // Adds sums of given path to the bottom layer of the Range Intersection Query
3724 // structure, updates index_ and previous_nontrivial_index_.
3725 void AppendPathDemandsToSums(int path);
3726 // Updates the Range Intersection Query structure from its bottom layer,
3727 // with [begin_index, end_index) the range of the change,
3728 // which must be at the end of the bottom layer.
3729 // Supposes that requests overlapping the range will be inside the range,
3730 // to avoid updating all layers.
3731 void UpdateRIQStructure(int begin_index, int end_index);
3732
3733 const PathState* const path_state_;
3734 const std::vector<ExtendedInterval> path_capacity_;
3735 const std::vector<int> path_class_;
3736 const std::vector<std::function<Interval(int64_t, int64_t)>>
3737 demand_per_path_class_;
3738 std::vector<ExtendedInterval> cached_demand_;
3739 const std::vector<ExtendedInterval> node_capacity_;
3740
3741 // Precomputed data.
3742 // Maps nodes to their pre-computed data, except for isolated nodes,
3743 // which do not have precomputed data.
3744 // Only valid for nodes that are in some path in the committed state.
3745 std::vector<int> index_;
3746 // Range intersection query in <O(n log n), O(1)>, with n = #nodes.
3747 // Let node be in a path, i = index_[node], start the start of node's path.
3748 // Let l such that index_[start] <= i - 2**l.
3749 // - riq_[l][i].tsum_at_lst contains the sum of demands from start to node.
3750 // - riq_[l][i].tsum_at_fst contains the sum of demands from start to the
3751 // node at i - 2**l.
3752 // - riq_[l][i].tightest_tsum contains the intersection of
3753 // riq_[0][j].tsum_at_lst for all j in (i - 2**l, i].
3754 // - riq_[0][i].cumuls_to_lst and riq_[0][i].cumuls_to_fst contain
3755 // the node's capacity.
3756 // - riq_[l][i].cumuls_to_lst is the intersection, for j in (i - 2**l, i], of
3757 // riq_[0][j].cumuls_to_lst + sum_{k in [j, i)} demand(k, k+1)
3758 // - riq_[l][i].cumuls_to_fst is the intersection, for j in (i - 2**l, i], of
3759 // riq_[0][j].cumuls_to_fst - sum_{k in (i-2**l, j)} demand(k, k+1)
3760 struct RIQNode {
3761 ExtendedInterval cumuls_to_fst;
3762 ExtendedInterval tightest_tsum;
3763 ExtendedInterval cumuls_to_lst;
3764 ExtendedInterval tsum_at_fst;
3765 ExtendedInterval tsum_at_lst;
3766 };
3767 std::vector<std::vector<RIQNode>> riq_;
3768 // The incremental branch of Commit() may waste space in the layers of the
3769 // RIQ structure. This is the upper limit of a layer's size.
3770 const int maximum_riq_layer_size_;
3771 // Range queries are used on a chain only if the range is larger than this.
3772 const int min_range_size_for_riq_;
3773};
3774
3775// Make a filter that takes ownership of a PathState and synchronizes it with
3776// solver events. The solver represents a graph with array of variables 'nexts'.
3777// Solver events are embodied by Assignment* deltas, that are translated to node
3778// changes during Relax(), committed during Synchronize(), and reverted on
3779// Revert().
3780LocalSearchFilter* MakePathStateFilter(Solver* solver,
3781 std::unique_ptr<PathState> path_state,
3782 const std::vector<IntVar*>& nexts);
3783
3784// Make a filter that translates solver events to the input checker's interface.
3785// Since DimensionChecker has a PathState, the filter returned by this
3786// must be synchronized to the corresponding PathStateFilter:
3787// - Relax() must be called after the PathStateFilter's.
3788// - Accept() must be called after.
3789// - Synchronize() must be called before.
3790// - Revert() must be called before.
3791LocalSearchFilter* MakeDimensionFilter(
3792 Solver* solver, std::unique_ptr<DimensionChecker> checker,
3793 const std::string& dimension_name);
3794
3795#endif // !defined(SWIG)
3796
3797} // namespace operations_research
3798
3799#endif // OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
IntegerValue size
const std::vector< IntVar * > vars_
int64_t max
int64_t min
int64_t MemoryUsage(int unused)
Definition sysinfo.h:24
Argument Holder: useful when visiting a model.
const E & Element(const V *const var) const
bool Contains(const V *const var) const
AssignmentContainer< IntVar, IntVarElement > IntContainer
IntVar * Var() override
Creates a variable from the expression.
bool HasFragments() const override
BaseLns(const std::vector< IntVar * > &vars)
--— Base Large Neighborhood Search operator --—
bool MakeOneNeighbor() override
This method should not be overridden. Override NextFragment() instead.
virtual bool NextFragment()=0
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
Copies bucket containing bit i from "other" to "this".
Definition bitset.h:564
void Clear(IndexType i)
Sets the bit at position i to 0.
Definition bitset.h:510
void Resize(IndexType size)
Definition bitset.h:479
void Set(IndexType i)
Sets the bit at position i to 1.
Definition bitset.h:548
Demon proxy to a method on the constraint with no arguments.
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
CallMethod0(T *const ct, void(T::*method)(), const std::string &name)
Demon proxy to a method on the constraint with one argument.
void Run(Solver *const s) override
This is the main callback of the demon.
CallMethod1(T *const ct, void(T::*method)(P), const std::string &name, P param1)
std::string DebugString() const override
Demon proxy to a method on the constraint with two arguments.
std::string DebugString() const override
CallMethod2(T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
void Run(Solver *const s) override
This is the main callback of the demon.
Demon proxy to a method on the constraint with three arguments.
void Run(Solver *const s) override
This is the main callback of the demon.
CallMethod3(T *const ct, void(T::*method)(P, Q, R), const std::string &name, P param1, Q param2, R param3)
std::string DebugString() const override
virtual int64_t ModifyValue(int64_t index, int64_t value)=0
bool MakeOneNeighbor() override
This method should not be overridden. Override ModifyValue() instead.
ChangeValue(const std::vector< IntVar * > &vars)
--— ChangeValue Operators --—
Low-priority demon proxy to a method on the constraint with no arguments.
void Run(Solver *const s) override
This is the main callback of the demon.
DelayedCallMethod0(T *const ct, void(T::*method)(), const std::string &name)
std::string DebugString() const override
Solver::DemonPriority priority() const override
---------------— Demon class -------------—
Low-priority demon proxy to a method on the constraint with one argument.
void Run(Solver *const s) override
This is the main callback of the demon.
DelayedCallMethod1(T *const ct, void(T::*method)(P), const std::string &name, P param1)
Solver::DemonPriority priority() const override
---------------— Demon class -------------—
std::string DebugString() const override
Low-priority demon proxy to a method on the constraint with two arguments.
std::string DebugString() const override
void Run(Solver *const s) override
This is the main callback of the demon.
Solver::DemonPriority priority() const override
---------------— Demon class -------------—
DelayedCallMethod2(T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
virtual void SetValue(int64_t v)
This method sets the value of the expression.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual int64_t Min() const =0
virtual int64_t Max() const =0
--— Main IntTupleSet class --—
Definition tuple_set.h:47
void AddToAssignment(IntVar *var, int64_t value, bool active, std::vector< int > *assignment_indices, int64_t index, Assignment *assignment) const
void SetValue(int64_t index, int64_t value)
void Start(const Assignment *assignment) override
void RevertChanges(bool change_was_incremental)
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
--— Base operator class for operators manipulating IntVars --—
void AddVars(const std::vector< IntVar * > &vars)
IntVar * Var(int64_t index) const
Returns the variable of given index.
bool ApplyChanges(Assignment *delta, Assignment *deltadelta) const
IntVarLocalSearchOperator(const std::vector< IntVar * > &vars, bool keep_inverse_values=false)
virtual void WhenBound(Demon *d)=0
LightIntFunctionElementCt(Solver *const solver, IntVar *const var, IntVar *const index, F values, std::function< bool()> deep_serialize)
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
std::string DebugString() const override
--------------— Constraint class ----------------—
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
LightIntIntFunctionElementCt(Solver *const solver, IntVar *const var, IntVar *const index1, IntVar *const index2, F values, std::function< bool()> deep_serialize)
std::string DebugString() const override
--------------— Constraint class ----------------—
void SetCandidateActive(int64_t index, bool active)
void SetCandidateValue(int64_t index, int64_t value)
const std::vector< int64_t > & IncrementalIndicesChanged() const
const std::vector< int64_t > & CandidateIndicesChanged() const
virtual bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta)=0
virtual const LocalSearchOperator * Self() const
virtual void Start(const Assignment *assignment)=0
virtual void VisitIntegerExpressionArgument(const std::string &arg_name, IntExpr *argument)
Visit integer expression argument.
virtual void BeginVisitConstraint(const std::string &type_name, const Constraint *constraint)
void VisitInt64ToInt64Extension(const Solver::IndexEvaluator1 &eval, int64_t index_min, int64_t index_max)
virtual void EndVisitConstraint(const std::string &type_name, const Constraint *constraint)
Subclass of Rev<T> which adds numerical operations.
int64_t Prev(int64_t node) const
Returns the node before node in the current delta.
PathOperator(const std::vector< IntVar * > &next_vars, const std::vector< IntVar * > &path_vars, IterationParameters iteration_parameters)
Builds an instance of PathOperator from next and path variables.
bool MakeActive(int64_t node, int64_t destination)
Insert the inactive node after destination.
bool IsPathStart(int64_t node) const
Returns true if node is the first node on the path.
bool SkipUnchanged(int index) const override
int number_of_nexts() const
Number of next variables.
int GetSiblingAlternativeIndex(int node) const
Returns the index of the alternative set of the sibling of node.
int64_t OldNext(int64_t node) const
bool MakeChainInactive(int64_t before_chain, int64_t chain_end)
int64_t PrevNext(int64_t node) const
bool IsInactive(int64_t node) const
Returns true if node is inactive.
virtual bool ConsiderAlternatives(int64_t base_index) const
bool SwapActiveAndInactive(int64_t active, int64_t inactive)
Replaces active by inactive in the current path, making active inactive.
void AddPairAlternativeSets(const std::vector< PairType > &pair_alternative_sets)
int BaseAlternative(int i) const
Returns the alternative for the ith base node.
int PathClass(int i) const
Returns the class of the path of the ith base node.
int BaseSiblingAlternative(int i) const
Returns the alternative for the sibling of the ith base node.
int64_t EndNode(int i) const
Returns the end node of the ith base node.
int PathClassFromStartNode(int64_t start_node) const
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
int64_t BaseSiblingAlternativeNode(int i) const
Returns the alternative node for the sibling of the ith base node.
int64_t BaseAlternativeNode(int i) const
Returns the alternative node for the ith base node.
const std::vector< int64_t > & path_starts() const
Returns the vector of path start nodes.
int64_t OldPath(int64_t node) const
int CurrentNodePathStart(int64_t node) const
int AddAlternativeSet(const std::vector< int64_t > &alternative_set)
int64_t OldPrev(int64_t node) const
int64_t Path(int64_t node) const
int CurrentNodePathEnd(int64_t node) const
bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination)
virtual int64_t GetBaseNodeRestartPosition(int base_index)
int64_t StartNode(int i) const
Returns the start node of the ith base node.
virtual bool OnSamePathAsPreviousBase(int64_t base_index)
virtual void SetNextBaseToIncrement(int64_t base_index)
void SetNext(int64_t from, int64_t to, int64_t path)
Sets 'to' to be the node after 'from' on the given path.
int64_t BaseNode(int i) const
Returns the ith base node of the operator.
bool ReverseChain(int64_t before_chain, int64_t after_chain, int64_t *chain_last)
A ChainRange is a range of Chains, committed or not.
A Chain is a range of committed nodes.
friend class NodeRange
Only a NodeRange can construct its Iterator.
Matrix version of the RevBitSet class.
bool IsSet(int64_t row, int64_t column) const
Returns whether the 'column' bit in the 'row' row is set.
void ClearAll(Solver *solver)
Cleans all bits.
Definition utilities.cc:221
int64_t GetFirstBit(int row, int start) const
Definition utilities.cc:205
void SetToZero(Solver *solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
Definition utilities.cc:179
void SetToOne(Solver *solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition utilities.cc:171
int64_t Cardinality() const
Returns the number of bits set to one.
Definition utilities.cc:113
void ClearAll(Solver *solver)
Cleans all bits.
Definition utilities.cc:152
RevBitSet(int64_t size)
-------— RevBitSet -------—
Definition utilities.cc:62
void SetToZero(Solver *solver, int64_t index)
Erases the 'index' bit.
Definition utilities.cc:96
bool IsCardinalityOne() const
Does it contains only one bit set?
Definition utilities.cc:130
void SetToOne(Solver *solver, int64_t index)
Sets the 'index' bit.
Definition utilities.cc:85
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition utilities.cc:107
int64_t GetFirstBit(int start) const
Definition utilities.cc:148
bool IsCardinalityZero() const
Is bitset null?
Definition utilities.cc:121
void Insert(const K &key, const V &value)
Inserts (key, value) in the multi-map.
bool ContainsKey(const K &key) const
Returns true if the multi-map contains at least one instance of 'key'.
RevImmutableMultiMap(Solver *const solver, int initial_size)
const V & FindWithDefault(const K &key, const V &default_value) const
const T * const_iterator
Iterators on the indices.
void Switch(Solver *const solver)
void SetValue(Solver *const s, const T &val)
A search monitor is a simple set of callbacks to monitor all search events.
void SetLastValue(const T &v)
Sets the last value in the FIFO.
const T * Last() const
Returns the last item of the FIFO.
void Push(Solver *const s, T val)
void PushIfNotTop(Solver *const s, T val)
Pushes the var on top if is not a duplicate of the current top object.
const T & LastValue() const
Returns the last value in the FIFO.
void SetToZero(Solver *solver, int64_t pos)
Erases the 'pos' bit.
Definition utilities.cc:44
SmallRevBitSet(int64_t size)
-------— SmallRevBitSet -------—
Definition utilities.cc:34
void SetToOne(Solver *solver, int64_t pos)
Sets the 'pos' bit.
Definition utilities.cc:39
bool IsCardinalityZero() const
Is bitset null?
int64_t Cardinality() const
Returns the number of bits set to one.
Definition utilities.cc:49
bool IsCardinalityOne() const
Does it contains only one bit set?
For the time being, Solver is neither MT_SAFE nor MT_HOT.
void SaveAndSetValue(T *adr, T val)
All-in-one SaveAndSetValue.
std::function< int64_t(int64_t, int64_t)> IndexEvaluator2
void ClearAndResize(IntegerType size)
Definition bitset.h:839
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
Definition bitset.h:878
void Set(IntegerType index)
Definition bitset.h:864
-------— Symmetry Breaking -------—
Definition search.cc:5175
void push_back(const value_type &val)
int64_t a
Definition table.cc:44
Block * next
const std::string name
A name for logging purposes.
const Constraint * ct
int64_t value
IntVar * var
GurobiMPCallbackContext * context
int index
RowIndex row
Definition markowitz.cc:186
int64_t hash
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).
Definition matchers.h:468
bool operator!=(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
Definition integer.h:1975
In SWIG mode, we don't want anything besides these top-level includes.
std::string ParameterDebugString(P param)
bool IsArrayConstant(const std::vector< T > &values, const T &value)
LinearExpr operator*(LinearExpr lhs, double rhs)
bool AreAllLessOrEqual(const std::vector< T > &values, const T &value)
SubDagComputer::ArcId ArcId
Demon * MakeConstraintDemon3(Solver *const s, T *const ct, void(T::*method)(P, Q, R), const std::string &name, P param1, Q param2, R param3)
bool AreAllNegative(const std::vector< T > &values)
bool AreAllGreaterOrEqual(const std::vector< T > &values, const T &value)
bool IsIncreasing(const std::vector< T > &values)
void AcceptUncheckedNeighbor(Search *search)
bool AreAllBoundOrNull(const std::vector< IntVar * > &vars, const std::vector< T > &values)
int64_t MaxVarArray(const std::vector< IntVar * > &vars)
LocalSearchOperator * MakeLocalSearchOperator(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
Operator Factories.
Demon * MakeConstraintDemon2(Solver *const s, T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
Demon * MakeDelayedConstraintDemon2(Solver *const s, T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
void FillValues(const std::vector< IntVar * > &vars, std::vector< int64_t > *const values)
bool AreAllBooleans(const std::vector< IntVar * > &vars)
bool AreAllStrictlyNegative(const std::vector< T > &values)
int64_t MinVarArray(const std::vector< IntVar * > &vars)
void RegisterDemon(Solver *const solver, Demon *const demon, DemonProfiler *const monitor)
--— Exported Methods for Unit Tests --—
LocalSearchOperator * MakeLocalSearchOperatorWithNeighbors(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors)
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
bool IsIncreasingContiguous(const std::vector< T > &values)
bool AreAllNull(const std::vector< T > &values)
bool AreAllPositive(const std::vector< T > &values)
Demon * MakeDelayedConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
LocalSearchState::VariableDomainId VariableDomainId
int64_t PosIntDivDown(int64_t e, int64_t v)
bool IsArrayInRange(const std::vector< IntVar * > &vars, T range_min, T range_max)
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
bool AreAllOnes(const std::vector< T > &values)
bool AreAllBound(const std::vector< IntVar * > &vars)
uint64_t Hash1(uint64_t value)
int64_t PosIntDivUp(int64_t e, int64_t v)
SubDagComputer::NodeId NodeId
STL namespace.
false true
Definition numbers.cc:228
bool Next()
trees with all degrees equal to
int64_t weight
Definition pack.cc:510
int line
int column
static int input(yyscan_t yyscanner)
int64_t delta
Definition resource.cc:1709
int head
int tail
int var_index
Definition search.cc:3268
std::optional< int64_t > end
int64_t start
#define DEFINE_STRONG_INT_TYPE(int_type_name, value_type)
Definition strong_int.h:168
Set of parameters used to configure how the neighnorhood is traversed.
std::function< const std::vector< int > &(int, int)> get_neighbors
Callback returning neighbors of a node on a path starting at start_node.
bool accept_path_end_base
True if path ends should be considered when iterating over neighbors.
int number_of_base_nodes
Number of nodes needed to define a neighbor.
static const int64_t kint64max
Definition types.h:32
static const int64_t kint64min
Definition types.h:31