Google OR-Tools v9.15
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-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
50
51#ifndef ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
52#define ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
53
54#include <stdint.h>
55#include <string.h>
56
57#include <algorithm>
58#include <functional>
59#include <memory>
60#include <string>
61#include <tuple>
62#include <utility>
63#include <vector>
64
65#include "absl/algorithm/container.h"
66#include "absl/container/flat_hash_map.h"
67#include "absl/container/flat_hash_set.h"
68#include "absl/log/check.h"
69#include "absl/strings/str_cat.h"
70#include "absl/strings/str_format.h"
71#include "absl/time/time.h"
72#include "absl/types/span.h"
77#include "ortools/base/timer.h"
78#include "ortools/base/types.h"
80#include "ortools/util/bitset.h"
82
83namespace operations_research {
84
111
112class BaseIntExpr : public IntExpr {
113 public:
114 explicit BaseIntExpr(Solver* const s) : IntExpr(s), var_(nullptr) {}
115 ~BaseIntExpr() override {}
117 IntVar* Var() override;
118 virtual IntVar* CastToVar();
120 private:
121 IntVar* var_;
122};
123
126enum VarTypes {
141
146#ifndef SWIG
147template <class T>
148class SimpleRevFIFO {
149 private:
150 enum { CHUNK_SIZE = 16 }; // TODO(user): could be an extra template param
151 struct Chunk {
152 T data[CHUNK_SIZE];
153 const Chunk* const next;
154 explicit Chunk(const Chunk* next) : next(next) {}
155 };
156
157 public:
159 class Iterator {
160 public:
161 explicit Iterator(const SimpleRevFIFO<T>* l)
162 : chunk_(l->chunks_), value_(l->Last()) {}
163 bool ok() const { return (value_ != nullptr); }
164 T operator*() const { return *value_; }
165 void operator++() {
166 ++value_;
167 if (value_ == chunk_->data + CHUNK_SIZE) {
168 chunk_ = chunk_->next;
169 value_ = chunk_ ? chunk_->data : nullptr;
170 }
171 }
172
173 private:
174 const Chunk* chunk_;
175 const T* value_;
176 };
177
178 SimpleRevFIFO() : chunks_(nullptr), pos_(0) {}
179
180 void Push(Solver* const s, T val) {
181 if (pos_.Value() == 0) {
182 Chunk* const chunk = s->UnsafeRevAlloc(new Chunk(chunks_));
183 s->SaveAndSetValue(reinterpret_cast<void**>(&chunks_),
184 reinterpret_cast<void*>(chunk));
185 pos_.SetValue(s, CHUNK_SIZE - 1);
186 } else {
187 pos_.Decr(s);
188 }
189 chunks_->data[pos_.Value()] = val;
190 }
191
193 void PushIfNotTop(Solver* const s, T val) {
194 if (chunks_ == nullptr || LastValue() != val) {
195 Push(s, val);
196 }
198
200 const T* Last() const {
201 return chunks_ ? &chunks_->data[pos_.Value()] : nullptr;
202 }
203
204 T* MutableLast() { return chunks_ ? &chunks_->data[pos_.Value()] : nullptr; }
205
207 const T& LastValue() const {
208 DCHECK(chunks_);
209 return chunks_->data[pos_.Value()];
210 }
213 void SetLastValue(const T& v) {
214 DCHECK(Last());
215 chunks_->data[pos_.Value()] = v;
216 }
218 private:
219 Chunk* chunks_;
221};
222
224// TODO(user): use murmurhash.
225inline uint64_t Hash1(uint64_t value) {
226 value = (~value) + (value << 21);
227 value ^= value >> 24;
228 value += (value << 3) + (value << 8);
229 value ^= value >> 14;
230 value += (value << 2) + (value << 4);
231 value ^= value >> 28;
232 value += (value << 31);
233 return value;
234}
235
236inline uint64_t Hash1(uint32_t value) {
237 uint64_t a = value;
238 a = (a + 0x7ed55d16) + (a << 12);
239 a = (a ^ 0xc761c23c) ^ (a >> 19);
240 a = (a + 0x165667b1) + (a << 5);
241 a = (a + 0xd3a2646c) ^ (a << 9);
242 a = (a + 0xfd7046c5) + (a << 3);
243 a = (a ^ 0xb55a4f09) ^ (a >> 16);
244 return a;
245}
246
247inline uint64_t Hash1(int64_t value) {
248 return Hash1(static_cast<uint64_t>(value));
249}
250
251inline uint64_t Hash1(int value) { return Hash1(static_cast<uint32_t>(value)); }
252
253inline uint64_t Hash1(void* const ptr) {
254#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || \
255 defined(__aarch64__) || (defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64))
256 return Hash1(reinterpret_cast<uint64_t>(ptr));
257#else
258 return Hash1(reinterpret_cast<uint32_t>(ptr));
259#endif
260}
261
262template <class T>
263uint64_t Hash1(const std::vector<T*>& ptrs) {
264 if (ptrs.empty()) return 0;
265 if (ptrs.size() == 1) return Hash1(ptrs[0]);
266 uint64_t hash = Hash1(ptrs[0]);
267 for (int i = 1; i < ptrs.size(); ++i) {
268 hash = hash * i + Hash1(ptrs[i]);
269 }
270 return hash;
271}
272
273inline uint64_t Hash1(const std::vector<int64_t>& ptrs) {
274 if (ptrs.empty()) return 0;
275 if (ptrs.size() == 1) return Hash1(ptrs[0]);
276 uint64_t hash = Hash1(ptrs[0]);
277 for (int i = 1; i < ptrs.size(); ++i) {
278 hash = hash * i + Hash1(ptrs[i]);
279 }
280 return hash;
281}
282
285template <class K, class V>
287 public:
288 RevImmutableMultiMap(Solver* const solver, int initial_size)
289 : solver_(solver),
290 array_(solver->UnsafeRevAllocArray(new Cell*[initial_size])),
291 size_(initial_size),
292 num_items_(0) {
293 memset(array_, 0, sizeof(*array_) * size_.Value());
294 }
295
297
298 int num_items() const { return num_items_.Value(); }
299
301 bool ContainsKey(const K& key) const {
302 uint64_t code = Hash1(key) % size_.Value();
303 Cell* tmp = array_[code];
304 while (tmp) {
305 if (tmp->key() == key) {
306 return true;
307 }
308 tmp = tmp->next();
309 }
310 return false;
311 }
312
316 const V& FindWithDefault(const K& key, const V& default_value) const {
317 uint64_t code = Hash1(key) % size_.Value();
318 Cell* tmp = array_[code];
319 while (tmp) {
320 if (tmp->key() == key) {
321 return tmp->value();
322 }
323 tmp = tmp->next();
324 }
325 return default_value;
326 }
327
329 void Insert(const K& key, const V& value) {
330 const int position = Hash1(key) % size_.Value();
331 Cell* const cell =
332 solver_->UnsafeRevAlloc(new Cell(key, value, array_[position]));
333 solver_->SaveAndSetValue(reinterpret_cast<void**>(&array_[position]),
334 reinterpret_cast<void*>(cell));
335 num_items_.Incr(solver_);
336 if (num_items_.Value() > 2 * size_.Value()) {
337 Double();
338 }
339 }
340
341 private:
342 class Cell {
343 public:
344 Cell(const K& key, const V& value, Cell* const next)
345 : key_(key), value_(value), next_(next) {}
346
347 void SetRevNext(Solver* const solver, Cell* const next) {
348 solver->SaveAndSetValue(reinterpret_cast<void**>(&next_),
349 reinterpret_cast<void*>(next));
350 }
351
352 Cell* next() const { return next_; }
353
354 const K& key() const { return key_; }
355
356 const V& value() const { return value_; }
357
358 private:
359 const K key_;
360 const V value_;
361 Cell* next_;
362 };
363
364 void Double() {
365 Cell** const old_cell_array = array_;
366 const int old_size = size_.Value();
367 size_.SetValue(solver_, size_.Value() * 2);
368 solver_->SaveAndSetValue(
369 reinterpret_cast<void**>(&array_),
370 reinterpret_cast<void*>(
371 solver_->UnsafeRevAllocArray(new Cell*[size_.Value()])));
372 memset(array_, 0, size_.Value() * sizeof(*array_));
373 for (int i = 0; i < old_size; ++i) {
374 Cell* tmp = old_cell_array[i];
375 while (tmp != nullptr) {
376 Cell* const to_reinsert = tmp;
377 tmp = tmp->next();
378 const uint64_t new_position = Hash1(to_reinsert->key()) % size_.Value();
379 to_reinsert->SetRevNext(solver_, array_[new_position]);
380 solver_->SaveAndSetValue(
381 reinterpret_cast<void**>(&array_[new_position]),
382 reinterpret_cast<void*>(to_reinsert));
383 }
384 }
385 }
386
387 Solver* const solver_;
388 Cell** array_;
389 NumericalRev<int> size_;
390 NumericalRev<int> num_items_;
391};
392
394class RevSwitch {
395 public:
396 RevSwitch() : value_(false) {}
397
398 bool Switched() const { return value_; }
399
400 void Switch(Solver* const solver) { solver->SaveAndSetValue(&value_, true); }
401
402 private:
403 bool value_;
405
408class SmallRevBitSet {
409 public:
410 explicit SmallRevBitSet(int64_t size);
412 void SetToOne(Solver* solver, int64_t pos);
414 void SetToZero(Solver* solver, int64_t pos);
416 int64_t Cardinality() const;
418 bool IsCardinalityZero() const { return bits_.Value() == uint64_t{0}; }
420 bool IsCardinalityOne() const {
421 return (bits_.Value() != 0) && !(bits_.Value() & (bits_.Value() - 1));
424 /// It returns -1 if the bitset is empty.
425 int64_t GetFirstOne() const;
426
427 private:
428 Rev<uint64_t> bits_;
429};
430
433class RevBitSet {
434 public:
435 explicit RevBitSet(int64_t size);
436
437 /// Sets the 'index' bit.
438 void SetToOne(Solver* solver, int64_t index);
440 void SetToZero(Solver* solver, int64_t index);
442 bool IsSet(int64_t index) const;
444 int64_t Cardinality() const;
446 bool IsCardinalityZero() const;
448 bool IsCardinalityOne() const;
451 int64_t GetFirstBit(int start) const;
453 void ClearAll(Solver* solver);
454
455 friend class RevBitMatrix;
456
457 private:
459 void Save(Solver* solver, int offset);
460 const int64_t size_;
461 const int64_t length_;
462 std::unique_ptr<uint64_t[]> bits_;
463 std::unique_ptr<uint64_t[]> stamps_;
464};
465
467class RevBitMatrix : private RevBitSet {
468 public:
469 RevBitMatrix(int64_t rows, int64_t columns);
473 void SetToOne(Solver* solver, int64_t row, int64_t column);
475 void SetToZero(Solver* solver, int64_t row, int64_t column);
477 bool IsSet(int64_t row, int64_t column) const {
478 DCHECK_GE(row, 0);
479 DCHECK_LT(row, rows_);
480 DCHECK_GE(column, 0);
481 DCHECK_LT(column, columns_);
482 return RevBitSet::IsSet(row * columns_ + column);
483 }
485 int64_t Cardinality(int row) const;
487 bool IsCardinalityZero(int row) const;
488
489 bool IsCardinalityOne(int row) const;
492 int64_t GetFirstBit(int row, int start) const;
494 void ClearAll(Solver* solver);
495
496 private:
497 const int64_t rows_;
498 const int64_t columns_;
499};
500
504
506
508template <class T>
509class CallMethod0 : public Demon {
510 public:
511 CallMethod0(T* const ct, void (T::*method)(), const std::string& name)
512 : constraint_(ct), method_(method), name_(name) {}
514 ~CallMethod0() override {}
516 void Run(Solver* const) override { (constraint_->*method_)(); }
517
518 std::string DebugString() const override {
519 return "CallMethod_" + name_ + "(" + constraint_->DebugString() + ")";
521
522 private:
523 T* const constraint_;
524 void (T::* const method_)();
525 const std::string name_;
526};
527
528template <class T>
529Demon* MakeConstraintDemon0(Solver* const s, T* const ct, void (T::*method)(),
530 const std::string& name) {
531 return s->RevAlloc(new CallMethod0<T>(ct, method, name));
532}
534template <class P>
535std::string ParameterDebugString(P param) {
536 return absl::StrCat(param);
537}
538
539/// Support limited to pointers to classes which define DebugString().
540template <class P>
541std::string ParameterDebugString(P* param) {
542 return param->DebugString();
543}
544
545/// Demon proxy to a method on the constraint with one argument.
546template <class T, class P>
547class CallMethod1 : public Demon {
548 public:
549 CallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
550 P param1)
551 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
552
553 ~CallMethod1() override {}
554
555 void Run(Solver* const) override { (constraint_->*method_)(param1_); }
556
557 std::string DebugString() const override {
558 return absl::StrCat("CallMethod_", name_, "(", constraint_->DebugString(),
559 ", ", ParameterDebugString(param1_), ")");
560 }
562 private:
563 T* const constraint_;
564 void (T::* const method_)(P);
565 const std::string name_;
566 P param1_;
567};
568
569template <class T, class P>
570Demon* MakeConstraintDemon1(Solver* const s, T* const ct, void (T::*method)(P),
571 const std::string& name, P param1) {
572 return s->RevAlloc(new CallMethod1<T, P>(ct, method, name, param1));
573}
576template <class T, class P, class Q>
577class CallMethod2 : public Demon {
578 public:
579 CallMethod2(T* const ct, void (T::*method)(P, Q), const std::string& name,
580 P param1, Q param2)
581 : constraint_(ct),
582 method_(method),
583 name_(name),
584 param1_(param1),
585 param2_(param2) {}
586
587 ~CallMethod2() override {}
588
589 void Run(Solver* const) override {
590 (constraint_->*method_)(param1_, param2_);
592
593 std::string DebugString() const override {
594 return absl::StrCat("CallMethod_", name_, "(", constraint_->DebugString(),
595 ", ", ParameterDebugString(param1_), ", ",
596 ParameterDebugString(param2_), ")");
598
599 private:
600 T* const constraint_;
601 void (T::* const method_)(P, Q);
602 const std::string name_;
603 P param1_;
604 Q param2_;
605};
606
607template <class T, class P, class Q>
608Demon* MakeConstraintDemon2(Solver* const s, T* const ct,
609 void (T::*method)(P, Q), const std::string& name,
610 P param1, Q param2) {
611 return s->RevAlloc(
612 new CallMethod2<T, P, Q>(ct, method, name, param1, param2));
613}
615template <class T, class P, class Q, class R>
616class CallMethod3 : public Demon {
617 public:
618 CallMethod3(T* const ct, void (T::*method)(P, Q, R), const std::string& name,
619 P param1, Q param2, R param3)
620 : constraint_(ct),
621 method_(method),
622 name_(name),
623 param1_(param1),
624 param2_(param2),
625 param3_(param3) {}
626
627 ~CallMethod3() override {}
628
629 void Run(Solver* const) override {
630 (constraint_->*method_)(param1_, param2_, param3_);
632
633 std::string DebugString() const override {
634 return absl::StrCat(absl::StrCat("CallMethod_", name_),
635 absl::StrCat("(", constraint_->DebugString()),
636 absl::StrCat(", ", ParameterDebugString(param1_)),
637 absl::StrCat(", ", ParameterDebugString(param2_)),
638 absl::StrCat(", ", ParameterDebugString(param3_), ")"));
639 }
640
641 private:
642 T* const constraint_;
643 void (T::* const method_)(P, Q, R);
644 const std::string name_;
645 P param1_;
646 Q param2_;
647 R param3_;
648};
649
650template <class T, class P, class Q, class R>
651Demon* MakeConstraintDemon3(Solver* const s, T* const ct,
652 void (T::*method)(P, Q, R), const std::string& name,
653 P param1, Q param2, R param3) {
654 return s->RevAlloc(
655 new CallMethod3<T, P, Q, R>(ct, method, name, param1, param2, param3));
656}
658
661
663
665template <class T>
666class DelayedCallMethod0 : public Demon {
667 public:
668 DelayedCallMethod0(T* const ct, void (T::*method)(), const std::string& name)
669 : constraint_(ct), method_(method), name_(name) {}
671 ~DelayedCallMethod0() override {}
673 void Run(Solver* const) override { (constraint_->*method_)(); }
674
678
679 std::string DebugString() const override {
680 return "DelayedCallMethod_" + name_ + "(" + constraint_->DebugString() +
681 ")";
682 }
684 private:
685 T* const constraint_;
686 void (T::* const method_)();
687 const std::string name_;
688};
689
690template <class T>
691Demon* MakeDelayedConstraintDemon0(Solver* const s, T* const ct,
692 void (T::*method)(),
693 const std::string& name) {
694 return s->RevAlloc(new DelayedCallMethod0<T>(ct, method, name));
696
698template <class T, class P>
699class DelayedCallMethod1 : public Demon {
700 public:
701 DelayedCallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
702 P param1)
703 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
704
706
707 void Run(Solver* const) override { (constraint_->*method_)(param1_); }
708
712
713 std::string DebugString() const override {
714 return absl::StrCat("DelayedCallMethod_", name_, "(",
715 constraint_->DebugString(), ", ",
716 ParameterDebugString(param1_), ")");
718
719 private:
720 T* const constraint_;
721 void (T::* const method_)(P);
722 const std::string name_;
723 P param1_;
724};
725
726template <class T, class P>
727Demon* MakeDelayedConstraintDemon1(Solver* const s, T* const ct,
728 void (T::*method)(P),
729 const std::string& name, P param1) {
730 return s->RevAlloc(new DelayedCallMethod1<T, P>(ct, method, name, param1));
732
734template <class T, class P, class Q>
735class DelayedCallMethod2 : public Demon {
736 public:
737 DelayedCallMethod2(T* const ct, void (T::*method)(P, Q),
738 const std::string& name, P param1, Q param2)
739 : constraint_(ct),
740 method_(method),
741 name_(name),
742 param1_(param1),
743 param2_(param2) {}
744
745 ~DelayedCallMethod2() override {}
746
747 void Run(Solver* const) override {
748 (constraint_->*method_)(param1_, param2_);
750
753 }
754
755 std::string DebugString() const override {
756 return absl::StrCat(absl::StrCat("DelayedCallMethod_", name_),
757 absl::StrCat("(", constraint_->DebugString()),
758 absl::StrCat(", ", ParameterDebugString(param1_)),
759 absl::StrCat(", ", ParameterDebugString(param2_), ")"));
760 }
761
762 private:
763 T* const constraint_;
764 void (T::* const method_)(P, Q);
765 const std::string name_;
766 P param1_;
767 Q param2_;
768};
769
770template <class T, class P, class Q>
771Demon* MakeDelayedConstraintDemon2(Solver* const s, T* const ct,
772 void (T::*method)(P, Q),
773 const std::string& name, P param1,
774 Q param2) {
775 return s->RevAlloc(
776 new DelayedCallMethod2<T, P, Q>(ct, method, name, param1, param2));
777}
779
780#endif // !defined(SWIG)
781
782// ----- LightIntFunctionElementCt -----
783
784template <typename F>
785class LightIntFunctionElementCt : public Constraint {
786 public:
787 LightIntFunctionElementCt(Solver* const solver, IntVar* const var,
788 IntVar* const index, F values,
789 std::function<bool()> deep_serialize)
791 var_(var),
792 index_(index),
793 values_(std::move(values)),
794 deep_serialize_(std::move(deep_serialize)) {}
795 ~LightIntFunctionElementCt() override {}
796
797 void Post() override {
798 Demon* demon = MakeConstraintDemon0(
799 solver(), this, &LightIntFunctionElementCt::IndexBound, "IndexBound");
800 index_->WhenBound(demon);
802
803 void InitialPropagate() override {
804 if (index_->Bound()) {
805 IndexBound();
806 }
808
809 std::string DebugString() const override {
810 return absl::StrFormat("LightIntFunctionElementCt(%s, %s)",
811 var_->DebugString(), index_->DebugString());
812 }
817 var_);
819 index_);
820 // Warning: This will expand all values into a vector.
821 if (deep_serialize_ == nullptr || deep_serialize_()) {
822 visitor->VisitInt64ToInt64Extension(values_, index_->Min(),
823 index_->Max());
824 }
826 }
827
828 private:
829 void IndexBound() { var_->SetValue(values_(index_->Min())); }
830
831 IntVar* const var_;
832 IntVar* const index_;
833 F values_;
834 std::function<bool()> deep_serialize_;
835};
836
837// ----- LightIntIntFunctionElementCt -----
838
839template <typename F>
841 public:
842 LightIntIntFunctionElementCt(Solver* const solver, IntVar* const var,
843 IntVar* const index1, IntVar* const index2,
844 F values, std::function<bool()> deep_serialize)
846 var_(var),
847 index1_(index1),
848 index2_(index2),
849 values_(std::move(values)),
850 deep_serialize_(std::move(deep_serialize)) {}
852 void Post() override {
853 Demon* demon = MakeConstraintDemon0(
854 solver(), this, &LightIntIntFunctionElementCt::IndexBound,
855 "IndexBound");
856 index1_->WhenBound(demon);
857 index2_->WhenBound(demon);
858 }
859 void InitialPropagate() override { IndexBound(); }
860
861 std::string DebugString() const override {
862 return "LightIntIntFunctionElementCt";
864
868 var_);
870 index1_);
872 index2_);
873 // Warning: This will expand all values into a vector.
874 const int64_t index1_min = index1_->Min();
875 const int64_t index1_max = index1_->Max();
878 if (deep_serialize_ == nullptr || deep_serialize_()) {
879 for (int i = index1_min; i <= index1_max; ++i) {
881 [this, i](int64_t j) { return values_(i, j); }, index2_->Min(),
882 index2_->Max());
883 }
884 }
886 }
887
888 private:
889 void IndexBound() {
890 if (index1_->Bound() && index2_->Bound()) {
891 var_->SetValue(values_(index1_->Min(), index2_->Min()));
892 }
893 }
894
895 IntVar* const var_;
896 IntVar* const index1_;
897 IntVar* const index2_;
898 F values_;
899 std::function<bool()> deep_serialize_;
900};
901
902// ----- LightIntIntIntFunctionElementCt -----
903
904template <typename F>
906 public:
907 LightIntIntIntFunctionElementCt(Solver* const solver, IntVar* const var,
908 IntVar* const index1, IntVar* const index2,
909 IntVar* const index3, F values)
911 var_(var),
912 index1_(index1),
913 index2_(index2),
914 index3_(index3),
915 values_(std::move(values)) {}
917 void Post() override {
918 Demon* demon = MakeConstraintDemon0(
919 solver(), this, &LightIntIntIntFunctionElementCt::IndexBound,
920 "IndexBound");
921 index1_->WhenBound(demon);
922 index2_->WhenBound(demon);
923 index3_->WhenBound(demon);
924 }
925 void InitialPropagate() override { IndexBound(); }
926
927 std::string DebugString() const override {
928 return "LightIntIntFunctionElementCt";
930
934 var_);
936 index1_);
938 index2_);
940 index3_);
942 }
943
944 private:
945 void IndexBound() {
946 if (index1_->Bound() && index2_->Bound() && index3_->Bound()) {
947 var_->SetValue(values_(index1_->Min(), index2_->Min(), index3_->Min()));
948 }
949 }
950
951 IntVar* const var_;
952 IntVar* const index1_;
953 IntVar* const index2_;
954 IntVar* const index3_;
955 F values_;
956};
957
961
975// TODO(user): rename Start to Synchronize ?
976// TODO(user): decouple the iterating from the defining of a neighbor.
977class LocalSearchOperator : public BaseObject {
978 public:
980 ~LocalSearchOperator() override {}
981 virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) = 0;
982 virtual void EnterSearch() {}
983 virtual void Start(const Assignment* assignment) = 0;
984 virtual void Reset() {}
985#ifndef SWIG
986 virtual const LocalSearchOperator* Self() const { return this; }
987#endif // SWIG
988 virtual bool HasFragments() const { return false; }
989 virtual bool HoldsDelta() const { return false; }
993 public:
995
997 max_inversible_index_ = candidate_values_.size();
998 candidate_value_to_index_.resize(max_value + 1, -1);
999 committed_value_to_index_.resize(max_value + 1, -1);
1001
1004 int64_t CandidateValue(int64_t index) const {
1005 DCHECK_LT(index, candidate_values_.size());
1006 return candidate_values_[index];
1007 }
1008 int64_t CommittedValue(int64_t index) const {
1009 return committed_values_[index];
1010 }
1011 int64_t CheckPointValue(int64_t index) const {
1012 return checkpoint_values_[index];
1013 }
1014 void SetCandidateValue(int64_t index, int64_t value) {
1015 candidate_values_[index] = value;
1016 if (index < max_inversible_index_) {
1017 candidate_value_to_index_[value] = index;
1018 }
1019 MarkChange(index);
1020 }
1021
1022 bool CandidateIsActive(int64_t index) const {
1023 return candidate_is_active_[index];
1024 }
1025 void SetCandidateActive(int64_t index, bool active) {
1026 if (active) {
1027 candidate_is_active_.Set(index);
1028 } else {
1029 candidate_is_active_.Clear(index);
1031 MarkChange(index);
1032 }
1034 void Commit() {
1035 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
1036 const int64_t value = candidate_values_[index];
1037 committed_values_[index] = value;
1038 if (index < max_inversible_index_) {
1039 committed_value_to_index_[value] = index;
1040 }
1041 committed_is_active_.CopyBucket(candidate_is_active_, index);
1043 changes_.ResetAllToFalse();
1044 incremental_changes_.ResetAllToFalse();
1045 }
1046
1047 void CheckPoint() { checkpoint_values_ = committed_values_; }
1048
1049 void Revert(bool only_incremental) {
1050 incremental_changes_.ResetAllToFalse();
1051 if (only_incremental) return;
1052
1053 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
1054 const int64_t committed_value = committed_values_[index];
1055 candidate_values_[index] = committed_value;
1056 if (index < max_inversible_index_) {
1057 candidate_value_to_index_[committed_value] = index;
1058 }
1059 candidate_is_active_.CopyBucket(committed_is_active_, index);
1060 }
1061 changes_.ResetAllToFalse();
1062 }
1063
1064 const std::vector<int64_t>& CandidateIndicesChanged() const {
1065 return changes_.PositionsSetAtLeastOnce();
1066 }
1067 const std::vector<int64_t>& IncrementalIndicesChanged() const {
1068 return incremental_changes_.PositionsSetAtLeastOnce();
1069 }
1070
1071 void Resize(int size) {
1072 candidate_values_.resize(size);
1073 committed_values_.resize(size);
1074 checkpoint_values_.resize(size);
1075 candidate_is_active_.Resize(size);
1076 committed_is_active_.Resize(size);
1077 changes_.ClearAndResize(size);
1078 incremental_changes_.ClearAndResize(size);
1080
1081 int64_t CandidateInverseValue(int64_t value) const {
1082 return candidate_value_to_index_[value];
1083 }
1084 int64_t CommittedInverseValue(int64_t value) const {
1085 return committed_value_to_index_[value];
1086 }
1087
1088 private:
1089 void MarkChange(int64_t index) {
1090 incremental_changes_.Set(index);
1091 changes_.Set(index);
1093
1094 std::vector<int64_t> candidate_values_;
1095 std::vector<int64_t> committed_values_;
1096 std::vector<int64_t> checkpoint_values_;
1097
1098 Bitset64<> candidate_is_active_;
1099 Bitset64<> committed_is_active_;
1100
1101 SparseBitset<> changes_;
1102 SparseBitset<> incremental_changes_;
1103
1104 int64_t max_inversible_index_ = -1;
1105 std::vector<int64_t> candidate_value_to_index_;
1106 std::vector<int64_t> committed_value_to_index_;
1107};
1108
1114class IntVarLocalSearchOperator : public LocalSearchOperator {
1115 public:
1116 // If keep_inverse_values is true, assumes that vars models an injective
1117 // function f with domain [0, vars.size()) in which case the operator will
1118 // maintain the inverse function.
1119 explicit IntVarLocalSearchOperator(const std::vector<IntVar*>& vars,
1120 bool keep_inverse_values = false) {
1121 AddVars(vars);
1122 if (keep_inverse_values) {
1123 int64_t max_value = -1;
1124 for (const IntVar* const var : vars) {
1125 max_value = std::max(max_value, var->Max());
1126 }
1127 state_.SetCurrentDomainInjectiveAndKeepInverseValues(max_value);
1128 }
1129 }
1130 ~IntVarLocalSearchOperator() override {}
1131
1132 bool HoldsDelta() const override { return true; }
1135 void Start(const Assignment* assignment) override {
1136 state_.CheckPoint();
1137 RevertChanges(false);
1138 const int size = Size();
1139 CHECK_LE(size, assignment->Size())
1140 << "Assignment contains fewer variables than operator";
1141 const Assignment::IntContainer& container = assignment->IntVarContainer();
1142 for (int i = 0; i < size; ++i) {
1143 const IntVarElement* element = &(container.Element(i));
1144 if (element->Var() != vars_[i]) {
1145 CHECK(container.Contains(vars_[i]))
1146 << "Assignment does not contain operator variable " << vars_[i];
1147 element = &(container.Element(vars_[i]));
1148 }
1149 state_.SetCandidateValue(i, element->Value());
1150 state_.SetCandidateActive(i, element->Activated());
1151 }
1152 state_.Commit();
1153 OnStart();
1154 }
1155 virtual bool IsIncremental() const { return false; }
1156
1157 int Size() const { return vars_.size(); }
1160 int64_t Value(int64_t index) const {
1161 DCHECK_LT(index, vars_.size());
1162 return state_.CandidateValue(index);
1165 IntVar* Var(int64_t index) const { return vars_[index]; }
1166 virtual bool SkipUnchanged(int) const { return false; }
1167 int64_t OldValue(int64_t index) const { return state_.CommittedValue(index); }
1168 int64_t PrevValue(int64_t index) const {
1169 return state_.CheckPointValue(index);
1170 }
1171 void SetValue(int64_t index, int64_t value) {
1172 state_.SetCandidateValue(index, value);
1174 bool Activated(int64_t index) const {
1175 return state_.CandidateIsActive(index);
1177 void Activate(int64_t index) { state_.SetCandidateActive(index, true); }
1178 void Deactivate(int64_t index) { state_.SetCandidateActive(index, false); }
1180 bool ApplyChanges(Assignment* delta, Assignment* deltadelta) const {
1181 if (IsIncremental() && candidate_has_changes_) {
1182 for (const int64_t index : state_.IncrementalIndicesChanged()) {
1183 IntVar* var = Var(index);
1184 const int64_t value = Value(index);
1185 const bool activated = Activated(index);
1186 AddToAssignment(var, value, activated, nullptr, index, deltadelta);
1187 AddToAssignment(var, value, activated, &assignment_indices_, index,
1188 delta);
1189 }
1190 } else {
1191 delta->Clear();
1192 for (const int64_t index : state_.CandidateIndicesChanged()) {
1193 const int64_t value = Value(index);
1194 const bool activated = Activated(index);
1195 if (!activated || value != OldValue(index) || !SkipUnchanged(index)) {
1196 AddToAssignment(Var(index), value, activated, &assignment_indices_,
1197 index, delta);
1198 }
1199 }
1200 }
1201 return true;
1202 }
1203
1204 void RevertChanges(bool change_was_incremental) {
1205 candidate_has_changes_ = change_was_incremental && IsIncremental();
1206
1207 if (!candidate_has_changes_) {
1208 for (const int64_t index : state_.CandidateIndicesChanged()) {
1209 assignment_indices_[index] = -1;
1210 }
1211 }
1212 state_.Revert(candidate_has_changes_);
1213 }
1214
1215 void AddVars(const std::vector<IntVar*>& vars) {
1216 if (!vars.empty()) {
1217 vars_.insert(vars_.end(), vars.begin(), vars.end());
1218 const int64_t size = Size();
1219 assignment_indices_.resize(size, -1);
1220 state_.Resize(size);
1221 }
1222 }
1227 virtual void OnStart() {}
1228
1231
1238 bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
1239
1240 protected:
1243 // TODO(user): make it pure virtual, implies porting all apps overriding
1245 virtual bool MakeOneNeighbor();
1246
1247 int64_t InverseValue(int64_t index) const {
1248 return state_.CandidateInverseValue(index);
1249 }
1250 int64_t OldInverseValue(int64_t index) const {
1251 return state_.CommittedInverseValue(index);
1252 }
1253
1254 void AddToAssignment(IntVar* var, int64_t value, bool active,
1255 std::vector<int>* assignment_indices, int64_t index,
1256 Assignment* assignment) const {
1257 Assignment::IntContainer* const container =
1259 IntVarElement* element = nullptr;
1260 if (assignment_indices != nullptr) {
1261 if ((*assignment_indices)[index] == -1) {
1262 (*assignment_indices)[index] = container->Size();
1263 element = assignment->FastAdd(var);
1264 } else {
1265 element = container->MutableElement((*assignment_indices)[index]);
1266 }
1267 } else {
1268 element = assignment->FastAdd(var);
1269 }
1270 if (active) {
1271 element->SetValue(value);
1272 element->Activate();
1273 } else {
1274 element->Deactivate();
1275 }
1276 }
1277
1278 private:
1279 std::vector<IntVar*> vars_;
1280 mutable std::vector<int> assignment_indices_;
1281 bool candidate_has_changes_ = false;
1282
1283 LocalSearchOperatorState state_;
1284};
1285
1293
1313class BaseLns : public IntVarLocalSearchOperator {
1314 public:
1315 explicit BaseLns(const std::vector<IntVar*>& vars);
1316 ~BaseLns() override;
1317 virtual void InitFragments();
1318 virtual bool NextFragment() = 0;
1319 void AppendToFragment(int index);
1320 int FragmentSize() const;
1321 bool HasFragments() const override { return true; }
1322
1323 protected:
1324 /// This method should not be overridden. Override NextFragment() instead.
1325 bool MakeOneNeighbor() override;
1326
1327 private:
1329 void OnStart() override;
1330 std::vector<int> fragment_;
1331};
1338 public:
1339 explicit ChangeValue(const std::vector<IntVar*>& vars);
1340 ~ChangeValue() override;
1341 virtual int64_t ModifyValue(int64_t index, int64_t value) = 0;
1342
1343 protected:
1345 bool MakeOneNeighbor() override;
1346
1347 private:
1348 void OnStart() override;
1349
1350 int index_;
1351};
1353// Iterators on nodes used by Pathoperator to traverse the search space.
1354
1356 public:
1357 explicit AlternativeNodeIterator(bool use_sibling)
1358 : use_sibling_(use_sibling) {}
1360 template <class PathOperator>
1361 void Reset(const PathOperator& path_operator, int base_index_reference) {
1362 index_ = 0;
1363 DCHECK(path_operator.ConsiderAlternatives(base_index_reference));
1364 const int64_t base_node = path_operator.BaseNode(base_index_reference);
1365 const int alternative_index =
1366 use_sibling_ ? path_operator.GetSiblingAlternativeIndex(base_node)
1367 : path_operator.GetAlternativeIndex(base_node);
1368 alternative_set_ =
1369 alternative_index >= 0
1370 ? absl::Span<const int64_t>(
1371 path_operator.alternative_sets_[alternative_index])
1372 : absl::Span<const int64_t>();
1373 }
1374 bool Next() { return ++index_ < alternative_set_.size(); }
1375 int GetValue() const {
1376 return (index_ >= alternative_set_.size()) ? -1 : alternative_set_[index_];
1377 }
1378
1379 private:
1380 const bool use_sibling_;
1381 int index_ = 0;
1382 absl::Span<const int64_t> alternative_set_;
1383};
1384
1386 public:
1389 template <class PathOperator>
1390 void Reset(const PathOperator& path_operator, int base_index_reference) {
1391 using Span = absl::Span<const int>;
1392 index_ = 0;
1393 const int64_t base_node = path_operator.BaseNode(base_index_reference);
1394 const int64_t start_node = path_operator.StartNode(base_index_reference);
1395 const auto& get_incoming_neighbors =
1396 path_operator.iteration_parameters_.get_incoming_neighbors;
1397 incoming_neighbors_ =
1398 path_operator.IsPathStart(base_node) || !get_incoming_neighbors
1399 ? Span()
1400 : Span(get_incoming_neighbors(base_node, start_node));
1401 const auto& get_outgoing_neighbors =
1402 path_operator.iteration_parameters_.get_outgoing_neighbors;
1403 outgoing_neighbors_ =
1404 path_operator.IsPathEnd(base_node) || !get_outgoing_neighbors
1405 ? Span()
1406 : Span(get_outgoing_neighbors(base_node, start_node));
1407 }
1408 bool Next() {
1409 return ++index_ < incoming_neighbors_.size() + outgoing_neighbors_.size();
1410 }
1411 int GetValue() const {
1412 if (index_ < incoming_neighbors_.size()) {
1413 return incoming_neighbors_[index_];
1414 }
1415 const int index = index_ - incoming_neighbors_.size();
1416 return (index >= outgoing_neighbors_.size()) ? -1
1417 : outgoing_neighbors_[index];
1418 }
1419 bool IsIncomingNeighbor() const {
1420 return index_ < incoming_neighbors_.size();
1421 }
1422 bool IsOutgoingNeighbor() const {
1423 return index_ >= incoming_neighbors_.size();
1424 }
1425
1426 private:
1427 int index_ = 0;
1428 absl::Span<const int> incoming_neighbors_;
1429 absl::Span<const int> outgoing_neighbors_;
1431
1432template <class PathOperator>
1434 public:
1435 BaseNodeIterators(const PathOperator* path_operator, int base_index_reference)
1436 : path_operator_(*path_operator),
1437 base_index_reference_(base_index_reference) {}
1439 DCHECK(!alternatives_.empty());
1440 DCHECK(!finished_);
1441 return alternatives_[0].get();
1442 }
1444 DCHECK(!alternatives_.empty());
1445 DCHECK(!finished_);
1446 return alternatives_[1].get();
1447 }
1449 DCHECK(neighbors_);
1450 DCHECK(!finished_);
1451 return neighbors_.get();
1452 }
1453 void Initialize() {
1454 if (path_operator_.ConsiderAlternatives(base_index_reference_)) {
1455 alternatives_.push_back(std::make_unique<AlternativeNodeIterator>(
1456 /*is_sibling=*/true));
1457 alternatives_.push_back(std::make_unique<AlternativeNodeIterator>(
1458 /*is_sibling=*/false));
1460 if (path_operator_.HasNeighbors()) {
1461 neighbors_ = std::make_unique<NodeNeighborIterator>();
1462 }
1463 }
1464 void Reset(bool update_end_nodes = false) {
1465 finished_ = false;
1466 for (auto& alternative_iterator : alternatives_) {
1467 alternative_iterator->Reset(path_operator_, base_index_reference_);
1468 }
1469 if (neighbors_) {
1470 neighbors_->Reset(path_operator_, base_index_reference_);
1471 if (update_end_nodes) neighbor_end_node_ = neighbors_->GetValue();
1472 }
1473 }
1474 bool Increment() {
1475 DCHECK(!finished_);
1476 for (auto& alternative_iterator : alternatives_) {
1477 if (alternative_iterator->Next()) return true;
1478 alternative_iterator->Reset(path_operator_, base_index_reference_);
1479 }
1480 if (neighbors_) {
1481 if (neighbors_->Next()) return true;
1482 neighbors_->Reset(path_operator_, base_index_reference_);
1483 }
1484 finished_ = true;
1485 return false;
1486 }
1487 bool HasReachedEnd() const {
1488 // TODO(user): Extend to other iterators.
1489 if (!neighbors_) return true;
1490 return neighbor_end_node_ == neighbors_->GetValue();
1491 }
1492
1493 private:
1494 const PathOperator& path_operator_;
1495 int base_index_reference_ = -1;
1496#ifndef SWIG
1497 std::vector<std::unique_ptr<AlternativeNodeIterator>> alternatives_;
1498#endif // SWIG
1499 std::unique_ptr<NodeNeighborIterator> neighbors_;
1500 int neighbor_end_node_ = -1;
1501 bool finished_ = false;
1502};
1503
1514
1517template <bool ignore_path_vars>
1519 public:
1521 struct IterationParameters {
1529 /// Callback returning an index such that if
1530 /// c1 = start_empty_path_class(StartNode(p1)),
1531 /// c2 = start_empty_path_class(StartNode(p2)),
1532 /// p1 and p2 are path indices,
1533 /// then if c1 == c2, p1 and p2 are equivalent if they are empty.
1534 /// This is used to remove neighborhood symmetries on equivalent empty
1535 /// paths; for instance if a node cannot be moved to an empty path, then all
1536 /// moves moving the same node to equivalent empty paths will be skipped.
1537 /// 'start_empty_path_class' can be nullptr in which case no symmetries will
1538 /// be removed.
1539 std::function<int(int64_t)> start_empty_path_class;
1542 std::function<const std::vector<int>&(
1543 /*node=*/int, /*start_node=*/int)>
1545 std::function<const std::vector<int>&(
1546 /*node=*/int, /*start_node=*/int)>
1548 };
1550 PathOperator(const std::vector<IntVar*>& next_vars,
1551 const std::vector<IntVar*>& path_vars,
1552 IterationParameters iteration_parameters)
1553 : IntVarLocalSearchOperator(next_vars, true),
1554 number_of_nexts_(next_vars.size()),
1555 base_nodes_(
1556 std::make_unique<int[]>(iteration_parameters.number_of_base_nodes)),
1557 end_nodes_(
1558 std::make_unique<int[]>(iteration_parameters.number_of_base_nodes)),
1559 base_paths_(
1560 std::make_unique<int[]>(iteration_parameters.number_of_base_nodes)),
1561 node_path_starts_(number_of_nexts_, -1),
1562 node_path_ends_(number_of_nexts_, -1),
1563 just_started_(false),
1564 first_start_(true),
1565 next_base_to_increment_(iteration_parameters.number_of_base_nodes),
1566 iteration_parameters_(std::move(iteration_parameters)),
1567 optimal_paths_enabled_(false),
1568 active_paths_(number_of_nexts_),
1569 alternative_index_(next_vars.size(), -1) {
1570 DCHECK_GT(iteration_parameters_.number_of_base_nodes, 0);
1571 for (int i = 0; i < iteration_parameters_.number_of_base_nodes; ++i) {
1572 base_node_iterators_.push_back(BaseNodeIterators<PathOperator>(this, i));
1573 }
1574 if constexpr (!ignore_path_vars) {
1575 AddVars(path_vars);
1576 }
1577 path_basis_.push_back(0);
1578 for (int i = 1; i < iteration_parameters_.number_of_base_nodes; ++i) {
1579 if (!OnSamePathAsPreviousBase(i)) path_basis_.push_back(i);
1580 }
1581 if ((path_basis_.size() > 2) ||
1582 (!next_vars.empty() && !next_vars.back()
1583 ->solver()
1584 ->parameters()
1585 .skip_locally_optimal_paths())) {
1586 iteration_parameters_.skip_locally_optimal_paths = false;
1587 }
1588 }
1590 const std::vector<IntVar*>& next_vars,
1591 const std::vector<IntVar*>& path_vars, int number_of_base_nodes,
1592 bool skip_locally_optimal_paths, bool accept_path_end_base,
1593 std::function<int(int64_t)> start_empty_path_class,
1594 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors,
1595 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors)
1596 : PathOperator(next_vars, path_vars,
1597 {number_of_base_nodes, skip_locally_optimal_paths,
1598 accept_path_end_base, std::move(start_empty_path_class),
1599 std::move(get_incoming_neighbors),
1600 std::move(get_outgoing_neighbors)}) {}
1601 ~PathOperator() override {}
1602 virtual bool MakeNeighbor() = 0;
1603 void EnterSearch() override {
1604 first_start_ = true;
1606 }
1607 void Reset() override {
1608 active_paths_.Clear();
1610 }
1611
1612 // TODO(user): Make the following methods protected.
1613 bool SkipUnchanged(int index) const override {
1614 if constexpr (ignore_path_vars) return true;
1615 if (index < number_of_nexts_) {
1616 const int path_index = index + number_of_nexts_;
1617 return Value(path_index) == OldValue(path_index);
1619 const int next_index = index - number_of_nexts_;
1620 return Value(next_index) == OldValue(next_index);
1621 }
1622
1624 int64_t Next(int64_t node) const {
1625 DCHECK(!IsPathEnd(node));
1626 return Value(node);
1627 }
1628
1630 int64_t Prev(int64_t node) const {
1631 DCHECK(!IsPathStart(node));
1632 DCHECK_EQ(Next(InverseValue(node)), node);
1633 return InverseValue(node);
1634 }
1638 int64_t Path(int64_t node) const {
1639 if constexpr (ignore_path_vars) return 0LL;
1640 return Value(node + number_of_nexts_);
1642
1644 int number_of_nexts() const { return number_of_nexts_; }
1645
1646 protected:
1648 bool MakeOneNeighbor() override {
1649 while (IncrementPosition()) {
1650 // Need to revert changes here since MakeNeighbor might have returned
1651 // false and have done changes in the previous iteration.
1652 RevertChanges(true);
1653 if (MakeNeighbor()) {
1654 return true;
1656 }
1657 return false;
1658 }
1663 virtual void OnNodeInitialization() {}
1668 virtual void ResetIncrementalism() {}
1669
1670
1671 int64_t BaseNode(int i) const { return base_nodes_[i]; }
1673 int64_t BaseAlternativeNode(int i) const {
1674 return GetNodeWithDefault(base_node_iterators_[i].GetAlternativeIterator(),
1675 BaseNode(i));
1676 }
1678 int64_t BaseSiblingAlternativeNode(int i) const {
1679 return GetNodeWithDefault(
1680 base_node_iterators_[i].GetSiblingAlternativeIterator(), BaseNode(i));
1681 }
1683 int64_t StartNode(int i) const { return path_starts_[base_paths_[i]]; }
1684 /// Returns the end node of the ith base node.
1685 int64_t EndNode(int i) const { return path_ends_[base_paths_[i]]; }
1687 const std::vector<int64_t>& path_starts() const { return path_starts_; }
1688
1689 int PathClass(int i) const { return PathClassFromStartNode(StartNode(i)); }
1690 int PathClassFromStartNode(int64_t start_node) const {
1691 return iteration_parameters_.start_empty_path_class != nullptr
1692 ? iteration_parameters_.start_empty_path_class(start_node)
1693 : start_node;
1695
1701 /// leading to potentially skipping neighbors.
1702 // TODO(user): remove this when automatic detection of such cases in done.
1703 virtual bool RestartAtPathStartOnSynchronize() { return false; }
1706
1707 // TODO(user): ideally this should be OnSamePath(int64_t node1, int64_t
1708 // node2);
1710 virtual bool OnSamePathAsPreviousBase(int64_t) { return false; }
1716 virtual int64_t GetBaseNodeRestartPosition(int base_index) {
1717 return StartNode(base_index);
1718 }
1721 virtual void SetNextBaseToIncrement(int64_t base_index) {
1722 next_base_to_increment_ = base_index;
1723 }
1726 virtual bool ConsiderAlternatives(int64_t) const { return false; }
1728 int64_t OldNext(int64_t node) const {
1729 DCHECK(!IsPathEnd(node));
1730 return OldValue(node);
1731 }
1733 int64_t PrevNext(int64_t node) const {
1734 DCHECK(!IsPathEnd(node));
1735 return PrevValue(node);
1736 }
1738 int64_t OldPrev(int64_t node) const {
1739 DCHECK(!IsPathStart(node));
1740 return OldInverseValue(node);
1741 }
1742
1743 int64_t OldPath(int64_t node) const {
1744 if constexpr (ignore_path_vars) return 0LL;
1745 return OldValue(node + number_of_nexts_);
1746 }
1747
1748 int CurrentNodePathStart(int64_t node) const {
1749 return node_path_starts_[node];
1750 }
1751
1752 int CurrentNodePathEnd(int64_t node) const { return node_path_ends_[node]; }
1753
1754 /// Moves the chain starting after the node before_chain and ending at the
1755 /// node chain_end after the node destination
1756 bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination) {
1757 if (destination == before_chain || destination == chain_end) return false;
1758 DCHECK(CheckChainValidity(before_chain, chain_end, destination) &&
1759 !IsPathEnd(chain_end) && !IsPathEnd(destination));
1760 const int64_t destination_path = Path(destination);
1761 const int64_t after_chain = Next(chain_end);
1762 SetNext(chain_end, Next(destination), destination_path);
1763 if constexpr (!ignore_path_vars) {
1764 int current = destination;
1765 int next = Next(before_chain);
1766 while (current != chain_end) {
1767 SetNext(current, next, destination_path);
1768 current = next;
1769 next = Next(next);
1770 }
1771 } else {
1772 SetNext(destination, Next(before_chain), destination_path);
1773 }
1774 SetNext(before_chain, after_chain, Path(before_chain));
1775 return true;
1776 }
1777
1780 bool ReverseChain(int64_t before_chain, int64_t after_chain,
1781 int64_t* chain_last) {
1782 if (CheckChainValidity(before_chain, after_chain, -1)) {
1783 int64_t path = Path(before_chain);
1784 int64_t current = Next(before_chain);
1785 if (current == after_chain) {
1786 return false;
1787 }
1788 int64_t current_next = Next(current);
1789 SetNext(current, after_chain, path);
1790 while (current_next != after_chain) {
1791 const int64_t next = Next(current_next);
1792 SetNext(current_next, current, path);
1793 current = current_next;
1794 current_next = next;
1795 }
1796 SetNext(before_chain, current, path);
1797 *chain_last = current;
1798 return true;
1799 }
1800 return false;
1801 }
1802
1804 bool SwapNodes(int64_t node1, int64_t node2) {
1805 if (IsPathEnd(node1) || IsPathEnd(node2) || IsPathStart(node1) ||
1806 IsPathStart(node2)) {
1807 return false;
1808 }
1809 if (node1 == node2) return false;
1810 const int64_t prev_node1 = Prev(node1);
1811 const bool ok = MoveChain(prev_node1, node1, Prev(node2));
1812 return MoveChain(Prev(node2), node2, prev_node1) || ok;
1813 }
1814
1815 /// Insert the inactive node after destination.
1816 bool MakeActive(int64_t node, int64_t destination) {
1817 if (IsPathEnd(destination)) return false;
1818 const int64_t destination_path = Path(destination);
1819 SetNext(node, Next(destination), destination_path);
1820 SetNext(destination, node, destination_path);
1821 return true;
1822 }
1825 bool MakeChainInactive(int64_t before_chain, int64_t chain_end) {
1826 const int64_t kNoPath = -1;
1827 if (CheckChainValidity(before_chain, chain_end, -1) &&
1828 !IsPathEnd(chain_end)) {
1829 const int64_t after_chain = Next(chain_end);
1830 int64_t current = Next(before_chain);
1831 while (current != after_chain) {
1832 const int64_t next = Next(current);
1833 SetNext(current, current, kNoPath);
1834 current = next;
1835 }
1836 SetNext(before_chain, after_chain, Path(before_chain));
1837 return true;
1838 }
1839 return false;
1840 }
1841
1843 bool SwapActiveAndInactive(int64_t active, int64_t inactive) {
1844 if (active == inactive) return false;
1845 const int64_t prev = Prev(active);
1846 return MakeChainInactive(prev, active) && MakeActive(inactive, prev);
1847 }
1850 bool SwapActiveAndInactiveChains(absl::Span<const int64_t> active_chain,
1851 absl::Span<const int64_t> inactive_chain) {
1852 if (active_chain.empty()) return false;
1853 if (active_chain == inactive_chain) return false;
1854 const int before_active_chain = Prev(active_chain.front());
1855 if (!MakeChainInactive(before_active_chain, active_chain.back())) {
1856 return false;
1857 }
1858 for (auto it = inactive_chain.crbegin(); it != inactive_chain.crend();
1859 ++it) {
1860 if (!MakeActive(*it, before_active_chain)) return false;
1862 return true;
1863 }
1864
1866 void SetNext(int64_t from, int64_t to, int64_t path) {
1867 DCHECK_LT(from, number_of_nexts_);
1868 SetValue(from, to);
1869 if constexpr (!ignore_path_vars) {
1870 DCHECK_LT(from + number_of_nexts_, Size());
1871 SetValue(from + number_of_nexts_, path);
1872 }
1873 }
1874
1875
1877 bool IsPathEnd(int64_t node) const { return node >= number_of_nexts_; }
1878
1880 bool IsPathStart(int64_t node) const { return OldInverseValue(node) == -1; }
1881
1883 bool IsInactive(int64_t node) const {
1884 return !IsPathEnd(node) && inactives_[node];
1885 }
1886
1889 virtual bool InitPosition() const { return false; }
1893 void ResetPosition() { just_started_ = true; }
1897
1898 int AddAlternativeSet(const std::vector<int64_t>& alternative_set) {
1899 const int alternative = alternative_sets_.size();
1900 for (int64_t node : alternative_set) {
1901 DCHECK_EQ(-1, alternative_index_[node]);
1902 alternative_index_[node] = alternative;
1903 }
1904 alternative_sets_.push_back(alternative_set);
1905 sibling_alternative_.push_back(-1);
1906 return alternative;
1907 }
1908#ifndef SWIG
1909 /// Adds all sets of node alternatives of a vector of alternative pairs. No
1910 /// node can be in two alternatives.
1911 template <typename PairType>
1913 const std::vector<PairType>& pair_alternative_sets) {
1914 for (const auto& [alternative_set, sibling_alternative_set] :
1915 pair_alternative_sets) {
1916 sibling_alternative_.back() = AddAlternativeSet(alternative_set) + 1;
1917 AddAlternativeSet(sibling_alternative_set);
1918 }
1919 }
1920#endif // SWIG
1922 int64_t GetActiveInAlternativeSet(int alternative_index) const {
1923 return alternative_index >= 0
1924 ? active_in_alternative_set_[alternative_index]
1925 : -1;
1926 }
1928 int64_t GetActiveAlternativeNode(int node) const {
1929 return GetActiveInAlternativeSet(alternative_index_[node]);
1930 }
1931
1932 int GetSiblingAlternativeIndex(int node) const {
1933 const int alternative = GetAlternativeIndex(node);
1934 return alternative >= 0 ? sibling_alternative_[alternative] : -1;
1935 }
1937 int GetAlternativeIndex(int node) const {
1938 return (node >= alternative_index_.size()) ? -1 : alternative_index_[node];
1942 int64_t GetActiveAlternativeSibling(int node) const {
1947
1948 /// before_chain on the path.
1949 /// Cycles are detected through chain length overflow.
1950 bool CheckChainValidity(int64_t before_chain, int64_t chain_end,
1951 int64_t exclude) const {
1952 if (before_chain == chain_end || before_chain == exclude) return false;
1953 int64_t current = before_chain;
1954 int chain_size = 0;
1955 while (current != chain_end) {
1956 if (chain_size > number_of_nexts_) return false;
1957 if (IsPathEnd(current)) return false;
1958 current = Next(current);
1959 ++chain_size;
1960 if (current == exclude) return false;
1962 return true;
1963 }
1964
1965 bool HasNeighbors() const {
1966 return iteration_parameters_.get_incoming_neighbors != nullptr ||
1967 iteration_parameters_.get_outgoing_neighbors != nullptr;
1968 }
1969
1970 struct Neighbor {
1971 // Index of the neighbor node.
1972 int neighbor;
1973 // True if 'neighbor' is an outgoing neighbor (i.e. arc main_node->neighbor)
1974 // and false if it's an incoming one (arc neighbor->main_node).
1975 bool outgoing;
1977 Neighbor GetNeighborForBaseNode(int64_t base_index) const {
1978 auto* iterator = base_node_iterators_[base_index].GetNeighborIterator();
1979 return {.neighbor = iterator->GetValue(),
1980 .outgoing = iterator->IsOutgoingNeighbor()};
1982
1984
1985 private:
1986 template <class NodeIterator>
1987 static int GetNodeWithDefault(const NodeIterator* node_iterator,
1988 int default_value) {
1989 const int node = node_iterator->GetValue();
1990 return node >= 0 ? node : default_value;
1991 }
1992
1993 void OnStart() override {
1994 optimal_paths_enabled_ = false;
1995 if (!iterators_initialized_) {
1996 iterators_initialized_ = true;
1997 for (int i = 0; i < iteration_parameters_.number_of_base_nodes; ++i) {
1998 base_node_iterators_[i].Initialize();
1999 }
2000 }
2001 InitializeBaseNodes();
2002 InitializeAlternatives();
2003 OnNodeInitialization();
2004 }
2005
2007 bool OnSamePath(int64_t node1, int64_t node2) const {
2008 if (IsInactive(node1) != IsInactive(node2)) {
2009 return false;
2010 }
2011 for (int node = node1; !IsPathEnd(node); node = OldNext(node)) {
2012 if (node == node2) {
2013 return true;
2014 }
2015 }
2016 for (int node = node2; !IsPathEnd(node); node = OldNext(node)) {
2017 if (node == node1) {
2018 return true;
2019 }
2020 }
2021 return false;
2022 }
2023
2024 bool CheckEnds() const {
2025 for (int i = iteration_parameters_.number_of_base_nodes - 1; i >= 0; --i) {
2026 if (base_nodes_[i] != end_nodes_[i] ||
2027 !base_node_iterators_[i].HasReachedEnd()) {
2028 return true;
2029 }
2030 }
2031 return false;
2032 }
2033 bool IncrementPosition() {
2034 const int base_node_size = iteration_parameters_.number_of_base_nodes;
2035
2036 if (just_started_) {
2037 just_started_ = false;
2038 return true;
2039 }
2040 const int number_of_paths = path_starts_.size();
2041 // Finding next base node positions.
2042 // Increment the position of inner base nodes first (higher index nodes);
2043 // if a base node is at the end of a path, reposition it at the start
2044 // of the path and increment the position of the preceding base node (this
2045 // action is called a restart).
2046 int last_restarted = base_node_size;
2047 for (int i = base_node_size - 1; i >= 0; --i) {
2048 if (base_nodes_[i] < number_of_nexts_ && i <= next_base_to_increment_) {
2049 if (base_node_iterators_[i].Increment()) break;
2050 base_nodes_[i] = OldNext(base_nodes_[i]);
2051 base_node_iterators_[i].Reset();
2052 if (iteration_parameters_.accept_path_end_base ||
2053 !IsPathEnd(base_nodes_[i])) {
2054 break;
2055 }
2056 }
2057 base_nodes_[i] = StartNode(i);
2058 base_node_iterators_[i].Reset();
2059 last_restarted = i;
2060 }
2061 next_base_to_increment_ = base_node_size;
2062 // At the end of the loop, base nodes with indexes in
2063 // [last_restarted, base_node_size[ have been restarted.
2064 // Restarted base nodes are then repositioned by the virtual
2065 // GetBaseNodeRestartPosition to reflect position constraints between
2066 // base nodes (by default GetBaseNodeRestartPosition leaves the nodes
2067 // at the start of the path).
2068 // Base nodes are repositioned in ascending order to ensure that all
2069 // base nodes "below" the node being repositioned have their final
2070 // position.
2071 for (int i = last_restarted; i < base_node_size; ++i) {
2072 base_nodes_[i] = GetBaseNodeRestartPosition(i);
2073 base_node_iterators_[i].Reset();
2074 }
2075 if (last_restarted > 0) {
2076 return CheckEnds();
2077 }
2078 // If all base nodes have been restarted, base nodes are moved to new paths.
2079 // First we mark the current paths as locally optimal if they have been
2080 // completely explored.
2081 if (optimal_paths_enabled_ &&
2082 iteration_parameters_.skip_locally_optimal_paths) {
2083 if (path_basis_.size() > 1) {
2084 for (int i = 1; i < path_basis_.size(); ++i) {
2085 active_paths_.DeactivatePathPair(StartNode(path_basis_[i - 1]),
2086 StartNode(path_basis_[i]));
2087 }
2088 } else {
2089 active_paths_.DeactivatePathPair(StartNode(path_basis_[0]),
2090 StartNode(path_basis_[0]));
2091 }
2092 }
2093 std::vector<int> current_starts(base_node_size);
2094 for (int i = 0; i < base_node_size; ++i) {
2095 current_starts[i] = StartNode(i);
2096 }
2097 // Exploration of next paths can lead to locally optimal paths since we are
2098 // exploring them from scratch.
2099 optimal_paths_enabled_ = true;
2100 while (true) {
2101 for (int i = base_node_size - 1; i >= 0; --i) {
2102 const int next_path_index = base_paths_[i] + 1;
2103 if (next_path_index < number_of_paths) {
2104 base_paths_[i] = next_path_index;
2105 base_nodes_[i] = path_starts_[next_path_index];
2106 base_node_iterators_[i].Reset();
2107 if (i == 0 || !OnSamePathAsPreviousBase(i)) {
2108 break;
2109 }
2110 } else {
2111 base_paths_[i] = 0;
2112 base_nodes_[i] = path_starts_[0];
2113 base_node_iterators_[i].Reset();
2114 }
2115 }
2116 if (!iteration_parameters_.skip_locally_optimal_paths) return CheckEnds();
2117 // If the new paths have already been completely explored, we can
2118 // skip them from now on.
2119 if (path_basis_.size() > 1) {
2120 for (int j = 1; j < path_basis_.size(); ++j) {
2121 if (active_paths_.IsPathPairActive(StartNode(path_basis_[j - 1]),
2122 StartNode(path_basis_[j]))) {
2123 return CheckEnds();
2124 }
2125 }
2126 } else {
2127 if (active_paths_.IsPathPairActive(StartNode(path_basis_[0]),
2128 StartNode(path_basis_[0]))) {
2129 return CheckEnds();
2130 }
2131 }
2132 // If we are back to paths we just iterated on or have reached the end
2133 // of the neighborhood search space, we can stop.
2134 if (!CheckEnds()) return false;
2135 bool stop = true;
2136 for (int i = 0; i < base_node_size; ++i) {
2137 if (StartNode(i) != current_starts[i]) {
2138 stop = false;
2139 break;
2140 }
2141 }
2142 if (stop) return false;
2143 }
2144 return CheckEnds();
2145 }
2146
2147 void InitializePathStarts() {
2148 // Detect nodes which do not have any possible predecessor in a path; these
2149 // nodes are path starts.
2150 int max_next = -1;
2151 std::vector<bool> has_prevs(number_of_nexts_, false);
2152 for (int i = 0; i < number_of_nexts_; ++i) {
2153 const int next = OldNext(i);
2154 if (next < number_of_nexts_) {
2155 has_prevs[next] = true;
2156 }
2157 max_next = std::max(max_next, next);
2158 }
2159 // Update locally optimal paths.
2160 if (iteration_parameters_.skip_locally_optimal_paths) {
2161 active_paths_.Initialize(
2162 /*is_start=*/[&has_prevs](int node) { return !has_prevs[node]; });
2163 for (int i = 0; i < number_of_nexts_; ++i) {
2164 if (!has_prevs[i]) {
2165 int current = i;
2166 while (!IsPathEnd(current)) {
2167 if ((OldNext(current) != PrevNext(current))) {
2168 active_paths_.ActivatePath(i);
2169 break;
2170 }
2171 current = OldNext(current);
2172 }
2173 }
2174 }
2175 }
2176 // Create a list of path starts, dropping equivalent path starts of
2177 // currently empty paths.
2178 std::vector<bool> empty_found(number_of_nexts_, false);
2179 std::vector<int64_t> new_path_starts;
2180 for (int i = 0; i < number_of_nexts_; ++i) {
2181 if (!has_prevs[i]) {
2182 if (IsPathEnd(OldNext(i))) {
2183 if (iteration_parameters_.start_empty_path_class != nullptr) {
2184 if (empty_found[iteration_parameters_.start_empty_path_class(i)])
2185 continue;
2186 empty_found[iteration_parameters_.start_empty_path_class(i)] = true;
2187 }
2188 }
2189 new_path_starts.push_back(i);
2190 }
2191 }
2192 if (!first_start_) {
2193 // Synchronizing base_paths_ with base node positions. When the last move
2194 // was performed a base node could have been moved to a new route in which
2195 // case base_paths_ needs to be updated. This needs to be done on the path
2196 // starts before we re-adjust base nodes for new path starts.
2197 std::vector<int> node_paths(max_next + 1, -1);
2198 for (int i = 0; i < path_starts_.size(); ++i) {
2199 int node = path_starts_[i];
2200 while (!IsPathEnd(node)) {
2201 node_paths[node] = i;
2202 node = OldNext(node);
2203 }
2204 node_paths[node] = i;
2205 }
2206 for (int j = 0; j < iteration_parameters_.number_of_base_nodes; ++j) {
2207 if (IsInactive(base_nodes_[j]) || node_paths[base_nodes_[j]] == -1) {
2208 // Base node was made inactive or was moved to a new path, reposition
2209 // the base node to its restart position.
2210 base_nodes_[j] = GetBaseNodeRestartPosition(j);
2211 base_paths_[j] = node_paths[base_nodes_[j]];
2212 } else {
2213 base_paths_[j] = node_paths[base_nodes_[j]];
2214 }
2215 // Always restart from first alternative.
2216 base_node_iterators_[j].Reset();
2217 }
2218 // Re-adjust current base_nodes and base_paths to take into account new
2219 // path starts (there could be fewer if a new path was made empty, or more
2220 // if nodes were added to a formerly empty path).
2221 int new_index = 0;
2222 absl::flat_hash_set<int> found_bases;
2223 for (int i = 0; i < path_starts_.size(); ++i) {
2224 int index = new_index;
2225 // Note: old and new path starts are sorted by construction.
2226 while (index < new_path_starts.size() &&
2227 new_path_starts[index] < path_starts_[i]) {
2228 ++index;
2229 }
2230 const bool found = (index < new_path_starts.size() &&
2231 new_path_starts[index] == path_starts_[i]);
2232 if (found) {
2233 new_index = index;
2234 }
2235 for (int j = 0; j < iteration_parameters_.number_of_base_nodes; ++j) {
2236 if (base_paths_[j] == i && !found_bases.contains(j)) {
2237 found_bases.insert(j);
2238 base_paths_[j] = new_index;
2239 // If the current position of the base node is a removed empty path,
2240 // readjusting it to the last visited path start.
2241 if (!found) {
2242 base_nodes_[j] = new_path_starts[new_index];
2243 }
2244 }
2245 }
2246 }
2247 }
2248 path_starts_.swap(new_path_starts);
2249 // For every base path, store the end corresponding to the path start.
2250 // TODO(user): make this faster, maybe by pairing starts with ends.
2251 path_ends_.clear();
2252 path_ends_.reserve(path_starts_.size());
2253 int64_t max_node_index = number_of_nexts_ - 1;
2254 for (const int start_node : path_starts_) {
2255 int64_t node = start_node;
2256 while (!IsPathEnd(node)) node = OldNext(node);
2257 path_ends_.push_back(node);
2258 max_node_index = std::max(max_node_index, node);
2259 }
2260 node_path_starts_.assign(max_node_index + 1, -1);
2261 node_path_ends_.assign(max_node_index + 1, -1);
2262 for (int i = 0; i < path_starts_.size(); ++i) {
2263 const int64_t start_node = path_starts_[i];
2264 const int64_t end_node = path_ends_[i];
2265 int64_t node = start_node;
2266 while (!IsPathEnd(node)) {
2267 node_path_starts_[node] = start_node;
2268 node_path_ends_[node] = end_node;
2269 node = OldNext(node);
2270 }
2271 node_path_starts_[node] = start_node;
2272 node_path_ends_[node] = end_node;
2273 }
2274 }
2275 void InitializeInactives() {
2276 inactives_.clear();
2277 for (int i = 0; i < number_of_nexts_; ++i) {
2278 inactives_.push_back(OldNext(i) == i);
2279 }
2280 }
2281 void InitializeBaseNodes() {
2282 // Inactive nodes must be detected before determining new path starts.
2283 InitializeInactives();
2284 InitializePathStarts();
2285 if (first_start_ || InitPosition()) {
2286 // Only do this once since the following starts will continue from the
2287 // preceding position
2288 for (int i = 0; i < iteration_parameters_.number_of_base_nodes; ++i) {
2289 base_paths_[i] = 0;
2290 base_nodes_[i] = path_starts_[0];
2291 }
2292 first_start_ = false;
2293 }
2294 for (int i = 0; i < iteration_parameters_.number_of_base_nodes; ++i) {
2295 // If base node has been made inactive, restart from path start.
2296 int64_t base_node = base_nodes_[i];
2297 if (RestartAtPathStartOnSynchronize() || IsInactive(base_node)) {
2298 base_node = path_starts_[base_paths_[i]];
2299 base_nodes_[i] = base_node;
2300 }
2301 end_nodes_[i] = base_node;
2302 }
2303 // Repair end_nodes_ in case some must be on the same path and are not
2304 // anymore (due to other operators moving these nodes).
2305 for (int i = 1; i < iteration_parameters_.number_of_base_nodes; ++i) {
2306 if (OnSamePathAsPreviousBase(i) &&
2307 !OnSamePath(base_nodes_[i - 1], base_nodes_[i])) {
2308 const int64_t base_node = base_nodes_[i - 1];
2309 base_nodes_[i] = base_node;
2310 end_nodes_[i] = base_node;
2311 base_paths_[i] = base_paths_[i - 1];
2312 }
2313 }
2314 for (int i = 0; i < iteration_parameters_.number_of_base_nodes; ++i) {
2315 base_node_iterators_[i].Reset(/*update_end_nodes=*/true);
2316 }
2317 just_started_ = true;
2318 }
2319 void InitializeAlternatives() {
2320 active_in_alternative_set_.resize(alternative_sets_.size(), -1);
2321 for (int i = 0; i < alternative_sets_.size(); ++i) {
2322 const int64_t current_active = active_in_alternative_set_[i];
2323 if (current_active >= 0 && !IsInactive(current_active)) continue;
2324 for (int64_t index : alternative_sets_[i]) {
2325 if (!IsInactive(index)) {
2326 active_in_alternative_set_[i] = index;
2327 break;
2328 }
2329 }
2330 }
2331 }
2332
2333 class ActivePaths {
2334 public:
2335 explicit ActivePaths(int num_nodes) : start_to_path_(num_nodes, -1) {}
2336 void Clear() { to_reset_ = true; }
2337 template <typename T>
2338 void Initialize(T is_start) {
2339 if (is_path_pair_active_.empty()) {
2340 num_paths_ = 0;
2341 absl::c_fill(start_to_path_, -1);
2342 for (int i = 0; i < start_to_path_.size(); ++i) {
2343 if (is_start(i)) {
2344 start_to_path_[i] = num_paths_;
2345 ++num_paths_;
2346 }
2347 }
2348 }
2349 }
2350 void DeactivatePathPair(int start1, int start2) {
2351 if (to_reset_) Reset();
2352 is_path_pair_active_[start_to_path_[start1] * num_paths_ +
2353 start_to_path_[start2]] = false;
2354 }
2355 void ActivatePath(int start) {
2356 if (to_reset_) Reset();
2357 const int p1 = start_to_path_[start];
2358 const int p1_block = num_paths_ * p1;
2359 for (int p2 = 0; p2 < num_paths_; ++p2) {
2360 is_path_pair_active_[p1_block + p2] = true;
2361 }
2362 for (int p2_block = 0; p2_block < is_path_pair_active_.size();
2363 p2_block += num_paths_) {
2364 is_path_pair_active_[p2_block + p1] = true;
2365 }
2366 }
2367 bool IsPathPairActive(int start1, int start2) const {
2368 if (to_reset_) return true;
2369 return is_path_pair_active_[start_to_path_[start1] * num_paths_ +
2370 start_to_path_[start2]];
2371 }
2372
2373 private:
2374 void Reset() {
2375 if (!to_reset_) return;
2376 is_path_pair_active_.assign(num_paths_ * num_paths_, true);
2377 to_reset_ = false;
2378 }
2379
2380 bool to_reset_ = true;
2381 int num_paths_ = 0;
2382 std::vector<int64_t> start_to_path_;
2383 std::vector<bool> is_path_pair_active_;
2384 };
2385
2386 std::unique_ptr<int[]> base_nodes_;
2387 std::unique_ptr<int[]> end_nodes_;
2388 std::unique_ptr<int[]> base_paths_;
2389 std::vector<int> node_path_starts_;
2390 std::vector<int> node_path_ends_;
2391 bool iterators_initialized_ = false;
2392#ifndef SWIG
2393 std::vector<BaseNodeIterators<PathOperator>> base_node_iterators_;
2394#endif // SWIG
2395 std::vector<int64_t> path_starts_;
2396 std::vector<int64_t> path_ends_;
2397 std::vector<bool> inactives_;
2398 bool just_started_;
2399 bool first_start_;
2400 int next_base_to_increment_;
2401 IterationParameters iteration_parameters_;
2402 bool optimal_paths_enabled_;
2403 std::vector<int> path_basis_;
2404 ActivePaths active_paths_;
2406#ifndef SWIG
2407 std::vector<std::vector<int64_t>> alternative_sets_;
2408#endif // SWIG
2409 std::vector<int> alternative_index_;
2410 std::vector<int64_t> active_in_alternative_set_;
2411 std::vector<int> sibling_alternative_;
2412
2413 friend class BaseNodeIterators<PathOperator>;
2414 friend class AlternativeNodeIterator;
2415 friend class NodeNeighborIterator;
2416};
2417
2418#ifndef SWIG
2420
2428
2429
2431 Solver* solver, const std::vector<IntVar*>& vars,
2432 const std::vector<IntVar*>& secondary_vars,
2433 std::function<int(int64_t)> start_empty_path_class,
2434 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
2435 nullptr,
2436 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
2437 nullptr);
2438
2440
2453
2455 Solver* solver, const std::vector<IntVar*>& vars,
2456 const std::vector<IntVar*>& secondary_vars,
2457 std::function<int(int64_t)> start_empty_path_class,
2458 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
2459 nullptr,
2460 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
2461 nullptr,
2462 int64_t chain_length = 1LL, bool single_path = false,
2463 const std::string& name = "Relocate");
2464
2466
2474
2476 Solver* solver, const std::vector<IntVar*>& vars,
2477 const std::vector<IntVar*>& secondary_vars,
2478 std::function<int(int64_t)> start_empty_path_class,
2479 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
2480 nullptr,
2481 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
2482 nullptr);
2483
2485
2495
2497 Solver* solver, const std::vector<IntVar*>& vars,
2498 const std::vector<IntVar*>& secondary_vars,
2499 std::function<int(int64_t)> start_empty_path_class,
2500 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
2501 nullptr,
2502 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
2503 nullptr);
2504
2506
2513
2515 Solver* solver, const std::vector<IntVar*>& vars,
2516 const std::vector<IntVar*>& secondary_vars,
2517 std::function<int(int64_t)> start_empty_path_class,
2518 std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
2519 nullptr,
2520 std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
2521 nullptr);
2522
2524
2531
2533 Solver* solver, const std::vector<IntVar*>& vars,
2534 const std::vector<IntVar*>& secondary_vars,
2535 std::function<int(int64_t)> start_empty_path_class);
2536
2537// ----- ExchangeAndMakeActive -----
2538
2539// ExchangeAndMakeActive exchanges two nodes and inserts an inactive node.
2540// Possible neighbors for paths 0 -> 2 -> 4, 1 -> 3 -> 6 and 5 inactive are:
2541// 0 -> 3 -> 4, 1 -> 5 -> 2 -> 6
2542// 0 -> 3 -> 5 -> 4, 1 -> 2 -> 6
2543// 0 -> 5 -> 3 -> 4, 1 -> 2 -> 6
2544// 0 -> 3 -> 4, 1 -> 2 -> 5 -> 6
2545//
2546// Warning this operator creates a very large neighborhood, with O(m*n^3)
2547// neighbors (n: number of active nodes, m: number of non active nodes).
2548// It should be used with only a small number of non active nodes.
2549// TODO(user): Add support for neighbors which would make this operator more
2550// usable.
2551
2553 Solver* solver, const std::vector<IntVar*>& vars,
2554 const std::vector<IntVar*>& secondary_vars,
2555 std::function<int(int64_t)> start_empty_path_class);
2556
2557// ----- ExchangePathEndsAndMakeActive -----
2558
2559// An operator which exchanges the first and last nodes of two paths and makes a
2560// node active.
2561// Possible neighbors for paths 0 -> 1 -> 2 -> 7, 6 -> 3 -> 4 -> 8
2562// and 5 inactive are:
2563// 0 -> 5 -> 3 -> 4 -> 7, 6 -> 1 -> 2 -> 8
2564// 0 -> 3 -> 4 -> 7, 6 -> 1 -> 5 -> 2 -> 8
2565// 0 -> 3 -> 4 -> 7, 6 -> 1 -> 2 -> 5 -> 8
2566// 0 -> 3 -> 5 -> 4 -> 7, 6 -> 1 -> 2 -> 8
2567// 0 -> 3 -> 4 -> 5 -> 7, 6 -> 1 -> 2 -> 8
2568//
2569// This neighborhood is an artificially reduced version of
2570// ExchangeAndMakeActiveOperator. It can still be used to opportunistically
2571// insert inactive nodes.
2572
2574 Solver* solver, const std::vector<IntVar*>& vars,
2575 const std::vector<IntVar*>& secondary_vars,
2576 std::function<int(int64_t)> start_empty_path_class);
2577
2579
2583
2585 Solver* solver, const std::vector<IntVar*>& vars,
2586 const std::vector<IntVar*>& secondary_vars,
2587 std::function<int(int64_t)> start_empty_path_class);
2588
2590
2596
2598 Solver* solver, const std::vector<IntVar*>& vars,
2599 const std::vector<IntVar*>& secondary_vars,
2600 std::function<int(int64_t)> start_empty_path_class);
2601
2603
2609
2611 Solver* solver, const std::vector<IntVar*>& vars,
2612 const std::vector<IntVar*>& secondary_vars,
2613 std::function<int(int64_t)> start_empty_path_class);
2614
2616
2623
2625 Solver* solver, const std::vector<IntVar*>& vars,
2626 const std::vector<IntVar*>& secondary_vars,
2627 std::function<int(int64_t)> start_empty_path_class);
2628
2630
2636
2638 Solver* solver, const std::vector<IntVar*>& vars,
2639 const std::vector<IntVar*>& secondary_vars,
2640 std::function<int(int64_t)> start_empty_path_class);
2641
2643
2645 Solver* solver, const std::vector<IntVar*>& vars,
2646 const std::vector<IntVar*>& secondary_vars,
2647 std::function<int(int64_t)> start_empty_path_class, int max_chain_size);
2648
2650
2661
2663 Solver* solver, const std::vector<IntVar*>& vars,
2664 const std::vector<IntVar*>& secondary_vars,
2665 std::function<int(int64_t)> start_empty_path_class);
2666
2668
2675
2677 const std::vector<IntVar*>& vars,
2678 const std::vector<IntVar*>& secondary_vars,
2679 Solver::IndexEvaluator3 evaluator,
2680 int chain_length);
2681
2689
2691 const std::vector<IntVar*>& vars,
2692 const std::vector<IntVar*>& secondary_vars,
2693 Solver::IndexEvaluator3 evaluator,
2694 int tsp_size);
2695
2697
2699 Solver* solver, const std::vector<IntVar*>& vars,
2700 const std::vector<IntVar*>& secondary_vars,
2701 const Solver::IndexEvaluator3& evaluator, bool topt);
2702
2704
2708
2710 const std::vector<IntVar*>& vars,
2711 const std::vector<IntVar*>& secondary_vars,
2712 int number_of_chunks, int chunk_size,
2713 bool unactive_fragments);
2714#endif // SWIG
2715
2716#if !defined(SWIG)
2717// After building a Directed Acyclic Graph, allows to generate sub-DAGs
2718// reachable from a node.
2719// Workflow:
2720// - Call AddArc() repeatedly to add arcs describing a DAG. Nodes are allocated
2721// on the user side, they must be nonnegative, and it is better but not
2722// mandatory for the set of nodes to be dense.
2723// - Call BuildGraph(). This precomputes all the information needed to make
2724// subsequent requests for sub-DAGs.
2725// - Call ComputeSortedSubDagArcs(node). This returns a view to arcs reachable
2726// from node, in topological order.
2727// All arcs must be added before calling BuildGraph(),
2728// and ComputeSortedSubDagArcs() can only be called after BuildGraph().
2729// If the arcs form a graph that has directed cycles,
2730// - in debug mode, BuildGraph() will crash.
2731// - otherwise, BuildGraph() will not crash, but ComputeSortedSubDagArcs()
2732// will only return a subset of arcs reachable by the given node.
2733class SubDagComputer {
2734 public:
2737 SubDagComputer() = default;
2738 // Adds an arc between node 'tail' and node 'head'. Nodes must be nonnegative.
2739 // Returns the index of the new arc, those are used to identify arcs when
2740 // calling ComputeSortedSubDagArcs().
2741 ArcId AddArc(NodeId tail, NodeId head) {
2742 DCHECK(!graph_was_built_);
2743 num_nodes_ = std::max(num_nodes_, std::max(tail.value(), head.value()) + 1);
2744 const ArcId arc_id(arcs_.size());
2745 arcs_.push_back({.tail = tail, .head = head, .arc_id = arc_id});
2746 return arc_id;
2748 // Finishes the construction of the DAG. 'num_nodes' is the number of nodes
2749 // in the DAG and must be greater than all node indices passed to AddArc().
2750 void BuildGraph(int num_nodes);
2751 // Computes the arcs of the sub-DAG reachable from node returns a view of
2752 // those arcs in topological order.
2753 const std::vector<ArcId>& ComputeSortedSubDagArcs(NodeId node);
2754
2755 private:
2756 // Checks whether the underlying graph has a directed cycle.
2757 // Should be called after the graph has been built.
2758 bool HasDirectedCycle() const;
2759
2760 struct Arc {
2761 NodeId tail;
2762 NodeId head;
2763 ArcId arc_id;
2764 bool operator<(const Arc& other) const {
2765 return std::tie(tail, arc_id) < std::tie(other.tail, other.arc_id);
2766 }
2767 };
2768 int num_nodes_ = 0;
2769 std::vector<Arc> arcs_;
2770 // Initialized by BuildGraph(), after which the outgoing arcs of node n are
2771 // the range from arcs_[arcs_of_node_[n]] included to
2772 // arcs_[arcs_of_node_[n+1]] excluded.
2774 // Must be false before BuildGraph() is called, true afterwards.
2775 bool graph_was_built_ = false;
2776 // Used by ComputeSortedSubDagArcs.
2778 // Used by ComputeSortedSubDagArcs.
2779 std::vector<NodeId> nodes_to_visit_;
2780 // Used as output, set up as a member to allow reuse.
2781 std::vector<ArcId> sorted_arcs_;
2782};
2783
2784// A LocalSearchState is a container for variables with domains that can be
2785// relaxed and tightened, saved and restored. It represents the solution state
2786// of a local search engine, and allows it to go from solution to solution by
2787// relaxing some variables to form a new subproblem, then tightening those
2788// variables to move to a new solution representation. That state may be saved
2789// to an internal copy, or reverted to the last saved internal copy.
2790// Relaxing a variable returns its bounds to their initial state.
2791// Tightening a variable's bounds may make its min larger than its max,
2792// in that case, the tightening function will return false, and the state will
2793// be marked as invalid. No other operations than Revert() can be called on an
2794// invalid state: in particular, an invalid state cannot be saved.
2795class LocalSearchState {
2796 public:
2797 class Variable;
2798 DEFINE_STRONG_INT_TYPE(VariableDomainId, int);
2799 DEFINE_STRONG_INT_TYPE(ConstraintId, int);
2800 // Adds a variable domain to this state, returns a handler to the new domain.
2801 VariableDomainId AddVariableDomain(int64_t relaxed_min, int64_t relaxed_max);
2802 // Relaxes the domain, returns false iff the domain was already relaxed.
2803 bool RelaxVariableDomain(VariableDomainId domain_id);
2804 bool TightenVariableDomainMin(VariableDomainId domain_id, int64_t value);
2805 bool TightenVariableDomainMax(VariableDomainId domain_id, int64_t value);
2806 int64_t VariableDomainMin(VariableDomainId domain_id) const;
2807 int64_t VariableDomainMax(VariableDomainId domain_id) const;
2808 void ChangeRelaxedVariableDomain(VariableDomainId domain_id, int64_t min,
2809 int64_t max);
2811 // Propagation of all events.
2812 void PropagateRelax(VariableDomainId domain_id);
2813 bool PropagateTighten(VariableDomainId domain_id);
2814 // Makes a variable, an object with restricted operations on the underlying
2815 // domain identified by domain_id: only Relax, Tighten and Min/Max read
2816 // operations are available.
2818 // Makes a variable from an interval without going through a domain_id.
2819 // Can be used when no direct manipulation of the domain is needed.
2820 Variable MakeVariableWithRelaxedDomain(int64_t min, int64_t max);
2821 // Makes a variable with no state, this is meant as a placeholder.
2822 static Variable DummyVariable();
2823 void Commit();
2824 void Revert();
2825 bool StateIsFeasible() const {
2826 return state_domains_are_all_nonempty_ && num_committed_empty_domains_ == 0;
2827 }
2828 // Adds a constraint that output = input_offset + sum_i weight_i * input_i.
2829 void AddWeightedSumConstraint(
2830 const std::vector<VariableDomainId>& input_domain_ids,
2831 const std::vector<int64_t>& input_weights, int64_t input_offset,
2832 VariableDomainId output_domain_id);
2833 // Precomputes which domain change triggers which constraint(s).
2834 // Should be run after adding all constraints, before any Relax()/Tighten().
2835 void CompileConstraints();
2836
2837 private:
2838 // VariableDomains implement the domain of Variables.
2839 // Those are trailed, meaning they are saved on their first modification,
2840 // and can be reverted or committed in O(1) per modification.
2841 struct VariableDomain {
2842 int64_t min;
2843 int64_t max;
2844 };
2845 bool IntersectionIsEmpty(const VariableDomain& d1,
2846 const VariableDomain& d2) const {
2847 return d1.max < d2.min || d2.max < d1.min;
2848 }
2851 struct TrailedVariableDomain {
2852 VariableDomain committed_domain;
2853 VariableDomainId domain_id;
2854 };
2855 std::vector<TrailedVariableDomain> trailed_domains_;
2856 util_intops::StrongVector<VariableDomainId, bool> domain_is_trailed_;
2857 // True iff all domains have their min <= max.
2858 bool state_domains_are_all_nonempty_ = true;
2859 bool state_has_relaxed_domains_ = false;
2860 // Number of domains d for which the intersection of
2861 // current_domains_[d] and relaxed_domains_[d] is empty.
2862 int num_committed_empty_domains_ = 0;
2863 int trailed_num_committed_empty_domains_ = 0;
2864
2865 // Constraints may be trailed too, they decide how to track their internal
2866 // structure.
2867 class Constraint;
2868 void TrailConstraint(Constraint* constraint) {
2869 trailed_constraints_.push_back(constraint);
2870 }
2871 std::vector<Constraint*> trailed_constraints_;
2872
2873 // Stores domain-constraint dependencies, allows to generate topological
2874 // orderings of dependency arcs reachable from nodes.
2875 class DependencyGraph {
2876 public:
2877 DependencyGraph() {}
2878 // There are two kinds of domain-constraint dependencies:
2879 // - domain -> constraint when the domain is an input to the constraint.
2880 // Then the label is the index of the domain in the input tuple.
2881 // - constraint -> domain when the domain is the output of the constraint.
2882 // Then, the label is -1.
2883 struct Dependency {
2884 VariableDomainId domain_id;
2885 int input_index;
2886 ConstraintId constraint_id;
2887 };
2888 // Adds all dependencies domains[i] -> constraint labelled by i.
2889 void AddDomainsConstraintDependencies(
2890 const std::vector<VariableDomainId>& domain_ids,
2891 ConstraintId constraint_id);
2892 // Adds a dependency domain -> constraint labelled by -1.
2893 void AddConstraintDomainDependency(ConstraintId constraint_id,
2894 VariableDomainId domain_id);
2895 // After all dependencies have been added,
2896 // builds the DAG representation that allows to compute sorted dependencies.
2897 void BuildDependencyDAG(int num_domains);
2898 // Returns a view on the list of arc dependencies reachable by given domain,
2899 // in some topological order of the overall DAG. Modifying the graph or
2900 // calling ComputeSortedDependencies() again invalidates the view.
2901 const std::vector<Dependency>& ComputeSortedDependencies(
2903
2904 private:
2905 using ArcId = SubDagComputer::ArcId;
2906 using NodeId = SubDagComputer::NodeId;
2907 // Returns dag_node_of_domain_[domain_id] if already defined,
2908 // or makes a node for domain_id, possibly extending dag_node_of_domain_.
2909 NodeId GetOrCreateNodeOfDomainId(VariableDomainId domain_id);
2910 // Returns dag_node_of_constraint_[constraint_id] if already defined,
2911 // or makes a node for constraint_id, possibly extending
2912 // dag_node_of_constraint_.
2913 NodeId GetOrCreateNodeOfConstraintId(ConstraintId constraint_id);
2914 // Structure of the expression DAG, used to buffer propagation storage.
2915 SubDagComputer dag_;
2916 // Maps arcs of dag_ to domain/constraint dependencies.
2917 util_intops::StrongVector<ArcId, Dependency> dependency_of_dag_arc_;
2918 // Maps domain ids to dag_ nodes.
2920 // Maps constraint ids to dag_ nodes.
2922 // Number of nodes currently allocated in dag_.
2923 // Reserve node 0 as a default dummy node with no dependencies.
2924 int num_dag_nodes_ = 1;
2925 // Used as reusable output of ComputeSortedDependencies().
2926 std::vector<Dependency> sorted_dependencies_;
2927 };
2928 DependencyGraph dependency_graph_;
2929
2930 // Propagation order storage: each domain change triggers constraints.
2931 // Each trigger tells a constraint that a domain changed, and identifies
2932 // the domain by the index in the list of the constraint's inputs.
2933 struct Trigger {
2934 Constraint* constraint;
2935 int input_index;
2936 };
2937 // Triggers of all constraints, concatenated.
2938 // The triggers of domain i are stored from triggers_of_domain_[i]
2939 // to triggers_of_domain_[i+1] excluded.
2940 std::vector<Trigger> triggers_;
2942
2943 // Constraints are used to form expressions that make up the objective.
2944 // Constraints are directed: they have inputs and an output, moreover the
2945 // constraint-domain graph must not have directed cycles.
2946 class Constraint {
2947 public:
2948 virtual ~Constraint() = default;
2949 virtual LocalSearchState::VariableDomain Propagate(int input_index) = 0;
2950 virtual VariableDomainId Output() const = 0;
2951 virtual void Commit() = 0;
2952 virtual void Revert() = 0;
2953 };
2954 // WeightedSum constraints enforces the equation:
2955 // output = offset + sum_i input_weights[i] * input_domain_ids[i]
2956 class WeightedSum final : public Constraint {
2957 public:
2958 WeightedSum(LocalSearchState* state,
2959 const std::vector<VariableDomainId>& input_domain_ids,
2960 const std::vector<int64_t>& input_weights, int64_t input_offset,
2961 VariableDomainId output);
2962 ~WeightedSum() override = default;
2963 LocalSearchState::VariableDomain Propagate(int input_index) override;
2964 void Commit() override;
2965 void Revert() override;
2966 VariableDomainId Output() const override { return output_; }
2967
2968 private:
2969 // Weighted variable holds a variable's domain, an associated weight,
2970 // and the variable's last known min and max.
2971 struct WeightedVariable {
2972 int64_t min;
2973 int64_t max;
2974 int64_t committed_min;
2975 int64_t committed_max;
2976 int64_t weight;
2977 VariableDomainId domain;
2978 bool is_trailed;
2979 void Commit() {
2980 committed_min = min;
2981 committed_max = max;
2982 is_trailed = false;
2983 }
2984 void Revert() {
2985 min = committed_min;
2986 max = committed_max;
2987 is_trailed = false;
2988 }
2989 };
2990 std::vector<WeightedVariable> inputs_;
2991 std::vector<WeightedVariable*> trailed_inputs_;
2992 // Invariants held by this constraint to allow O(1) propagation.
2993 struct Invariants {
2994 // Number of inputs_[i].min equal to kint64min.
2995 int64_t num_neg_inf;
2996 // Sum of inputs_[i].min that are different from kint64min.
2997 int64_t wsum_mins;
2998 // Number of inputs_[i].max equal to kint64max.
2999 int64_t num_pos_inf;
3000 // Sum of inputs_[i].max that are different from kint64max.
3001 int64_t wsum_maxs;
3002 };
3003 Invariants invariants_;
3004 Invariants committed_invariants_;
3005
3006 const VariableDomainId output_;
3007 LocalSearchState* const state_;
3008 bool constraint_is_trailed_ = false;
3009 };
3010 // Used to identify constraints and hold ownership.
3011 util_intops::StrongVector<ConstraintId, std::unique_ptr<Constraint>>
3012 constraints_;
3013};
3014
3015// A LocalSearchState Variable can only be created by a LocalSearchState,
3016// then it is meant to be passed by copy. If at some point the duplication of
3017// LocalSearchState pointers is too expensive, we could switch to index only,
3018// and the user would have to know the relevant state. The present setup allows
3019// to ensure that variable users will not misuse the state.
3020class LocalSearchState::Variable {
3021 public:
3022 Variable() : state_(nullptr), domain_id_(VariableDomainId(-1)) {}
3023 int64_t Min() const {
3024 DCHECK(Exists());
3025 return state_->VariableDomainMin(domain_id_);
3026 }
3027 int64_t Max() const {
3028 DCHECK(Exists());
3029 return state_->VariableDomainMax(domain_id_);
3030 }
3031 // Sets variable's minimum to max(Min(), new_min) and propagates the change.
3032 // Returns true iff the variable domain is nonempty and propagation succeeded.
3033 bool SetMin(int64_t new_min) const {
3034 if (!Exists()) return true;
3035 return state_->TightenVariableDomainMin(domain_id_, new_min) &&
3036 state_->PropagateTighten(domain_id_);
3037 }
3038 // Sets variable's maximum to min(Max(), new_max) and propagates the change.
3039 // Returns true iff the variable domain is nonempty and propagation succeeded.
3040 bool SetMax(int64_t new_max) const {
3041 if (!Exists()) return true;
3042 return state_->TightenVariableDomainMax(domain_id_, new_max) &&
3043 state_->PropagateTighten(domain_id_);
3044 }
3045 void Relax() const {
3046 if (state_ == nullptr) return;
3047 if (state_->RelaxVariableDomain(domain_id_)) {
3048 state_->PropagateRelax(domain_id_);
3049 }
3050 }
3051 bool Exists() const { return state_ != nullptr; }
3053 private:
3054 // Only LocalSearchState can construct LocalSearchVariables.
3055 friend class LocalSearchState;
3056
3058 : state_(state), domain_id_(domain_id) {}
3059
3060 LocalSearchState* state_;
3061 VariableDomainId domain_id_;
3062};
3063#endif // !defined(SWIG)
3064
3075
3081class LocalSearchFilter : public BaseObject {
3082 public:
3085 virtual void Relax(const Assignment*, const Assignment*) {}
3087 virtual void Commit(const Assignment*, const Assignment*) {}
3088
3093 /// must be between objective_min and objective_max.
3094 /// Sample: supposing one wants to maintain a[0,1] + b[0,1] <= 1,
3095 /// for the assignment (a,1), (b,0), the delta (b,1) will be rejected
3096 /// but the delta (a,0) will be accepted.
3097 /// TODO(user): Remove arguments when there are no more need for those.
3098 virtual bool Accept(const Assignment* delta, const Assignment* deltadelta,
3099 int64_t objective_min, int64_t objective_max) = 0;
3100 virtual bool IsIncremental() const { return false; }
3101
3107 virtual void Synchronize(const Assignment* assignment,
3108 const Assignment* delta) = 0;
3110 virtual void Revert() {}
3111
3113 virtual void Reset() {}
3114
3116 virtual int64_t GetSynchronizedObjectiveValue() const { return 0LL; }
3118 // If the last Accept() call returned false, returns an undefined value.
3119 virtual int64_t GetAcceptedObjectiveValue() const { return 0LL; }
3120};
3121
3126 public:
3127 // This class is responsible for calling filters methods in a correct order.
3128 // For now, an order is specified explicitly by the user.
3129 enum FilterEventType { kAccept, kRelax };
3130 struct FilterEvent {
3132 FilterEventType event_type;
3133 int priority;
3134 };
3135
3136 std::string DebugString() const override {
3137 return "LocalSearchFilterManager";
3138 }
3139 // Builds a manager that calls filter methods ordered by increasing priority.
3140 // Note that some filters might appear only once, if their Relax() or Accept()
3141 // are trivial.
3142 explicit LocalSearchFilterManager(std::vector<FilterEvent> filter_events);
3143 // Builds a manager that calls filter methods using the following ordering:
3144 // first Relax() in vector order, then Accept() in vector order.
3145 explicit LocalSearchFilterManager(std::vector<LocalSearchFilter*> filters);
3146
3147 // Calls Revert() of filters, in reverse order of Relax events.
3148 void Revert();
3151
3152 bool Accept(LocalSearchMonitor* monitor, const Assignment* delta,
3153 const Assignment* deltadelta, int64_t objective_min,
3154 int64_t objective_max);
3156 void Synchronize(const Assignment* assignment, const Assignment* delta);
3157 int64_t GetSynchronizedObjectiveValue() const { return synchronized_value_; }
3158 int64_t GetAcceptedObjectiveValue() const { return accepted_value_; }
3159
3160 private:
3161 // Finds the last event (incremental -itself- or not) with the same priority
3162 // as the last incremental event.
3163 void FindIncrementalEventEnd();
3164
3165 std::vector<FilterEvent> events_;
3166 int last_event_called_ = -1;
3167 // If a filter is incremental, its Relax() and Accept() must be called for
3168 // every candidate, even if the Accept() of a prior filter rejected it.
3169 // To ensure that those incremental filters have consistent inputs, all
3170 // intermediate events with Relax() must also be called.
3171 int incremental_events_end_ = 0;
3172 int64_t synchronized_value_;
3173 int64_t accepted_value_;
3174};
3175
3177 public:
3178 explicit IntVarLocalSearchFilter(const std::vector<IntVar*>& vars);
3179 ~IntVarLocalSearchFilter() override;
3182 void Synchronize(const Assignment* assignment,
3183 const Assignment* delta) override;
3184
3185 bool FindIndex(IntVar* const var, int64_t* index) const {
3186 DCHECK(index != nullptr);
3187 const int var_index = var->index();
3188 *index = (var_index < var_index_to_index_.size())
3189 ? var_index_to_index_[var_index]
3190 : kUnassigned;
3191 return *index != kUnassigned;
3192 }
3193
3195 void AddVars(const std::vector<IntVar*>& vars);
3196 int Size() const { return vars_.size(); }
3197 IntVar* Var(int index) const { return vars_[index]; }
3198 int64_t Value(int index) const {
3199 DCHECK(IsVarSynced(index));
3200 return values_[index];
3201 }
3202 bool IsVarSynced(int index) const { return var_synced_[index]; }
3203
3204 protected:
3205 virtual void OnSynchronize(const Assignment*) {}
3206 void SynchronizeOnAssignment(const Assignment* assignment);
3207
3208 private:
3209 std::vector<IntVar*> vars_;
3210 std::vector<int64_t> values_;
3211 std::vector<bool> var_synced_;
3212 std::vector<int> var_index_to_index_;
3213 static const int kUnassigned;
3215
3216class PropagationMonitor : public SearchMonitor {
3217 public:
3218 explicit PropagationMonitor(Solver* solver);
3219 ~PropagationMonitor() override;
3220 std::string DebugString() const override { return "PropagationMonitor"; }
3221
3223 virtual void BeginConstraintInitialPropagation(Constraint* constraint) = 0;
3224 virtual void EndConstraintInitialPropagation(Constraint* constraint) = 0;
3225 virtual void BeginNestedConstraintInitialPropagation(Constraint* parent,
3226 Constraint* nested) = 0;
3227 virtual void EndNestedConstraintInitialPropagation(Constraint* parent,
3228 Constraint* nested) = 0;
3229 virtual void RegisterDemon(Demon* demon) = 0;
3230 virtual void BeginDemonRun(Demon* demon) = 0;
3231 virtual void EndDemonRun(Demon* demon) = 0;
3233 virtual void EndProcessingIntegerVariable(IntVar* var) = 0;
3234 virtual void PushContext(const std::string& context) = 0;
3235 virtual void PopContext() = 0;
3237 virtual void SetMin(IntExpr* expr, int64_t new_min) = 0;
3238 virtual void SetMax(IntExpr* expr, int64_t new_max) = 0;
3239 virtual void SetRange(IntExpr* expr, int64_t new_min, int64_t new_max) = 0;
3241 virtual void SetMin(IntVar* var, int64_t new_min) = 0;
3242 virtual void SetMax(IntVar* var, int64_t new_max) = 0;
3243 virtual void SetRange(IntVar* var, int64_t new_min, int64_t new_max) = 0;
3244 virtual void RemoveValue(IntVar* var, int64_t value) = 0;
3245 virtual void SetValue(IntVar* var, int64_t value) = 0;
3246 virtual void RemoveInterval(IntVar* var, int64_t imin, int64_t imax) = 0;
3247 virtual void SetValues(IntVar* var, const std::vector<int64_t>& values) = 0;
3248 virtual void RemoveValues(IntVar* var,
3249 const std::vector<int64_t>& values) = 0;
3251 virtual void SetStartMin(IntervalVar* var, int64_t new_min) = 0;
3252 virtual void SetStartMax(IntervalVar* var, int64_t new_max) = 0;
3253 virtual void SetStartRange(IntervalVar* var, int64_t new_min,
3254 int64_t new_max) = 0;
3255 virtual void SetEndMin(IntervalVar* var, int64_t new_min) = 0;
3256 virtual void SetEndMax(IntervalVar* var, int64_t new_max) = 0;
3257 virtual void SetEndRange(IntervalVar* var, int64_t new_min,
3258 int64_t new_max) = 0;
3259 virtual void SetDurationMin(IntervalVar* var, int64_t new_min) = 0;
3260 virtual void SetDurationMax(IntervalVar* var, int64_t new_max) = 0;
3261 virtual void SetDurationRange(IntervalVar* var, int64_t new_min,
3262 int64_t new_max) = 0;
3263 virtual void SetPerformed(IntervalVar* var, bool value) = 0;
3265 virtual void RankFirst(SequenceVar* var, int index) = 0;
3266 virtual void RankNotFirst(SequenceVar* var, int index) = 0;
3267 virtual void RankLast(SequenceVar* var, int index) = 0;
3268 virtual void RankNotLast(SequenceVar* var, int index) = 0;
3269 virtual void RankSequence(SequenceVar* var,
3270 const std::vector<int>& rank_first,
3271 const std::vector<int>& rank_last,
3272 const std::vector<int>& unperformed) = 0;
3274 void Install() override;
3276
3278 // TODO(user): Add monitoring of local search filters.
3279 public:
3282 std::string DebugString() const override { return "LocalSearchMonitor"; }
3283
3285 virtual void BeginOperatorStart() = 0;
3286 virtual void EndOperatorStart() = 0;
3287 virtual void BeginMakeNextNeighbor(const LocalSearchOperator* op) = 0;
3288 virtual void EndMakeNextNeighbor(const LocalSearchOperator* op,
3289 bool neighbor_found, const Assignment* delta,
3290 const Assignment* deltadelta) = 0;
3291 virtual void BeginFilterNeighbor(const LocalSearchOperator* op) = 0;
3292 virtual void EndFilterNeighbor(const LocalSearchOperator* op,
3293 bool neighbor_found) = 0;
3294 virtual void BeginAcceptNeighbor(const LocalSearchOperator* op) = 0;
3295 virtual void EndAcceptNeighbor(const LocalSearchOperator* op,
3296 bool neighbor_found) = 0;
3297 virtual void BeginFiltering(const LocalSearchFilter* filter) = 0;
3298 virtual void EndFiltering(const LocalSearchFilter* filter, bool reject) = 0;
3300 virtual bool IsActive() const = 0;
3301
3303 void Install() override;
3305
3306class OR_DLL BooleanVar : public IntVar {
3307 public:
3308 static const int kUnboundBooleanVarValue;
3310 explicit BooleanVar(Solver* const s, const std::string& name = "")
3311 : IntVar(s, name), value_(kUnboundBooleanVarValue) {}
3313 ~BooleanVar() override {}
3314
3315 int64_t Min() const override { return (value_ == 1); }
3316 void SetMin(int64_t m) override;
3317 int64_t Max() const override { return (value_ != 0); }
3318 void SetMax(int64_t m) override;
3319 void SetRange(int64_t mi, int64_t ma) override;
3320 bool Bound() const override { return (value_ != kUnboundBooleanVarValue); }
3321 int64_t Value() const override {
3322 CHECK_NE(value_, kUnboundBooleanVarValue) << "variable is not bound";
3323 return value_;
3324 }
3325 void RemoveValue(int64_t v) override;
3326 void RemoveInterval(int64_t l, int64_t u) override;
3327 void WhenBound(Demon* d) override;
3328 void WhenRange(Demon* d) override { WhenBound(d); }
3329 void WhenDomain(Demon* d) override { WhenBound(d); }
3330 uint64_t Size() const override;
3331 bool Contains(int64_t v) const override;
3332 IntVarIterator* MakeHoleIterator(bool reversible) const override;
3333 IntVarIterator* MakeDomainIterator(bool reversible) const override;
3334 std::string DebugString() const override;
3335 int VarType() const override { return BOOLEAN_VAR; }
3336
3337 IntVar* IsEqual(int64_t constant) override;
3338 IntVar* IsDifferent(int64_t constant) override;
3339 IntVar* IsGreaterOrEqual(int64_t constant) override;
3340 IntVar* IsLessOrEqual(int64_t constant) override;
3342 virtual void RestoreValue() = 0;
3343 std::string BaseName() const override { return "BooleanVar"; }
3344
3345 int RawValue() const { return value_; }
3346
3347 protected:
3348 int value_;
3351};
3352
3353class SymmetryManager;
3358class SymmetryBreaker : public DecisionVisitor {
3359 public:
3361 : symmetry_manager_(nullptr), index_in_symmetry_manager_(-1) {}
3362 ~SymmetryBreaker() override {}
3363
3364 void AddIntegerVariableEqualValueClause(IntVar* var, int64_t value);
3365 void AddIntegerVariableGreaterOrEqualValueClause(IntVar* var, int64_t value);
3366 void AddIntegerVariableLessOrEqualValueClause(IntVar* var, int64_t value);
3367
3368 private:
3369 friend class SymmetryManager;
3370 void set_symmetry_manager_and_index(SymmetryManager* manager, int index) {
3371 CHECK(symmetry_manager_ == nullptr);
3372 CHECK_EQ(-1, index_in_symmetry_manager_);
3373 symmetry_manager_ = manager;
3374 index_in_symmetry_manager_ = index;
3375 }
3376 SymmetryManager* symmetry_manager() const { return symmetry_manager_; }
3377 int index_in_symmetry_manager() const { return index_in_symmetry_manager_; }
3378
3379 SymmetryManager* symmetry_manager_;
3381 int index_in_symmetry_manager_;
3382};
3383
3386class SearchLog : public SearchMonitor {
3387 public:
3388 SearchLog(Solver* solver, std::vector<IntVar*> vars, std::string vars_name,
3389 std::vector<double> scaling_factors, std::vector<double> offsets,
3390 std::function<std::string()> display_callback,
3391 bool display_on_new_solutions_only, int period);
3392 ~SearchLog() override;
3393 void EnterSearch() override;
3394 void ExitSearch() override;
3395 bool AtSolution() override;
3396 void BeginFail() override;
3397 void NoMoreSolutions() override;
3399 void ApplyDecision(Decision* decision) override;
3400 void RefuteDecision(Decision* decision) override;
3401 void OutputDecision();
3402 void Maintain();
3403 void BeginInitialPropagation() override;
3404 void EndInitialPropagation() override;
3405 std::string DebugString() const override;
3406
3407 protected:
3408 /* Bottleneck function used for all UI related output. */
3409 virtual void OutputLine(const std::string& line);
3410
3411 private:
3412 static std::string MemoryUsage();
3413
3414 const int period_;
3415 std::unique_ptr<WallTimer> timer_;
3416 const std::vector<IntVar*> vars_;
3417 const std::string vars_name_;
3418 const std::vector<double> scaling_factors_;
3419 const std::vector<double> offsets_;
3420 std::function<std::string()> display_callback_;
3421 const bool display_on_new_solutions_only_;
3422 int nsol_;
3423 absl::Duration tick_;
3424 std::vector<int64_t> objective_min_;
3425 std::vector<int64_t> objective_max_;
3426 std::vector<int64_t> last_objective_value_;
3427 absl::Duration last_objective_timestamp_;
3428 int min_right_depth_;
3429 int max_depth_;
3430 int sliding_min_depth_;
3431 int sliding_max_depth_;
3432 int neighbors_offset_ = 0;
3433};
3434
3439class ModelCache {
3440 public:
3441 enum VoidConstraintType {
3442 VOID_FALSE_CONSTRAINT = 0,
3443 VOID_TRUE_CONSTRAINT,
3444 VOID_CONSTRAINT_MAX,
3445 };
3446
3447 enum VarConstantConstraintType {
3448 VAR_CONSTANT_EQUALITY = 0,
3449 VAR_CONSTANT_GREATER_OR_EQUAL,
3450 VAR_CONSTANT_LESS_OR_EQUAL,
3458 };
3471 EXPR_OPPOSITE = 0,
3525 VAR_ARRAY_MAX = 0,
3530
3535
3537 virtual ~ModelCache();
3539 virtual void Clear() = 0;
3542
3547
3550 IntVar* var, int64_t value, VarConstantConstraintType type) const = 0;
3552 virtual void InsertVarConstantConstraint(Constraint* ct, IntVar* var,
3553 int64_t value,
3554 VarConstantConstraintType type) = 0;
3559 IntVar* var, int64_t value1, int64_t value2,
3560 VarConstantConstantConstraintType type) const = 0;
3563 Constraint* ct, IntVar* var, int64_t value1, int64_t value2,
3565
3567
3569 IntExpr* expr1, IntExpr* expr2, ExprExprConstraintType type) const = 0;
3571 virtual void InsertExprExprConstraint(Constraint* ct, IntExpr* expr1,
3572 IntExpr* expr2,
3573 ExprExprConstraintType type) = 0;
3576
3577 virtual IntExpr* FindExprExpression(IntExpr* expr,
3578 ExprExpressionType type) const = 0;
3579
3580 virtual void InsertExprExpression(IntExpr* expression, IntExpr* expr,
3581 ExprExpressionType type) = 0;
3582
3584
3586 IntExpr* expr, int64_t value, ExprConstantExpressionType type) const = 0;
3587
3588 virtual void InsertExprConstantExpression(
3589 IntExpr* expression, IntExpr* var, int64_t value,
3591
3593
3595 IntExpr* var1, IntExpr* var2, ExprExprExpressionType type) const = 0;
3596
3597 virtual void InsertExprExprExpression(IntExpr* expression, IntExpr* var1,
3598 IntExpr* var2,
3599 ExprExprExpressionType type) = 0;
3602
3604 IntExpr* var1, IntExpr* var2, int64_t constant,
3605 ExprExprConstantExpressionType type) const = 0;
3608 IntExpr* expression, IntExpr* var1, IntExpr* var2, int64_t constant,
3610
3612
3614 IntVar* var, int64_t value1, int64_t value2,
3616
3618 IntExpr* expression, IntVar* var, int64_t value1, int64_t value2,
3620
3622
3624 IntVar* var, const std::vector<int64_t>& values,
3626
3628 IntExpr* expression, IntVar* var, const std::vector<int64_t>& values,
3630
3632
3634 const std::vector<IntVar*>& vars, VarArrayExpressionType type) const = 0;
3636 virtual void InsertVarArrayExpression(IntExpr* expression,
3637 const std::vector<IntVar*>& vars,
3638 VarArrayExpressionType type) = 0;
3641
3643 const std::vector<IntVar*>& vars, const std::vector<int64_t>& values,
3647 IntExpr* expression, const std::vector<IntVar*>& var,
3648 const std::vector<int64_t>& values,
3650
3652
3654 const std::vector<IntVar*>& vars, int64_t value,
3655 VarArrayConstantExpressionType type) const = 0;
3656
3658 IntExpr* expression, const std::vector<IntVar*>& var, int64_t value,
3660
3661 Solver* solver() const;
3662
3663 private:
3664 Solver* const solver_;
3666
3668#if !defined(SWIG)
3670 public:
3672 const std::string& TypeName() const;
3673 void SetTypeName(const std::string& type_name);
3674
3676 void SetIntegerArgument(const std::string& arg_name, int64_t value);
3677 void SetIntegerArrayArgument(const std::string& arg_name,
3678 const std::vector<int64_t>& values);
3679 void SetIntegerMatrixArgument(const std::string& arg_name,
3680 const IntTupleSet& values);
3681 void SetIntegerExpressionArgument(const std::string& arg_name, IntExpr* expr);
3682 void SetIntegerVariableArrayArgument(const std::string& arg_name,
3683 const std::vector<IntVar*>& vars);
3684 void SetIntervalArgument(const std::string& arg_name, IntervalVar* var);
3685 void SetIntervalArrayArgument(const std::string& arg_name,
3686 const std::vector<IntervalVar*>& vars);
3687 void SetSequenceArgument(const std::string& arg_name, SequenceVar* var);
3688 void SetSequenceArrayArgument(const std::string& arg_name,
3689 const std::vector<SequenceVar*>& vars);
3690
3692 bool HasIntegerExpressionArgument(const std::string& arg_name) const;
3693 bool HasIntegerVariableArrayArgument(const std::string& arg_name) const;
3694
3696 int64_t FindIntegerArgumentWithDefault(const std::string& arg_name,
3697 int64_t def) const;
3698 int64_t FindIntegerArgumentOrDie(const std::string& arg_name) const;
3699 const std::vector<int64_t>& FindIntegerArrayArgumentOrDie(
3700 const std::string& arg_name) const;
3702 const std::string& arg_name) const;
3703
3705 const std::string& arg_name) const;
3706 const std::vector<IntVar*>& FindIntegerVariableArrayArgumentOrDie(
3707 const std::string& arg_name) const;
3708
3709 private:
3710 std::string type_name_;
3711 absl::flat_hash_map<std::string, int64_t> integer_argument_;
3712 absl::flat_hash_map<std::string, std::vector<int64_t>>
3713 integer_array_argument_;
3714 absl::flat_hash_map<std::string, IntTupleSet> matrix_argument_;
3715 absl::flat_hash_map<std::string, IntExpr*> integer_expression_argument_;
3716 absl::flat_hash_map<std::string, IntervalVar*> interval_argument_;
3717 absl::flat_hash_map<std::string, SequenceVar*> sequence_argument_;
3718 absl::flat_hash_map<std::string, std::vector<IntVar*>>
3719 integer_variable_array_argument_;
3720 absl::flat_hash_map<std::string, std::vector<IntervalVar*>>
3721 interval_array_argument_;
3722 absl::flat_hash_map<std::string, std::vector<SequenceVar*>>
3723 sequence_array_argument_;
3724};
3725
3727class ModelParser : public ModelVisitor {
3728 public:
3729 ModelParser();
3730
3731 ~ModelParser() override;
3732
3734 void BeginVisitModel(const std::string& solver_name) override;
3735 void EndVisitModel(const std::string& solver_name) override;
3736 void BeginVisitConstraint(const std::string& type_name,
3737 const Constraint* constraint) override;
3738 void EndVisitConstraint(const std::string& type_name,
3739 const Constraint* constraint) override;
3740 void BeginVisitIntegerExpression(const std::string& type_name,
3741 const IntExpr* expr) override;
3742 void EndVisitIntegerExpression(const std::string& type_name,
3743 const IntExpr* expr) override;
3744 void VisitIntegerVariable(const IntVar* variable, IntExpr* delegate) override;
3745 void VisitIntegerVariable(const IntVar* variable,
3746 const std::string& operation, int64_t value,
3747 IntVar* delegate) override;
3748 void VisitIntervalVariable(const IntervalVar* variable,
3749 const std::string& operation, int64_t value,
3750 IntervalVar* delegate) override;
3751 void VisitSequenceVariable(const SequenceVar* variable) override;
3753 void VisitIntegerArgument(const std::string& arg_name,
3754 int64_t value) override;
3755 void VisitIntegerArrayArgument(const std::string& arg_name,
3756 const std::vector<int64_t>& values) override;
3757 void VisitIntegerMatrixArgument(const std::string& arg_name,
3758 const IntTupleSet& values) override;
3760 void VisitIntegerExpressionArgument(const std::string& arg_name,
3761 IntExpr* argument) override;
3763 const std::string& arg_name,
3764 const std::vector<IntVar*>& arguments) override;
3766 void VisitIntervalArgument(const std::string& arg_name,
3767 IntervalVar* argument) override;
3769 const std::string& arg_name,
3770 const std::vector<IntervalVar*>& arguments) override;
3772 void VisitSequenceArgument(const std::string& arg_name,
3773 SequenceVar* argument) override;
3775 const std::string& arg_name,
3776 const std::vector<SequenceVar*>& arguments) override;
3777
3778 protected:
3779 void PushArgumentHolder();
3780 void PopArgumentHolder();
3781 ArgumentHolder* Top() const;
3782
3783 private:
3784 std::vector<ArgumentHolder*> holders_;
3785};
3786
3787template <class T>
3788class ArrayWithOffset : public BaseObject {
3789 public:
3790 ArrayWithOffset(int64_t index_min, int64_t index_max)
3791 : index_min_(index_min),
3792 index_max_(index_max),
3793 values_(new T[index_max - index_min + 1]) {
3794 DCHECK_LE(index_min, index_max);
3795 }
3796
3797 ~ArrayWithOffset() override {}
3798
3799 virtual T Evaluate(int64_t index) const {
3800 DCHECK_GE(index, index_min_);
3801 DCHECK_LE(index, index_max_);
3802 return values_[index - index_min_];
3803 }
3804
3805 void SetValue(int64_t index, T value) {
3806 DCHECK_GE(index, index_min_);
3807 DCHECK_LE(index, index_max_);
3808 values_[index - index_min_] = value;
3810
3811 std::string DebugString() const override { return "ArrayWithOffset"; }
3812
3813 private:
3814 const int64_t index_min_;
3815 const int64_t index_max_;
3816 std::unique_ptr<T[]> values_;
3818#endif // SWIG
3819
3822
3824template <class T, class C>
3825class RevGrowingArray {
3826 public:
3827 explicit RevGrowingArray(int64_t block_size)
3828 : block_size_(block_size), block_offset_(0) {
3829 CHECK_GT(block_size, 0);
3830 }
3831
3833 for (int i = 0; i < elements_.size(); ++i) {
3834 delete[] elements_[i];
3835 }
3836 }
3838 T At(int64_t index) const {
3839 const int64_t block_index = ComputeBlockIndex(index);
3840 const int64_t relative_index = block_index - block_offset_;
3841 if (relative_index < 0 || relative_index >= elements_.size()) {
3842 return T();
3843 }
3844 const T* block = elements_[relative_index];
3845 return block != nullptr ? block[index - block_index * block_size_] : T();
3846 }
3847
3848 void RevInsert(Solver* const solver, int64_t index, T value) {
3849 const int64_t block_index = ComputeBlockIndex(index);
3850 T* const block = GetOrCreateBlock(block_index);
3851 const int64_t residual = index - block_index * block_size_;
3852 solver->SaveAndSetValue(reinterpret_cast<C*>(&block[residual]),
3853 reinterpret_cast<C>(value));
3854 }
3855
3856 private:
3857 T* NewBlock() const {
3858 T* const result = new T[block_size_];
3859 for (int i = 0; i < block_size_; ++i) {
3860 result[i] = T();
3861 }
3862 return result;
3863 }
3864
3865 T* GetOrCreateBlock(int block_index) {
3866 if (elements_.size() == 0) {
3867 block_offset_ = block_index;
3868 GrowUp(block_index);
3869 } else if (block_index < block_offset_) {
3870 GrowDown(block_index);
3871 } else if (block_index - block_offset_ >= elements_.size()) {
3872 GrowUp(block_index);
3873 }
3874 T* block = elements_[block_index - block_offset_];
3875 if (block == nullptr) {
3876 block = NewBlock();
3877 elements_[block_index - block_offset_] = block;
3878 }
3879 return block;
3880 }
3881
3882 int64_t ComputeBlockIndex(int64_t value) const {
3883 return value >= 0 ? value / block_size_
3884 : (value - block_size_ + 1) / block_size_;
3885 }
3886
3887 void GrowUp(int64_t block_index) {
3888 elements_.resize(block_index - block_offset_ + 1);
3889 }
3890
3891 void GrowDown(int64_t block_index) {
3892 const int64_t delta = block_offset_ - block_index;
3893 block_offset_ = block_index;
3894 DCHECK_GT(delta, 0);
3895 elements_.insert(elements_.begin(), delta, nullptr);
3896 }
3897
3898 const int64_t block_size_;
3899 std::vector<T*> elements_;
3900 int block_offset_;
3901};
3902
3907template <class T>
3908class RevIntSet {
3909 public:
3910 static constexpr int kNoInserted = -1;
3911
3913 explicit RevIntSet(int capacity)
3914 : elements_(new T[capacity]),
3915 num_elements_(0),
3916 capacity_(capacity),
3917 position_(new int[capacity]),
3918 delete_position_(true) {
3919 for (int i = 0; i < capacity; ++i) {
3920 position_[i] = kNoInserted;
3921 }
3923
3925 RevIntSet(int capacity, int* shared_positions, int shared_positions_size)
3926 : elements_(new T[capacity]),
3927 num_elements_(0),
3928 capacity_(capacity),
3929 position_(shared_positions),
3930 delete_position_(false) {
3931 for (int i = 0; i < shared_positions_size; ++i) {
3932 position_[i] = kNoInserted;
3933 }
3934 }
3935
3936 ~RevIntSet() {
3937 if (delete_position_) {
3938 delete[] position_;
3939 }
3940 }
3941
3942 int Size() const { return num_elements_.Value(); }
3943
3944 int Capacity() const { return capacity_; }
3945
3946 T Element(int i) const {
3947 DCHECK_GE(i, 0);
3948 DCHECK_LT(i, num_elements_.Value());
3949 return elements_[i];
3950 }
3951
3952 T RemovedElement(int i) const {
3953 DCHECK_GE(i, 0);
3954 DCHECK_LT(i + num_elements_.Value(), capacity_);
3955 return elements_[i + num_elements_.Value()];
3957
3958 void Insert(Solver* const solver, const T& elt) {
3959 const int position = num_elements_.Value();
3960 DCHECK_LT(position, capacity_);
3961 DCHECK(NotAlreadyInserted(elt));
3962 elements_[position] = elt;
3963 position_[elt] = position;
3964 num_elements_.Incr(solver);
3965 }
3966
3967 void Remove(Solver* const solver, const T& value_index) {
3968 num_elements_.Decr(solver);
3969 SwapTo(value_index, num_elements_.Value());
3971
3972 void Restore(Solver* const solver, const T& value_index) {
3973 SwapTo(value_index, num_elements_.Value());
3974 num_elements_.Incr(solver);
3975 }
3976
3977 void Clear(Solver* const solver) { num_elements_.SetValue(solver, 0); }
3978
3979 /// Iterators on the indices.
3980 typedef const T* const_iterator;
3981 const_iterator begin() const { return elements_.get(); }
3982 const_iterator end() const { return elements_.get() + num_elements_.Value(); }
3983
3984 private:
3986 bool NotAlreadyInserted(const T& elt) {
3987 for (int i = 0; i < num_elements_.Value(); ++i) {
3988 if (elt == elements_[i]) {
3989 return false;
3990 }
3991 }
3992 return true;
3995 void SwapTo(T value_index, int next_position) {
3996 const int current_position = position_[value_index];
3997 if (current_position != next_position) {
3998 const T next_value_index = elements_[next_position];
3999 elements_[current_position] = next_value_index;
4000 elements_[next_position] = value_index;
4001 position_[value_index] = next_position;
4002 position_[next_value_index] = current_position;
4003 }
4004 }
4005
4007 std::unique_ptr<T[]> elements_;
4009 NumericalRev<int> num_elements_;
4011 const int capacity_;
4013 int* position_;
4015 const bool delete_position_;
4016};
4017
4019
4020class RevPartialSequence {
4021 public:
4022 explicit RevPartialSequence(const std::vector<int>& items)
4023 : elements_(items),
4024 first_ranked_(0),
4025 last_ranked_(items.size() - 1),
4026 size_(items.size()),
4027 position_(new int[size_]) {
4028 for (int i = 0; i < size_; ++i) {
4029 elements_[i] = items[i];
4030 position_[i] = i;
4031 }
4033
4034 explicit RevPartialSequence(int size)
4035 : elements_(size),
4036 first_ranked_(0),
4037 last_ranked_(size - 1),
4038 size_(size),
4039 position_(new int[size_]) {
4040 for (int i = 0; i < size_; ++i) {
4041 elements_[i] = i;
4042 position_[i] = i;
4043 }
4044 }
4045
4047
4048 int NumFirstRanked() const { return first_ranked_.Value(); }
4049
4050 int NumLastRanked() const { return size_ - 1 - last_ranked_.Value(); }
4051
4052 int Size() const { return size_; }
4053
4054#if !defined(SWIG)
4055 const int& operator[](int index) const {
4056 DCHECK_GE(index, 0);
4057 DCHECK_LT(index, size_);
4058 return elements_[index];
4059 }
4060#endif
4061
4062 void RankFirst(Solver* const solver, int elt) {
4063 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
4064 SwapTo(elt, first_ranked_.Value());
4065 first_ranked_.Incr(solver);
4066 }
4068 void RankLast(Solver* const solver, int elt) {
4069 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
4070 SwapTo(elt, last_ranked_.Value());
4071 last_ranked_.Decr(solver);
4072 }
4073
4074 bool IsRanked(int elt) const {
4075 const int position = position_[elt];
4076 return (position < first_ranked_.Value() ||
4077 position > last_ranked_.Value());
4078 }
4079
4080 std::string DebugString() const {
4081 std::string result = "[";
4082 for (int i = 0; i < first_ranked_.Value(); ++i) {
4083 absl::StrAppend(&result, elements_[i]);
4084 if (i != first_ranked_.Value() - 1) {
4085 result.append("-");
4087 }
4088 result.append("|");
4089 for (int i = first_ranked_.Value(); i <= last_ranked_.Value(); ++i) {
4090 absl::StrAppend(&result, elements_[i]);
4091 if (i != last_ranked_.Value()) {
4092 result.append("-");
4093 }
4094 }
4095 result.append("|");
4096 for (int i = last_ranked_.Value() + 1; i < size_; ++i) {
4097 absl::StrAppend(&result, elements_[i]);
4098 if (i != size_ - 1) {
4099 result.append("-");
4100 }
4101 }
4102 result.append("]");
4103 return result;
4104 }
4105
4106 private:
4107 void SwapTo(int elt, int next_position) {
4108 const int current_position = position_[elt];
4109 if (current_position != next_position) {
4110 const int next_elt = elements_[next_position];
4111 elements_[current_position] = next_elt;
4112 elements_[next_position] = elt;
4113 position_[elt] = next_position;
4114 position_[next_elt] = current_position;
4115 }
4116 }
4117
4119 std::vector<int> elements_;
4121 NumericalRev<int> first_ranked_;
4123 NumericalRev<int> last_ranked_;
4125 const int size_;
4127 std::unique_ptr<int[]> position_;
4128};
4129
4134class UnsortedNullableRevBitset {
4135 public:
4137 explicit UnsortedNullableRevBitset(int bit_size);
4138
4139 ~UnsortedNullableRevBitset() {}
4140
4141
4143 void Init(Solver* solver, const std::vector<uint64_t>& mask);
4144
4146 /// the active bitset was changed in the process.
4147 bool RevSubtract(Solver* solver, const std::vector<uint64_t>& mask);
4148
4151 bool RevAnd(Solver* solver, const std::vector<uint64_t>& mask);
4152
4155 int ActiveWordSize() const { return active_words_.Size(); }
4156
4158 bool Empty() const { return active_words_.Size() == 0; }
4159
4167 bool Intersects(const std::vector<uint64_t>& mask, int* support_index);
4168
4170 int64_t bit_size() const { return bit_size_; }
4172 int64_t word_size() const { return word_size_; }
4174 const RevIntSet<int>& active_words() const { return active_words_; }
4175
4176 private:
4177 void CleanUpActives(Solver* solver);
4178
4179 const int64_t bit_size_;
4180 const int64_t word_size_;
4181 RevArray<uint64_t> bits_;
4182 RevIntSet<int> active_words_;
4183 std::vector<int> to_remove_;
4185
4186template <class T>
4187bool IsArrayConstant(const std::vector<T>& values, const T& value) {
4188 for (int i = 0; i < values.size(); ++i) {
4189 if (values[i] != value) {
4190 return false;
4191 }
4192 }
4193 return true;
4194}
4195
4196template <class T>
4197bool IsArrayBoolean(const std::vector<T>& values) {
4198 for (int i = 0; i < values.size(); ++i) {
4199 if (values[i] != 0 && values[i] != 1) {
4200 return false;
4201 }
4202 }
4203 return true;
4204}
4205
4206template <class T>
4207bool AreAllOnes(const std::vector<T>& values) {
4208 return IsArrayConstant(values, T(1));
4210
4211template <class T>
4212bool AreAllNull(const std::vector<T>& values) {
4213 return IsArrayConstant(values, T(0));
4214}
4215
4216template <class T>
4217bool AreAllGreaterOrEqual(const std::vector<T>& values, const T& value) {
4218 for (const T& current_value : values) {
4219 if (current_value < value) {
4220 return false;
4221 }
4222 }
4223 return true;
4225
4226template <class T>
4227bool AreAllLessOrEqual(const std::vector<T>& values, const T& value) {
4228 for (const T& current_value : values) {
4229 if (current_value > value) {
4230 return false;
4231 }
4232 }
4233 return true;
4234}
4235
4236template <class T>
4237bool AreAllPositive(const std::vector<T>& values) {
4238 return AreAllGreaterOrEqual(values, T(0));
4240
4241template <class T>
4242bool AreAllNegative(const std::vector<T>& values) {
4243 return AreAllLessOrEqual(values, T(0));
4244}
4245
4246template <class T>
4247bool AreAllStrictlyPositive(const std::vector<T>& values) {
4248 return AreAllGreaterOrEqual(values, T(1));
4250
4251template <class T>
4252bool AreAllStrictlyNegative(const std::vector<T>& values) {
4253 return AreAllLessOrEqual(values, T(-1));
4255
4256template <class T>
4257bool IsIncreasingContiguous(const std::vector<T>& values) {
4258 for (int i = 0; i < values.size() - 1; ++i) {
4259 if (values[i + 1] != values[i] + 1) {
4260 return false;
4261 }
4262 }
4263 return true;
4265
4266template <class T>
4267bool IsIncreasing(const std::vector<T>& values) {
4268 for (int i = 0; i < values.size() - 1; ++i) {
4269 if (values[i + 1] < values[i]) {
4270 return false;
4271 }
4272 }
4273 return true;
4274}
4275
4276template <class T>
4277bool IsArrayInRange(const std::vector<IntVar*>& vars, T range_min,
4278 T range_max) {
4279 for (int i = 0; i < vars.size(); ++i) {
4280 if (vars[i]->Min() < range_min || vars[i]->Max() > range_max) {
4281 return false;
4282 }
4283 }
4284 return true;
4285}
4286
4287inline bool AreAllBound(const std::vector<IntVar*>& vars) {
4288 for (int i = 0; i < vars.size(); ++i) {
4289 if (!vars[i]->Bound()) {
4290 return false;
4291 }
4292 }
4293 return true;
4294}
4295
4296inline bool AreAllBooleans(const std::vector<IntVar*>& vars) {
4297 return IsArrayInRange(vars, 0, 1);
4298}
4302template <class T>
4303bool AreAllBoundOrNull(const std::vector<IntVar*>& vars,
4304 const std::vector<T>& values) {
4305 for (int i = 0; i < vars.size(); ++i) {
4306 if (values[i] != 0 && !vars[i]->Bound()) {
4307 return false;
4309 }
4310 return true;
4311}
4312
4314inline bool AreAllBoundTo(const std::vector<IntVar*>& vars, int64_t value) {
4315 for (int i = 0; i < vars.size(); ++i) {
4316 if (!vars[i]->Bound() || vars[i]->Min() != value) {
4317 return false;
4318 }
4319 }
4320 return true;
4321}
4322
4323inline int64_t MaxVarArray(const std::vector<IntVar*>& vars) {
4324 DCHECK(!vars.empty());
4325 int64_t result = kint64min;
4326 for (int i = 0; i < vars.size(); ++i) {
4328 result = std::max<int64_t>(result, vars[i]->Max());
4329 }
4330 return result;
4331}
4332
4333inline int64_t MinVarArray(const std::vector<IntVar*>& vars) {
4334 DCHECK(!vars.empty());
4335 int64_t result = kint64max;
4336 for (int i = 0; i < vars.size(); ++i) {
4338 result = std::min<int64_t>(result, vars[i]->Min());
4339 }
4340 return result;
4341}
4342
4343inline void FillValues(const std::vector<IntVar*>& vars,
4344 std::vector<int64_t>* const values) {
4345 values->clear();
4346 values->resize(vars.size());
4347 for (int i = 0; i < vars.size(); ++i) {
4348 (*values)[i] = vars[i]->Value();
4349 }
4350}
4351
4352inline int64_t PosIntDivUp(int64_t e, int64_t v) {
4353 DCHECK_GT(v, 0);
4354 return (e < 0 || e % v == 0) ? e / v : e / v + 1;
4356
4357inline int64_t PosIntDivDown(int64_t e, int64_t v) {
4358 DCHECK_GT(v, 0);
4359 return (e >= 0 || e % v == 0) ? e / v : e / v - 1;
4360}
4361
4362std::vector<int64_t> ToInt64Vector(const std::vector<int>& input);
4363
4364} // namespace operations_research
4365
4366#endif // ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
int64_t MemoryUsage(int unused)
Definition sysinfo.h:24
#define OR_DLL
Definition base_export.h:27
void Reset(const PathOperator &path_operator, int base_index_reference)
Argument Holder: useful when visiting a model.
const IntTupleSet & FindIntegerMatrixArgumentOrDie(const std::string &arg_name) const
Definition visitor.cc:117
void SetIntegerVariableArrayArgument(const std::string &arg_name, const std::vector< IntVar * > &vars)
Definition visitor.cc:56
void SetIntervalArgument(const std::string &arg_name, IntervalVar *var)
Definition visitor.cc:61
void SetIntervalArrayArgument(const std::string &arg_name, const std::vector< IntervalVar * > &vars)
Definition visitor.cc:66
IntExpr * FindIntegerExpressionArgumentOrDie(const std::string &arg_name) const
Definition visitor.cc:106
bool HasIntegerExpressionArgument(const std::string &arg_name) const
Checks if arguments exist.
Definition visitor.cc:81
const std::vector< IntVar * > & FindIntegerVariableArrayArgumentOrDie(const std::string &arg_name) const
Definition visitor.cc:112
void SetSequenceArgument(const std::string &arg_name, SequenceVar *var)
Definition visitor.cc:71
bool HasIntegerVariableArrayArgument(const std::string &arg_name) const
Definition visitor.cc:86
const std::vector< int64_t > & FindIntegerArrayArgumentOrDie(const std::string &arg_name) const
Definition visitor.cc:101
int64_t FindIntegerArgumentOrDie(const std::string &arg_name) const
Definition visitor.cc:96
void SetIntegerExpressionArgument(const std::string &arg_name, IntExpr *expr)
Definition visitor.cc:51
void SetSequenceArrayArgument(const std::string &arg_name, const std::vector< SequenceVar * > &vars)
Definition visitor.cc:76
int64_t FindIntegerArgumentWithDefault(const std::string &arg_name, int64_t def) const
Getters.
Definition visitor.cc:91
std::string DebugString() const override
const E & Element(const V *const var) const
bool Contains(const V *const var) const
IntVarElement * FastAdd(IntVar *var)
Adds without checking if variable has been previously added.
AssignmentContainer< IntVar, IntVarElement > IntContainer
IntVar * Var() override
Creates a variable from the expression.
Here's a sample relaxing one variable at a time:
bool HasFragments() const override
BaseLns(const std::vector< IntVar * > &vars)
bool MakeOneNeighbor() override
This method should not be overridden. Override NextFragment() instead.
virtual bool NextFragment()=0
BaseNodeIterators(const PathOperator *path_operator, int base_index_reference)
AlternativeNodeIterator * GetAlternativeIterator() const
NodeNeighborIterator * GetNeighborIterator() const
void Reset(bool update_end_nodes=false)
AlternativeNodeIterator * GetSiblingAlternativeIterator() const
virtual std::string DebugString() const
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
Definition bitset.h:560
void Clear(IndexType i)
Definition bitset.h:505
void Set(IndexType i)
Definition bitset.h:543
IntVarIterator * MakeDomainIterator(bool reversible) const override
IntVarIterator * MakeHoleIterator(bool reversible) const override
void RemoveValue(int64_t v) override
This method removes the value 'v' from the domain of the variable.
SimpleRevFIFO< Demon * > delayed_bound_demons_
void SetMax(int64_t m) override
void SetRange(int64_t mi, int64_t ma) override
This method sets both the min and the max of the expression.
void RemoveInterval(int64_t l, int64_t u) override
SimpleRevFIFO< Demon * > bound_demons_
void WhenBound(Demon *d) override
bool Bound() const override
Returns true if the min and the max of the expression are equal.
IntVar * IsLessOrEqual(int64_t constant) override
std::string BaseName() const override
Returns a base name for automatic naming.
void WhenRange(Demon *d) override
Attach a demon that will watch the min or the max of the expression.
Demon proxy to a method on the constraint with no arguments.
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.
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)
Demon proxy to a method on the constraint with three arguments.
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)
Low-priority demon proxy to a method on the constraint with no arguments.
DelayedCallMethod0(T *const ct, void(T::*method)(), const std::string &name)
std::string DebugString() const override
Solver::DemonPriority priority() const override
DelayedCallMethod1(T *const ct, void(T::*method)(P), const std::string &name, P param1)
Solver::DemonPriority priority() const override
std::string DebugString() const override
Low-priority demon proxy to a method on the constraint with two arguments.
std::string DebugString() const override
Solver::DemonPriority priority() const override
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
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
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 bool MakeOneNeighbor()
MakeNextNeighbor() in a subclass of IntVarLocalSearchOperator.
int index() const
Returns the index of the variable.
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.
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)
LightIntIntIntFunctionElementCt(Solver *const solver, IntVar *const var, IntVar *const index1, IntVar *const index2, IntVar *const index3, F values)
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
LocalSearchFilterManager(std::vector< FilterEvent > filter_events)
void Synchronize(const Assignment *assignment, const Assignment *delta)
Synchronizes all filters to assignment.
bool Accept(LocalSearchMonitor *monitor, const Assignment *delta, const Assignment *deltadelta, int64_t objective_min, int64_t objective_max)
virtual void Reset()
Sets the filter to empty solution.
virtual void Revert()
Cancels the changes made by the last Relax()/Accept() calls.
virtual bool Accept(const Assignment *delta, const Assignment *deltadelta, int64_t objective_min, int64_t objective_max)=0
virtual int64_t GetAcceptedObjectiveValue() const
Objective value from the last time Accept() was called and returned true.
virtual void Synchronize(const Assignment *assignment, const Assignment *delta)=0
virtual void EndAcceptNeighbor(const LocalSearchOperator *op, bool neighbor_found)=0
virtual void BeginAcceptNeighbor(const LocalSearchOperator *op)=0
virtual void BeginFilterNeighbor(const LocalSearchOperator *op)=0
void Install() override
Install itself on the solver.
virtual void BeginFiltering(const LocalSearchFilter *filter)=0
virtual void EndFilterNeighbor(const LocalSearchOperator *op, bool neighbor_found)=0
virtual void EndFiltering(const LocalSearchFilter *filter, bool reject)=0
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
The base class for all local search operators.
virtual bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta)=0
virtual const LocalSearchOperator * Self() const
virtual void Start(const Assignment *assignment)=0
void ChangeRelaxedVariableDomain(VariableDomainId domain_id, int64_t min, int64_t max)
void PropagateRelax(VariableDomainId domain_id)
Variable MakeVariable(VariableDomainId domain_id)
Variable MakeVariableWithRelaxedDomain(int64_t min, int64_t max)
int64_t VariableDomainMax(VariableDomainId domain_id) const
bool PropagateTighten(VariableDomainId domain_id)
virtual void InsertVarArrayConstantArrayExpression(IntExpr *expression, const std::vector< IntVar * > &var, const std::vector< int64_t > &values, VarArrayConstantArrayExpressionType type)=0
virtual void InsertVarConstantConstraint(Constraint *ct, IntVar *var, int64_t value, VarConstantConstraintType type)=0
virtual IntExpr * FindExprExprExpression(IntExpr *var1, IntExpr *var2, ExprExprExpressionType type) const =0
Expr Expr Expressions.
virtual Constraint * FindExprExprConstraint(IntExpr *expr1, IntExpr *expr2, ExprExprConstraintType type) const =0
Expr Expr Constraints.
virtual Constraint * FindVoidConstraint(VoidConstraintType type) const =0
Void constraints.
virtual IntExpr * FindVarArrayConstantArrayExpression(const std::vector< IntVar * > &vars, const std::vector< int64_t > &values, VarArrayConstantArrayExpressionType type) const =0
Var Array Constant Array Expressions.
virtual IntExpr * FindVarArrayExpression(const std::vector< IntVar * > &vars, VarArrayExpressionType type) const =0
Var Array Expressions.
virtual IntExpr * FindExprExpression(IntExpr *expr, ExprExpressionType type) const =0
Expr Expressions.
virtual void InsertExprExprConstraint(Constraint *ct, IntExpr *expr1, IntExpr *expr2, ExprExprConstraintType type)=0
virtual void InsertExprExpression(IntExpr *expression, IntExpr *expr, ExprExpressionType type)=0
virtual void InsertVoidConstraint(Constraint *ct, VoidConstraintType type)=0
virtual void InsertExprExprExpression(IntExpr *expression, IntExpr *var1, IntExpr *var2, ExprExprExpressionType type)=0
virtual void InsertVarConstantArrayExpression(IntExpr *expression, IntVar *var, const std::vector< int64_t > &values, VarConstantArrayExpressionType type)=0
virtual IntExpr * FindVarArrayConstantExpression(const std::vector< IntVar * > &vars, int64_t value, VarArrayConstantExpressionType type) const =0
Var Array Constant Expressions.
virtual void InsertExprConstantExpression(IntExpr *expression, IntExpr *var, int64_t value, ExprConstantExpressionType type)=0
virtual void InsertVarConstantConstantConstraint(Constraint *ct, IntVar *var, int64_t value1, int64_t value2, VarConstantConstantConstraintType type)=0
virtual void InsertVarArrayConstantExpression(IntExpr *expression, const std::vector< IntVar * > &var, int64_t value, VarArrayConstantExpressionType type)=0
virtual void InsertVarConstantConstantExpression(IntExpr *expression, IntVar *var, int64_t value1, int64_t value2, VarConstantConstantExpressionType type)=0
virtual Constraint * FindVarConstantConstraint(IntVar *var, int64_t value, VarConstantConstraintType type) const =0
Var Constant Constraints.
virtual IntExpr * FindVarConstantArrayExpression(IntVar *var, const std::vector< int64_t > &values, VarConstantArrayExpressionType type) const =0
Var Constant Array Expressions.
virtual IntExpr * FindExprConstantExpression(IntExpr *expr, int64_t value, ExprConstantExpressionType type) const =0
Expr Constant Expressions.
virtual void InsertExprExprConstantExpression(IntExpr *expression, IntExpr *var1, IntExpr *var2, int64_t constant, ExprExprConstantExpressionType type)=0
virtual IntExpr * FindExprExprConstantExpression(IntExpr *var1, IntExpr *var2, int64_t constant, ExprExprConstantExpressionType type) const =0
Expr Expr Constant Expressions.
virtual IntExpr * FindVarConstantConstantExpression(IntVar *var, int64_t value1, int64_t value2, VarConstantConstantExpressionType type) const =0
Var Constant Constant Expressions.
virtual Constraint * FindVarConstantConstantConstraint(IntVar *var, int64_t value1, int64_t value2, VarConstantConstantConstraintType type) const =0
Var Constant Constant Constraints.
virtual void InsertVarArrayExpression(IntExpr *expression, const std::vector< IntVar * > &vars, VarArrayExpressionType type)=0
void VisitIntervalArgument(const std::string &arg_name, IntervalVar *argument) override
Visit interval argument.
Definition visitor.cc:216
void VisitIntervalArrayArgument(const std::string &arg_name, const std::vector< IntervalVar * > &arguments) override
Definition visitor.cc:222
void VisitIntervalVariable(const IntervalVar *variable, const std::string &operation, int64_t value, IntervalVar *delegate) override
Definition visitor.cc:170
void VisitIntegerArgument(const std::string &arg_name, int64_t value) override
Integer arguments.
Definition visitor.cc:185
void VisitIntegerArrayArgument(const std::string &arg_name, const std::vector< int64_t > &values) override
Definition visitor.cc:190
void VisitSequenceVariable(const SequenceVar *variable) override
Definition visitor.cc:180
void BeginVisitIntegerExpression(const std::string &type_name, const IntExpr *expr) override
Definition visitor.cc:147
void VisitSequenceArgument(const std::string &arg_name, SequenceVar *argument) override
Visit sequence argument.
Definition visitor.cc:231
void VisitSequenceArrayArgument(const std::string &arg_name, const std::vector< SequenceVar * > &arguments) override
Definition visitor.cc:237
void VisitIntegerVariable(const IntVar *variable, IntExpr *delegate) override
Definition visitor.cc:158
void VisitIntegerVariableArrayArgument(const std::string &arg_name, const std::vector< IntVar * > &arguments) override
Definition visitor.cc:207
ArgumentHolder * Top() const
Definition visitor.cc:255
void VisitIntegerMatrixArgument(const std::string &arg_name, const IntTupleSet &values) override
Definition visitor.cc:195
void EndVisitIntegerExpression(const std::string &type_name, const IntExpr *expr) override
Definition visitor.cc:152
void VisitIntegerExpressionArgument(const std::string &arg_name, IntExpr *argument) override
Variables.
Definition visitor.cc:201
virtual void VisitIntegerArgument(const std::string &arg_name, int64_t value)
Visit integer arguments.
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)
void Reset(const PathOperator &path_operator, int base_index_reference)
Subclass of Rev<T> which adds numerical operations.
int number_of_nexts() const
Number of next variables.
bool SkipUnchanged(int index) const override
bool MakeChainInactive(int64_t before_chain, int64_t chain_end)
int64_t Prev(int64_t node) const
Returns the node before node in the current delta.
bool SwapActiveAndInactive(int64_t active, int64_t inactive)
Replaces active by inactive in the current path, making active inactive.
int PathClassFromStartNode(int64_t start_node) const
int64_t Path(int64_t node) const
void AddPairAlternativeSets(const std::vector< PairType > &pair_alternative_sets)
bool MakeActive(int64_t node, int64_t destination)
Insert the inactive node after destination.
int64_t OldNext(int64_t node) const
virtual bool ConsiderAlternatives(int64_t) const
bool SwapNodes(int64_t node1, int64_t node2)
Swaps the nodes node1 and node2.
int64_t BaseSiblingAlternativeNode(int i) const
Returns the alternative node for the sibling of the ith base node.
void SetNext(int64_t from, int64_t to, int64_t path)
Sets 'to' to be the node after 'from' on the given path.
virtual bool OnSamePathAsPreviousBase(int64_t)
it's currently way more complicated to implement.
virtual int64_t GetBaseNodeRestartPosition(int base_index)
int CurrentNodePathStart(int64_t node) const
int GetSiblingAlternativeIndex(int node) const
Returns the index of the alternative set of the sibling of node.
int64_t OldPath(int64_t node) const
int GetAlternativeIndex(int node) const
Returns the index of the alternative set of the node.
int64_t PrevNext(int64_t node) const
int64_t OldPrev(int64_t node) const
int AddAlternativeSet(const std::vector< int64_t > &alternative_set)
bool IsPathStart(int64_t node) const
Returns true if node is the first node on the path.
bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination)
bool SwapActiveAndInactiveChains(absl::Span< const int64_t > active_chain, absl::Span< const int64_t > inactive_chain)
int64_t EndNode(int i) const
Returns the end node of the ith base node.
int64_t GetActiveInAlternativeSet(int alternative_index) const
Returns the active node in the given alternative set.
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 IsInactive(int64_t node) const
Returns true if node is inactive.
const std::vector< int64_t > & path_starts() const
Returns the vector of path start nodes.
bool CheckChainValidity(int64_t before_chain, int64_t chain_end, int64_t exclude) const
bool ReverseChain(int64_t before_chain, int64_t after_chain, int64_t *chain_last)
int PathClass(int i) const
Returns the class of the path of the ith base node.
virtual void SetNextBaseToIncrement(int64_t base_index)
int64_t BaseAlternativeNode(int i) const
Returns the alternative node for the ith base node.
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
int64_t StartNode(int i) const
Returns the start node of the ith base node.
int64_t BaseNode(int i) const
Returns the ith base node of the operator.
int CurrentNodePathEnd(int64_t node) const
virtual void SetValues(IntVar *var, const std::vector< int64_t > &values)=0
virtual void SetDurationMax(IntervalVar *var, int64_t new_max)=0
virtual void SetStartMax(IntervalVar *var, int64_t new_max)=0
virtual void SetStartMin(IntervalVar *var, int64_t new_min)=0
IntervalVar modifiers.
virtual void RankSequence(SequenceVar *var, const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)=0
virtual void RankNotFirst(SequenceVar *var, int index)=0
virtual void RankNotLast(SequenceVar *var, int index)=0
virtual void PushContext(const std::string &context)=0
virtual void SetPerformed(IntervalVar *var, bool value)=0
virtual void SetEndMax(IntervalVar *var, int64_t new_max)=0
virtual void RemoveValue(IntVar *var, int64_t value)=0
virtual void EndDemonRun(Demon *demon)=0
virtual void SetDurationMin(IntervalVar *var, int64_t new_min)=0
virtual void RegisterDemon(Demon *demon)=0
virtual void SetMin(IntExpr *expr, int64_t new_min)=0
IntExpr modifiers.
virtual void SetEndMin(IntervalVar *var, int64_t new_min)=0
virtual void RankFirst(SequenceVar *var, int index)=0
SequenceVar modifiers.
virtual void SetMax(IntExpr *expr, int64_t new_max)=0
virtual void RankLast(SequenceVar *var, int index)=0
virtual void SetDurationRange(IntervalVar *var, int64_t new_min, int64_t new_max)=0
virtual void StartProcessingIntegerVariable(IntVar *var)=0
virtual void EndProcessingIntegerVariable(IntVar *var)=0
void Install() override
Install itself on the solver.
virtual void RemoveInterval(IntVar *var, int64_t imin, int64_t imax)=0
virtual void SetRange(IntExpr *expr, int64_t new_min, int64_t new_max)=0
virtual void BeginDemonRun(Demon *demon)=0
virtual void RemoveValues(IntVar *var, const std::vector< int64_t > &values)=0
virtual void SetStartRange(IntervalVar *var, int64_t new_min, int64_t new_max)=0
virtual void SetValue(IntVar *var, int64_t value)=0
virtual void SetEndRange(IntervalVar *var, int64_t new_min, int64_t new_max)=0
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:216
int64_t GetFirstBit(int row, int start) const
Definition utilities.cc:200
void SetToZero(Solver *solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
Definition utilities.cc:174
void SetToOne(Solver *solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition utilities.cc:166
int64_t Cardinality() const
Returns the number of bits set to one.
Definition utilities.cc:108
void ClearAll(Solver *solver)
Cleans all bits.
Definition utilities.cc:147
void SetToZero(Solver *solver, int64_t index)
Erases the 'index' bit.
Definition utilities.cc:91
bool IsCardinalityOne() const
Does it contains only one bit set?
Definition utilities.cc:125
void SetToOne(Solver *solver, int64_t index)
Sets the 'index' bit.
Definition utilities.cc:80
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition utilities.cc:102
int64_t GetFirstBit(int start) const
Definition utilities.cc:143
bool IsCardinalityZero() const
Is bitset null?
Definition utilities.cc:116
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
RevIntSet(int capacity)
Capacity is the fixed size of the set (it cannot grow).
const T * const_iterator
Iterators on the indices.
void Insert(Solver *const solver, const T &elt)
void RankLast(Solver *const solver, int elt)
RevPartialSequence(const std::vector< int > &items)
void RankFirst(Solver *const solver, int elt)
A reversible switch that can switch once from false to true.
void Switch(Solver *const solver)
virtual void OutputLine(const std::string &line)
Definition search.cc:306
void AcceptUncheckedNeighbor() override
After accepting an unchecked neighbor during local search.
Definition search.cc:220
void EndInitialPropagation() override
After the initial propagation.
Definition search.cc:297
void BeginInitialPropagation() override
Before the initial propagation.
Definition search.cc:295
void RefuteDecision(Decision *decision) override
Before refuting the decision.
Definition search.cc:253
std::string DebugString() const override
Definition search.cc:86
void ApplyDecision(Decision *decision) override
Before applying the decision.
Definition search.cc:245
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
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?
std::function< int64_t(int64_t, int64_t, int64_t)> IndexEvaluator3
void SaveAndSetValue(T *adr, T val)
All-in-one SaveAndSetValue.
const std::vector< ArcId > & ComputeSortedSubDagArcs(NodeId node)
bool Intersects(const std::vector< uint64_t > &mask, int *support_index)
Definition utilities.cc:291
bool RevSubtract(Solver *solver, const std::vector< uint64_t > &mask)
Definition utilities.cc:239
int64_t bit_size() const
Returns the number of bits given in the constructor of the bitset.
bool RevAnd(Solver *solver, const std::vector< uint64_t > &mask)
Definition utilities.cc:266
absl::Status Exists(absl::string_view path, Options options)
Definition file.cc:500
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
Definition matchers.h:467
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
OR-Tools root namespace.
LocalSearchOperator * MakeExtendedSwapActive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
--— ExtendedSwapActive --—
std::string ParameterDebugString(P param)
bool IsArrayConstant(const std::vector< T > &values, const T &value)
LocalSearchOperator * RelocateAndMakeInactive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
--— RelocateAndMakeInactive --—
LocalSearchOperator * MakeTSPOpt(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, Solver::IndexEvaluator3 evaluator, int chain_length)
--— TSP-based operators --—
LocalSearchOperator * MakeCross(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_incoming_neighbors=nullptr, std::function< const std::vector< int > &(int, int)> get_outgoing_neighbors=nullptr)
--— Cross --—
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)
LocalSearchOperator * MakeSwapActive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
--— SwapActive --—
LocalSearchOperator * ExchangeAndMakeActive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
bool AreAllGreaterOrEqual(const std::vector< T > &values, const T &value)
bool AreAllStrictlyPositive(const std::vector< T > &values)
bool IsArrayBoolean(const std::vector< T > &values)
LocalSearchOperator * MakeExchange(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_incoming_neighbors=nullptr, std::function< const std::vector< int > &(int, int)> get_outgoing_neighbors=nullptr)
--— Exchange --—
LocalSearchOperator * MakeActiveAndRelocate(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
--— MakeActiveAndRelocate --—
bool AreAllBoundOrNull(const std::vector< IntVar * > &vars, const std::vector< T > &values)
int64_t MaxVarArray(const std::vector< IntVar * > &vars)
LocalSearchOperator * MakeTSPLns(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, Solver::IndexEvaluator3 evaluator, int tsp_size)
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)
ClosedInterval::Iterator end(ClosedInterval interval)
LocalSearchOperator * MakeRelocate(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_incoming_neighbors=nullptr, std::function< const std::vector< int > &(int, int)> get_outgoing_neighbors=nullptr, int64_t chain_length=1LL, bool single_path=false, const std::string &name="Relocate")
--— Relocate --—
bool AreAllBoundTo(const std::vector< IntVar * > &vars, int64_t value)
Returns true if all variables are assigned to 'value'.
LocalSearchOperator * RelocateAndMakeActive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
-— RelocateAndMakeActive --—
void FillValues(const std::vector< IntVar * > &vars, std::vector< int64_t > *const values)
bool AreAllBooleans(const std::vector< IntVar * > &vars)
LocalSearchOperator * MakePathLns(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, int number_of_chunks, int chunk_size, bool unactive_fragments)
--— Path-based Large Neighborhood Search --—
int64_t MinVarArray(const std::vector< IntVar * > &vars)
LocalSearchOperator * MakeInactive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
--— MakeInactive --—
LocalSearchOperator * MakeTwoOpt(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_incoming_neighbors=nullptr, std::function< const std::vector< int > &(int, int)> get_outgoing_neighbors=nullptr)
--— 2Opt --—
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition utilities.cc:824
bool AreAllPositive(const std::vector< T > &values)
LocalSearchOperator * ExchangePathStartEndsAndMakeActive(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
Demon * MakeDelayedConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
LocalSearchOperator * MakeSwapActiveChain(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, int max_chain_size)
--— SwapActiveChain --—
LocalSearchOperator * MakeLinKernighan(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, const Solver::IndexEvaluator3 &evaluator, bool topt)
--— Lin-Kernighan --—
LocalSearchState::VariableDomainId VariableDomainId
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)
Hash functions.
int64_t PosIntDivUp(int64_t e, int64_t v)
SubDagComputer::NodeId NodeId
STL namespace.
false true
Definition numbers.cc:223
bool Next()
trees with all degrees equal to
static int input(yyscan_t yyscanner)
#define DEFINE_STRONG_INT_TYPE(type_name, value_type)
Set of parameters used to configure how the neighborhood is traversed.
bool accept_path_end_base
True if path ends should be considered when iterating over neighbors.
std::function< const std::vector< int > &(int, int)> get_outgoing_neighbors
int number_of_base_nodes
Number of nodes needed to define a neighbor.
std::function< const std::vector< int > &(int, int)> get_incoming_neighbors
static const int64_t kint64max
Definition types.h:32
static const int64_t kint64min
Definition types.h:31