OR-Tools  9.3
constraint_solveri.h
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
48
49#ifndef OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
50#define OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
51
52#include <stdint.h>
53#include <string.h>
54
55#include <algorithm>
56#include <functional>
57#include <initializer_list>
58#include <memory>
59#include <string>
60#include <utility>
61#include <vector>
62
63#include "absl/container/flat_hash_map.h"
64#include "absl/strings/str_cat.h"
67#include "ortools/base/timer.h"
69#include "ortools/util/bitset.h"
71
72namespace operations_research {
73
99class LocalSearchMonitor;
100
101class BaseIntExpr : public IntExpr {
102 public:
103 explicit BaseIntExpr(Solver* const s) : IntExpr(s), var_(nullptr) {}
104 ~BaseIntExpr() override {}
105
106 IntVar* Var() override;
107 virtual IntVar* CastToVar();
108
109 private:
110 IntVar* var_;
111};
112
126
135#ifndef SWIG
136template <class T>
138 private:
139 enum { CHUNK_SIZE = 16 }; // TODO(user): could be an extra template param
140 struct Chunk {
141 T data_[CHUNK_SIZE];
142 const Chunk* const next_;
143 explicit Chunk(const Chunk* next) : next_(next) {}
144 };
145
146 public:
148 class Iterator {
149 public:
150 explicit Iterator(const SimpleRevFIFO<T>* l)
151 : chunk_(l->chunks_), value_(l->Last()) {}
152 bool ok() const { return (value_ != nullptr); }
153 T operator*() const { return *value_; }
154 void operator++() {
155 ++value_;
156 if (value_ == chunk_->data_ + CHUNK_SIZE) {
157 chunk_ = chunk_->next_;
158 value_ = chunk_ ? chunk_->data_ : nullptr;
159 }
160 }
161
162 private:
163 const Chunk* chunk_;
164 const T* value_;
165 };
166
167 SimpleRevFIFO() : chunks_(nullptr), pos_(0) {}
168
169 void Push(Solver* const s, T val) {
170 if (pos_.Value() == 0) {
171 Chunk* const chunk = s->UnsafeRevAlloc(new Chunk(chunks_));
172 s->SaveAndSetValue(reinterpret_cast<void**>(&chunks_),
173 reinterpret_cast<void*>(chunk));
174 pos_.SetValue(s, CHUNK_SIZE - 1);
175 } else {
176 pos_.Decr(s);
177 }
178 chunks_->data_[pos_.Value()] = val;
179 }
180
182 void PushIfNotTop(Solver* const s, T val) {
183 if (chunks_ == nullptr || LastValue() != val) {
184 Push(s, val);
185 }
186 }
187
189 const T* Last() const {
190 return chunks_ ? &chunks_->data_[pos_.Value()] : nullptr;
191 }
192
193 T* MutableLast() { return chunks_ ? &chunks_->data_[pos_.Value()] : nullptr; }
194
196 const T& LastValue() const {
197 DCHECK(chunks_);
198 return chunks_->data_[pos_.Value()];
199 }
200
202 void SetLastValue(const T& v) {
203 DCHECK(Last());
204 chunks_->data_[pos_.Value()] = v;
205 }
206
207 private:
208 Chunk* chunks_;
210};
211
213// TODO(user): use murmurhash.
214inline uint64_t Hash1(uint64_t value) {
215 value = (~value) + (value << 21);
216 value ^= value >> 24;
217 value += (value << 3) + (value << 8);
218 value ^= value >> 14;
219 value += (value << 2) + (value << 4);
220 value ^= value >> 28;
221 value += (value << 31);
222 return value;
223}
224
225inline uint64_t Hash1(uint32_t value) {
226 uint64_t a = value;
227 a = (a + 0x7ed55d16) + (a << 12);
228 a = (a ^ 0xc761c23c) ^ (a >> 19);
229 a = (a + 0x165667b1) + (a << 5);
230 a = (a + 0xd3a2646c) ^ (a << 9);
231 a = (a + 0xfd7046c5) + (a << 3);
232 a = (a ^ 0xb55a4f09) ^ (a >> 16);
233 return a;
234}
235
236inline uint64_t Hash1(int64_t value) {
237 return Hash1(static_cast<uint64_t>(value));
238}
239
240inline uint64_t Hash1(int value) { return Hash1(static_cast<uint32_t>(value)); }
241
242inline uint64_t Hash1(void* const ptr) {
243#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || \
244 defined(__aarch64__)
245 return Hash1(reinterpret_cast<uint64_t>(ptr));
246#else
247 return Hash1(reinterpret_cast<uint32_t>(ptr));
248#endif
249}
250
251template <class T>
252uint64_t Hash1(const std::vector<T*>& ptrs) {
253 if (ptrs.empty()) return 0;
254 if (ptrs.size() == 1) return Hash1(ptrs[0]);
255 uint64_t hash = Hash1(ptrs[0]);
256 for (int i = 1; i < ptrs.size(); ++i) {
257 hash = hash * i + Hash1(ptrs[i]);
258 }
259 return hash;
260}
261
262inline uint64_t Hash1(const std::vector<int64_t>& ptrs) {
263 if (ptrs.empty()) return 0;
264 if (ptrs.size() == 1) return Hash1(ptrs[0]);
265 uint64_t hash = Hash1(ptrs[0]);
266 for (int i = 1; i < ptrs.size(); ++i) {
267 hash = hash * i + Hash1(ptrs[i]);
268 }
269 return hash;
270}
271
274template <class K, class V>
276 public:
277 RevImmutableMultiMap(Solver* const solver, int initial_size)
278 : solver_(solver),
279 array_(solver->UnsafeRevAllocArray(new Cell*[initial_size])),
280 size_(initial_size),
281 num_items_(0) {
282 memset(array_, 0, sizeof(*array_) * size_.Value());
283 }
284
286
287 int num_items() const { return num_items_.Value(); }
288
290 bool ContainsKey(const K& key) const {
291 uint64_t code = Hash1(key) % size_.Value();
292 Cell* tmp = array_[code];
293 while (tmp) {
294 if (tmp->key() == key) {
295 return true;
296 }
297 tmp = tmp->next();
298 }
299 return false;
300 }
301
305 const V& FindWithDefault(const K& key, const V& default_value) const {
306 uint64_t code = Hash1(key) % size_.Value();
307 Cell* tmp = array_[code];
308 while (tmp) {
309 if (tmp->key() == key) {
310 return tmp->value();
311 }
312 tmp = tmp->next();
313 }
314 return default_value;
315 }
316
318 void Insert(const K& key, const V& value) {
319 const int position = Hash1(key) % size_.Value();
320 Cell* const cell =
321 solver_->UnsafeRevAlloc(new Cell(key, value, array_[position]));
322 solver_->SaveAndSetValue(reinterpret_cast<void**>(&array_[position]),
323 reinterpret_cast<void*>(cell));
324 num_items_.Incr(solver_);
325 if (num_items_.Value() > 2 * size_.Value()) {
326 Double();
327 }
328 }
329
330 private:
331 class Cell {
332 public:
333 Cell(const K& key, const V& value, Cell* const next)
334 : key_(key), value_(value), next_(next) {}
335
336 void SetRevNext(Solver* const solver, Cell* const next) {
337 solver->SaveAndSetValue(reinterpret_cast<void**>(&next_),
338 reinterpret_cast<void*>(next));
339 }
340
341 Cell* next() const { return next_; }
342
343 const K& key() const { return key_; }
344
345 const V& value() const { return value_; }
346
347 private:
348 const K key_;
349 const V value_;
350 Cell* next_;
351 };
352
353 void Double() {
354 Cell** const old_cell_array = array_;
355 const int old_size = size_.Value();
356 size_.SetValue(solver_, size_.Value() * 2);
357 solver_->SaveAndSetValue(
358 reinterpret_cast<void**>(&array_),
359 reinterpret_cast<void*>(
360 solver_->UnsafeRevAllocArray(new Cell*[size_.Value()])));
361 memset(array_, 0, size_.Value() * sizeof(*array_));
362 for (int i = 0; i < old_size; ++i) {
363 Cell* tmp = old_cell_array[i];
364 while (tmp != nullptr) {
365 Cell* const to_reinsert = tmp;
366 tmp = tmp->next();
367 const uint64_t new_position = Hash1(to_reinsert->key()) % size_.Value();
368 to_reinsert->SetRevNext(solver_, array_[new_position]);
369 solver_->SaveAndSetValue(
370 reinterpret_cast<void**>(&array_[new_position]),
371 reinterpret_cast<void*>(to_reinsert));
372 }
373 }
374 }
375
376 Solver* const solver_;
377 Cell** array_;
378 NumericalRev<int> size_;
379 NumericalRev<int> num_items_;
380};
381
384 public:
385 RevSwitch() : value_(false) {}
386
387 bool Switched() const { return value_; }
388
389 void Switch(Solver* const solver) { solver->SaveAndSetValue(&value_, true); }
390
391 private:
392 bool value_;
393};
394
398 public:
399 explicit SmallRevBitSet(int64_t size);
401 void SetToOne(Solver* const solver, int64_t pos);
403 void SetToZero(Solver* const solver, int64_t pos);
405 int64_t Cardinality() const;
407 bool IsCardinalityZero() const { return bits_.Value() == uint64_t{0}; }
409 bool IsCardinalityOne() const {
410 return (bits_.Value() != 0) && !(bits_.Value() & (bits_.Value() - 1));
411 }
414 int64_t GetFirstOne() const;
415
416 private:
417 Rev<uint64_t> bits_;
418};
419
423 public:
424 explicit RevBitSet(int64_t size);
425 ~RevBitSet();
426
428 void SetToOne(Solver* const solver, int64_t index);
430 void SetToZero(Solver* const solver, int64_t index);
432 bool IsSet(int64_t index) const;
434 int64_t Cardinality() const;
436 bool IsCardinalityZero() const;
438 bool IsCardinalityOne() const;
441 int64_t GetFirstBit(int start) const;
443 void ClearAll(Solver* const solver);
444
445 friend class RevBitMatrix;
446
447 private:
449 void Save(Solver* const solver, int offset);
450 const int64_t size_;
451 const int64_t length_;
452 uint64_t* bits_;
453 uint64_t* stamps_;
454};
455
457class RevBitMatrix : private RevBitSet {
458 public:
459 RevBitMatrix(int64_t rows, int64_t columns);
461
463 void SetToOne(Solver* const solver, int64_t row, int64_t column);
465 void SetToZero(Solver* const solver, int64_t row, int64_t column);
467 bool IsSet(int64_t row, int64_t column) const {
468 DCHECK_GE(row, 0);
469 DCHECK_LT(row, rows_);
470 DCHECK_GE(column, 0);
471 DCHECK_LT(column, columns_);
472 return RevBitSet::IsSet(row * columns_ + column);
473 }
475 int64_t Cardinality(int row) const;
477 bool IsCardinalityZero(int row) const;
479 bool IsCardinalityOne(int row) const;
482 int64_t GetFirstBit(int row, int start) const;
484 void ClearAll(Solver* const solver);
485
486 private:
487 const int64_t rows_;
488 const int64_t columns_;
489};
490
496
498template <class T>
499class CallMethod0 : public Demon {
500 public:
501 CallMethod0(T* const ct, void (T::*method)(), const std::string& name)
502 : constraint_(ct), method_(method), name_(name) {}
503
504 ~CallMethod0() override {}
505
506 void Run(Solver* const s) override { (constraint_->*method_)(); }
507
508 std::string DebugString() const override {
509 return "CallMethod_" + name_ + "(" + constraint_->DebugString() + ")";
510 }
511
512 private:
513 T* const constraint_;
514 void (T::*const method_)();
515 const std::string name_;
516};
517
518template <class T>
519Demon* MakeConstraintDemon0(Solver* const s, T* const ct, void (T::*method)(),
520 const std::string& name) {
521 return s->RevAlloc(new CallMethod0<T>(ct, method, name));
522}
523
524template <class P>
525std::string ParameterDebugString(P param) {
526 return absl::StrCat(param);
527}
528
530template <class P>
531std::string ParameterDebugString(P* param) {
532 return param->DebugString();
533}
534
536template <class T, class P>
537class CallMethod1 : public Demon {
538 public:
539 CallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
540 P param1)
541 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
542
543 ~CallMethod1() override {}
544
545 void Run(Solver* const s) override { (constraint_->*method_)(param1_); }
546
547 std::string DebugString() const override {
548 return absl::StrCat("CallMethod_", name_, "(", constraint_->DebugString(),
549 ", ", ParameterDebugString(param1_), ")");
550 }
551
552 private:
553 T* const constraint_;
554 void (T::*const method_)(P);
555 const std::string name_;
556 P param1_;
557};
558
559template <class T, class P>
560Demon* MakeConstraintDemon1(Solver* const s, T* const ct, void (T::*method)(P),
561 const std::string& name, P param1) {
562 return s->RevAlloc(new CallMethod1<T, P>(ct, method, name, param1));
563}
564
566template <class T, class P, class Q>
567class CallMethod2 : public Demon {
568 public:
569 CallMethod2(T* const ct, void (T::*method)(P, Q), const std::string& name,
570 P param1, Q param2)
571 : constraint_(ct),
572 method_(method),
573 name_(name),
574 param1_(param1),
575 param2_(param2) {}
576
577 ~CallMethod2() override {}
578
579 void Run(Solver* const s) override {
580 (constraint_->*method_)(param1_, param2_);
581 }
582
583 std::string DebugString() const override {
584 return absl::StrCat(absl::StrCat("CallMethod_", name_),
585 absl::StrCat("(", constraint_->DebugString()),
586 absl::StrCat(", ", ParameterDebugString(param1_)),
587 absl::StrCat(", ", ParameterDebugString(param2_), ")"));
588 }
589
590 private:
591 T* const constraint_;
592 void (T::*const method_)(P, Q);
593 const std::string name_;
594 P param1_;
595 Q param2_;
596};
597
598template <class T, class P, class Q>
600 void (T::*method)(P, Q), const std::string& name,
601 P param1, Q param2) {
602 return s->RevAlloc(
603 new CallMethod2<T, P, Q>(ct, method, name, param1, param2));
604}
606template <class T, class P, class Q, class R>
607class CallMethod3 : public Demon {
608 public:
609 CallMethod3(T* const ct, void (T::*method)(P, Q, R), const std::string& name,
610 P param1, Q param2, R param3)
611 : constraint_(ct),
612 method_(method),
613 name_(name),
614 param1_(param1),
615 param2_(param2),
616 param3_(param3) {}
617
618 ~CallMethod3() override {}
619
620 void Run(Solver* const s) override {
621 (constraint_->*method_)(param1_, param2_, param3_);
622 }
623
624 std::string DebugString() const override {
625 return absl::StrCat(absl::StrCat("CallMethod_", name_),
626 absl::StrCat("(", constraint_->DebugString()),
627 absl::StrCat(", ", ParameterDebugString(param1_)),
628 absl::StrCat(", ", ParameterDebugString(param2_)),
629 absl::StrCat(", ", ParameterDebugString(param3_), ")"));
630 }
631
632 private:
633 T* const constraint_;
634 void (T::*const method_)(P, Q, R);
635 const std::string name_;
636 P param1_;
637 Q param2_;
638 R param3_;
639};
640
641template <class T, class P, class Q, class R>
643 void (T::*method)(P, Q, R), const std::string& name,
644 P param1, Q param2, R param3) {
645 return s->RevAlloc(
646 new CallMethod3<T, P, Q, R>(ct, method, name, param1, param2, param3));
647}
649
654
656template <class T>
657class DelayedCallMethod0 : public Demon {
658 public:
659 DelayedCallMethod0(T* const ct, void (T::*method)(), const std::string& name)
660 : constraint_(ct), method_(method), name_(name) {}
661
663
664 void Run(Solver* const s) override { (constraint_->*method_)(); }
665
668 }
669
670 std::string DebugString() const override {
671 return "DelayedCallMethod_" + name_ + "(" + constraint_->DebugString() +
672 ")";
673 }
674
675 private:
676 T* const constraint_;
677 void (T::*const method_)();
678 const std::string name_;
679};
680
681template <class T>
683 void (T::*method)(),
684 const std::string& name) {
685 return s->RevAlloc(new DelayedCallMethod0<T>(ct, method, name));
686}
687
689template <class T, class P>
690class DelayedCallMethod1 : public Demon {
691 public:
692 DelayedCallMethod1(T* const ct, void (T::*method)(P), const std::string& name,
693 P param1)
694 : constraint_(ct), method_(method), name_(name), param1_(param1) {}
695
697
698 void Run(Solver* const s) override { (constraint_->*method_)(param1_); }
699
702 }
703
704 std::string DebugString() const override {
705 return absl::StrCat("DelayedCallMethod_", name_, "(",
706 constraint_->DebugString(), ", ",
707 ParameterDebugString(param1_), ")");
708 }
709
710 private:
711 T* const constraint_;
712 void (T::*const method_)(P);
713 const std::string name_;
714 P param1_;
715};
716
717template <class T, class P>
719 void (T::*method)(P),
720 const std::string& name, P param1) {
721 return s->RevAlloc(new DelayedCallMethod1<T, P>(ct, method, name, param1));
722}
723
725template <class T, class P, class Q>
726class DelayedCallMethod2 : public Demon {
727 public:
728 DelayedCallMethod2(T* const ct, void (T::*method)(P, Q),
729 const std::string& name, P param1, Q param2)
730 : constraint_(ct),
731 method_(method),
732 name_(name),
733 param1_(param1),
734 param2_(param2) {}
735
737
738 void Run(Solver* const s) override {
739 (constraint_->*method_)(param1_, param2_);
740 }
741
744 }
745
746 std::string DebugString() const override {
747 return absl::StrCat(absl::StrCat("DelayedCallMethod_", name_),
748 absl::StrCat("(", constraint_->DebugString()),
749 absl::StrCat(", ", ParameterDebugString(param1_)),
750 absl::StrCat(", ", ParameterDebugString(param2_), ")"));
751 }
752
753 private:
754 T* const constraint_;
755 void (T::*const method_)(P, Q);
756 const std::string name_;
757 P param1_;
758 Q param2_;
759};
760
761template <class T, class P, class Q>
763 void (T::*method)(P, Q),
764 const std::string& name, P param1,
765 Q param2) {
766 return s->RevAlloc(
767 new DelayedCallMethod2<T, P, Q>(ct, method, name, param1, param2));
768}
770
771#endif // !defined(SWIG)
772
790// TODO(user): rename Start to Synchronize ?
791// TODO(user): decouple the iterating from the defining of a neighbor.
793 public:
796 virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) = 0;
797 virtual void Start(const Assignment* assignment) = 0;
798 virtual void Reset() {}
799#ifndef SWIG
800 virtual const LocalSearchOperator* Self() const { return this; }
801#endif // SWIG
802 virtual bool HasFragments() const { return false; }
803 virtual bool HoldsDelta() const { return false; }
804};
805
807template <class V, class Val, class Handler>
809 public:
811 explicit VarLocalSearchOperator(Handler var_handler)
812 : activated_(),
814 cleared_(true),
815 var_handler_(var_handler) {}
817 bool HoldsDelta() const override { return true; }
820 void Start(const Assignment* assignment) override {
821 const int size = Size();
822 CHECK_LE(size, assignment->Size())
823 << "Assignment contains fewer variables than operator";
824 for (int i = 0; i < size; ++i) {
825 activated_.Set(i, var_handler_.ValueFromAssignment(*assignment, vars_[i],
826 i, &values_[i]));
827 }
831 OnStart();
832 }
833 virtual bool IsIncremental() const { return false; }
834 int Size() const { return vars_.size(); }
837 const Val& Value(int64_t index) const {
838 DCHECK_LT(index, vars_.size());
839 return values_[index];
840 }
842 V* Var(int64_t index) const { return vars_[index]; }
843 virtual bool SkipUnchanged(int index) const { return false; }
844 const Val& OldValue(int64_t index) const { return old_values_[index]; }
845 void SetValue(int64_t index, const Val& value) {
848 }
849 bool Activated(int64_t index) const { return activated_[index]; }
850 void Activate(int64_t index) {
853 }
854 void Deactivate(int64_t index) {
857 }
858 bool ApplyChanges(Assignment* delta, Assignment* deltadelta) const {
859 if (IsIncremental() && !cleared_) {
860 for (const int64_t index : delta_changes_.PositionsSetAtLeastOnce()) {
861 V* var = Var(index);
862 const Val& value = Value(index);
863 const bool activated = activated_[index];
864 var_handler_.AddToAssignment(var, value, activated, nullptr, index,
865 deltadelta);
866 var_handler_.AddToAssignment(var, value, activated,
868 }
869 } else {
870 delta->Clear();
871 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
872 const Val& value = Value(index);
873 const bool activated = activated_[index];
874 if (!activated || value != OldValue(index) || !SkipUnchanged(index)) {
875 var_handler_.AddToAssignment(Var(index), value, activated_[index],
877 }
878 }
879 }
880 return true;
881 }
882 void RevertChanges(bool incremental) {
883 cleared_ = false;
885 if (incremental && IsIncremental()) return;
886 cleared_ = true;
887 for (const int64_t index : changes_.PositionsSetAtLeastOnce()) {
889 var_handler_.OnRevertChanges(index, values_[index]);
892 }
894 }
895 void AddVars(const std::vector<V*>& vars) {
896 if (!vars.empty()) {
897 vars_.insert(vars_.end(), vars.begin(), vars.end());
898 const int64_t size = Size();
899 values_.resize(size);
900 old_values_.resize(size);
901 prev_values_.resize(size);
902 assignment_indices_.resize(size, -1);
903 activated_.Resize(size);
907 var_handler_.OnAddVars();
908 }
909 }
910
914 virtual void OnStart() {}
915
918 protected:
919 void MarkChange(int64_t index) {
922 }
923
924 std::vector<V*> vars_;
925 std::vector<Val> values_;
926 std::vector<Val> old_values_;
927 std::vector<Val> prev_values_;
928 mutable std::vector<int> assignment_indices_;
935};
936
939
941 public:
942 IntVarLocalSearchHandler() : op_(nullptr) {}
944 : op_(other.op_) {}
946 void AddToAssignment(IntVar* var, int64_t value, bool active,
947 std::vector<int>* assignment_indices, int64_t index,
948 Assignment* assignment) const {
949 Assignment::IntContainer* const container =
950 assignment->MutableIntVarContainer();
951 IntVarElement* element = nullptr;
952 if (assignment_indices != nullptr) {
953 if ((*assignment_indices)[index] == -1) {
954 (*assignment_indices)[index] = container->Size();
955 element = assignment->FastAdd(var);
956 } else {
957 element = container->MutableElement((*assignment_indices)[index]);
958 }
959 } else {
960 element = assignment->FastAdd(var);
961 }
962 if (active) {
963 element->SetValue(value);
964 element->Activate();
965 } else {
966 element->Deactivate();
967 }
968 }
969 bool ValueFromAssignment(const Assignment& assignment, IntVar* var,
970 int64_t index, int64_t* value);
971 void OnRevertChanges(int64_t index, int64_t value);
972 void OnAddVars() {}
973
974 private:
975 IntVarLocalSearchOperator* const op_;
976};
977
983
984#ifdef SWIG
988// TODO(user): find a way to move this code back to the .i file, where it
992#if defined(SWIGPYTHON)
993// clang-format off
994%unignore VarLocalSearchOperator<IntVar, int64_t,
995 IntVarLocalSearchHandler>::Size;
996%unignore VarLocalSearchOperator<IntVar, int64_t,
997 IntVarLocalSearchHandler>::Value;
998%unignore VarLocalSearchOperator<IntVar, int64_t,
999 IntVarLocalSearchHandler>::OldValue;
1000%unignore VarLocalSearchOperator<IntVar, int64_t,
1001 IntVarLocalSearchHandler>::SetValue;
1002%feature("director") VarLocalSearchOperator<IntVar, int64_t,
1003 IntVarLocalSearchHandler>::IsIncremental;
1004%feature("director") VarLocalSearchOperator<IntVar, int64_t,
1005 IntVarLocalSearchHandler>::OnStart;
1006%unignore VarLocalSearchOperator<IntVar, int64_t,
1007 IntVarLocalSearchHandler>::IsIncremental;
1008%unignore VarLocalSearchOperator<IntVar, int64_t,
1009 IntVarLocalSearchHandler>::OnStart;
1010// clang-format on
1011#endif // SWIGPYTHON
1012
1013// clang-format off
1014%rename(IntVarLocalSearchOperatorTemplate)
1015 VarLocalSearchOperator<IntVar, int64_t, IntVarLocalSearchHandler>;
1016%template(IntVarLocalSearchOperatorTemplate)
1017 VarLocalSearchOperator<IntVar, int64_t, IntVarLocalSearchHandler>;
1018// clang-format on
1019#endif // SWIG
1020
1023 public:
1024 IntVarLocalSearchOperator() : max_inverse_value_(-1) {}
1025 // If keep_inverse_values is true, assumes that vars models an injective
1026 // function f with domain [0, vars.size()) in which case the operator will
1027 // maintain the inverse function.
1028 explicit IntVarLocalSearchOperator(const std::vector<IntVar*>& vars,
1029 bool keep_inverse_values = false)
1032 max_inverse_value_(keep_inverse_values ? vars.size() - 1 : -1) {
1033 AddVars(vars);
1034 if (keep_inverse_values) {
1035 int64_t max_value = -1;
1036 for (const IntVar* const var : vars) {
1037 max_value = std::max(max_value, var->Max());
1038 }
1039 inverse_values_.resize(max_value + 1, -1);
1040 old_inverse_values_.resize(max_value + 1, -1);
1041 }
1042 }
1050 bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
1051
1052 protected:
1054
1057 // TODO(user): make it pure virtual, implies porting all apps overriding
1059 virtual bool MakeOneNeighbor();
1060
1061 bool IsInverseValue(int64_t index) const {
1062 DCHECK_GE(index, 0);
1063 return index <= max_inverse_value_;
1064 }
1065
1066 int64_t InverseValue(int64_t index) const { return inverse_values_[index]; }
1067
1068 int64_t OldInverseValue(int64_t index) const {
1069 return old_inverse_values_[index];
1070 }
1071
1072 void SetInverseValue(int64_t index, int64_t value) {
1073 inverse_values_[index] = value;
1074 }
1075
1076 void SetOldInverseValue(int64_t index, int64_t value) {
1077 old_inverse_values_[index] = value;
1078 }
1079
1080 private:
1081 const int64_t max_inverse_value_;
1082 std::vector<int64_t> old_inverse_values_;
1083 std::vector<int64_t> inverse_values_;
1084};
1085
1087 const Assignment& assignment, IntVar* var, int64_t index, int64_t* value) {
1088 const Assignment::IntContainer& container = assignment.IntVarContainer();
1089 const IntVarElement* element = &(container.Element(index));
1090 if (element->Var() != var) {
1091 CHECK(container.Contains(var))
1092 << "Assignment does not contain operator variable " << var;
1093 element = &(container.Element(var));
1094 }
1095 *value = element->Value();
1096 if (op_->IsInverseValue(index)) {
1097 op_->SetInverseValue(*value, index);
1099 }
1100 return element->Activated();
1101}
1102
1104 int64_t value) {
1105 if (op_->IsInverseValue(index)) {
1107 }
1108}
1109
1112
1114 public:
1117 : op_(other.op_) {}
1119 : op_(op) {}
1120 void AddToAssignment(SequenceVar* var, const std::vector<int>& value,
1121 bool active, std::vector<int>* assignment_indices,
1122 int64_t index, Assignment* assignment) const;
1123 bool ValueFromAssignment(const Assignment& assignment, SequenceVar* var,
1124 int64_t index, std::vector<int>* value);
1125 void OnRevertChanges(int64_t index, const std::vector<int>& value);
1126 void OnAddVars();
1127
1128 private:
1130};
1131
1132#ifdef SWIG
1136// TODO(user): find a way to move this code back to the .i file, where it
1138// clang-format off
1139%rename(SequenceVarLocalSearchOperatorTemplate) VarLocalSearchOperator<
1140 SequenceVar, std::vector<int>, SequenceVarLocalSearchHandler>;
1141%template(SequenceVarLocalSearchOperatorTemplate) VarLocalSearchOperator<
1142 SequenceVar, std::vector<int>, SequenceVarLocalSearchHandler>;
1143// clang-format on
1144#endif
1145
1146typedef VarLocalSearchOperator<SequenceVar, std::vector<int>,
1147 SequenceVarLocalSearchHandler>
1149
1152 public:
1154 explicit SequenceVarLocalSearchOperator(const std::vector<SequenceVar*>& vars)
1157 AddVars(vars);
1158 }
1162 const std::vector<int>& Sequence(int64_t index) const { return Value(index); }
1163 const std::vector<int>& OldSequence(int64_t index) const {
1164 return OldValue(index);
1165 }
1166 void SetForwardSequence(int64_t index, const std::vector<int>& value) {
1168 }
1169 void SetBackwardSequence(int64_t index, const std::vector<int>& value) {
1172 }
1173
1174 protected:
1176
1177 std::vector<std::vector<int>> backward_values_;
1178};
1179
1181 SequenceVar* var, const std::vector<int>& value, bool active,
1182 std::vector<int>* assignment_indices, int64_t index,
1183 Assignment* assignment) const {
1184 Assignment::SequenceContainer* const container =
1185 assignment->MutableSequenceVarContainer();
1186 SequenceVarElement* element = nullptr;
1187 if (assignment_indices != nullptr) {
1188 if ((*assignment_indices)[index] == -1) {
1189 (*assignment_indices)[index] = container->Size();
1190 element = assignment->FastAdd(var);
1191 } else {
1192 element = container->MutableElement((*assignment_indices)[index]);
1193 }
1194 } else {
1195 element = assignment->FastAdd(var);
1196 }
1197 if (active) {
1198 element->SetForwardSequence(value);
1200 element->Activate();
1201 } else {
1202 element->Deactivate();
1203 }
1204}
1205
1207 const Assignment& assignment, SequenceVar* var, int64_t index,
1208 std::vector<int>* value) {
1209 const Assignment::SequenceContainer& container =
1210 assignment.SequenceVarContainer();
1211 const SequenceVarElement* element = &(container.Element(index));
1212 if (element->Var() != var) {
1213 CHECK(container.Contains(var))
1214 << "Assignment does not contain operator variable " << var;
1215 element = &(container.Element(var));
1216 }
1217 const std::vector<int>& element_value = element->ForwardSequence();
1218 CHECK_GE(var->size(), element_value.size());
1219 op_->backward_values_[index].clear();
1220 *value = element_value;
1221 return element->Activated();
1222}
1223
1225 int64_t index, const std::vector<int>& value) {
1226 op_->backward_values_[index].clear();
1227}
1228
1230 op_->backward_values_.resize(op_->Size());
1231}
1232
1261 public:
1262 explicit BaseLns(const std::vector<IntVar*>& vars);
1263 ~BaseLns() override;
1264 virtual void InitFragments();
1265 virtual bool NextFragment() = 0;
1266 void AppendToFragment(int index);
1267 int FragmentSize() const;
1268 bool HasFragments() const override { return true; }
1269
1270 protected:
1272 bool MakeOneNeighbor() override;
1273
1274 private:
1276 void OnStart() override;
1277 std::vector<int> fragment_;
1278};
1279
1285 public:
1286 explicit ChangeValue(const std::vector<IntVar*>& vars);
1287 ~ChangeValue() override;
1288 virtual int64_t ModifyValue(int64_t index, int64_t value) = 0;
1289
1290 protected:
1292 bool MakeOneNeighbor() override;
1293
1294 private:
1295 void OnStart() override;
1296
1297 int index_;
1298};
1299
1314 public:
1334 std::function<int(int64_t)> start_empty_path_class;
1335 };
1337 PathOperator(const std::vector<IntVar*>& next_vars,
1338 const std::vector<IntVar*>& path_vars,
1339 IterationParameters iteration_parameters);
1340 PathOperator(const std::vector<IntVar*>& next_vars,
1341 const std::vector<IntVar*>& path_vars, int number_of_base_nodes,
1342 bool skip_locally_optimal_paths, bool accept_path_end_base,
1343 std::function<int(int64_t)> start_empty_path_class)
1344 : PathOperator(
1345 next_vars, path_vars,
1346 {number_of_base_nodes, skip_locally_optimal_paths,
1347 accept_path_end_base, std::move(start_empty_path_class)}) {}
1348 ~PathOperator() override {}
1349 virtual bool MakeNeighbor() = 0;
1350 void Reset() override;
1351
1352 // TODO(user): Make the following methods protected.
1353 bool SkipUnchanged(int index) const override;
1354
1356 int64_t Next(int64_t node) const {
1357 DCHECK(!IsPathEnd(node));
1358 return Value(node);
1359 }
1360
1362 int64_t Prev(int64_t node) const {
1363 DCHECK(!IsPathStart(node));
1364 DCHECK_EQ(Next(InverseValue(node)), node);
1365 return InverseValue(node);
1366 }
1367
1370 int64_t Path(int64_t node) const {
1371 return ignore_path_vars_ ? 0LL : Value(node + number_of_nexts_);
1372 }
1373
1375 int number_of_nexts() const { return number_of_nexts_; }
1376
1377 protected:
1379 bool MakeOneNeighbor() override;
1383 virtual void OnNodeInitialization() {}
1384
1386 int64_t BaseNode(int i) const { return base_nodes_[i]; }
1388 int BaseAlternative(int i) const { return base_alternatives_[i]; }
1390 int64_t BaseAlternativeNode(int i) const {
1391 if (!ConsiderAlternatives(i)) return BaseNode(i);
1392 const int alternative_index = alternative_index_[BaseNode(i)];
1393 return alternative_index >= 0
1394 ? alternative_sets_[alternative_index][base_alternatives_[i]]
1395 : BaseNode(i);
1396 }
1398 int BaseSiblingAlternative(int i) const {
1399 return base_sibling_alternatives_[i];
1400 }
1402 int64_t BaseSiblingAlternativeNode(int i) const {
1403 if (!ConsiderAlternatives(i)) return BaseNode(i);
1404 const int sibling_alternative_index =
1406 return sibling_alternative_index >= 0
1407 ? alternative_sets_[sibling_alternative_index]
1408 [base_sibling_alternatives_[i]]
1409 : BaseNode(i);
1410 }
1412 int64_t StartNode(int i) const { return path_starts_[base_paths_[i]]; }
1414 const std::vector<int64_t>& path_starts() const { return path_starts_; }
1416 int PathClass(int i) const {
1417 return iteration_parameters_.start_empty_path_class != nullptr
1418 ? iteration_parameters_.start_empty_path_class(StartNode(i))
1419 : StartNode(i);
1420 }
1421
1428 // TODO(user): remove this when automatic detection of such cases in done.
1429 virtual bool RestartAtPathStartOnSynchronize() { return false; }
1433 // TODO(user): ideally this should be OnSamePath(int64_t node1, int64_t
1434 // node2);
1436 virtual bool OnSamePathAsPreviousBase(int64_t base_index) { return false; }
1442 virtual int64_t GetBaseNodeRestartPosition(int base_index) {
1443 return StartNode(base_index);
1444 }
1447 virtual void SetNextBaseToIncrement(int64_t base_index) {
1448 next_base_to_increment_ = base_index;
1449 }
1452 virtual bool ConsiderAlternatives(int64_t base_index) const { return false; }
1453
1454 int64_t OldNext(int64_t node) const {
1455 DCHECK(!IsPathEnd(node));
1456 return OldValue(node);
1457 }
1458
1459 int64_t OldPrev(int64_t node) const {
1460 DCHECK(!IsPathStart(node));
1461 return OldInverseValue(node);
1462 }
1463
1464 int64_t OldPath(int64_t node) const {
1465 return ignore_path_vars_ ? 0LL : OldValue(node + number_of_nexts_);
1466 }
1467
1470 bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination);
1471
1474 bool ReverseChain(int64_t before_chain, int64_t after_chain,
1475 int64_t* chain_last);
1476
1478 bool MakeActive(int64_t node, int64_t destination);
1481 bool MakeChainInactive(int64_t before_chain, int64_t chain_end);
1483 bool SwapActiveAndInactive(int64_t active, int64_t inactive);
1484
1486 void SetNext(int64_t from, int64_t to, int64_t path) {
1488 SetValue(from, to);
1489 SetInverseValue(to, from);
1490 if (!ignore_path_vars_) {
1491 DCHECK_LT(from + number_of_nexts_, Size());
1492 SetValue(from + number_of_nexts_, path);
1493 }
1494 }
1495
1498 bool IsPathEnd(int64_t node) const { return node >= number_of_nexts_; }
1499
1501 bool IsPathStart(int64_t node) const { return OldInverseValue(node) == -1; }
1502
1504 bool IsInactive(int64_t node) const {
1505 return !IsPathEnd(node) && inactives_[node];
1506 }
1507
1510 virtual bool InitPosition() const { return false; }
1514 void ResetPosition() { just_started_ = true; }
1515
1519 int AddAlternativeSet(const std::vector<int64_t>& alternative_set) {
1520 const int alternative = alternative_sets_.size();
1521 for (int64_t node : alternative_set) {
1522 DCHECK_EQ(-1, alternative_index_[node]);
1523 alternative_index_[node] = alternative;
1524 }
1525 alternative_sets_.push_back(alternative_set);
1526 sibling_alternative_.push_back(-1);
1527 return alternative;
1528 }
1529#ifndef SWIG
1533 const std::vector<std::pair<std::vector<int64_t>, std::vector<int64_t>>>&
1534 pair_alternative_sets) {
1535 for (const auto& pair_alternative_set : pair_alternative_sets) {
1536 const int alternative = AddAlternativeSet(pair_alternative_set.first);
1537 sibling_alternative_.back() = alternative + 1;
1538 AddAlternativeSet(pair_alternative_set.second);
1539 }
1540 }
1541#endif // SWIG
1543 int64_t GetActiveInAlternativeSet(int alternative_index) const {
1544 return alternative_index >= 0
1545 ? active_in_alternative_set_[alternative_index]
1546 : -1;
1547 }
1549 int64_t GetActiveAlternativeNode(int node) const {
1550 return GetActiveInAlternativeSet(alternative_index_[node]);
1551 }
1553 int GetSiblingAlternativeIndex(int node) const {
1554 if (node >= alternative_index_.size()) return -1;
1555 const int alternative = alternative_index_[node];
1556 return alternative >= 0 ? sibling_alternative_[alternative] : -1;
1557 }
1560 int64_t GetActiveAlternativeSibling(int node) const {
1561 if (node >= alternative_index_.size()) return -1;
1562 const int alternative = alternative_index_[node];
1563 const int sibling_alternative =
1564 alternative >= 0 ? sibling_alternative_[alternative] : -1;
1565 return GetActiveInAlternativeSet(sibling_alternative);
1566 }
1569 bool CheckChainValidity(int64_t before_chain, int64_t chain_end,
1570 int64_t exclude) const;
1571
1575 int num_paths_ = 0;
1576 std::vector<int64_t> start_to_path_;
1577
1578 private:
1579 void OnStart() override;
1581 bool OnSamePath(int64_t node1, int64_t node2) const;
1582
1583 bool CheckEnds() const {
1584 const int base_node_size = base_nodes_.size();
1585 for (int i = base_node_size - 1; i >= 0; --i) {
1586 if (base_nodes_[i] != end_nodes_[i]) {
1587 return true;
1588 }
1589 }
1590 return false;
1591 }
1592 bool IncrementPosition();
1593 void InitializePathStarts();
1594 void InitializeInactives();
1595 void InitializeBaseNodes();
1596 void InitializeAlternatives();
1597 void Synchronize();
1598
1599 std::vector<int> base_nodes_;
1600 std::vector<int> base_alternatives_;
1601 std::vector<int> base_sibling_alternatives_;
1602 std::vector<int> end_nodes_;
1603 std::vector<int> base_paths_;
1604 std::vector<int64_t> path_starts_;
1605 std::vector<bool> inactives_;
1606 bool just_started_;
1607 bool first_start_;
1608 IterationParameters iteration_parameters_;
1609 bool optimal_paths_enabled_;
1610 std::vector<int> path_basis_;
1611 std::vector<bool> optimal_paths_;
1613#ifndef SWIG
1614 std::vector<std::vector<int64_t>> alternative_sets_;
1615#endif // SWIG
1616 std::vector<int> alternative_index_;
1617 std::vector<int64_t> active_in_alternative_set_;
1618 std::vector<int> sibling_alternative_;
1619};
1620
1622template <class T>
1623LocalSearchOperator* MakeLocalSearchOperator(
1624 Solver* solver, const std::vector<IntVar*>& vars,
1625 const std::vector<IntVar*>& secondary_vars,
1626 std::function<int(int64_t)> start_empty_path_class);
1627
1642
1643#if !defined(SWIG)
1644// A LocalSearchState is a container for variables with bounds that can be
1645// relaxed and tightened, saved and restored. It represents the solution state
1646// of a local search engine, and allows it to go from solution to solution by
1647// relaxing some variables to form a new subproblem, then tightening those
1648// variables to move to a new solution representation. That state may be saved
1649// to an internal copy, or reverted to the last saved internal copy.
1650// Relaxing a variable returns its bounds to their initial state.
1651// Tightening a variable's bounds may make its min larger than its max,
1652// in that case, the tightening function will return false, and the state will
1653// be marked as invalid. No other operations than Revert() can be called on an
1654// invalid state: in particular, an invalid state cannot be saved.
1655class LocalSearchVariable;
1656
1658 public:
1659 LocalSearchVariable AddVariable(int64_t initial_min, int64_t initial_max);
1660 void Commit();
1661 void Revert();
1662 bool StateIsValid() const { return state_is_valid_; }
1663
1664 private:
1666
1667 struct Bounds {
1668 int64_t min;
1669 int64_t max;
1670 };
1671
1672 void RelaxVariableBounds(int variable_index);
1673 bool TightenVariableMin(int variable_index, int64_t value);
1674 bool TightenVariableMax(int variable_index, int64_t value);
1675 int64_t VariableMin(int variable_index) const;
1676 int64_t VariableMax(int variable_index) const;
1677
1678 std::vector<Bounds> initial_variable_bounds_;
1679 std::vector<Bounds> variable_bounds_;
1680 std::vector<std::pair<Bounds, int>> saved_variable_bounds_trail_;
1681 std::vector<bool> variable_is_relaxed_;
1682 bool state_is_valid_ = true;
1683};
1684
1685// A LocalSearchVariable can only be created by a LocalSearchState, then it is
1686// meant to be passed by copy. If at some point the duplication of
1687// LocalSearchState pointers is too expensive, we could switch to index only,
1688// and the user would have to know the relevant state. The present setup allows
1689// to ensure that variable users will not misuse the state.
1691 public:
1692 int64_t Min() const { return state_->VariableMin(variable_index_); }
1693 int64_t Max() const { return state_->VariableMax(variable_index_); }
1694 bool SetMin(int64_t new_min) {
1695 return state_->TightenVariableMin(variable_index_, new_min);
1696 }
1697 bool SetMax(int64_t new_max) {
1698 return state_->TightenVariableMax(variable_index_, new_max);
1699 }
1700 void Relax() { state_->RelaxVariableBounds(variable_index_); }
1701
1702 private:
1703 // Only LocalSearchState can construct LocalSearchVariables.
1704 friend class LocalSearchState;
1705
1706 LocalSearchVariable(LocalSearchState* state, int variable_index)
1707 : state_(state), variable_index_(variable_index) {}
1708
1709 LocalSearchState* const state_;
1710 const int variable_index_;
1711};
1712#endif // !defined(SWIG)
1713
1731 public:
1734 virtual void Relax(const Assignment* delta, const Assignment* deltadelta) {}
1736 virtual void Commit(const Assignment* delta, const Assignment* deltadelta) {}
1737
1747 virtual bool Accept(const Assignment* delta, const Assignment* deltadelta,
1748 int64_t objective_min, int64_t objective_max) = 0;
1749 virtual bool IsIncremental() const { return false; }
1750
1756 virtual void Synchronize(const Assignment* assignment,
1757 const Assignment* delta) = 0;
1759 virtual void Revert() {}
1760
1762 virtual void Reset() {}
1763
1765 virtual int64_t GetSynchronizedObjectiveValue() const { return 0LL; }
1767 // If the last Accept() call returned false, returns an undefined value.
1768 virtual int64_t GetAcceptedObjectiveValue() const { return 0LL; }
1769};
1770
1775 public:
1776 // This class is responsible for calling filters methods in a correct order.
1777 // For now, an order is specified explicitly by the user.
1778 enum FilterEventType { kAccept, kRelax };
1782 };
1783
1784 std::string DebugString() const override {
1785 return "LocalSearchFilterManager";
1786 }
1787 // Builds a manager that calls filter methods using an explicit ordering.
1788 explicit LocalSearchFilterManager(std::vector<FilterEvent> filter_events);
1789 // Builds a manager that calls filter methods using the following ordering:
1790 // first Relax() in vector order, then Accept() in vector order.
1791 // Note that some filters might appear only once, if their Relax() or Accept()
1792 // are trivial.
1793 explicit LocalSearchFilterManager(std::vector<LocalSearchFilter*> filters);
1794
1795 // Calls Revert() of filters, in reverse order of Relax events.
1796 void Revert();
1800 bool Accept(LocalSearchMonitor* const monitor, const Assignment* delta,
1801 const Assignment* deltadelta, int64_t objective_min,
1802 int64_t objective_max);
1804 void Synchronize(const Assignment* assignment, const Assignment* delta);
1805 int64_t GetSynchronizedObjectiveValue() const { return synchronized_value_; }
1806 int64_t GetAcceptedObjectiveValue() const { return accepted_value_; }
1807
1808 private:
1809 void InitializeForcedEvents();
1810
1811 std::vector<FilterEvent> filter_events_;
1812 int last_event_called_ = -1;
1813 // If a filter is incremental, its Relax() and Accept() must be called for
1814 // every candidate, even if a previous Accept() rejected it.
1815 // To ensure that those filters have consistent inputs, all intermediate
1816 // Relax events are also triggered. All those events are called 'forced'.
1817 std::vector<int> next_forced_events_;
1818 int64_t synchronized_value_;
1819 int64_t accepted_value_;
1820};
1821
1823 public:
1824 explicit IntVarLocalSearchFilter(const std::vector<IntVar*>& vars);
1825 ~IntVarLocalSearchFilter() override;
1828 void Synchronize(const Assignment* assignment,
1829 const Assignment* delta) override;
1830
1831 bool FindIndex(IntVar* const var, int64_t* index) const {
1832 DCHECK(index != nullptr);
1833 const int var_index = var->index();
1834 *index = (var_index < var_index_to_index_.size())
1835 ? var_index_to_index_[var_index]
1836 : kUnassigned;
1837 return *index != kUnassigned;
1838 }
1839
1841 void AddVars(const std::vector<IntVar*>& vars);
1842 int Size() const { return vars_.size(); }
1843 IntVar* Var(int index) const { return vars_[index]; }
1844 int64_t Value(int index) const {
1845 DCHECK(IsVarSynced(index));
1846 return values_[index];
1847 }
1848 bool IsVarSynced(int index) const { return var_synced_[index]; }
1849
1850 protected:
1851 virtual void OnSynchronize(const Assignment* delta) {}
1852 void SynchronizeOnAssignment(const Assignment* assignment);
1853
1854 private:
1855 std::vector<IntVar*> vars_;
1856 std::vector<int64_t> values_;
1857 std::vector<bool> var_synced_;
1858 std::vector<int> var_index_to_index_;
1859 static const int kUnassigned;
1860};
1861
1863 public:
1864 explicit PropagationMonitor(Solver* const solver);
1865 ~PropagationMonitor() override;
1866 std::string DebugString() const override { return "PropagationMonitor"; }
1867
1870 Constraint* const constraint) = 0;
1872 Constraint* const constraint) = 0;
1874 Constraint* const parent, Constraint* const nested) = 0;
1876 Constraint* const parent, Constraint* const nested) = 0;
1877 virtual void RegisterDemon(Demon* const demon) = 0;
1878 virtual void BeginDemonRun(Demon* const demon) = 0;
1879 virtual void EndDemonRun(Demon* const demon) = 0;
1881 virtual void EndProcessingIntegerVariable(IntVar* const var) = 0;
1882 virtual void PushContext(const std::string& context) = 0;
1883 virtual void PopContext() = 0;
1885 virtual void SetMin(IntExpr* const expr, int64_t new_min) = 0;
1886 virtual void SetMax(IntExpr* const expr, int64_t new_max) = 0;
1887 virtual void SetRange(IntExpr* const expr, int64_t new_min,
1888 int64_t new_max) = 0;
1890 virtual void SetMin(IntVar* const var, int64_t new_min) = 0;
1891 virtual void SetMax(IntVar* const var, int64_t new_max) = 0;
1892 virtual void SetRange(IntVar* const var, int64_t new_min,
1893 int64_t new_max) = 0;
1894 virtual void RemoveValue(IntVar* const var, int64_t value) = 0;
1895 virtual void SetValue(IntVar* const var, int64_t value) = 0;
1896 virtual void RemoveInterval(IntVar* const var, int64_t imin,
1897 int64_t imax) = 0;
1898 virtual void SetValues(IntVar* const var,
1899 const std::vector<int64_t>& values) = 0;
1900 virtual void RemoveValues(IntVar* const var,
1901 const std::vector<int64_t>& values) = 0;
1903 virtual void SetStartMin(IntervalVar* const var, int64_t new_min) = 0;
1904 virtual void SetStartMax(IntervalVar* const var, int64_t new_max) = 0;
1905 virtual void SetStartRange(IntervalVar* const var, int64_t new_min,
1906 int64_t new_max) = 0;
1907 virtual void SetEndMin(IntervalVar* const var, int64_t new_min) = 0;
1908 virtual void SetEndMax(IntervalVar* const var, int64_t new_max) = 0;
1909 virtual void SetEndRange(IntervalVar* const var, int64_t new_min,
1910 int64_t new_max) = 0;
1911 virtual void SetDurationMin(IntervalVar* const var, int64_t new_min) = 0;
1912 virtual void SetDurationMax(IntervalVar* const var, int64_t new_max) = 0;
1913 virtual void SetDurationRange(IntervalVar* const var, int64_t new_min,
1914 int64_t new_max) = 0;
1915 virtual void SetPerformed(IntervalVar* const var, bool value) = 0;
1917 virtual void RankFirst(SequenceVar* const var, int index) = 0;
1918 virtual void RankNotFirst(SequenceVar* const var, int index) = 0;
1919 virtual void RankLast(SequenceVar* const var, int index) = 0;
1920 virtual void RankNotLast(SequenceVar* const var, int index) = 0;
1921 virtual void RankSequence(SequenceVar* const var,
1922 const std::vector<int>& rank_first,
1923 const std::vector<int>& rank_last,
1924 const std::vector<int>& unperformed) = 0;
1926 void Install() override;
1927};
1928
1930 // TODO(user): Add monitoring of local search filters.
1931 public:
1932 explicit LocalSearchMonitor(Solver* const solver);
1933 ~LocalSearchMonitor() override;
1934 std::string DebugString() const override { return "LocalSearchMonitor"; }
1935
1937 virtual void BeginOperatorStart() = 0;
1938 virtual void EndOperatorStart() = 0;
1939 virtual void BeginMakeNextNeighbor(const LocalSearchOperator* op) = 0;
1941 bool neighbor_found, const Assignment* delta,
1942 const Assignment* deltadelta) = 0;
1943 virtual void BeginFilterNeighbor(const LocalSearchOperator* op) = 0;
1945 bool neighbor_found) = 0;
1946 virtual void BeginAcceptNeighbor(const LocalSearchOperator* op) = 0;
1948 bool neighbor_found) = 0;
1949 virtual void BeginFiltering(const LocalSearchFilter* filter) = 0;
1950 virtual void EndFiltering(const LocalSearchFilter* filter, bool reject) = 0;
1951
1953 void Install() override;
1954};
1955
1956class BooleanVar : public IntVar {
1957 public:
1958 static const int kUnboundBooleanVarValue;
1959
1960 explicit BooleanVar(Solver* const s, const std::string& name = "")
1961 : IntVar(s, name), value_(kUnboundBooleanVarValue) {}
1962
1963 ~BooleanVar() override {}
1964
1965 int64_t Min() const override { return (value_ == 1); }
1966 void SetMin(int64_t m) override;
1967 int64_t Max() const override { return (value_ != 0); }
1968 void SetMax(int64_t m) override;
1969 void SetRange(int64_t mi, int64_t ma) override;
1970 bool Bound() const override { return (value_ != kUnboundBooleanVarValue); }
1971 int64_t Value() const override {
1972 CHECK_NE(value_, kUnboundBooleanVarValue) << "variable is not bound";
1973 return value_;
1974 }
1975 void RemoveValue(int64_t v) override;
1976 void RemoveInterval(int64_t l, int64_t u) override;
1977 void WhenBound(Demon* d) override;
1978 void WhenRange(Demon* d) override { WhenBound(d); }
1979 void WhenDomain(Demon* d) override { WhenBound(d); }
1980 uint64_t Size() const override;
1981 bool Contains(int64_t v) const override;
1982 IntVarIterator* MakeHoleIterator(bool reversible) const override;
1983 IntVarIterator* MakeDomainIterator(bool reversible) const override;
1984 std::string DebugString() const override;
1985 int VarType() const override { return BOOLEAN_VAR; }
1986
1987 IntVar* IsEqual(int64_t constant) override;
1988 IntVar* IsDifferent(int64_t constant) override;
1989 IntVar* IsGreaterOrEqual(int64_t constant) override;
1990 IntVar* IsLessOrEqual(int64_t constant) override;
1991
1992 virtual void RestoreValue() = 0;
1993 std::string BaseName() const override { return "BooleanVar"; }
1994
1995 int RawValue() const { return value_; }
1996
1997 protected:
2001};
2002
2003class SymmetryManager;
2004
2009 public:
2011 : symmetry_manager_(nullptr), index_in_symmetry_manager_(-1) {}
2012 ~SymmetryBreaker() override {}
2013
2014 void AddIntegerVariableEqualValueClause(IntVar* const var, int64_t value);
2015 void AddIntegerVariableGreaterOrEqualValueClause(IntVar* const var,
2016 int64_t value);
2017 void AddIntegerVariableLessOrEqualValueClause(IntVar* const var,
2018 int64_t value);
2019
2020 private:
2021 friend class SymmetryManager;
2022 void set_symmetry_manager_and_index(SymmetryManager* manager, int index) {
2023 CHECK(symmetry_manager_ == nullptr);
2024 CHECK_EQ(-1, index_in_symmetry_manager_);
2025 symmetry_manager_ = manager;
2026 index_in_symmetry_manager_ = index;
2027 }
2028 SymmetryManager* symmetry_manager() const { return symmetry_manager_; }
2029 int index_in_symmetry_manager() const { return index_in_symmetry_manager_; }
2030
2031 SymmetryManager* symmetry_manager_;
2033 int index_in_symmetry_manager_;
2034};
2035
2038class SearchLog : public SearchMonitor {
2039 public:
2040 SearchLog(Solver* const s, OptimizeVar* const obj, IntVar* const var,
2041 double scaling_factor, double offset,
2042 std::function<std::string()> display_callback,
2043 bool display_on_new_solutions_only, int period);
2044 ~SearchLog() override;
2045 void EnterSearch() override;
2046 void ExitSearch() override;
2047 bool AtSolution() override;
2048 void BeginFail() override;
2049 void NoMoreSolutions() override;
2050 void AcceptUncheckedNeighbor() override;
2051 void ApplyDecision(Decision* const decision) override;
2052 void RefuteDecision(Decision* const decision) override;
2053 void OutputDecision();
2054 void Maintain();
2055 void BeginInitialPropagation() override;
2056 void EndInitialPropagation() override;
2057 std::string DebugString() const override;
2058
2059 protected:
2060 /* Bottleneck function used for all UI related output. */
2061 virtual void OutputLine(const std::string& line);
2062
2063 private:
2064 static std::string MemoryUsage();
2065
2066 const int period_;
2067 std::unique_ptr<WallTimer> timer_;
2068 IntVar* const var_;
2069 OptimizeVar* const obj_;
2070 const double scaling_factor_;
2071 const double offset_;
2072 std::function<std::string()> display_callback_;
2073 const bool display_on_new_solutions_only_;
2074 int nsol_;
2075 int64_t tick_;
2076 int64_t objective_min_;
2077 int64_t objective_max_;
2078 int min_right_depth_;
2079 int max_depth_;
2080 int sliding_min_depth_;
2081 int sliding_max_depth_;
2082};
2083
2089 public:
2091 VOID_FALSE_CONSTRAINT = 0,
2094 };
2095
2097 VAR_CONSTANT_EQUALITY = 0,
2102 };
2103
2105 VAR_CONSTANT_CONSTANT_BETWEEN = 0,
2107 };
2108
2110 EXPR_EXPR_EQUALITY = 0,
2117 };
2118
2120 EXPR_OPPOSITE = 0,
2124 };
2125
2127 EXPR_EXPR_DIFFERENCE = 0,
2138 };
2139
2141 EXPR_EXPR_CONSTANT_CONDITIONAL = 0,
2143 };
2144
2146 EXPR_CONSTANT_DIFFERENCE = 0,
2157 };
2159 VAR_CONSTANT_CONSTANT_SEMI_CONTINUOUS = 0,
2161 };
2162
2164 VAR_CONSTANT_ARRAY_ELEMENT = 0,
2166 };
2167
2169 VAR_ARRAY_CONSTANT_ARRAY_SCAL_PROD = 0,
2171 };
2172
2174 VAR_ARRAY_MAX = 0,
2178 };
2179
2181 VAR_ARRAY_CONSTANT_INDEX = 0,
2183 };
2184
2185 explicit ModelCache(Solver* const solver);
2186 virtual ~ModelCache();
2187
2188 virtual void Clear() = 0;
2189
2191
2193
2195 VoidConstraintType type) = 0;
2196
2199 IntVar* const var, int64_t value,
2200 VarConstantConstraintType type) const = 0;
2201
2203 IntVar* const var, int64_t value,
2204 VarConstantConstraintType type) = 0;
2205
2207
2209 IntVar* const var, int64_t value1, int64_t value2,
2210 VarConstantConstantConstraintType type) const = 0;
2211
2213 Constraint* const ct, IntVar* const var, int64_t value1, int64_t value2,
2215
2217
2219 IntExpr* const expr1, IntExpr* const expr2,
2220 ExprExprConstraintType type) const = 0;
2221
2223 IntExpr* const expr1,
2224 IntExpr* const expr2,
2225 ExprExprConstraintType type) = 0;
2226
2228
2229 virtual IntExpr* FindExprExpression(IntExpr* const expr,
2230 ExprExpressionType type) const = 0;
2231
2232 virtual void InsertExprExpression(IntExpr* const expression,
2233 IntExpr* const expr,
2234 ExprExpressionType type) = 0;
2235
2237
2239 IntExpr* const expr, int64_t value,
2240 ExprConstantExpressionType type) const = 0;
2241
2243 IntExpr* const expression, IntExpr* const var, int64_t value,
2245
2247
2249 IntExpr* const var1, IntExpr* const var2,
2250 ExprExprExpressionType type) const = 0;
2251
2252 virtual void InsertExprExprExpression(IntExpr* const expression,
2253 IntExpr* const var1,
2254 IntExpr* const var2,
2255 ExprExprExpressionType type) = 0;
2256
2258
2260 IntExpr* const var1, IntExpr* const var2, int64_t constant,
2261 ExprExprConstantExpressionType type) const = 0;
2262
2264 IntExpr* const expression, IntExpr* const var1, IntExpr* const var2,
2265 int64_t constant, ExprExprConstantExpressionType type) = 0;
2266
2268
2270 IntVar* const var, int64_t value1, int64_t value2,
2271 VarConstantConstantExpressionType type) const = 0;
2272
2274 IntExpr* const expression, IntVar* const var, int64_t value1,
2275 int64_t value2, VarConstantConstantExpressionType type) = 0;
2276
2278
2280 IntVar* const var, const std::vector<int64_t>& values,
2281 VarConstantArrayExpressionType type) const = 0;
2282
2284 IntExpr* const expression, IntVar* const var,
2285 const std::vector<int64_t>& values,
2287
2289
2291 const std::vector<IntVar*>& vars, VarArrayExpressionType type) const = 0;
2292
2293 virtual void InsertVarArrayExpression(IntExpr* const expression,
2294 const std::vector<IntVar*>& vars,
2295 VarArrayExpressionType type) = 0;
2296
2298
2300 const std::vector<IntVar*>& vars, const std::vector<int64_t>& values,
2302
2304 IntExpr* const expression, const std::vector<IntVar*>& var,
2305 const std::vector<int64_t>& values,
2307
2309
2311 const std::vector<IntVar*>& vars, int64_t value,
2312 VarArrayConstantExpressionType type) const = 0;
2313
2315 IntExpr* const expression, const std::vector<IntVar*>& var, int64_t value,
2317
2318 Solver* solver() const;
2319
2320 private:
2321 Solver* const solver_;
2322};
2323
2325#if !defined(SWIG)
2327 public:
2329 const std::string& TypeName() const;
2330 void SetTypeName(const std::string& type_name);
2331
2333 void SetIntegerArgument(const std::string& arg_name, int64_t value);
2334 void SetIntegerArrayArgument(const std::string& arg_name,
2335 const std::vector<int64_t>& values);
2336 void SetIntegerMatrixArgument(const std::string& arg_name,
2337 const IntTupleSet& values);
2338 void SetIntegerExpressionArgument(const std::string& arg_name,
2339 IntExpr* const expr);
2340 void SetIntegerVariableArrayArgument(const std::string& arg_name,
2341 const std::vector<IntVar*>& vars);
2342 void SetIntervalArgument(const std::string& arg_name, IntervalVar* const var);
2343 void SetIntervalArrayArgument(const std::string& arg_name,
2344 const std::vector<IntervalVar*>& vars);
2345 void SetSequenceArgument(const std::string& arg_name, SequenceVar* const var);
2346 void SetSequenceArrayArgument(const std::string& arg_name,
2347 const std::vector<SequenceVar*>& vars);
2348
2350 bool HasIntegerExpressionArgument(const std::string& arg_name) const;
2351 bool HasIntegerVariableArrayArgument(const std::string& arg_name) const;
2352
2354 int64_t FindIntegerArgumentWithDefault(const std::string& arg_name,
2355 int64_t def) const;
2356 int64_t FindIntegerArgumentOrDie(const std::string& arg_name) const;
2357 const std::vector<int64_t>& FindIntegerArrayArgumentOrDie(
2358 const std::string& arg_name) const;
2359 const IntTupleSet& FindIntegerMatrixArgumentOrDie(
2360 const std::string& arg_name) const;
2361
2362 IntExpr* FindIntegerExpressionArgumentOrDie(
2363 const std::string& arg_name) const;
2364 const std::vector<IntVar*>& FindIntegerVariableArrayArgumentOrDie(
2365 const std::string& arg_name) const;
2366
2367 private:
2368 std::string type_name_;
2369 absl::flat_hash_map<std::string, int64_t> integer_argument_;
2370 absl::flat_hash_map<std::string, std::vector<int64_t>>
2371 integer_array_argument_;
2372 absl::flat_hash_map<std::string, IntTupleSet> matrix_argument_;
2373 absl::flat_hash_map<std::string, IntExpr*> integer_expression_argument_;
2374 absl::flat_hash_map<std::string, IntervalVar*> interval_argument_;
2375 absl::flat_hash_map<std::string, SequenceVar*> sequence_argument_;
2376 absl::flat_hash_map<std::string, std::vector<IntVar*>>
2377 integer_variable_array_argument_;
2378 absl::flat_hash_map<std::string, std::vector<IntervalVar*>>
2379 interval_array_argument_;
2380 absl::flat_hash_map<std::string, std::vector<SequenceVar*>>
2381 sequence_array_argument_;
2382};
2383
2386 public:
2387 ModelParser();
2388
2389 ~ModelParser() override;
2390
2392 void BeginVisitModel(const std::string& solver_name) override;
2393 void EndVisitModel(const std::string& solver_name) override;
2394 void BeginVisitConstraint(const std::string& type_name,
2395 const Constraint* const constraint) override;
2396 void EndVisitConstraint(const std::string& type_name,
2397 const Constraint* const constraint) override;
2398 void BeginVisitIntegerExpression(const std::string& type_name,
2399 const IntExpr* const expr) override;
2400 void EndVisitIntegerExpression(const std::string& type_name,
2401 const IntExpr* const expr) override;
2402 void VisitIntegerVariable(const IntVar* const variable,
2403 IntExpr* const delegate) override;
2404 void VisitIntegerVariable(const IntVar* const variable,
2405 const std::string& operation, int64_t value,
2406 IntVar* const delegate) override;
2407 void VisitIntervalVariable(const IntervalVar* const variable,
2408 const std::string& operation, int64_t value,
2409 IntervalVar* const delegate) override;
2410 void VisitSequenceVariable(const SequenceVar* const variable) override;
2412 void VisitIntegerArgument(const std::string& arg_name,
2413 int64_t value) override;
2414 void VisitIntegerArrayArgument(const std::string& arg_name,
2415 const std::vector<int64_t>& values) override;
2416 void VisitIntegerMatrixArgument(const std::string& arg_name,
2417 const IntTupleSet& values) override;
2419 void VisitIntegerExpressionArgument(const std::string& arg_name,
2420 IntExpr* const argument) override;
2421 void VisitIntegerVariableArrayArgument(
2422 const std::string& arg_name,
2423 const std::vector<IntVar*>& arguments) override;
2425 void VisitIntervalArgument(const std::string& arg_name,
2426 IntervalVar* const argument) override;
2427 void VisitIntervalArrayArgument(
2428 const std::string& arg_name,
2429 const std::vector<IntervalVar*>& arguments) override;
2431 void VisitSequenceArgument(const std::string& arg_name,
2432 SequenceVar* const argument) override;
2433 void VisitSequenceArrayArgument(
2434 const std::string& arg_name,
2435 const std::vector<SequenceVar*>& arguments) override;
2436
2437 protected:
2438 void PushArgumentHolder();
2439 void PopArgumentHolder();
2440 ArgumentHolder* Top() const;
2441
2442 private:
2443 std::vector<ArgumentHolder*> holders_;
2444};
2445
2446template <class T>
2448 public:
2449 ArrayWithOffset(int64_t index_min, int64_t index_max)
2450 : index_min_(index_min),
2451 index_max_(index_max),
2452 values_(new T[index_max - index_min + 1]) {
2453 DCHECK_LE(index_min, index_max);
2454 }
2455
2456 ~ArrayWithOffset() override {}
2457
2458 virtual T Evaluate(int64_t index) const {
2459 DCHECK_GE(index, index_min_);
2460 DCHECK_LE(index, index_max_);
2461 return values_[index - index_min_];
2462 }
2463
2464 void SetValue(int64_t index, T value) {
2465 DCHECK_GE(index, index_min_);
2466 DCHECK_LE(index, index_max_);
2467 values_[index - index_min_] = value;
2468 }
2469
2470 std::string DebugString() const override { return "ArrayWithOffset"; }
2471
2472 private:
2473 const int64_t index_min_;
2474 const int64_t index_max_;
2475 std::unique_ptr<T[]> values_;
2476};
2477#endif // SWIG
2478
2483template <class T, class C>
2485 public:
2486 explicit RevGrowingArray(int64_t block_size)
2487 : block_size_(block_size), block_offset_(0) {
2488 CHECK_GT(block_size, 0);
2489 }
2490
2492 for (int i = 0; i < elements_.size(); ++i) {
2493 delete[] elements_[i];
2494 }
2495 }
2496
2497 T At(int64_t index) const {
2498 const int64_t block_index = ComputeBlockIndex(index);
2499 const int64_t relative_index = block_index - block_offset_;
2500 if (relative_index < 0 || relative_index >= elements_.size()) {
2501 return T();
2502 }
2503 const T* block = elements_[relative_index];
2504 return block != nullptr ? block[index - block_index * block_size_] : T();
2505 }
2506
2507 void RevInsert(Solver* const solver, int64_t index, T value) {
2508 const int64_t block_index = ComputeBlockIndex(index);
2509 T* const block = GetOrCreateBlock(block_index);
2510 const int64_t residual = index - block_index * block_size_;
2511 solver->SaveAndSetValue(reinterpret_cast<C*>(&block[residual]),
2512 reinterpret_cast<C>(value));
2513 }
2514
2515 private:
2516 T* NewBlock() const {
2517 T* const result = new T[block_size_];
2518 for (int i = 0; i < block_size_; ++i) {
2519 result[i] = T();
2520 }
2521 return result;
2522 }
2523
2524 T* GetOrCreateBlock(int block_index) {
2525 if (elements_.size() == 0) {
2526 block_offset_ = block_index;
2527 GrowUp(block_index);
2528 } else if (block_index < block_offset_) {
2529 GrowDown(block_index);
2530 } else if (block_index - block_offset_ >= elements_.size()) {
2531 GrowUp(block_index);
2532 }
2533 T* block = elements_[block_index - block_offset_];
2534 if (block == nullptr) {
2535 block = NewBlock();
2536 elements_[block_index - block_offset_] = block;
2537 }
2538 return block;
2539 }
2540
2541 int64_t ComputeBlockIndex(int64_t value) const {
2542 return value >= 0 ? value / block_size_
2543 : (value - block_size_ + 1) / block_size_;
2544 }
2545
2546 void GrowUp(int64_t block_index) {
2547 elements_.resize(block_index - block_offset_ + 1);
2548 }
2549
2550 void GrowDown(int64_t block_index) {
2551 const int64_t delta = block_offset_ - block_index;
2552 block_offset_ = block_index;
2553 DCHECK_GT(delta, 0);
2554 elements_.insert(elements_.begin(), delta, nullptr);
2555 }
2556
2557 const int64_t block_size_;
2558 std::vector<T*> elements_;
2559 int block_offset_;
2560};
2561
2566template <class T>
2568 public:
2569 static constexpr int kNoInserted = -1;
2570
2572 explicit RevIntSet(int capacity)
2573 : elements_(new T[capacity]),
2574 num_elements_(0),
2575 capacity_(capacity),
2576 position_(new int[capacity]),
2577 delete_position_(true) {
2578 for (int i = 0; i < capacity; ++i) {
2579 position_[i] = kNoInserted;
2580 }
2581 }
2582
2584 RevIntSet(int capacity, int* shared_positions, int shared_positions_size)
2585 : elements_(new T[capacity]),
2586 num_elements_(0),
2587 capacity_(capacity),
2588 position_(shared_positions),
2589 delete_position_(false) {
2590 for (int i = 0; i < shared_positions_size; ++i) {
2591 position_[i] = kNoInserted;
2592 }
2593 }
2594
2596 if (delete_position_) {
2597 delete[] position_;
2598 }
2599 }
2600
2601 int Size() const { return num_elements_.Value(); }
2602
2603 int Capacity() const { return capacity_; }
2604
2605 T Element(int i) const {
2606 DCHECK_GE(i, 0);
2607 DCHECK_LT(i, num_elements_.Value());
2608 return elements_[i];
2609 }
2610
2611 T RemovedElement(int i) const {
2612 DCHECK_GE(i, 0);
2613 DCHECK_LT(i + num_elements_.Value(), capacity_);
2614 return elements_[i + num_elements_.Value()];
2615 }
2616
2617 void Insert(Solver* const solver, const T& elt) {
2618 const int position = num_elements_.Value();
2619 DCHECK_LT(position, capacity_);
2620 DCHECK(NotAlreadyInserted(elt));
2621 elements_[position] = elt;
2622 position_[elt] = position;
2623 num_elements_.Incr(solver);
2624 }
2625
2626 void Remove(Solver* const solver, const T& value_index) {
2627 num_elements_.Decr(solver);
2628 SwapTo(value_index, num_elements_.Value());
2629 }
2630
2631 void Restore(Solver* const solver, const T& value_index) {
2632 SwapTo(value_index, num_elements_.Value());
2633 num_elements_.Incr(solver);
2634 }
2635
2636 void Clear(Solver* const solver) { num_elements_.SetValue(solver, 0); }
2637
2639 typedef const T* const_iterator;
2640 const_iterator begin() const { return elements_.get(); }
2641 const_iterator end() const { return elements_.get() + num_elements_.Value(); }
2642
2643 private:
2645 bool NotAlreadyInserted(const T& elt) {
2646 for (int i = 0; i < num_elements_.Value(); ++i) {
2647 if (elt == elements_[i]) {
2648 return false;
2649 }
2650 }
2651 return true;
2652 }
2653
2654 void SwapTo(T value_index, int next_position) {
2655 const int current_position = position_[value_index];
2656 if (current_position != next_position) {
2657 const T next_value_index = elements_[next_position];
2658 elements_[current_position] = next_value_index;
2659 elements_[next_position] = value_index;
2660 position_[value_index] = next_position;
2661 position_[next_value_index] = current_position;
2662 }
2663 }
2664
2666 std::unique_ptr<T[]> elements_;
2668 NumericalRev<int> num_elements_;
2670 const int capacity_;
2672 int* position_;
2674 const bool delete_position_;
2675};
2676
2678
2680 public:
2681 explicit RevPartialSequence(const std::vector<int>& items)
2682 : elements_(items),
2683 first_ranked_(0),
2684 last_ranked_(items.size() - 1),
2685 size_(items.size()),
2686 position_(new int[size_]) {
2687 for (int i = 0; i < size_; ++i) {
2688 elements_[i] = items[i];
2689 position_[i] = i;
2690 }
2691 }
2692
2693 explicit RevPartialSequence(int size)
2694 : elements_(size),
2695 first_ranked_(0),
2696 last_ranked_(size - 1),
2697 size_(size),
2698 position_(new int[size_]) {
2699 for (int i = 0; i < size_; ++i) {
2700 elements_[i] = i;
2701 position_[i] = i;
2702 }
2703 }
2704
2706
2707 int NumFirstRanked() const { return first_ranked_.Value(); }
2708
2709 int NumLastRanked() const { return size_ - 1 - last_ranked_.Value(); }
2710
2711 int Size() const { return size_; }
2712
2713#if !defined(SWIG)
2714 const int& operator[](int index) const {
2715 DCHECK_GE(index, 0);
2716 DCHECK_LT(index, size_);
2717 return elements_[index];
2718 }
2719#endif
2720
2721 void RankFirst(Solver* const solver, int elt) {
2722 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
2723 SwapTo(elt, first_ranked_.Value());
2724 first_ranked_.Incr(solver);
2725 }
2726
2727 void RankLast(Solver* const solver, int elt) {
2728 DCHECK_LE(first_ranked_.Value(), last_ranked_.Value());
2729 SwapTo(elt, last_ranked_.Value());
2730 last_ranked_.Decr(solver);
2731 }
2732
2733 bool IsRanked(int elt) const {
2734 const int position = position_[elt];
2735 return (position < first_ranked_.Value() ||
2736 position > last_ranked_.Value());
2737 }
2738
2739 std::string DebugString() const {
2740 std::string result = "[";
2741 for (int i = 0; i < first_ranked_.Value(); ++i) {
2742 absl::StrAppend(&result, elements_[i]);
2743 if (i != first_ranked_.Value() - 1) {
2744 result.append("-");
2745 }
2746 }
2747 result.append("|");
2748 for (int i = first_ranked_.Value(); i <= last_ranked_.Value(); ++i) {
2749 absl::StrAppend(&result, elements_[i]);
2750 if (i != last_ranked_.Value()) {
2751 result.append("-");
2752 }
2753 }
2754 result.append("|");
2755 for (int i = last_ranked_.Value() + 1; i < size_; ++i) {
2756 absl::StrAppend(&result, elements_[i]);
2757 if (i != size_ - 1) {
2758 result.append("-");
2759 }
2760 }
2761 result.append("]");
2762 return result;
2763 }
2764
2765 private:
2766 void SwapTo(int elt, int next_position) {
2767 const int current_position = position_[elt];
2768 if (current_position != next_position) {
2769 const int next_elt = elements_[next_position];
2770 elements_[current_position] = next_elt;
2771 elements_[next_position] = elt;
2772 position_[elt] = next_position;
2773 position_[next_elt] = current_position;
2774 }
2775 }
2776
2778 std::vector<int> elements_;
2780 NumericalRev<int> first_ranked_;
2782 NumericalRev<int> last_ranked_;
2784 const int size_;
2786 std::unique_ptr<int[]> position_;
2787};
2788
2794 public:
2796 explicit UnsortedNullableRevBitset(int bit_size);
2797
2799
2802 void Init(Solver* const solver, const std::vector<uint64_t>& mask);
2803
2806 bool RevSubtract(Solver* const solver, const std::vector<uint64_t>& mask);
2807
2810 bool RevAnd(Solver* const solver, const std::vector<uint64_t>& mask);
2811
2814 int ActiveWordSize() const { return active_words_.Size(); }
2815
2817 bool Empty() const { return active_words_.Size() == 0; }
2818
2826 bool Intersects(const std::vector<uint64_t>& mask, int* support_index);
2827
2829 int64_t bit_size() const { return bit_size_; }
2831 int64_t word_size() const { return word_size_; }
2833 const RevIntSet<int>& active_words() const { return active_words_; }
2834
2835 private:
2836 void CleanUpActives(Solver* const solver);
2837
2838 const int64_t bit_size_;
2839 const int64_t word_size_;
2840 RevArray<uint64_t> bits_;
2841 RevIntSet<int> active_words_;
2842 std::vector<int> to_remove_;
2843};
2844
2845template <class T>
2846bool IsArrayConstant(const std::vector<T>& values, const T& value) {
2847 for (int i = 0; i < values.size(); ++i) {
2848 if (values[i] != value) {
2849 return false;
2850 }
2851 }
2852 return true;
2853}
2854
2855template <class T>
2856bool IsArrayBoolean(const std::vector<T>& values) {
2857 for (int i = 0; i < values.size(); ++i) {
2858 if (values[i] != 0 && values[i] != 1) {
2859 return false;
2860 }
2861 }
2862 return true;
2863}
2864
2865template <class T>
2866bool AreAllOnes(const std::vector<T>& values) {
2867 return IsArrayConstant(values, T(1));
2868}
2869
2870template <class T>
2871bool AreAllNull(const std::vector<T>& values) {
2872 return IsArrayConstant(values, T(0));
2873}
2874
2875template <class T>
2876bool AreAllGreaterOrEqual(const std::vector<T>& values, const T& value) {
2877 for (const T& current_value : values) {
2878 if (current_value < value) {
2879 return false;
2880 }
2881 }
2882 return true;
2883}
2884
2885template <class T>
2886bool AreAllLessOrEqual(const std::vector<T>& values, const T& value) {
2887 for (const T& current_value : values) {
2888 if (current_value > value) {
2889 return false;
2890 }
2891 }
2892 return true;
2893}
2894
2895template <class T>
2896bool AreAllPositive(const std::vector<T>& values) {
2897 return AreAllGreaterOrEqual(values, T(0));
2898}
2899
2900template <class T>
2901bool AreAllNegative(const std::vector<T>& values) {
2902 return AreAllLessOrEqual(values, T(0));
2903}
2904
2905template <class T>
2906bool AreAllStrictlyPositive(const std::vector<T>& values) {
2907 return AreAllGreaterOrEqual(values, T(1));
2908}
2909
2910template <class T>
2911bool AreAllStrictlyNegative(const std::vector<T>& values) {
2912 return AreAllLessOrEqual(values, T(-1));
2913}
2914
2915template <class T>
2916bool IsIncreasingContiguous(const std::vector<T>& values) {
2917 for (int i = 0; i < values.size() - 1; ++i) {
2918 if (values[i + 1] != values[i] + 1) {
2919 return false;
2920 }
2921 }
2922 return true;
2923}
2924
2925template <class T>
2926bool IsIncreasing(const std::vector<T>& values) {
2927 for (int i = 0; i < values.size() - 1; ++i) {
2928 if (values[i + 1] < values[i]) {
2929 return false;
2930 }
2931 }
2932 return true;
2933}
2934
2935template <class T>
2936bool IsArrayInRange(const std::vector<IntVar*>& vars, T range_min,
2937 T range_max) {
2938 for (int i = 0; i < vars.size(); ++i) {
2939 if (vars[i]->Min() < range_min || vars[i]->Max() > range_max) {
2940 return false;
2941 }
2942 }
2943 return true;
2944}
2945
2946inline bool AreAllBound(const std::vector<IntVar*>& vars) {
2947 for (int i = 0; i < vars.size(); ++i) {
2948 if (!vars[i]->Bound()) {
2949 return false;
2950 }
2951 }
2952 return true;
2953}
2954
2955inline bool AreAllBooleans(const std::vector<IntVar*>& vars) {
2956 return IsArrayInRange(vars, 0, 1);
2957}
2958
2961template <class T>
2962bool AreAllBoundOrNull(const std::vector<IntVar*>& vars,
2963 const std::vector<T>& values) {
2964 for (int i = 0; i < vars.size(); ++i) {
2965 if (values[i] != 0 && !vars[i]->Bound()) {
2966 return false;
2967 }
2968 }
2969 return true;
2970}
2971
2973inline bool AreAllBoundTo(const std::vector<IntVar*>& vars, int64_t value) {
2974 for (int i = 0; i < vars.size(); ++i) {
2975 if (!vars[i]->Bound() || vars[i]->Min() != value) {
2976 return false;
2977 }
2978 }
2979 return true;
2980}
2981
2982inline int64_t MaxVarArray(const std::vector<IntVar*>& vars) {
2983 DCHECK(!vars.empty());
2984 int64_t result = kint64min;
2985 for (int i = 0; i < vars.size(); ++i) {
2987 result = std::max<int64_t>(result, vars[i]->Max());
2988 }
2989 return result;
2990}
2991
2992inline int64_t MinVarArray(const std::vector<IntVar*>& vars) {
2993 DCHECK(!vars.empty());
2994 int64_t result = kint64max;
2995 for (int i = 0; i < vars.size(); ++i) {
2997 result = std::min<int64_t>(result, vars[i]->Min());
2998 }
2999 return result;
3000}
3001
3002inline void FillValues(const std::vector<IntVar*>& vars,
3003 std::vector<int64_t>* const values) {
3004 values->clear();
3005 values->resize(vars.size());
3006 for (int i = 0; i < vars.size(); ++i) {
3007 (*values)[i] = vars[i]->Value();
3008 }
3009}
3010
3011inline int64_t PosIntDivUp(int64_t e, int64_t v) {
3012 DCHECK_GT(v, 0);
3013 return (e < 0 || e % v == 0) ? e / v : e / v + 1;
3014}
3015
3016inline int64_t PosIntDivDown(int64_t e, int64_t v) {
3017 DCHECK_GT(v, 0);
3018 return (e >= 0 || e % v == 0) ? e / v : e / v - 1;
3019}
3020
3021std::vector<int64_t> ToInt64Vector(const std::vector<int>& input);
3022
3023#if !defined(SWIG)
3024// A PathState represents a set of paths and changes made on it.
3025//
3026// More accurately, let us define P_{num_nodes, starts, ends}-graphs the set of
3027// directed graphs with nodes [0, num_nodes) whose connected components are
3028// paths from starts[i] to ends[i] (for the same i) and loops.
3029// Let us fix num_nodes, starts and ends, so we call these P-graphs.
3030//
3031// A P-graph can be described by the sequence of nodes of each of its paths,
3032// and its set of loops. To describe a change made on a given P-graph G0 that
3033// yields another P-graph G1, we choose to describe G1 in terms of G0. When
3034// the difference between G0 and G1 is small, as is almost always the case in a
3035// local search setting, the description is compact, allowing for incremental
3036// filters to be efficient.
3037//
3038// In order to describe G1 in terms of G0 succintly, we describe each path of
3039// G1 as a sequence of chains of G0. A chain of G0 is either a nonempty sequence
3040// of consecutive nodes of a path of G0, or a node that was a loop in G0.
3041// For instance, a path that was not modified from G0 to G1 has one chain,
3042// the sequence of all nodes in the path. Typically, local search operators
3043// modify one or two paths, and the resulting paths can described as sequences
3044// of two to four chains of G0. Paths that were modified are listed explicitly,
3045// allowing to iterate only on changed paths.
3046// The loops of G1 are described more implicitly: the loops of G1 not in G0
3047// are listed explicitly, but those in both G1 and G0 are not listed.
3048//
3049// A PathState object can be in two states: committed or changed.
3050// At construction, the object is committed, G0.
3051// To enter a changed state G1, one can pass modifications with ChangePath() and
3052// ChangeLoops(). For reasons of efficiency, a chain is described as a range of
3053// node indices in the representation of the committed graph G0. To that effect,
3054// the nodes of a path of G0 are guaranteed to have consecutive indices.
3055//
3056// Filters can then browse the change efficiently using ChangedPaths(),
3057// Chains(), Nodes() and ChangedLoops().
3058//
3059// Then Commit() or Revert() can be called: Commit() sets the changed state G1
3060// as the new committed state, Revert() erases all changes.
3062 public:
3063 // A Chain allows to iterate on all nodes of a chain, and access some data:
3064 // first node, last node, number of nodes in the chain.
3065 // Chain is a range, its iterator ChainNodeIterator, its value type int.
3066 // Chains are returned by PathChainIterator's operator*().
3067 class Chain;
3068 // A ChainRange allows to iterate on all chains of a path.
3069 // ChainRange is a range, its iterator Chain*, its value type Chain.
3070 class ChainRange;
3071 // A NodeRange allows to iterate on all nodes of a path.
3072 // NodeRange is a range, its iterator PathNodeIterator, its value type int.
3073 class NodeRange;
3074
3076 ChainBounds() = default;
3077 ChainBounds(int begin_index, int end_index)
3078 : begin_index(begin_index), end_index(end_index) {}
3081 };
3082 int CommittedIndex(int node) const { return committed_index_[node]; }
3083 ChainBounds CommittedPathRange(int path) const { return chains_[path]; }
3084
3085 // Path constructor: path_start and path_end must be disjoint,
3086 // their values in [0, num_nodes).
3087 PathState(int num_nodes, std::vector<int> path_start,
3088 std::vector<int> path_end);
3089
3090 // Instance-constant accessors.
3091
3092 // Returns the number of nodes in the underlying graph.
3093 int NumNodes() const { return num_nodes_; }
3094 // Returns the number of paths (empty paths included).
3095 int NumPaths() const { return num_paths_; }
3096 // Returns the start of a path.
3097 int Start(int path) const { return path_start_end_[path].start; }
3098 // Returns the end of a path.
3099 int End(int path) const { return path_start_end_[path].end; }
3100
3101 // State-dependent accessors.
3102
3103 // Returns the committed path of a given node, -1 if it is a loop.
3104 int Path(int node) const {
3105 return committed_nodes_[committed_index_[node]].path;
3106 }
3107 // Returns the set of paths that actually changed,
3108 // i.e. that have more than one chain.
3109 const std::vector<int>& ChangedPaths() const { return changed_paths_; }
3110 // Returns the set of loops that were added by the change.
3111 const std::vector<int>& ChangedLoops() const { return changed_loops_; }
3112 // Returns the current range of chains of path.
3113 ChainRange Chains(int path) const;
3114 // Returns the current range of nodes of path.
3115 NodeRange Nodes(int path) const;
3116
3117 // State modifiers.
3118
3119 // Changes the path to the given sequence of chains of the committed state.
3120 // Chains are described by semi-open intervals. No optimization is made in
3121 // case two consecutive chains are actually already consecutive in the
3122 // committed state: they are not merged into one chain, and Chains(path) will
3123 // report the two chains.
3124 void ChangePath(int path, const std::vector<ChainBounds>& chains);
3125 // Same as above, but the initializer_list interface avoids the need to pass
3126 // a vector.
3127 void ChangePath(int path, const std::initializer_list<ChainBounds>& chains) {
3128 changed_paths_.push_back(path);
3129 const int path_begin_index = chains_.size();
3130 chains_.insert(chains_.end(), chains.begin(), chains.end());
3131 const int path_end_index = chains_.size();
3132 paths_[path] = {path_begin_index, path_end_index};
3133 // Always add sentinel, in case this is the last path change.
3134 chains_.emplace_back(0, 0);
3135 }
3136
3137 // Describes the nodes that are newly loops in this change.
3138 void ChangeLoops(const std::vector<int>& new_loops);
3139
3140 // Set the current state G1 as committed. See class comment for details.
3141 void Commit();
3142 // Erase incremental changes. See class comment for details.
3143 void Revert();
3144
3145 // LNS Operators may not fix variables,
3146 // in which case we mark the candidate invalid.
3147 void SetInvalid() { is_invalid_ = true; }
3148 bool IsInvalid() const { return is_invalid_; }
3149
3150 private:
3151 // Most structs below are named pairs of ints, for typing purposes.
3152
3153 // Start and end are stored together to optimize (likely) simultaneous access.
3154 struct PathStartEnd {
3155 PathStartEnd(int start, int end) : start(start), end(end) {}
3156 int start;
3157 int end;
3158 };
3159 // Paths are ranges of chains, which are ranges of committed nodes, see below.
3160 struct PathBounds {
3161 int begin_index;
3162 int end_index;
3163 };
3164 struct CommittedNode {
3165 CommittedNode(int node, int path) : node(node), path(path) {}
3166 int node;
3167 // Path of node in the committed state, -1 for loop nodes.
3168 // TODO(user): check if path would be better stored
3169 // with committed_index_, or in its own vector, or just recomputed.
3170 int path;
3171 };
3172
3173 // Copies nodes in chains of path at the end of nodes,
3174 // and sets those nodes' path member to value path.
3175 void CopyNewPathAtEndOfNodes(int path);
3176 // Commits paths in O(#{changed paths' nodes}) time,
3177 // increasing this object's space usage by O(|changed path nodes|).
3178 void IncrementalCommit();
3179 // Commits paths in O(num_nodes + num_paths) time,
3180 // reducing this object's space usage to O(num_nodes + num_paths).
3181 void FullCommit();
3182
3183 // Instance-constant data.
3184 const int num_nodes_;
3185 const int num_paths_;
3186 std::vector<PathStartEnd> path_start_end_;
3187
3188 // Representation of the committed and changed paths.
3189 // A path is a range of chains, which is a range of nodes.
3190 // Ranges are represented internally by indices in vectors:
3191 // ChainBounds are indices in committed_nodes_. PathBounds are indices in
3192 // chains_. When committed (after construction, Revert() or Commit()):
3193 // - path ranges are [path, path+1): they have one chain.
3194 // - chain ranges don't overlap, chains_ has an empty sentinel at the end.
3195 // The sentinel allows the Nodes() iterator to maintain its current pointer
3196 // to committed nodes on NodeRange::operator++().
3197 // - committed_nodes_ contains all nodes, both paths and loops.
3198 // Actually, old duplicates will likely appear,
3199 // the current version of a node is at the index given by
3200 // committed_index_[node]. A Commit() can add nodes at the end of
3201 // committed_nodes_ in a space/time tradeoff, but if committed_nodes_' size
3202 // is above num_nodes_threshold_, Commit() must reclaim useless duplicates'
3203 // space by rewriting the path/chain/nodes structure.
3204 // When changed (after ChangePaths() and ChangeLoops()),
3205 // the structure is updated accordingly:
3206 // - path ranges that were changed have nonoverlapping values [begin, end)
3207 // where begin is >= num_paths_ + 1, i.e. new chains are stored after
3208 // the committed state.
3209 // - additional chain ranges are stored after the committed chains and its
3210 // sentinel to represent the new chains resulting from the changes.
3211 // Those chains do not overlap with one another or with committed chains.
3212 // - committed_nodes_ are not modified, and still represent the committed
3213 // paths. committed_index_ is not modified either.
3214 std::vector<CommittedNode> committed_nodes_;
3215 std::vector<int> committed_index_;
3216 const int num_nodes_threshold_;
3217 std::vector<ChainBounds> chains_;
3218 std::vector<PathBounds> paths_;
3219
3220 // Incremental information.
3221 std::vector<int> changed_paths_;
3222 std::vector<int> changed_loops_;
3223
3224 // See IsInvalid() and SetInvalid().
3225 bool is_invalid_ = false;
3226};
3227
3228// A Chain is a range of committed nodes.
3230 public:
3231 class Iterator {
3232 public:
3234 ++current_node_;
3235 return *this;
3236 }
3237 int operator*() const { return current_node_->node; }
3238 bool operator!=(Iterator other) const {
3239 return current_node_ != other.current_node_;
3240 }
3241
3242 private:
3243 // Only a Chain can construct its iterator.
3244 friend class PathState::Chain;
3245 explicit Iterator(const CommittedNode* node) : current_node_(node) {}
3246 const CommittedNode* current_node_;
3247 };
3248
3249 // Chains hold CommittedNode* values, a Chain may be invalidated
3250 // if the underlying vector is modified.
3251 Chain(const CommittedNode* begin_node, const CommittedNode* end_node)
3252 : begin_(begin_node), end_(end_node) {}
3253
3254 int NumNodes() const { return end_ - begin_; }
3255 int First() const { return begin_->node; }
3256 int Last() const { return (end_ - 1)->node; }
3257 Iterator begin() const { return Iterator(begin_); }
3258 Iterator end() const { return Iterator(end_); }
3259
3260 private:
3261 const CommittedNode* const begin_;
3262 const CommittedNode* const end_;
3263};
3264
3265// A ChainRange is a range of Chains, committed or not.
3267 public:
3268 class Iterator {
3269 public:
3271 ++current_chain_;
3272 return *this;
3273 }
3275 return {first_node_ + current_chain_->begin_index,
3276 first_node_ + current_chain_->end_index};
3277 }
3278 bool operator!=(Iterator other) const {
3279 return current_chain_ != other.current_chain_;
3280 }
3281
3282 private:
3283 // Only a ChainRange can construct its Iterator.
3284 friend class ChainRange;
3285 Iterator(const ChainBounds* chain, const CommittedNode* const first_node)
3286 : current_chain_(chain), first_node_(first_node) {}
3287 const ChainBounds* current_chain_;
3288 const CommittedNode* const first_node_;
3289 };
3290
3291 // ChainRanges hold ChainBounds* and CommittedNode*,
3292 // a ChainRange may be invalidated if on of the underlying vector is modified.
3293 ChainRange(const ChainBounds* const begin_chain,
3294 const ChainBounds* const end_chain,
3295 const CommittedNode* const first_node)
3296 : begin_(begin_chain), end_(end_chain), first_node_(first_node) {}
3297
3298 Iterator begin() const { return {begin_, first_node_}; }
3299 Iterator end() const { return {end_, first_node_}; }
3300
3301 private:
3302 const ChainBounds* const begin_;
3303 const ChainBounds* const end_;
3304 const CommittedNode* const first_node_;
3305};
3306
3307// A NodeRange allows to iterate on all nodes of a path,
3308// by a two-level iteration on ChainBounds* and CommittedNode* of a PathState.
3310 public:
3311 class Iterator {
3312 public:
3314 ++current_node_;
3315 if (current_node_ == end_node_) {
3316 ++current_chain_;
3317 // Note: dereferencing bounds is valid because there is a sentinel
3318 // value at the end of PathState::chains_ to that intent.
3319 const ChainBounds bounds = *current_chain_;
3320 current_node_ = first_node_ + bounds.begin_index;
3321 end_node_ = first_node_ + bounds.end_index;
3322 }
3323 return *this;
3324 }
3325 int operator*() const { return current_node_->node; }
3326 bool operator!=(Iterator other) const {
3327 return current_chain_ != other.current_chain_;
3328 }
3329
3330 private:
3331 // Only a NodeRange can construct its Iterator.
3332 friend class NodeRange;
3333 Iterator(const ChainBounds* current_chain,
3334 const CommittedNode* const first_node)
3335 : current_node_(first_node + current_chain->begin_index),
3336 end_node_(first_node + current_chain->end_index),
3337 current_chain_(current_chain),
3338 first_node_(first_node) {}
3339 const CommittedNode* current_node_;
3340 const CommittedNode* end_node_;
3341 const ChainBounds* current_chain_;
3342 const CommittedNode* const first_node_;
3343 };
3344
3345 // NodeRanges hold ChainBounds* and CommittedNode*,
3346 // a NodeRange may be invalidated if on of the underlying vector is modified.
3347 NodeRange(const ChainBounds* begin_chain, const ChainBounds* end_chain,
3348 const CommittedNode* first_node)
3349 : begin_chain_(begin_chain),
3350 end_chain_(end_chain),
3351 first_node_(first_node) {}
3352 Iterator begin() const { return {begin_chain_, first_node_}; }
3353 // Note: there is a sentinel value at the end of PathState::chains_,
3354 // so dereferencing chain_range_.end()->begin_ is always valid.
3355 Iterator end() const { return {end_chain_, first_node_}; }
3356
3357 private:
3358 const ChainBounds* begin_chain_;
3359 const ChainBounds* end_chain_;
3360 const CommittedNode* const first_node_;
3361};
3362
3363// This checker enforces unary dimension requirements.
3364// A unary dimension requires that there is some valuation of
3365// node_capacity and demand such that for all paths,
3366// if arc A -> B is on a path of path_class p,
3367// then node_capacity[A] + demand[p][A] = node_capacity[B].
3368// Moreover, all node_capacities of a path must be inside interval
3369// path_capacity[path].
3370// Note that Intervals have two meanings:
3371// - for demand and node_capacity, those are values allowed for each associated
3372// decision variable.
3373// - for path_capacity, those are set of values that node_capacities of the path
3374// must respect.
3375// If the path capacity of a path is [kint64min, kint64max],
3376// then the unary dimension requirements are not enforced on this path.
3378 public:
3379 struct Interval {
3380 int64_t min;
3381 int64_t max;
3382 };
3383
3384 UnaryDimensionChecker(const PathState* path_state,
3385 std::vector<Interval> path_capacity,
3386 std::vector<int> path_class,
3387 std::vector<std::function<Interval(int64_t)>>
3388 min_max_demand_per_path_class,
3389 std::vector<Interval> node_capacity);
3390
3391 // Given the change made in PathState, checks that the unary dimension
3392 // constraint is still feasible.
3393 bool Check() const;
3394
3395 // Commits to the changes made in PathState,
3396 // must be called before PathState::Commit().
3397 void Commit();
3398
3399 private:
3400 // Range min/max query on partial_demand_sums_.
3401 // The first_node and last_node MUST form a subpath in the committed state.
3402 // Nodes first_node and last_node are passed by their index in precomputed
3403 // data, they must be committed in some path, and it has to be the same path.
3404 // See partial_demand_sums_.
3405 Interval GetMinMaxPartialDemandSum(int first_node_index,
3406 int last_node_index) const;
3407
3408 // Queries whether all nodes in the committed subpath [first_node, last_node]
3409 // have fixed demands and trivial node_capacity [kint64min, kint64max].
3410 // first_node and last_node MUST form a subpath in the committed state.
3411 // Nodes are passed by their index in precomputed data.
3412 bool SubpathOnlyHasTrivialNodes(int first_node_index,
3413 int last_node_index) const;
3414
3415 // Commits to the current solution and rebuilds structures from scratch.
3416 void FullCommit();
3417 // Commits to the current solution and only build structures for paths that
3418 // changed, using additional space to do so in a time-memory tradeoff.
3419 void IncrementalCommit();
3420 // Adds sums of given path to the bottom layer of the RMQ structure,
3421 // updates index_ and previous_nontrivial_index_.
3422 void AppendPathDemandsToSums(int path);
3423 // Updates the RMQ structure from its bottom layer,
3424 // with [begin_index, end_index) the range of the change,
3425 // which must be at the end of the bottom layer.
3426 // Supposes that requests overlapping the range will be inside the range,
3427 // to avoid updating all layers.
3428 void UpdateRMQStructure(int begin_index, int end_index);
3429
3430 const PathState* const path_state_;
3431 const std::vector<Interval> path_capacity_;
3432 const std::vector<int> path_class_;
3433 const std::vector<std::function<Interval(int64_t)>>
3434 min_max_demand_per_path_class_;
3435 std::vector<Interval> cached_demand_;
3436 const std::vector<Interval> node_capacity_;
3437
3438 // Precomputed data.
3439 // Maps nodes to their pre-computed data, except for isolated nodes,
3440 // which do not have precomputed data.
3441 // Only valid for nodes that are in some path in the committed state.
3442 std::vector<int> index_;
3443 // Implementation of a <O(n log n), O(1)> range min/max query, n = #nodes.
3444 // partial_demand_sums_rmq_[0][index_[node]] contains the sum of demands
3445 // from the start of the node's path to the node.
3446 // If node is the start of path, the sum is demand_[path_class_[path]][node],
3447 // moreover partial_demand_sums_rmq_[0][index_[node]-1] is {0, 0}.
3448 // partial_demand_sums_rmq_[layer][index] contains an interval
3449 // [min_value, max_value] such that min_value is
3450 // min(partial_demand_sums_rmq_[0][index+i].min | i in [0, 2^layer)),
3451 // similarly max_value is the maximum of .max on the same range.
3452 std::vector<std::vector<Interval>> partial_demand_sums_rmq_;
3453 // The incremental branch of Commit() may waste space in the layers of the
3454 // RMQ structure. This is the upper limit of a layer's size.
3455 const int maximum_partial_demand_layer_size_;
3456 // previous_nontrivial_index_[index_[node]] has the index of the previous
3457 // node on its committed path that has nonfixed demand or nontrivial node
3458 // capacity. This allows for O(1) queries that all nodes on a subpath
3459 // are nonfixed and nontrivial.
3460 std::vector<int> previous_nontrivial_index_;
3461};
3462
3463// Make a filter that takes ownership of a PathState and synchronizes it with
3464// solver events. The solver represents a graph with array of variables 'nexts'.
3465// Solver events are embodied by Assignment* deltas, that are translated to node
3466// changes during Relax(), committed during Synchronize(), and reverted on
3467// Revert().
3469 std::unique_ptr<PathState> path_state,
3470 const std::vector<IntVar*>& nexts);
3471
3472// Make a filter that translates solver events to the input checker's interface.
3473// Since UnaryDimensionChecker has a PathState, the filter returned by this
3474// must be synchronized to the corresponding PathStateFilter:
3475// - Relax() must be called after the PathStateFilter's.
3476// - Accept() must be called after.
3477// - Synchronize() must be called before.
3478// - Revert() must be called before.
3480 Solver* solver, std::unique_ptr<UnaryDimensionChecker> checker,
3481 const std::string& dimension_name);
3482
3483#endif // !defined(SWIG)
3484
3485} // namespace operations_research
3486
3487#endif // OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_
const std::vector< IntVar * > vars_
Definition: alldiff_cst.cc:44
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:495
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:893
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
#define CHECK_GE(val1, val2)
Definition: base/logging.h:707
#define CHECK_GT(val1, val2)
Definition: base/logging.h:708
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:895
#define CHECK_NE(val1, val2)
Definition: base/logging.h:704
#define DCHECK_GT(val1, val2)
Definition: base/logging.h:896
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:894
#define DCHECK(condition)
Definition: base/logging.h:890
#define CHECK_LE(val1, val2)
Definition: base/logging.h:705
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:891
int64_t MemoryUsage(int unused)
Definition: base/sysinfo.h:24
Argument Holder: useful when visiting a model.
virtual T Evaluate(int64_t index) const
ArrayWithOffset(int64_t index_min, int64_t index_max)
void SetValue(int64_t index, T value)
std::string DebugString() const override
bool Contains(const V *const var) const
const E & Element(const V *const var) const
An Assignment is a variable -> domains mapping, used to report solutions to the user.
SequenceContainer * MutableSequenceVarContainer()
const SequenceContainer & SequenceVarContainer() const
const IntContainer & IntVarContainer() const
IntVarElement * FastAdd(IntVar *const var)
Adds without checking if variable has been previously added.
IntVar * Var() override
Creates a variable from the expression.
This is the base class for building an Lns operator.
virtual bool NextFragment()=0
bool HasFragments() const override
void AppendToFragment(int index)
BaseLns(const std::vector< IntVar * > &vars)
bool MakeOneNeighbor() override
This method should not be overridden. Override NextFragment() instead.
A BaseObject is the root of all reversibly allocated objects.
void SetContentFromBitsetOfSameSize(const Bitset64< OtherIndexType > &other)
Definition: bitset.h:535
void Clear(IndexType i)
Definition: bitset.h:457
void Set(IndexType i)
Definition: bitset.h:495
void Resize(IndexType size)
Definition: bitset.h:433
void CopyBucket(const Bitset64< IndexType > &other, IndexType i)
Definition: bitset.h:511
bool Bound() const override
Returns true if the min and the max of the expression are equal.
void WhenRange(Demon *d) override
Attach a demon that will watch the min or the max of the expression.
SimpleRevFIFO< Demon * > delayed_bound_demons_
void WhenDomain(Demon *d) override
This method attaches a demon that will watch any domain modification of the domain of the variable.
int64_t Value() const override
This method returns the value of the variable.
SimpleRevFIFO< Demon * > bound_demons_
std::string BaseName() const override
Returns a base name for automatic naming.
BooleanVar(Solver *const s, const std::string &name="")
Demon proxy to a method on the constraint with no arguments.
CallMethod0(T *const ct, void(T::*method)(), const std::string &name)
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
Demon proxy to a method on the constraint with one argument.
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
CallMethod1(T *const ct, void(T::*method)(P), const std::string &name, P param1)
Demon proxy to a method on the constraint with two arguments.
CallMethod2(T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
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)
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
Defines operators which change the value of variables; each neighbor corresponds to one modified vari...
ChangeValue(const std::vector< IntVar * > &vars)
virtual int64_t ModifyValue(int64_t index, int64_t value)=0
bool MakeOneNeighbor() override
This method should not be overridden. Override ModifyValue() instead.
A constraint is the main modeling object.
A Decision represents a choice point in the search tree.
A DecisionVisitor is used to inspect a decision.
Low-priority demon proxy to a method on the constraint with no arguments.
Solver::DemonPriority priority() const override
This method returns the priority of the demon.
void Run(Solver *const s) override
This is the main callback of the demon.
DelayedCallMethod0(T *const ct, void(T::*method)(), const std::string &name)
std::string DebugString() const override
Low-priority demon proxy to a method on the constraint with one argument.
Solver::DemonPriority priority() const override
This method returns the priority of the demon.
DelayedCallMethod1(T *const ct, void(T::*method)(P), const std::string &name, P param1)
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
Low-priority demon proxy to a method on the constraint with two arguments.
Solver::DemonPriority priority() const override
This method returns the priority of the demon.
DelayedCallMethod2(T *const ct, void(T::*method)(P, Q), const std::string &name, P param1, Q param2)
void Run(Solver *const s) override
This is the main callback of the demon.
std::string DebugString() const override
A Demon is the base element of a propagation queue.
The class IntExpr is the base of all integer expressions in constraint programming.
virtual int64_t Max() const =0
The class IntVar is a subset of IntExpr.
The class Iterator has two direct subclasses.
virtual void OnSynchronize(const Assignment *delta)
bool FindIndex(IntVar *const var, int64_t *index) const
bool ValueFromAssignment(const Assignment &assignment, IntVar *var, int64_t index, int64_t *value)
IntVarLocalSearchHandler(const IntVarLocalSearchHandler &other)
IntVarLocalSearchHandler(IntVarLocalSearchOperator *op)
void OnRevertChanges(int64_t index, int64_t value)
void AddToAssignment(IntVar *var, int64_t value, bool active, std::vector< int > *assignment_indices, int64_t index, Assignment *assignment) const
Specialization of LocalSearchOperator built from an array of IntVars which specifies the scope of the...
void SetOldInverseValue(int64_t index, int64_t value)
void SetInverseValue(int64_t index, int64_t value)
IntVarLocalSearchOperator(const std::vector< IntVar * > &vars, bool keep_inverse_values=false)
Interval variables are often used in scheduling.
Local Search Filters are used for fast neighbor pruning.
virtual void Synchronize(const Assignment *assignment, const Assignment *delta)=0
Synchronizes the filter with the current solution, delta being the difference with the solution passe...
virtual int64_t GetAcceptedObjectiveValue() const
Objective value from the last time Accept() was called and returned true.
virtual void Reset()
Sets the filter to empty solution.
virtual void Relax(const Assignment *delta, const Assignment *deltadelta)
Lets the filter know what delta and deltadelta will be passed in the next Accept().
virtual bool Accept(const Assignment *delta, const Assignment *deltadelta, int64_t objective_min, int64_t objective_max)=0
Accepts a "delta" given the assignment with which the filter has been synchronized; the delta holds t...
virtual int64_t GetSynchronizedObjectiveValue() const
Objective value from last time Synchronize() was called.
virtual void Revert()
Cancels the changes made by the last Relax()/Accept() calls.
virtual void Commit(const Assignment *delta, const Assignment *deltadelta)
Dual of Relax(), lets the filter know that the delta was accepted.
Filter manager: when a move is made, filters are executed to decide whether the solution is feasible ...
virtual void EndMakeNextNeighbor(const LocalSearchOperator *op, bool neighbor_found, const Assignment *delta, const Assignment *deltadelta)=0
virtual void EndAcceptNeighbor(const LocalSearchOperator *op, bool neighbor_found)=0
virtual void BeginMakeNextNeighbor(const LocalSearchOperator *op)=0
virtual void BeginOperatorStart()=0
Local search operator events.
virtual void EndFiltering(const LocalSearchFilter *filter, bool reject)=0
virtual void BeginFilterNeighbor(const LocalSearchOperator *op)=0
virtual void BeginAcceptNeighbor(const LocalSearchOperator *op)=0
virtual void BeginFiltering(const LocalSearchFilter *filter)=0
virtual void EndFilterNeighbor(const LocalSearchOperator *op, bool neighbor_found)=0
std::string DebugString() const override
The base class for all local search operators.
virtual const LocalSearchOperator * Self() const
virtual bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta)=0
virtual void Start(const Assignment *assignment)=0
Implements a complete cache for model elements: expressions and constraints.
virtual IntExpr * FindVarArrayExpression(const std::vector< IntVar * > &vars, VarArrayExpressionType type) const =0
Var Array Expressions.
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 * FindExprConstantExpression(IntExpr *const expr, int64_t value, ExprConstantExpressionType type) const =0
Expr Constant Expressions.
virtual void InsertExprExprConstantExpression(IntExpr *const expression, IntExpr *const var1, IntExpr *const var2, int64_t constant, ExprExprConstantExpressionType type)=0
virtual IntExpr * FindExprExpression(IntExpr *const expr, ExprExpressionType type) const =0
Expr Expressions.
virtual IntExpr * FindVarConstantConstantExpression(IntVar *const var, int64_t value1, int64_t value2, VarConstantConstantExpressionType type) const =0
Var Constant Constant Expressions.
virtual void InsertExprExprExpression(IntExpr *const expression, IntExpr *const var1, IntExpr *const var2, ExprExprExpressionType type)=0
virtual void InsertVarConstantArrayExpression(IntExpr *const expression, IntVar *const var, const std::vector< int64_t > &values, VarConstantArrayExpressionType type)=0
virtual IntExpr * FindExprExprConstantExpression(IntExpr *const var1, IntExpr *const var2, int64_t constant, ExprExprConstantExpressionType type) const =0
Expr Expr Constant Expressions.
virtual void InsertVoidConstraint(Constraint *const ct, VoidConstraintType type)=0
virtual Constraint * FindVarConstantConstraint(IntVar *const var, int64_t value, VarConstantConstraintType type) const =0
Var Constant Constraints.
virtual void InsertVarArrayExpression(IntExpr *const expression, const std::vector< IntVar * > &vars, VarArrayExpressionType type)=0
virtual Constraint * FindVoidConstraint(VoidConstraintType type) const =0
Void constraints.
virtual IntExpr * FindVarConstantArrayExpression(IntVar *const var, const std::vector< int64_t > &values, VarConstantArrayExpressionType type) const =0
Var Constant Array Expressions.
virtual void InsertVarArrayConstantExpression(IntExpr *const expression, const std::vector< IntVar * > &var, int64_t value, VarArrayConstantExpressionType type)=0
virtual void InsertVarConstantConstraint(Constraint *const ct, IntVar *const var, int64_t value, VarConstantConstraintType type)=0
virtual IntExpr * FindVarArrayConstantExpression(const std::vector< IntVar * > &vars, int64_t value, VarArrayConstantExpressionType type) const =0
Var Array Constant Expressions.
virtual Constraint * FindVarConstantConstantConstraint(IntVar *const var, int64_t value1, int64_t value2, VarConstantConstantConstraintType type) const =0
Var Constant Constant Constraints.
virtual void InsertVarArrayConstantArrayExpression(IntExpr *const expression, const std::vector< IntVar * > &var, const std::vector< int64_t > &values, VarArrayConstantArrayExpressionType type)=0
virtual void InsertExprConstantExpression(IntExpr *const expression, IntExpr *const var, int64_t value, ExprConstantExpressionType type)=0
virtual IntExpr * FindExprExprExpression(IntExpr *const var1, IntExpr *const var2, ExprExprExpressionType type) const =0
Expr Expr Expressions.
virtual void InsertVarConstantConstantExpression(IntExpr *const expression, IntVar *const var, int64_t value1, int64_t value2, VarConstantConstantExpressionType type)=0
virtual void InsertVarConstantConstantConstraint(Constraint *const ct, IntVar *const var, int64_t value1, int64_t value2, VarConstantConstantConstraintType type)=0
virtual Constraint * FindExprExprConstraint(IntExpr *const expr1, IntExpr *const expr2, ExprExprConstraintType type) const =0
Expr Expr Constraints.
virtual void InsertExprExpression(IntExpr *const expression, IntExpr *const expr, ExprExpressionType type)=0
virtual void InsertExprExprConstraint(Constraint *const ct, IntExpr *const expr1, IntExpr *const expr2, ExprExprConstraintType type)=0
This class encapsulates an objective.
Base class of the local search operators dedicated to path modifications (a path is a set of nodes li...
int64_t StartNode(int i) const
Returns the start node of the ith base node.
bool IsInactive(int64_t node) const
Returns true if node is inactive.
int64_t OldPrev(int64_t node) const
virtual bool ConsiderAlternatives(int64_t base_index) const
Indicates if alternatives should be considered when iterating over base nodes.
int PathClass(int i) const
Returns the class of the path of the ith base node.
virtual void OnNodeInitialization()
Called by OnStart() after initializing node information.
virtual bool OnSamePathAsPreviousBase(int64_t base_index)
Returns true if a base node has to be on the same path as the "previous" base node (base node of inde...
int64_t OldPath(int64_t node) const
bool IsPathStart(int64_t node) const
Returns true if node is the first node on the path.
int64_t GetActiveAlternativeNode(int node) const
Returns the active node in the alternative set of the given node.
int number_of_nexts() const
Number of next variables.
int AddAlternativeSet(const std::vector< int64_t > &alternative_set)
Handling node alternatives.
const std::vector< int64_t > & path_starts() const
Returns the vector of path start nodes.
virtual bool RestartAtPathStartOnSynchronize()
When the operator is being synchronized with a new solution (when Start() is called),...
bool IsPathEnd(int64_t node) const
Returns true if node is the last node on the path; defined by the fact that node is outside the range...
int BaseSiblingAlternative(int i) const
Returns the alternative for the sibling of the ith base node.
int64_t Next(int64_t node) const
Returns the node after node in the current delta.
bool MoveChain(int64_t before_chain, int64_t chain_end, int64_t destination)
Moves the chain starting after the node before_chain and ending at the node chain_end after the node ...
bool MakeActive(int64_t node, int64_t destination)
Insert the inactive node after destination.
int BaseAlternative(int i) const
Returns the alternative for the ith base node.
bool ReverseChain(int64_t before_chain, int64_t after_chain, int64_t *chain_last)
Reverses the chain starting after before_chain and ending before after_chain.
void SetNext(int64_t from, int64_t to, int64_t path)
Sets 'to' to be the node after 'from' on the given path.
void AddPairAlternativeSets(const std::vector< std::pair< std::vector< int64_t >, std::vector< int64_t > > > &pair_alternative_sets)
Adds all sets of node alternatives of a vector of alternative pairs.
int64_t BaseSiblingAlternativeNode(int i) const
Returns the alternative node for the sibling of the ith base node.
int64_t Prev(int64_t node) const
Returns the node before node in the current delta.
int64_t GetActiveAlternativeSibling(int node) const
Returns the active node in the alternative set of the sibling of the given node.
int64_t OldNext(int64_t node) const
bool SkipUnchanged(int index) const override
bool SwapActiveAndInactive(int64_t active, int64_t inactive)
Replaces active by inactive in the current path, making active inactive.
void ResetPosition()
Reset the position of the operator to its position when Start() was last called; this can be used to ...
virtual int64_t GetBaseNodeRestartPosition(int base_index)
Returns the index of the node to which the base node of index base_index must be set to when it reach...
int64_t BaseNode(int i) const
Returns the ith base node of the operator.
PathOperator(const std::vector< IntVar * > &next_vars, const std::vector< IntVar * > &path_vars, int number_of_base_nodes, bool skip_locally_optimal_paths, bool accept_path_end_base, std::function< int(int64_t)> start_empty_path_class)
int64_t BaseAlternativeNode(int i) const
Returns the alternative node for the ith base node.
int GetSiblingAlternativeIndex(int node) const
Returns the index of the alternative set of the sibling of node.
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
int64_t Path(int64_t node) const
Returns the index of the path to which node belongs in the current delta.
virtual bool InitPosition() const
Returns true if the operator needs to restart its initial position at each call to Start()
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.
virtual void SetNextBaseToIncrement(int64_t base_index)
Set the next base to increment on next iteration.
bool MakeChainInactive(int64_t before_chain, int64_t chain_end)
Makes the nodes on the chain starting after before_chain and ending at chain_end inactive.
Chain(const CommittedNode *begin_node, const CommittedNode *end_node)
ChainRange(const ChainBounds *const begin_chain, const ChainBounds *const end_chain, const CommittedNode *const first_node)
NodeRange(const ChainBounds *begin_chain, const ChainBounds *end_chain, const CommittedNode *first_node)
const std::vector< int > & ChangedPaths() const
const std::vector< int > & ChangedLoops() const
ChainBounds CommittedPathRange(int path) const
void ChangePath(int path, const std::initializer_list< ChainBounds > &chains)
virtual void SetValues(IntVar *const var, const std::vector< int64_t > &values)=0
virtual void SetDurationMax(IntervalVar *const var, int64_t new_max)=0
virtual void SetDurationRange(IntervalVar *const var, int64_t new_min, int64_t new_max)=0
virtual void SetMax(IntExpr *const expr, int64_t new_max)=0
virtual void RankLast(SequenceVar *const var, int index)=0
virtual void EndConstraintInitialPropagation(Constraint *const constraint)=0
virtual void SetMin(IntVar *const var, int64_t new_min)=0
IntVar modifiers.
virtual void RemoveValue(IntVar *const var, int64_t value)=0
virtual void SetValue(IntVar *const var, int64_t value)=0
virtual void SetDurationMin(IntervalVar *const var, int64_t new_min)=0
virtual void SetStartMin(IntervalVar *const var, int64_t new_min)=0
IntervalVar modifiers.
virtual void RankNotLast(SequenceVar *const var, int index)=0
virtual void RankNotFirst(SequenceVar *const var, int index)=0
virtual void BeginDemonRun(Demon *const demon)=0
virtual void SetRange(IntExpr *const expr, int64_t new_min, int64_t new_max)=0
virtual void RankSequence(SequenceVar *const var, const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)=0
virtual void SetEndRange(IntervalVar *const var, int64_t new_min, int64_t new_max)=0
virtual void SetEndMax(IntervalVar *const var, int64_t new_max)=0
virtual void PushContext(const std::string &context)=0
virtual void RemoveInterval(IntVar *const var, int64_t imin, int64_t imax)=0
virtual void SetEndMin(IntervalVar *const var, int64_t new_min)=0
virtual void BeginNestedConstraintInitialPropagation(Constraint *const parent, Constraint *const nested)=0
virtual void EndNestedConstraintInitialPropagation(Constraint *const parent, Constraint *const nested)=0
virtual void SetMax(IntVar *const var, int64_t new_max)=0
virtual void SetPerformed(IntervalVar *const var, bool value)=0
virtual void StartProcessingIntegerVariable(IntVar *const var)=0
virtual void BeginConstraintInitialPropagation(Constraint *const constraint)=0
Propagation events.
virtual void SetRange(IntVar *const var, int64_t new_min, int64_t new_max)=0
virtual void SetMin(IntExpr *const expr, int64_t new_min)=0
IntExpr modifiers.
virtual void SetStartMax(IntervalVar *const var, int64_t new_max)=0
virtual void EndDemonRun(Demon *const demon)=0
virtual void RegisterDemon(Demon *const demon)=0
virtual void EndProcessingIntegerVariable(IntVar *const var)=0
virtual void RemoveValues(IntVar *const var, const std::vector< int64_t > &values)=0
std::string DebugString() const override
virtual void SetStartRange(IntervalVar *const var, int64_t new_min, int64_t new_max)=0
virtual void RankFirst(SequenceVar *const var, int index)=0
SequenceVar modifiers.
Matrix version of the RevBitSet class.
void SetToZero(Solver *const solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
Definition: utilities.cc:178
bool IsSet(int64_t row, int64_t column) const
Returns whether the 'column' bit in the 'row' row is set.
void SetToOne(Solver *const solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition: utilities.cc:170
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:220
int64_t GetFirstBit(int row, int start) const
Returns the first bit in the row 'row' which position is >= 'start'.
Definition: utilities.cc:204
This class represents a reversible bitset.
void SetToOne(Solver *const solver, int64_t index)
Sets the 'index' bit.
Definition: utilities.cc:84
bool IsCardinalityOne() const
Does it contains only one bit set?
Definition: utilities.cc:129
void SetToZero(Solver *const solver, int64_t index)
Erases the 'index' bit.
Definition: utilities.cc:95
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:112
int64_t GetFirstBit(int start) const
Gets the index of the first bit set starting from start.
Definition: utilities.cc:147
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition: utilities.cc:106
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:151
bool IsCardinalityZero() const
Is bitset null?
Definition: utilities.cc:120
This class is a reversible growing array.
void RevInsert(Solver *const solver, int64_t index, T value)
void SetValue(Solver *const s, const T &val)
Reversible Immutable MultiMap class.
void Insert(const K &key, const V &value)
Inserts (key, value) in the multi-map.
RevImmutableMultiMap(Solver *const solver, int initial_size)
const V & FindWithDefault(const K &key, const V &default_value) const
Returns one value attached to 'key', or 'default_value' if 'key' is not in the multi-map.
bool ContainsKey(const K &key) const
Returns true if the multi-map contains at least one instance of 'key'.
This is a special class to represent a 'residual' set of T.
void Insert(Solver *const solver, const T &elt)
RevIntSet(int capacity)
Capacity is the fixed size of the set (it cannot grow).
const T * const_iterator
Iterators on the indices.
RevIntSet(int capacity, int *shared_positions, int shared_positions_size)
Capacity is the fixed size of the set (it cannot grow).
void Restore(Solver *const solver, const T &value_index)
void Remove(Solver *const solver, const T &value_index)
void Clear(Solver *const solver)
--— RevPartialSequence --—
void RankLast(Solver *const solver, int elt)
const int & operator[](int index) const
void RankFirst(Solver *const solver, int elt)
RevPartialSequence(const std::vector< int > &items)
A reversible switch that can switch once from false to true.
void Switch(Solver *const solver)
The base class of all search logs that periodically outputs information when the search is running.
A search monitor is a simple set of callbacks to monitor all search events.
The SequenceVarElement stores a partial representation of ranked interval variables in the underlying...
void SetBackwardSequence(const std::vector< int > &backward_sequence)
const std::vector< int > & ForwardSequence() const
void SetForwardSequence(const std::vector< int > &forward_sequence)
A sequence variable is a variable whose domain is a set of possible orderings of the interval variabl...
void OnRevertChanges(int64_t index, const std::vector< int > &value)
bool ValueFromAssignment(const Assignment &assignment, SequenceVar *var, int64_t index, std::vector< int > *value)
SequenceVarLocalSearchHandler(const SequenceVarLocalSearchHandler &other)
SequenceVarLocalSearchHandler(SequenceVarLocalSearchOperator *op)
void AddToAssignment(SequenceVar *var, const std::vector< int > &value, bool active, std::vector< int > *assignment_indices, int64_t index, Assignment *assignment) const
void SetBackwardSequence(int64_t index, const std::vector< int > &value)
void SetForwardSequence(int64_t index, const std::vector< int > &value)
const std::vector< int > & Sequence(int64_t index) const
Returns the value in the current assignment of the variable of given index.
SequenceVarLocalSearchOperator(const std::vector< SequenceVar * > &vars)
const std::vector< int > & OldSequence(int64_t index) const
This iterator is not stable with respect to deletion.
This class represent a reversible FIFO structure.
void SetLastValue(const T &v)
Sets the last value in the FIFO.
const T * Last() const
Returns the last item of the FIFO.
const T & LastValue() const
Returns the last value in the FIFO.
void PushIfNotTop(Solver *const s, T val)
Pushes the var on top if is not a duplicate of the current top object.
void Push(Solver *const s, T val)
This class represents a small reversible bitset (size <= 64).
bool IsCardinalityOne() const
Does it contains only one bit set?
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:48
void SetToZero(Solver *const solver, int64_t pos)
Erases the 'pos' bit.
Definition: utilities.cc:43
bool IsCardinalityZero() const
Is bitset null?
int64_t GetFirstOne() const
Gets the index of the first bit set starting from 0.
Definition: utilities.cc:52
void SetToOne(Solver *const solver, int64_t pos)
Sets the 'pos' bit.
Definition: utilities.cc:38
DemonPriority
This enum represents the three possible priorities for a demon in the Solver queue.
@ DELAYED_PRIORITY
DELAYED_PRIORITY is the lowest priority: Demons will be processed after VAR_PRIORITY and NORMAL_PRIOR...
void SaveAndSetValue(T *adr, T val)
All-in-one SaveAndSetValue.
T * RevAlloc(T *object)
Registers the given object as being reversible.
void Set(IntegerType index)
Definition: bitset.h:809
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
Definition: bitset.h:819
void ClearAndResize(IntegerType size)
Definition: bitset.h:784
A symmetry breaker is an object that will visit a decision and create the 'symmetrical' decision in r...
This class represents a reversible bitset.
int64_t word_size() const
Returns the number of 64 bit words used to store the bitset.
int64_t bit_size() const
Returns the number of bits given in the constructor of the bitset.
const RevIntSet< int > & active_words() const
Returns the set of active word indices.
bool Empty() const
This method returns true if the active bitset is null.
int ActiveWordSize() const
This method returns the number of non null 64 bit words in the bitset representation.
Base operator class for operators manipulating variables.
virtual bool SkipUnchanged(int index) const
void SetValue(int64_t index, const Val &value)
const Val & Value(int64_t index) const
Returns the value in the current assignment of the variable of given index.
const Val & OldValue(int64_t index) const
V * Var(int64_t index) const
Returns the variable of given index.
bool ApplyChanges(Assignment *delta, Assignment *deltadelta) const
virtual void OnStart()
Called by Start() after synchronizing the operator with the current assignment.
void MarkChange(int64_t index)
OnStart() should really be protected, but then SWIG doesn't see it.
void AddVars(const std::vector< V * > &vars)
void Start(const Assignment *assignment) override
This method should not be overridden.
int64_t a
std::vector< int64_t > to_remove_
Block * next
SharedBoundsManager * bounds
const std::string name
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GurobiMPCallbackContext * context
static const int64_t kint64max
static const int64_t kint64min
const int64_t offset_
Definition: interval.cc:2108
int index
RowIndex row
Definition: markowitz.cc:182
int64_t hash
Definition: matrix_utils.cc:61
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1683
Collection of objects used to extend the Constraint Solver library.
std::string ParameterDebugString(P param)
bool IsArrayConstant(const std::vector< T > &values, const T &value)
bool AreAllLessOrEqual(const std::vector< T > &values, const T &value)
LocalSearchOperator * MakeLocalSearchOperator(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class)
Operator Factories.
LocalSearchFilter * MakeUnaryDimensionFilter(Solver *solver, std::unique_ptr< UnaryDimensionChecker > checker, const std::string &dimension_name)
Demon * MakeConstraintDemon3(Solver *const s, T *const ct, void(T::*method)(P, Q, R), const std::string &name, P param1, Q param2, R param3)
bool AreAllNegative(const std::vector< T > &values)
bool AreAllGreaterOrEqual(const std::vector< T > &values, const T &value)
bool IsIncreasing(const std::vector< T > &values)
bool AreAllStrictlyPositive(const std::vector< T > &values)
bool IsArrayBoolean(const std::vector< T > &values)
VarTypes
This enum is used internally to do dynamic typing on subclasses of integer variables.
bool AreAllBoundOrNull(const std::vector< IntVar * > &vars, const std::vector< T > &values)
Returns true if all the variables are assigned to a single value, or if their corresponding value is ...
int64_t MaxVarArray(const std::vector< IntVar * > &vars)
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)
bool AreAllBoundTo(const std::vector< IntVar * > &vars, int64_t value)
Returns true if all variables are assigned to 'value'.
void FillValues(const std::vector< IntVar * > &vars, std::vector< int64_t > *const values)
bool AreAllBooleans(const std::vector< IntVar * > &vars)
bool AreAllStrictlyNegative(const std::vector< T > &values)
int64_t MinVarArray(const std::vector< IntVar * > &vars)
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
bool IsIncreasingContiguous(const std::vector< T > &values)
bool AreAllNull(const std::vector< T > &values)
bool AreAllPositive(const std::vector< T > &values)
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:828
Demon * MakeDelayedConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
VarLocalSearchOperator< SequenceVar, std::vector< int >, SequenceVarLocalSearchHandler > SequenceVarLocalSearchOperatorTemplate
int64_t PosIntDivDown(int64_t e, int64_t v)
bool IsArrayInRange(const std::vector< IntVar * > &vars, T range_min, T range_max)
static const int kUnassigned
Definition: routing.cc:878
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
LocalSearchFilter * MakePathStateFilter(Solver *solver, std::unique_ptr< PathState > path_state, const std::vector< IntVar * > &nexts)
bool AreAllOnes(const std::vector< T > &values)
bool AreAllBound(const std::vector< IntVar * > &vars)
uint64_t Hash1(uint64_t value)
Hash functions.
void AcceptUncheckedNeighbor(Search *const search)
int64_t PosIntDivUp(int64_t e, int64_t v)
static int input(yyscan_t yyscanner)
int64_t delta
Definition: resource.cc:1694
int64_t capacity
std::optional< int64_t > end
int64_t start
Set of parameters used to configure how the neighnorhood is traversed.
bool accept_path_end_base
True if path ends should be considered when iterating over neighbors.
int number_of_base_nodes
Number of nodes needed to define a neighbor.
std::function< int(int64_t)> start_empty_path_class
Callback returning an index such that if c1 = start_empty_path_class(StartNode(p1)),...
bool skip_locally_optimal_paths
Skip paths which have been proven locally optimal.
ChainBounds(int begin_index, int end_index)
const double constant