OR-Tools  9.1
constraint_solver.cc
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
14//
15// This file implements the core objects of the constraint solver:
16// Solver, Search, Queue, ... along with the main resolution loop.
17
19
20#include <csetjmp>
21#include <cstdint>
22#include <deque>
23#include <iosfwd>
24#include <limits>
25#include <memory>
26#include <string>
27#include <utility>
28
29#include "absl/memory/memory.h"
30#include "absl/time/clock.h"
31#include "absl/time/time.h"
33#include "ortools/base/file.h"
36#include "ortools/base/macros.h"
43#include "zlib.h"
44
45// These flags are used to set the fields in the DefaultSolverParameters proto.
46ABSL_FLAG(bool, cp_trace_propagation, false,
47 "Trace propagation events (constraint and demon executions,"
48 " variable modifications).");
49ABSL_FLAG(bool, cp_trace_search, false, "Trace search events");
50ABSL_FLAG(bool, cp_print_added_constraints, false,
51 "show all constraints added to the solver.");
52ABSL_FLAG(bool, cp_print_model, false,
53 "use PrintModelVisitor on model before solving.");
54ABSL_FLAG(bool, cp_model_stats, false,
55 "use StatisticsModelVisitor on model before solving.");
56ABSL_FLAG(bool, cp_disable_solve, false,
57 "Force failure at the beginning of a search.");
58ABSL_FLAG(std::string, cp_profile_file, "",
59 "Export profiling overview to file.");
60ABSL_FLAG(bool, cp_print_local_search_profile, false,
61 "Print local search profiling data after solving.");
62ABSL_FLAG(bool, cp_name_variables, false, "Force all variables to have names.");
63ABSL_FLAG(bool, cp_name_cast_variables, false,
64 "Name variables casted from expressions");
65ABSL_FLAG(bool, cp_use_small_table, true,
66 "Use small compact table constraint when possible.");
67ABSL_FLAG(bool, cp_use_cumulative_edge_finder, true,
68 "Use the O(n log n) cumulative edge finding algorithm described "
69 "in 'Edge Finding Filtering Algorithm for Discrete Cumulative "
70 "Resources in O(kn log n)' by Petr Vilim, CP 2009.");
71ABSL_FLAG(bool, cp_use_cumulative_time_table, true,
72 "Use a O(n^2) cumulative time table propagation algorithm.");
73ABSL_FLAG(bool, cp_use_cumulative_time_table_sync, false,
74 "Use a synchronized O(n^2 log n) cumulative time table propagation "
75 "algorithm.");
76ABSL_FLAG(bool, cp_use_sequence_high_demand_tasks, true,
77 "Use a sequence constraints for cumulative tasks that have a "
78 "demand greater than half of the capacity of the resource.");
79ABSL_FLAG(bool, cp_use_all_possible_disjunctions, true,
80 "Post temporal disjunctions for all pairs of tasks sharing a "
81 "cumulative resource and that cannot overlap because the sum of "
82 "their demand exceeds the capacity.");
83ABSL_FLAG(int, cp_max_edge_finder_size, 50,
84 "Do not post the edge finder in the cumulative constraints if "
85 "it contains more than this number of tasks");
86ABSL_FLAG(bool, cp_diffn_use_cumulative, true,
87 "Diffn constraint adds redundant cumulative constraint");
88ABSL_FLAG(bool, cp_use_element_rmq, true,
89 "If true, rmq's will be used in element expressions.");
90ABSL_FLAG(int, cp_check_solution_period, 1,
91 "Number of solutions explored between two solution checks during "
92 "local search.");
93ABSL_FLAG(int64_t, cp_random_seed, 12345,
94 "Random seed used in several (but not all) random number "
95 "generators used by the CP solver. Use -1 to auto-generate an"
96 "undeterministic random seed.");
97
98void ConstraintSolverFailsHere() { VLOG(3) << "Fail"; }
99
100#if defined(_MSC_VER) // WINDOWS
101#pragma warning(disable : 4351 4355)
102#endif
103
104namespace operations_research {
105
106namespace {
107// Calls the given method with the provided arguments on all objects in the
108// collection.
109template <typename T, typename MethodPointer, typename... Args>
110void ForAll(const std::vector<T*>& objects, MethodPointer method,
111 const Args&... args) {
112 for (T* const object : objects) {
113 DCHECK(object != nullptr);
114 (object->*method)(args...);
115 }
116}
117} // namespace
118
119// ----- ConstraintSolverParameters -----
120
124 params.set_trail_block_size(8000);
125 params.set_array_split_size(16);
126 params.set_store_names(true);
127 params.set_profile_propagation(!absl::GetFlag(FLAGS_cp_profile_file).empty());
128 params.set_trace_propagation(absl::GetFlag(FLAGS_cp_trace_propagation));
129 params.set_trace_search(absl::GetFlag(FLAGS_cp_trace_search));
130 params.set_name_all_variables(absl::GetFlag(FLAGS_cp_name_variables));
131 params.set_profile_file(absl::GetFlag(FLAGS_cp_profile_file));
133 absl::GetFlag(FLAGS_cp_print_local_search_profile));
135 absl::GetFlag(FLAGS_cp_print_local_search_profile));
136 params.set_print_model(absl::GetFlag(FLAGS_cp_print_model));
137 params.set_print_model_stats(absl::GetFlag(FLAGS_cp_model_stats));
138 params.set_disable_solve(absl::GetFlag(FLAGS_cp_disable_solve));
139 params.set_name_cast_variables(absl::GetFlag(FLAGS_cp_name_cast_variables));
141 absl::GetFlag(FLAGS_cp_print_added_constraints));
142 params.set_use_small_table(absl::GetFlag(FLAGS_cp_use_small_table));
144 absl::GetFlag(FLAGS_cp_use_cumulative_edge_finder));
146 absl::GetFlag(FLAGS_cp_use_cumulative_time_table));
148 absl::GetFlag(FLAGS_cp_use_cumulative_time_table_sync));
150 absl::GetFlag(FLAGS_cp_use_sequence_high_demand_tasks));
152 absl::GetFlag(FLAGS_cp_use_all_possible_disjunctions));
153 params.set_max_edge_finder_size(absl::GetFlag(FLAGS_cp_max_edge_finder_size));
154 params.set_diffn_use_cumulative(absl::GetFlag(FLAGS_cp_diffn_use_cumulative));
155 params.set_use_element_rmq(absl::GetFlag(FLAGS_cp_use_element_rmq));
157 absl::GetFlag(FLAGS_cp_check_solution_period));
158 return params;
159}
160
161// ----- Forward Declarations and Profiling Support -----
162extern DemonProfiler* BuildDemonProfiler(Solver* const solver);
163extern void DeleteDemonProfiler(DemonProfiler* const monitor);
164extern void InstallDemonProfiler(DemonProfiler* const monitor);
168
169// TODO(user): remove this complex logic.
170// We need the double test because parameters are set too late when using
171// python in the open source. This is the cheapest work-around.
174}
175
177 return parameters_.profile_propagation() ||
178 !parameters_.profile_file().empty();
179}
180
182 return parameters_.profile_local_search() ||
183 parameters_.print_local_search_profile();
184}
185
187 return parameters_.trace_propagation();
188}
189
191 return parameters_.name_all_variables();
192}
193
194// ------------------ Demon class ----------------
195
198}
199
200std::string Demon::DebugString() const { return "Demon"; }
201
202void Demon::inhibit(Solver* const s) {
203 if (stamp_ < std::numeric_limits<uint64_t>::max()) {
205 }
206}
207
208void Demon::desinhibit(Solver* const s) {
209 if (stamp_ == std::numeric_limits<uint64_t>::max()) {
210 s->SaveAndSetValue(&stamp_, s->stamp() - 1);
211 }
212}
213
214// ------------------ Queue class ------------------
215
216extern void CleanVariableOnFail(IntVar* const var);
217
218class Queue {
219 public:
220 static constexpr int64_t kTestPeriod = 10000;
221
222 explicit Queue(Solver* const s)
223 : solver_(s),
224 stamp_(1),
225 freeze_level_(0),
226 in_process_(false),
227 clean_action_(nullptr),
228 clean_variable_(nullptr),
229 in_add_(false),
230 instruments_demons_(s->InstrumentsDemons()) {}
231
233
234 void Freeze() {
235 freeze_level_++;
236 stamp_++;
237 }
238
239 void Unfreeze() {
240 if (--freeze_level_ == 0) {
241 Process();
242 }
243 }
244
245 void ProcessOneDemon(Demon* const demon) {
246 demon->set_stamp(stamp_ - 1);
247 if (!instruments_demons_) {
248 if (++solver_->demon_runs_[demon->priority()] % kTestPeriod == 0) {
249 solver_->TopPeriodicCheck();
250 }
251 demon->Run(solver_);
252 solver_->CheckFail();
253 } else {
254 solver_->GetPropagationMonitor()->BeginDemonRun(demon);
255 if (++solver_->demon_runs_[demon->priority()] % kTestPeriod == 0) {
256 solver_->TopPeriodicCheck();
257 }
258 demon->Run(solver_);
259 solver_->CheckFail();
260 solver_->GetPropagationMonitor()->EndDemonRun(demon);
261 }
262 }
263
264 void Process() {
265 if (!in_process_) {
266 in_process_ = true;
267 while (!var_queue_.empty() || !delayed_queue_.empty()) {
268 if (!var_queue_.empty()) {
269 Demon* const demon = var_queue_.front();
270 var_queue_.pop_front();
271 ProcessOneDemon(demon);
272 } else {
273 DCHECK(!delayed_queue_.empty());
274 Demon* const demon = delayed_queue_.front();
275 delayed_queue_.pop_front();
276 ProcessOneDemon(demon);
277 }
278 }
279 in_process_ = false;
280 }
281 }
282
283 void ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
284 if (!instruments_demons_) {
285 for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
286 Demon* const demon = *it;
287 if (demon->stamp() < stamp_) {
289 if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % kTestPeriod ==
290 0) {
291 solver_->TopPeriodicCheck();
292 }
293 demon->Run(solver_);
294 solver_->CheckFail();
295 }
296 }
297 } else {
298 for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
299 Demon* const demon = *it;
300 if (demon->stamp() < stamp_) {
302 solver_->GetPropagationMonitor()->BeginDemonRun(demon);
303 if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % kTestPeriod ==
304 0) {
305 solver_->TopPeriodicCheck();
306 }
307 demon->Run(solver_);
308 solver_->CheckFail();
309 solver_->GetPropagationMonitor()->EndDemonRun(demon);
310 }
311 }
312 }
313 }
314
315 void EnqueueAll(const SimpleRevFIFO<Demon*>& demons) {
316 for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
318 }
319 }
320
321 void EnqueueVar(Demon* const demon) {
323 if (demon->stamp() < stamp_) {
324 demon->set_stamp(stamp_);
325 var_queue_.push_back(demon);
326 if (freeze_level_ == 0) {
327 Process();
328 }
329 }
330 }
331
332 void EnqueueDelayedDemon(Demon* const demon) {
334 if (demon->stamp() < stamp_) {
335 demon->set_stamp(stamp_);
336 delayed_queue_.push_back(demon);
337 }
338 }
339
341 // Clean queue.
342 var_queue_.clear();
343 delayed_queue_.clear();
344
345 // Call cleaning actions on variables.
346 if (clean_action_ != nullptr) {
347 clean_action_(solver_);
348 clean_action_ = nullptr;
349 } else if (clean_variable_ != nullptr) {
350 CleanVariableOnFail(clean_variable_);
351 clean_variable_ = nullptr;
352 }
353
354 freeze_level_ = 0;
355 in_process_ = false;
356 in_add_ = false;
357 to_add_.clear();
358 }
359
360 void increase_stamp() { stamp_++; }
361
362 uint64_t stamp() const { return stamp_; }
363
365 DCHECK(clean_variable_ == nullptr);
366 clean_action_ = std::move(a);
367 }
368
370 DCHECK(clean_action_ == nullptr);
371 clean_variable_ = var;
372 }
373
375 DCHECK(clean_variable_ == nullptr);
376 clean_action_ = nullptr;
377 }
378
379 void AddConstraint(Constraint* const c) {
380 to_add_.push_back(c);
382 }
383
385 if (!in_add_) {
386 in_add_ = true;
387 // We cannot store to_add_.size() as constraints can add other
388 // constraints. For the same reason a range-based for loop cannot be used.
389 // TODO(user): Make to_add_ a queue to make the behavior more obvious.
390 for (int counter = 0; counter < to_add_.size(); ++counter) {
391 Constraint* const constraint = to_add_[counter];
392 // TODO(user): Add profiling to initial propagation
393 constraint->PostAndPropagate();
394 }
395 in_add_ = false;
396 to_add_.clear();
397 }
398 }
399
400 private:
401 Solver* const solver_;
402 std::deque<Demon*> var_queue_;
403 std::deque<Demon*> delayed_queue_;
404 uint64_t stamp_;
405 // The number of nested freeze levels. The queue is frozen if and only if
406 // freeze_level_ > 0.
407 uint32_t freeze_level_;
408 bool in_process_;
409 Solver::Action clean_action_;
410 IntVar* clean_variable_;
411 std::vector<Constraint*> to_add_;
412 bool in_add_;
413 const bool instruments_demons_;
414};
415
416// ------------------ StateMarker / StateInfo struct -----------
417
418struct StateInfo { // This is an internal structure to store
419 // additional information on the choice point.
420 public:
422 : ptr_info(nullptr),
423 int_info(0),
424 depth(0),
425 left_depth(0),
426 reversible_action(nullptr) {}
427 StateInfo(void* pinfo, int iinfo)
428 : ptr_info(pinfo),
429 int_info(iinfo),
430 depth(0),
431 left_depth(0),
432 reversible_action(nullptr) {}
433 StateInfo(void* pinfo, int iinfo, int d, int ld)
434 : ptr_info(pinfo),
435 int_info(iinfo),
436 depth(d),
437 left_depth(ld),
438 reversible_action(nullptr) {}
440 : ptr_info(nullptr),
441 int_info(static_cast<int>(fast)),
442 depth(0),
443 left_depth(0),
444 reversible_action(std::move(a)) {}
445
446 void* ptr_info;
448 int depth;
451};
452
454 public:
456 friend class Solver;
457 friend struct Trail;
458
459 private:
460 Solver::MarkerType type_;
461 int rev_int_index_;
462 int rev_int64_index_;
463 int rev_uint64_index_;
464 int rev_double_index_;
465 int rev_ptr_index_;
466 int rev_boolvar_list_index_;
467 int rev_bools_index_;
468 int rev_int_memory_index_;
469 int rev_int64_memory_index_;
470 int rev_double_memory_index_;
471 int rev_object_memory_index_;
472 int rev_object_array_memory_index_;
473 int rev_memory_index_;
474 int rev_memory_array_index_;
475 StateInfo info_;
476};
477
479 : type_(t),
480 rev_int_index_(0),
481 rev_int64_index_(0),
482 rev_uint64_index_(0),
483 rev_double_index_(0),
484 rev_ptr_index_(0),
485 rev_boolvar_list_index_(0),
486 rev_bools_index_(0),
487 rev_int_memory_index_(0),
488 rev_int64_memory_index_(0),
489 rev_double_memory_index_(0),
490 rev_object_memory_index_(0),
491 rev_object_array_memory_index_(0),
492 info_(info) {}
493
494// ---------- Trail and Reversibility ----------
495
496namespace {
497// ----- addrval struct -----
498
499// This template class is used internally to implement reversibility.
500// It stores an address and the value that was at the address.
501template <class T>
502struct addrval {
503 public:
504 addrval() : address_(nullptr) {}
505 explicit addrval(T* adr) : address_(adr), old_value_(*adr) {}
506 void restore() const { (*address_) = old_value_; }
507
508 private:
509 T* address_;
510 T old_value_;
511};
512
513// ----- Compressed trail -----
514
515// ---------- Trail Packer ---------
516// Abstract class to pack trail blocks.
517
518template <class T>
519class TrailPacker {
520 public:
521 explicit TrailPacker(int block_size) : block_size_(block_size) {}
522 virtual ~TrailPacker() {}
523 int input_size() const { return block_size_ * sizeof(addrval<T>); }
524 virtual void Pack(const addrval<T>* block, std::string* packed_block) = 0;
525 virtual void Unpack(const std::string& packed_block, addrval<T>* block) = 0;
526
527 private:
528 const int block_size_;
529 DISALLOW_COPY_AND_ASSIGN(TrailPacker);
530};
531
532template <class T>
533class NoCompressionTrailPacker : public TrailPacker<T> {
534 public:
535 explicit NoCompressionTrailPacker(int block_size)
536 : TrailPacker<T>(block_size) {}
537 ~NoCompressionTrailPacker() override {}
538 void Pack(const addrval<T>* block, std::string* packed_block) override {
539 DCHECK(block != nullptr);
540 DCHECK(packed_block != nullptr);
541 absl::string_view block_str(reinterpret_cast<const char*>(block),
542 this->input_size());
543 packed_block->assign(block_str.data(), block_str.size());
544 }
545 void Unpack(const std::string& packed_block, addrval<T>* block) override {
546 DCHECK(block != nullptr);
547 memcpy(block, packed_block.c_str(), packed_block.size());
548 }
549
550 private:
551 DISALLOW_COPY_AND_ASSIGN(NoCompressionTrailPacker<T>);
552};
553
554template <class T>
555class ZlibTrailPacker : public TrailPacker<T> {
556 public:
557 explicit ZlibTrailPacker(int block_size)
558 : TrailPacker<T>(block_size),
559 tmp_size_(compressBound(this->input_size())),
560 tmp_block_(new char[tmp_size_]) {}
561
562 ~ZlibTrailPacker() override {}
563
564 void Pack(const addrval<T>* block, std::string* packed_block) override {
565 DCHECK(block != nullptr);
566 DCHECK(packed_block != nullptr);
567 uLongf size = tmp_size_;
568 const int result =
569 compress(reinterpret_cast<Bytef*>(tmp_block_.get()), &size,
570 reinterpret_cast<const Bytef*>(block), this->input_size());
571 CHECK_EQ(Z_OK, result);
572 absl::string_view block_str;
573 block_str = absl::string_view(tmp_block_.get(), size);
574 packed_block->assign(block_str.data(), block_str.size());
575 }
576
577 void Unpack(const std::string& packed_block, addrval<T>* block) override {
578 DCHECK(block != nullptr);
579 uLongf size = this->input_size();
580 const int result =
581 uncompress(reinterpret_cast<Bytef*>(block), &size,
582 reinterpret_cast<const Bytef*>(packed_block.c_str()),
583 packed_block.size());
584 CHECK_EQ(Z_OK, result);
585 }
586
587 private:
588 const uint64_t tmp_size_;
589 std::unique_ptr<char[]> tmp_block_;
590 DISALLOW_COPY_AND_ASSIGN(ZlibTrailPacker<T>);
591};
592
593template <class T>
594class CompressedTrail {
595 public:
596 CompressedTrail(
597 int block_size,
599 : block_size_(block_size),
600 blocks_(nullptr),
601 free_blocks_(nullptr),
602 data_(new addrval<T>[block_size]),
603 buffer_(new addrval<T>[block_size]),
604 buffer_used_(false),
605 current_(0),
606 size_(0) {
607 switch (compression_level) {
609 packer_.reset(new NoCompressionTrailPacker<T>(block_size));
610 break;
611 }
613 packer_.reset(new ZlibTrailPacker<T>(block_size));
614 break;
615 }
616 default: {
617 LOG(ERROR) << "Should not be here";
618 }
619 }
620
621 // We zero all memory used by addrval arrays.
622 // Because of padding, all bytes may not be initialized, while compression
623 // will read them all, even if the uninitialized bytes are never used.
624 // This makes valgrind happy.
625
626 memset(data_.get(), 0, sizeof(*data_.get()) * block_size);
627 memset(buffer_.get(), 0, sizeof(*buffer_.get()) * block_size);
628 }
629 ~CompressedTrail() {
630 FreeBlocks(blocks_);
631 FreeBlocks(free_blocks_);
632 }
633 const addrval<T>& Back() const {
634 // Back of empty trail.
636 return data_[current_ - 1];
637 }
638 void PopBack() {
639 if (size_ > 0) {
640 --current_;
641 if (current_ <= 0) {
642 if (buffer_used_) {
643 data_.swap(buffer_);
644 current_ = block_size_;
645 buffer_used_ = false;
646 } else if (blocks_ != nullptr) {
647 packer_->Unpack(blocks_->compressed, data_.get());
648 FreeTopBlock();
649 current_ = block_size_;
650 }
651 }
652 --size_;
653 }
654 }
655 void PushBack(const addrval<T>& addr_val) {
656 if (current_ >= block_size_) {
657 if (buffer_used_) { // Buffer is used.
658 NewTopBlock();
659 packer_->Pack(buffer_.get(), &blocks_->compressed);
660 // O(1) operation.
661 data_.swap(buffer_);
662 } else {
663 data_.swap(buffer_);
664 buffer_used_ = true;
665 }
666 current_ = 0;
667 }
668 data_[current_] = addr_val;
669 ++current_;
670 ++size_;
671 }
672 int64_t size() const { return size_; }
673
674 private:
675 struct Block {
676 std::string compressed;
677 Block* next;
678 };
679
680 void FreeTopBlock() {
681 Block* block = blocks_;
682 blocks_ = block->next;
683 block->compressed.clear();
684 block->next = free_blocks_;
685 free_blocks_ = block;
686 }
687 void NewTopBlock() {
688 Block* block = nullptr;
689 if (free_blocks_ != nullptr) {
690 block = free_blocks_;
691 free_blocks_ = block->next;
692 } else {
693 block = new Block;
694 }
695 block->next = blocks_;
696 blocks_ = block;
697 }
698 void FreeBlocks(Block* blocks) {
699 while (nullptr != blocks) {
700 Block* next = blocks->next;
701 delete blocks;
702 blocks = next;
703 }
704 }
705
706 std::unique_ptr<TrailPacker<T> > packer_;
707 const int block_size_;
708 Block* blocks_;
709 Block* free_blocks_;
710 std::unique_ptr<addrval<T>[]> data_;
711 std::unique_ptr<addrval<T>[]> buffer_;
712 bool buffer_used_;
713 int current_;
714 int size_;
715};
716} // namespace
717
718// ----- Trail -----
719
720// Object are explicitly copied using the copy ctor instead of
721// passing and storing a pointer. As objects are small, copying is
722// much faster than allocating (around 35% on a complete solve).
723
724extern void RestoreBoolValue(IntVar* const var);
725
726struct Trail {
727 CompressedTrail<int> rev_ints_;
728 CompressedTrail<int64_t> rev_int64s_;
729 CompressedTrail<uint64_t> rev_uint64s_;
730 CompressedTrail<double> rev_doubles_;
731 CompressedTrail<void*> rev_ptrs_;
732 std::vector<IntVar*> rev_boolvar_list_;
733 std::vector<bool*> rev_bools_;
734 std::vector<bool> rev_bool_value_;
735 std::vector<int*> rev_int_memory_;
736 std::vector<int64_t*> rev_int64_memory_;
737 std::vector<double*> rev_double_memory_;
738 std::vector<BaseObject*> rev_object_memory_;
739 std::vector<BaseObject**> rev_object_array_memory_;
740 std::vector<void*> rev_memory_;
741 std::vector<void**> rev_memory_array_;
742
743 Trail(int block_size,
745 : rev_ints_(block_size, compression_level),
746 rev_int64s_(block_size, compression_level),
747 rev_uint64s_(block_size, compression_level),
748 rev_doubles_(block_size, compression_level),
749 rev_ptrs_(block_size, compression_level) {}
750
752 int target = m->rev_int_index_;
753 for (int curr = rev_ints_.size(); curr > target; --curr) {
754 const addrval<int>& cell = rev_ints_.Back();
755 cell.restore();
756 rev_ints_.PopBack();
757 }
758 DCHECK_EQ(rev_ints_.size(), target);
759 // Incorrect trail size after backtrack.
760 target = m->rev_int64_index_;
761 for (int curr = rev_int64s_.size(); curr > target; --curr) {
762 const addrval<int64_t>& cell = rev_int64s_.Back();
763 cell.restore();
764 rev_int64s_.PopBack();
765 }
766 DCHECK_EQ(rev_int64s_.size(), target);
767 // Incorrect trail size after backtrack.
768 target = m->rev_uint64_index_;
769 for (int curr = rev_uint64s_.size(); curr > target; --curr) {
770 const addrval<uint64_t>& cell = rev_uint64s_.Back();
771 cell.restore();
772 rev_uint64s_.PopBack();
773 }
774 DCHECK_EQ(rev_uint64s_.size(), target);
775 // Incorrect trail size after backtrack.
776 target = m->rev_double_index_;
777 for (int curr = rev_doubles_.size(); curr > target; --curr) {
778 const addrval<double>& cell = rev_doubles_.Back();
779 cell.restore();
780 rev_doubles_.PopBack();
781 }
782 DCHECK_EQ(rev_doubles_.size(), target);
783 // Incorrect trail size after backtrack.
784 target = m->rev_ptr_index_;
785 for (int curr = rev_ptrs_.size(); curr > target; --curr) {
786 const addrval<void*>& cell = rev_ptrs_.Back();
787 cell.restore();
788 rev_ptrs_.PopBack();
789 }
790 DCHECK_EQ(rev_ptrs_.size(), target);
791 // Incorrect trail size after backtrack.
792 target = m->rev_boolvar_list_index_;
793 for (int curr = rev_boolvar_list_.size() - 1; curr >= target; --curr) {
794 IntVar* const var = rev_boolvar_list_[curr];
796 }
797 rev_boolvar_list_.resize(target);
798
799 DCHECK_EQ(rev_bools_.size(), rev_bool_value_.size());
800 target = m->rev_bools_index_;
801 for (int curr = rev_bools_.size() - 1; curr >= target; --curr) {
802 *(rev_bools_[curr]) = rev_bool_value_[curr];
803 }
804 rev_bools_.resize(target);
805 rev_bool_value_.resize(target);
806
807 target = m->rev_int_memory_index_;
808 for (int curr = rev_int_memory_.size() - 1; curr >= target; --curr) {
809 delete[] rev_int_memory_[curr];
810 }
811 rev_int_memory_.resize(target);
812
813 target = m->rev_int64_memory_index_;
814 for (int curr = rev_int64_memory_.size() - 1; curr >= target; --curr) {
815 delete[] rev_int64_memory_[curr];
816 }
817 rev_int64_memory_.resize(target);
818
819 target = m->rev_double_memory_index_;
820 for (int curr = rev_double_memory_.size() - 1; curr >= target; --curr) {
821 delete[] rev_double_memory_[curr];
822 }
823 rev_double_memory_.resize(target);
824
825 target = m->rev_object_memory_index_;
826 for (int curr = rev_object_memory_.size() - 1; curr >= target; --curr) {
827 delete rev_object_memory_[curr];
828 }
829 rev_object_memory_.resize(target);
830
831 target = m->rev_object_array_memory_index_;
832 for (int curr = rev_object_array_memory_.size() - 1; curr >= target;
833 --curr) {
834 delete[] rev_object_array_memory_[curr];
835 }
836 rev_object_array_memory_.resize(target);
837
838 target = m->rev_memory_index_;
839 for (int curr = rev_memory_.size() - 1; curr >= target; --curr) {
840 // Explicitly call unsized delete
841 ::operator delete(reinterpret_cast<char*>(rev_memory_[curr]));
842 // The previous cast is necessary to deallocate generic memory
843 // described by a void* when passed to the RevAlloc procedure
844 // We cannot do a delete[] there
845 // This is useful for cells of RevFIFO and should not be used outside
846 // of the product
847 }
848 rev_memory_.resize(target);
849
850 target = m->rev_memory_array_index_;
851 for (int curr = rev_memory_array_.size() - 1; curr >= target; --curr) {
852 delete[] rev_memory_array_[curr];
853 // delete [] version of the previous unsafe case.
854 }
855 rev_memory_array_.resize(target);
856 }
857};
858
859void Solver::InternalSaveValue(int* valptr) {
860 trail_->rev_ints_.PushBack(addrval<int>(valptr));
861}
862
863void Solver::InternalSaveValue(int64_t* valptr) {
864 trail_->rev_int64s_.PushBack(addrval<int64_t>(valptr));
865}
866
867void Solver::InternalSaveValue(uint64_t* valptr) {
868 trail_->rev_uint64s_.PushBack(addrval<uint64_t>(valptr));
869}
870
871void Solver::InternalSaveValue(double* valptr) {
872 trail_->rev_doubles_.PushBack(addrval<double>(valptr));
873}
874
875void Solver::InternalSaveValue(void** valptr) {
876 trail_->rev_ptrs_.PushBack(addrval<void*>(valptr));
877}
878
879// TODO(user) : this code is unsafe if you save the same alternating
880// bool multiple times.
881// The correct code should use a bitset and a single list.
882void Solver::InternalSaveValue(bool* valptr) {
883 trail_->rev_bools_.push_back(valptr);
884 trail_->rev_bool_value_.push_back(*valptr);
885}
886
887BaseObject* Solver::SafeRevAlloc(BaseObject* ptr) {
888 check_alloc_state();
889 trail_->rev_object_memory_.push_back(ptr);
890 return ptr;
891}
892
893int* Solver::SafeRevAllocArray(int* ptr) {
894 check_alloc_state();
895 trail_->rev_int_memory_.push_back(ptr);
896 return ptr;
897}
898
899int64_t* Solver::SafeRevAllocArray(int64_t* ptr) {
900 check_alloc_state();
901 trail_->rev_int64_memory_.push_back(ptr);
902 return ptr;
903}
904
905double* Solver::SafeRevAllocArray(double* ptr) {
906 check_alloc_state();
907 trail_->rev_double_memory_.push_back(ptr);
908 return ptr;
909}
910
911uint64_t* Solver::SafeRevAllocArray(uint64_t* ptr) {
912 check_alloc_state();
913 trail_->rev_int64_memory_.push_back(reinterpret_cast<int64_t*>(ptr));
914 return ptr;
915}
916
917BaseObject** Solver::SafeRevAllocArray(BaseObject** ptr) {
918 check_alloc_state();
919 trail_->rev_object_array_memory_.push_back(ptr);
920 return ptr;
921}
922
923IntVar** Solver::SafeRevAllocArray(IntVar** ptr) {
924 BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
925 return reinterpret_cast<IntVar**>(in);
926}
927
928IntExpr** Solver::SafeRevAllocArray(IntExpr** ptr) {
929 BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
930 return reinterpret_cast<IntExpr**>(in);
931}
932
933Constraint** Solver::SafeRevAllocArray(Constraint** ptr) {
934 BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
935 return reinterpret_cast<Constraint**>(in);
936}
937
938void* Solver::UnsafeRevAllocAux(void* ptr) {
939 check_alloc_state();
940 trail_->rev_memory_.push_back(ptr);
941 return ptr;
942}
943
944void** Solver::UnsafeRevAllocArrayAux(void** ptr) {
945 check_alloc_state();
946 trail_->rev_memory_array_.push_back(ptr);
947 return ptr;
948}
949
950void InternalSaveBooleanVarValue(Solver* const solver, IntVar* const var) {
951 solver->trail_->rev_boolvar_list_.push_back(var);
952}
953
954// ------------------ Search class -----------------
955
956class Search {
957 public:
958 explicit Search(Solver* const s)
959 : solver_(s),
960 marker_stack_(),
961 fail_buffer_(),
962 solution_counter_(0),
963 unchecked_solution_counter_(0),
964 decision_builder_(nullptr),
965 created_by_solve_(false),
966 search_depth_(0),
967 left_search_depth_(0),
968 should_restart_(false),
969 should_finish_(false),
970 sentinel_pushed_(0),
971 jmpbuf_filled_(false),
972 backtrack_at_the_end_of_the_search_(true) {}
973
974 // Constructor for a dummy search. The only difference between a dummy search
975 // and a regular one is that the search depth and left search depth is
976 // initialized to -1 instead of zero.
977 Search(Solver* const s, int /* dummy_argument */)
978 : solver_(s),
979 marker_stack_(),
980 fail_buffer_(),
981 solution_counter_(0),
982 unchecked_solution_counter_(0),
983 decision_builder_(nullptr),
984 created_by_solve_(false),
985 search_depth_(-1),
986 left_search_depth_(-1),
987 should_restart_(false),
988 should_finish_(false),
989 sentinel_pushed_(0),
990 jmpbuf_filled_(false),
991 backtrack_at_the_end_of_the_search_(true) {}
992
993 ~Search() { gtl::STLDeleteElements(&marker_stack_); }
994
995 void EnterSearch();
996 void RestartSearch();
997 void ExitSearch();
998 void BeginNextDecision(DecisionBuilder* const db);
999 void EndNextDecision(DecisionBuilder* const db, Decision* const d);
1000 void ApplyDecision(Decision* const d);
1001 void AfterDecision(Decision* const d, bool apply);
1002 void RefuteDecision(Decision* const d);
1003 void BeginFail();
1004 void EndFail();
1006 void EndInitialPropagation();
1007 bool AtSolution();
1008 bool AcceptSolution();
1009 void NoMoreSolutions();
1010 bool LocalOptimum();
1011 bool AcceptDelta(Assignment* delta, Assignment* deltadelta);
1012 void AcceptNeighbor();
1015 void PeriodicCheck();
1016 int ProgressPercent();
1017 void Accept(ModelVisitor* const visitor) const;
1018 void push_monitor(SearchMonitor* const m);
1019 void Clear();
1020 void IncrementSolutionCounter() { ++solution_counter_; }
1021 int64_t solution_counter() const { return solution_counter_; }
1022 void IncrementUncheckedSolutionCounter() { ++unchecked_solution_counter_; }
1024 return unchecked_solution_counter_;
1025 }
1027 decision_builder_ = db;
1028 }
1029 DecisionBuilder* decision_builder() const { return decision_builder_; }
1030 void set_created_by_solve(bool c) { created_by_solve_ = c; }
1031 bool created_by_solve() const { return created_by_solve_; }
1034 void LeftMove() {
1035 search_depth_++;
1036 left_search_depth_++;
1037 }
1038 void RightMove() { search_depth_++; }
1040 return backtrack_at_the_end_of_the_search_;
1041 }
1043 backtrack_at_the_end_of_the_search_ = restore;
1044 }
1045 int search_depth() const { return search_depth_; }
1046 void set_search_depth(int d) { search_depth_ = d; }
1047 int left_search_depth() const { return left_search_depth_; }
1048 void set_search_left_depth(int d) { left_search_depth_ = d; }
1049 void set_should_restart(bool s) { should_restart_ = s; }
1050 bool should_restart() const { return should_restart_; }
1051 void set_should_finish(bool s) { should_finish_ = s; }
1052 bool should_finish() const { return should_finish_; }
1053 void CheckFail() {
1054 if (should_finish_ || should_restart_) {
1055 solver_->Fail();
1056 }
1057 }
1058 void set_search_context(const std::string& search_context) {
1059 search_context_ = search_context;
1060 }
1061 std::string search_context() const { return search_context_; }
1062 friend class Solver;
1063
1064 private:
1065 // Jumps back to the previous choice point, Checks if it was correctly set.
1066 void JumpBack();
1067 void ClearBuffer() {
1068 CHECK(jmpbuf_filled_) << "Internal error in backtracking";
1069 jmpbuf_filled_ = false;
1070 }
1071
1072 Solver* const solver_;
1073 std::vector<StateMarker*> marker_stack_;
1074 std::vector<SearchMonitor*> monitors_;
1075 jmp_buf fail_buffer_;
1076 int64_t solution_counter_;
1077 int64_t unchecked_solution_counter_;
1078 DecisionBuilder* decision_builder_;
1079 bool created_by_solve_;
1081 int search_depth_;
1082 int left_search_depth_;
1083 bool should_restart_;
1084 bool should_finish_;
1085 int sentinel_pushed_;
1086 bool jmpbuf_filled_;
1087 bool backtrack_at_the_end_of_the_search_;
1088 std::string search_context_;
1089};
1090
1091// Backtrack is implemented using 3 primitives:
1092// CP_TRY to start searching
1093// CP_DO_FAIL to signal a failure. The program will continue on the CP_ON_FAIL
1094// primitive.
1095// Implementation of backtrack using setjmp/longjmp.
1096// The clean portable way is to use exceptions, unfortunately, it can be much
1097// slower. Thus we use ideas from Prolog, CP/CLP implementations,
1098// continuations in C and implement the default failing and backtracking
1099// using setjmp/longjmp. You can still use exceptions by defining
1100// CP_USE_EXCEPTIONS_FOR_BACKTRACK
1101#ifndef CP_USE_EXCEPTIONS_FOR_BACKTRACK
1102// We cannot use a method/function for this as we would lose the
1103// context in the setjmp implementation.
1104#define CP_TRY(search) \
1105 CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
1106 search->jmpbuf_filled_ = true; \
1107 if (setjmp(search->fail_buffer_) == 0)
1108#define CP_ON_FAIL else
1109#define CP_DO_FAIL(search) longjmp(search->fail_buffer_, 1)
1110#else // CP_USE_EXCEPTIONS_FOR_BACKTRACK
1111class FailException {};
1112#define CP_TRY(search) \
1113 CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
1114 search->jmpbuf_filled_ = true; \
1115 try
1116#define CP_ON_FAIL catch (FailException&)
1117#define CP_DO_FAIL(search) throw FailException()
1118#endif // CP_USE_EXCEPTIONS_FOR_BACKTRACK
1119
1120void Search::JumpBack() {
1121 if (jmpbuf_filled_) {
1122 jmpbuf_filled_ = false;
1123 CP_DO_FAIL(this);
1124 } else {
1125 std::string explanation = "Failure outside of search";
1126 solver_->AddConstraint(solver_->MakeFalseConstraint(explanation));
1127 }
1128}
1129
1130Search* Solver::ActiveSearch() const { return searches_.back(); }
1131
1132namespace {
1133class ApplyBranchSelector : public DecisionBuilder {
1134 public:
1135 explicit ApplyBranchSelector(Solver::BranchSelector bs)
1136 : selector_(std::move(bs)) {}
1137 ~ApplyBranchSelector() override {}
1138
1139 Decision* Next(Solver* const s) override {
1140 s->SetBranchSelector(selector_);
1141 return nullptr;
1142 }
1143
1144 std::string DebugString() const override { return "Apply(BranchSelector)"; }
1145
1146 private:
1148};
1149} // namespace
1150
1152 selector_ = std::move(bs);
1153}
1154
1156 // We cannot use the trail as the search can be nested and thus
1157 // deleted upon backtrack. Thus we guard the undo action by a
1158 // check on the number of nesting of solve().
1159 const int solve_depth = SolveDepth();
1161 [solve_depth](Solver* s) {
1162 if (s->SolveDepth() == solve_depth) {
1163 s->ActiveSearch()->SetBranchSelector(nullptr);
1164 }
1165 },
1166 false);
1167 searches_.back()->SetBranchSelector(std::move(bs));
1168}
1169
1171 return RevAlloc(new ApplyBranchSelector(std::move(bs)));
1172}
1173
1175 return state_ == OUTSIDE_SEARCH ? 0 : searches_.size() - 1;
1176}
1177
1178int Solver::SearchDepth() const { return searches_.back()->search_depth(); }
1179
1181 return searches_.back()->left_search_depth();
1182}
1183
1185 if (selector_ != nullptr) {
1186 return selector_();
1187 }
1188 return Solver::NO_CHANGE;
1189}
1190
1192 if (m) {
1193 monitors_.push_back(m);
1194 }
1195}
1196
1198 monitors_.clear();
1199 search_depth_ = 0;
1200 left_search_depth_ = 0;
1201 selector_ = nullptr;
1202 backtrack_at_the_end_of_the_search_ = true;
1203}
1204
1206 // The solution counter is reset when entering search and not when
1207 // leaving search. This enables the information to persist outside of
1208 // top-level search.
1209 solution_counter_ = 0;
1210 unchecked_solution_counter_ = 0;
1211
1212 ForAll(monitors_, &SearchMonitor::EnterSearch);
1213}
1214
1216 // Backtrack to the correct state.
1217 ForAll(monitors_, &SearchMonitor::ExitSearch);
1218}
1219
1221 ForAll(monitors_, &SearchMonitor::RestartSearch);
1222}
1223
1225 ForAll(monitors_, &SearchMonitor::BeginNextDecision, db);
1226 CheckFail();
1227}
1228
1230 ForAll(monitors_, &SearchMonitor::EndNextDecision, db, d);
1231 CheckFail();
1232}
1233
1235 ForAll(monitors_, &SearchMonitor::ApplyDecision, d);
1236 CheckFail();
1237}
1238
1239void Search::AfterDecision(Decision* const d, bool apply) {
1240 ForAll(monitors_, &SearchMonitor::AfterDecision, d, apply);
1241 CheckFail();
1242}
1243
1245 ForAll(monitors_, &SearchMonitor::RefuteDecision, d);
1246 CheckFail();
1247}
1248
1249void Search::BeginFail() { ForAll(monitors_, &SearchMonitor::BeginFail); }
1250
1251void Search::EndFail() { ForAll(monitors_, &SearchMonitor::EndFail); }
1252
1254 ForAll(monitors_, &SearchMonitor::BeginInitialPropagation);
1255}
1256
1258 ForAll(monitors_, &SearchMonitor::EndInitialPropagation);
1259}
1260
1262 bool valid = true;
1263 for (SearchMonitor* const monitor : monitors_) {
1264 if (!monitor->AcceptSolution()) {
1265 // Even though we know the return value, we cannot return yet: this would
1266 // break the contract we have with solution monitors. They all deserve
1267 // a chance to look at the solution.
1268 valid = false;
1269 }
1270 }
1271 return valid;
1272}
1273
1275 bool should_continue = false;
1276 for (SearchMonitor* const monitor : monitors_) {
1277 if (monitor->AtSolution()) {
1278 // Even though we know the return value, we cannot return yet: this would
1279 // break the contract we have with solution monitors. They all deserve
1280 // a chance to look at the solution.
1281 should_continue = true;
1282 }
1283 }
1284 return should_continue;
1285}
1286
1288 ForAll(monitors_, &SearchMonitor::NoMoreSolutions);
1289}
1290
1292 bool res = false;
1293 for (SearchMonitor* const monitor : monitors_) {
1294 if (monitor->LocalOptimum()) {
1295 res = true;
1296 }
1297 }
1298 return res;
1299}
1300
1302 bool accept = true;
1303 for (SearchMonitor* const monitor : monitors_) {
1304 if (!monitor->AcceptDelta(delta, deltadelta)) {
1305 accept = false;
1306 }
1307 }
1308 return accept;
1309}
1310
1312 ForAll(monitors_, &SearchMonitor::AcceptNeighbor);
1313}
1314
1316 ForAll(monitors_, &SearchMonitor::AcceptUncheckedNeighbor);
1317}
1318
1320 for (SearchMonitor* const monitor : monitors_) {
1321 if (monitor->IsUncheckedSolutionLimitReached()) {
1322 return true;
1323 }
1324 }
1325 return false;
1326}
1327
1329 ForAll(monitors_, &SearchMonitor::PeriodicCheck);
1330}
1331
1333 int progress = SearchMonitor::kNoProgress;
1334 for (SearchMonitor* const monitor : monitors_) {
1335 progress = std::max(progress, monitor->ProgressPercent());
1336 }
1337 return progress;
1338}
1339
1340void Search::Accept(ModelVisitor* const visitor) const {
1341 ForAll(monitors_, &SearchMonitor::Accept, visitor);
1342 if (decision_builder_ != nullptr) {
1343 decision_builder_->Accept(visitor);
1344 }
1345}
1346
1347bool LocalOptimumReached(Search* const search) {
1348 return search->LocalOptimum();
1349}
1350
1351bool AcceptDelta(Search* const search, Assignment* delta,
1352 Assignment* deltadelta) {
1353 return search->AcceptDelta(delta, deltadelta);
1354}
1355
1356void AcceptNeighbor(Search* const search) { search->AcceptNeighbor(); }
1357
1358void AcceptUncheckedNeighbor(Search* const search) {
1359 search->AcceptUncheckedNeighbor();
1360}
1361
1362namespace {
1363
1364// ---------- Fail Decision ----------
1365
1366class FailDecision : public Decision {
1367 public:
1368 void Apply(Solver* const s) override { s->Fail(); }
1369 void Refute(Solver* const s) override { s->Fail(); }
1370};
1371
1372// Balancing decision
1373
1374class BalancingDecision : public Decision {
1375 public:
1376 ~BalancingDecision() override {}
1377 void Apply(Solver* const s) override {}
1378 void Refute(Solver* const s) override {}
1379};
1380} // namespace
1381
1382Decision* Solver::MakeFailDecision() { return fail_decision_.get(); }
1383
1384// ------------------ Solver class -----------------
1385
1386// These magic numbers are there to make sure we pop the correct
1387// sentinels throughout the search.
1388namespace {
1389enum SentinelMarker {
1390 INITIAL_SEARCH_SENTINEL = 10000000,
1391 ROOT_NODE_SENTINEL = 20000000,
1392 SOLVER_CTOR_SENTINEL = 40000000
1393};
1394} // namespace
1395
1396extern PropagationMonitor* BuildTrace(Solver* const s);
1397extern LocalSearchMonitor* BuildLocalSearchMonitorMaster(Solver* const s);
1398extern ModelCache* BuildModelCache(Solver* const solver);
1399
1400std::string Solver::model_name() const { return name_; }
1401
1402namespace {
1403void CheckSolverParameters(const ConstraintSolverParameters& parameters) {
1404 CHECK_GT(parameters.array_split_size(), 0)
1405 << "Were parameters built using Solver::DefaultSolverParameters() ?";
1406}
1407} // namespace
1408
1409Solver::Solver(const std::string& name,
1411 : name_(name),
1412 parameters_(parameters),
1413 random_(CpRandomSeed()),
1414 demon_profiler_(BuildDemonProfiler(this)),
1415 use_fast_local_search_(true),
1416 local_search_profiler_(BuildLocalSearchProfiler(this)) {
1417 Init();
1418}
1419
1420Solver::Solver(const std::string& name)
1421 : name_(name),
1422 parameters_(DefaultSolverParameters()),
1423 random_(CpRandomSeed()),
1424 demon_profiler_(BuildDemonProfiler(this)),
1425 use_fast_local_search_(true),
1426 local_search_profiler_(BuildLocalSearchProfiler(this)) {
1427 Init();
1428}
1429
1430void Solver::Init() {
1431 CheckSolverParameters(parameters_);
1432 queue_ = absl::make_unique<Queue>(this);
1433 trail_ = absl::make_unique<Trail>(parameters_.trail_block_size(),
1434 parameters_.compress_trail());
1435 state_ = OUTSIDE_SEARCH;
1436 branches_ = 0;
1437 fails_ = 0;
1438 decisions_ = 0;
1439 neighbors_ = 0;
1440 filtered_neighbors_ = 0;
1441 accepted_neighbors_ = 0;
1442 optimization_direction_ = NOT_SET;
1443 timer_ = absl::make_unique<ClockTimer>();
1444 searches_.assign(1, new Search(this, 0));
1445 fail_stamp_ = uint64_t{1};
1446 balancing_decision_ = absl::make_unique<BalancingDecision>();
1447 fail_intercept_ = nullptr;
1448 true_constraint_ = nullptr;
1449 false_constraint_ = nullptr;
1450 fail_decision_ = absl::make_unique<FailDecision>();
1451 constraint_index_ = 0;
1452 additional_constraint_index_ = 0;
1453 num_int_vars_ = 0;
1454 propagation_monitor_.reset(BuildTrace(this));
1455 local_search_monitor_.reset(BuildLocalSearchMonitorMaster(this));
1456 print_trace_ = nullptr;
1457 anonymous_variable_index_ = 0;
1458 should_fail_ = false;
1459
1460 for (int i = 0; i < kNumPriorities; ++i) {
1461 demon_runs_[i] = 0;
1462 }
1463 searches_.push_back(new Search(this));
1464 PushSentinel(SOLVER_CTOR_SENTINEL);
1465 InitCachedIntConstants(); // to be called after the SENTINEL is set.
1466 InitCachedConstraint(); // Cache the true constraint.
1467 timer_->Restart();
1468 model_cache_.reset(BuildModelCache(this));
1469 AddPropagationMonitor(reinterpret_cast<PropagationMonitor*>(demon_profiler_));
1471 reinterpret_cast<LocalSearchMonitor*>(local_search_profiler_));
1472}
1473
1475 // solver destructor called with searches open.
1476 CHECK_EQ(2, searches_.size());
1477 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
1478
1479 StateInfo info;
1480 Solver::MarkerType finalType = PopState(&info);
1481 // Not popping a SENTINEL in Solver destructor.
1482 DCHECK_EQ(finalType, SENTINEL);
1483 // Not popping initial SENTINEL in Solver destructor.
1484 DCHECK_EQ(info.int_info, SOLVER_CTOR_SENTINEL);
1485 gtl::STLDeleteElements(&searches_);
1486 DeleteDemonProfiler(demon_profiler_);
1487 DeleteLocalSearchProfiler(local_search_profiler_);
1488}
1489
1490std::string Solver::DebugString() const {
1491 std::string out = "Solver(name = \"" + name_ + "\", state = ";
1492 switch (state_) {
1493 case OUTSIDE_SEARCH:
1494 out += "OUTSIDE_SEARCH";
1495 break;
1496 case IN_ROOT_NODE:
1497 out += "IN_ROOT_NODE";
1498 break;
1499 case IN_SEARCH:
1500 out += "IN_SEARCH";
1501 break;
1502 case AT_SOLUTION:
1503 out += "AT_SOLUTION";
1504 break;
1505 case NO_MORE_SOLUTIONS:
1506 out += "NO_MORE_SOLUTIONS";
1507 break;
1508 case PROBLEM_INFEASIBLE:
1509 out += "PROBLEM_INFEASIBLE";
1510 break;
1511 }
1512 absl::StrAppendFormat(
1513 &out,
1514 ", branches = %d, fails = %d, decisions = %d, delayed demon runs = %d, "
1515 "var demon runs = %d, normal demon runs = %d, Run time = %d ms)",
1516 branches_, fails_, decisions_, demon_runs_[DELAYED_PRIORITY],
1517 demon_runs_[VAR_PRIORITY], demon_runs_[NORMAL_PRIORITY], wall_time());
1518 return out;
1519}
1520
1522
1523int64_t Solver::wall_time() const {
1524 return absl::ToInt64Milliseconds(timer_->GetDuration());
1525}
1526
1527absl::Time Solver::Now() const {
1528 return absl::FromUnixSeconds(0) + timer_->GetDuration();
1529}
1530
1531int64_t Solver::solutions() const {
1532 return TopLevelSearch()->solution_counter();
1533}
1534
1536 return TopLevelSearch()->unchecked_solution_counter();
1537}
1538
1539void Solver::IncrementUncheckedSolutionCounter() {
1540 TopLevelSearch()->IncrementUncheckedSolutionCounter();
1541}
1542
1543bool Solver::IsUncheckedSolutionLimitReached() {
1544 return TopLevelSearch()->IsUncheckedSolutionLimitReached();
1545}
1546
1547void Solver::TopPeriodicCheck() { TopLevelSearch()->PeriodicCheck(); }
1548
1549int Solver::TopProgressPercent() { return TopLevelSearch()->ProgressPercent(); }
1550
1553 stats.set_num_branches(branches());
1554 stats.set_num_failures(failures());
1556 stats.set_bytes_used(MemoryUsage());
1557 stats.set_duration_seconds(absl::ToDoubleSeconds(timer_->GetDuration()));
1558 return stats;
1559}
1560
1562 StateInfo info;
1563 PushState(SIMPLE_MARKER, info);
1564}
1565
1567 StateInfo info;
1568 Solver::MarkerType t = PopState(&info);
1570}
1571
1572void Solver::PushState(Solver::MarkerType t, const StateInfo& info) {
1573 StateMarker* m = new StateMarker(t, info);
1574 if (t != REVERSIBLE_ACTION || info.int_info == 0) {
1575 m->rev_int_index_ = trail_->rev_ints_.size();
1576 m->rev_int64_index_ = trail_->rev_int64s_.size();
1577 m->rev_uint64_index_ = trail_->rev_uint64s_.size();
1578 m->rev_double_index_ = trail_->rev_doubles_.size();
1579 m->rev_ptr_index_ = trail_->rev_ptrs_.size();
1580 m->rev_boolvar_list_index_ = trail_->rev_boolvar_list_.size();
1581 m->rev_bools_index_ = trail_->rev_bools_.size();
1582 m->rev_int_memory_index_ = trail_->rev_int_memory_.size();
1583 m->rev_int64_memory_index_ = trail_->rev_int64_memory_.size();
1584 m->rev_double_memory_index_ = trail_->rev_double_memory_.size();
1585 m->rev_object_memory_index_ = trail_->rev_object_memory_.size();
1586 m->rev_object_array_memory_index_ = trail_->rev_object_array_memory_.size();
1587 m->rev_memory_index_ = trail_->rev_memory_.size();
1588 m->rev_memory_array_index_ = trail_->rev_memory_array_.size();
1589 }
1590 searches_.back()->marker_stack_.push_back(m);
1591 queue_->increase_stamp();
1592}
1593
1595 StateInfo info(std::move(a), fast);
1597}
1598
1600 CHECK(!searches_.back()->marker_stack_.empty())
1601 << "PopState() on an empty stack";
1602 CHECK(info != nullptr);
1603 StateMarker* const m = searches_.back()->marker_stack_.back();
1604 if (m->type_ != REVERSIBLE_ACTION || m->info_.int_info == 0) {
1605 trail_->BacktrackTo(m);
1606 }
1607 Solver::MarkerType t = m->type_;
1608 (*info) = m->info_;
1609 searches_.back()->marker_stack_.pop_back();
1610 delete m;
1611 queue_->increase_stamp();
1612 return t;
1613}
1614
1615void Solver::check_alloc_state() {
1616 switch (state_) {
1617 case OUTSIDE_SEARCH:
1618 case IN_ROOT_NODE:
1619 case IN_SEARCH:
1620 case NO_MORE_SOLUTIONS:
1621 case PROBLEM_INFEASIBLE:
1622 break;
1623 case AT_SOLUTION:
1624 LOG(FATAL) << "allocating at a leaf node";
1625 default:
1626 LOG(FATAL) << "This switch was supposed to be exhaustive, but it is not!";
1627 }
1628}
1629
1630void Solver::FreezeQueue() { queue_->Freeze(); }
1631
1632void Solver::UnfreezeQueue() { queue_->Unfreeze(); }
1633
1634void Solver::EnqueueVar(Demon* const d) { queue_->EnqueueVar(d); }
1635
1636void Solver::EnqueueDelayedDemon(Demon* const d) {
1637 queue_->EnqueueDelayedDemon(d);
1638}
1639
1640void Solver::ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
1641 queue_->ExecuteAll(demons);
1642}
1643
1644void Solver::EnqueueAll(const SimpleRevFIFO<Demon*>& demons) {
1645 queue_->EnqueueAll(demons);
1646}
1647
1648uint64_t Solver::stamp() const { return queue_->stamp(); }
1649
1650uint64_t Solver::fail_stamp() const { return fail_stamp_; }
1651
1652void Solver::set_action_on_fail(Action a) {
1653 queue_->set_action_on_fail(std::move(a));
1654}
1655
1656void Solver::set_variable_to_clean_on_fail(IntVar* v) {
1657 queue_->set_variable_to_clean_on_fail(v);
1658}
1659
1660void Solver::reset_action_on_fail() { queue_->reset_action_on_fail(); }
1661
1663 DCHECK(c != nullptr);
1664 if (c == true_constraint_) {
1665 return;
1666 }
1667 if (state_ == IN_SEARCH) {
1668 queue_->AddConstraint(c);
1669 } else if (state_ == IN_ROOT_NODE) {
1670 DCHECK_GE(constraint_index_, 0);
1671 DCHECK_LE(constraint_index_, constraints_list_.size());
1672 const int constraint_parent =
1673 constraint_index_ == constraints_list_.size()
1674 ? additional_constraints_parent_list_[additional_constraint_index_]
1675 : constraint_index_;
1676 additional_constraints_list_.push_back(c);
1677 additional_constraints_parent_list_.push_back(constraint_parent);
1678 } else {
1679 if (parameters_.print_added_constraints()) {
1680 LOG(INFO) << c->DebugString();
1681 }
1682 constraints_list_.push_back(c);
1683 }
1684}
1685
1687 IntVar* const target_var, IntExpr* const expr) {
1688 if (constraint != nullptr) {
1689 if (state_ != IN_SEARCH) {
1690 cast_constraints_.insert(constraint);
1691 cast_information_[target_var] =
1692 Solver::IntegerCastInfo(target_var, expr, constraint);
1693 }
1694 AddConstraint(constraint);
1695 }
1696}
1697
1698void Solver::Accept(ModelVisitor* const visitor) const {
1699 visitor->BeginVisitModel(name_);
1700 ForAll(constraints_list_, &Constraint::Accept, visitor);
1701 visitor->EndVisitModel(name_);
1702}
1703
1704void Solver::ProcessConstraints() {
1705 // Both constraints_list_ and additional_constraints_list_ are used in
1706 // a FIFO way.
1707 if (parameters_.print_model()) {
1708 ModelVisitor* const visitor = MakePrintModelVisitor();
1709 Accept(visitor);
1710 }
1711 if (parameters_.print_model_stats()) {
1712 ModelVisitor* const visitor = MakeStatisticsModelVisitor();
1713 Accept(visitor);
1714 }
1715
1716 if (parameters_.disable_solve()) {
1717 LOG(INFO) << "Forcing early failure";
1718 Fail();
1719 }
1720
1721 // Clear state before processing constraints.
1722 const int constraints_size = constraints_list_.size();
1723 additional_constraints_list_.clear();
1724 additional_constraints_parent_list_.clear();
1725
1726 for (constraint_index_ = 0; constraint_index_ < constraints_size;
1727 ++constraint_index_) {
1728 Constraint* const constraint = constraints_list_[constraint_index_];
1729 propagation_monitor_->BeginConstraintInitialPropagation(constraint);
1730 constraint->PostAndPropagate();
1731 propagation_monitor_->EndConstraintInitialPropagation(constraint);
1732 }
1733 CHECK_EQ(constraints_list_.size(), constraints_size);
1734
1735 // Process nested constraints added during the previous step.
1736 for (int additional_constraint_index_ = 0;
1737 additional_constraint_index_ < additional_constraints_list_.size();
1738 ++additional_constraint_index_) {
1739 Constraint* const nested =
1740 additional_constraints_list_[additional_constraint_index_];
1741 const int parent_index =
1742 additional_constraints_parent_list_[additional_constraint_index_];
1743 Constraint* const parent = constraints_list_[parent_index];
1744 propagation_monitor_->BeginNestedConstraintInitialPropagation(parent,
1745 nested);
1746 nested->PostAndPropagate();
1747 propagation_monitor_->EndNestedConstraintInitialPropagation(parent, nested);
1748 }
1749}
1750
1752 DCHECK_GT(SolveDepth(), 0);
1753 DCHECK(searches_.back() != nullptr);
1754 return searches_.back()->created_by_solve();
1755}
1756
1757bool Solver::Solve(DecisionBuilder* const db, SearchMonitor* const m1) {
1758 std::vector<SearchMonitor*> monitors;
1759 monitors.push_back(m1);
1760 return Solve(db, monitors);
1761}
1762
1764 std::vector<SearchMonitor*> monitors;
1765 return Solve(db, monitors);
1766}
1767
1769 SearchMonitor* const m2) {
1770 std::vector<SearchMonitor*> monitors;
1771 monitors.push_back(m1);
1772 monitors.push_back(m2);
1773 return Solve(db, monitors);
1774}
1775
1777 SearchMonitor* const m2, SearchMonitor* const m3) {
1778 std::vector<SearchMonitor*> monitors;
1779 monitors.push_back(m1);
1780 monitors.push_back(m2);
1781 monitors.push_back(m3);
1782 return Solve(db, monitors);
1783}
1784
1786 SearchMonitor* const m2, SearchMonitor* const m3,
1787 SearchMonitor* const m4) {
1788 std::vector<SearchMonitor*> monitors;
1789 monitors.push_back(m1);
1790 monitors.push_back(m2);
1791 monitors.push_back(m3);
1792 monitors.push_back(m4);
1793 return Solve(db, monitors);
1794}
1795
1797 const std::vector<SearchMonitor*>& monitors) {
1798 NewSearch(db, monitors);
1799 searches_.back()->set_created_by_solve(true); // Overwrites default.
1800 NextSolution();
1801 const bool solution_found = searches_.back()->solution_counter() > 0;
1802 EndSearch();
1803 return solution_found;
1804}
1805
1807 std::vector<SearchMonitor*> monitors;
1808 monitors.push_back(m1);
1809 return NewSearch(db, monitors);
1810}
1811
1813 std::vector<SearchMonitor*> monitors;
1814 return NewSearch(db, monitors);
1815}
1816
1818 SearchMonitor* const m2) {
1819 std::vector<SearchMonitor*> monitors;
1820 monitors.push_back(m1);
1821 monitors.push_back(m2);
1822 return NewSearch(db, monitors);
1823}
1824
1826 SearchMonitor* const m2, SearchMonitor* const m3) {
1827 std::vector<SearchMonitor*> monitors;
1828 monitors.push_back(m1);
1829 monitors.push_back(m2);
1830 monitors.push_back(m3);
1831 return NewSearch(db, monitors);
1832}
1833
1835 SearchMonitor* const m2, SearchMonitor* const m3,
1836 SearchMonitor* const m4) {
1837 std::vector<SearchMonitor*> monitors;
1838 monitors.push_back(m1);
1839 monitors.push_back(m2);
1840 monitors.push_back(m3);
1841 monitors.push_back(m4);
1842 return NewSearch(db, monitors);
1843}
1844
1845extern PropagationMonitor* BuildPrintTrace(Solver* const s);
1846
1847// Opens a new top level search.
1849 const std::vector<SearchMonitor*>& monitors) {
1850 // TODO(user) : reset statistics
1851
1852 CHECK(db != nullptr);
1853 const bool nested = state_ == IN_SEARCH;
1854
1855 if (state_ == IN_ROOT_NODE) {
1856 LOG(FATAL) << "Cannot start new searches here.";
1857 }
1858
1859 Search* const search = nested ? new Search(this) : searches_.back();
1860 search->set_created_by_solve(false); // default behavior.
1861
1862 // ----- jumps to correct state -----
1863
1864 if (nested) {
1865 // Nested searches are created on demand, and deleted afterwards.
1866 DCHECK_GE(searches_.size(), 2);
1867 searches_.push_back(search);
1868 } else {
1869 // Top level search is persistent.
1870 // TODO(user): delete top level search after EndSearch().
1871 DCHECK_EQ(2, searches_.size());
1872 // TODO(user): Check if these two lines are still necessary.
1873 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
1874 state_ = OUTSIDE_SEARCH;
1875 }
1876
1877 // ----- manages all monitors -----
1878
1879 // Always install the main propagation and local search monitors.
1880 propagation_monitor_->Install();
1881 if (demon_profiler_ != nullptr) {
1882 InstallDemonProfiler(demon_profiler_);
1883 }
1884 local_search_monitor_->Install();
1885 if (local_search_profiler_ != nullptr) {
1886 InstallLocalSearchProfiler(local_search_profiler_);
1887 }
1888
1889 // Push monitors and enter search.
1890 for (SearchMonitor* const monitor : monitors) {
1891 if (monitor != nullptr) {
1892 monitor->Install();
1893 }
1894 }
1895 std::vector<SearchMonitor*> extras;
1896 db->AppendMonitors(this, &extras);
1897 for (SearchMonitor* const monitor : extras) {
1898 if (monitor != nullptr) {
1899 monitor->Install();
1900 }
1901 }
1902 // Install the print trace if needed.
1903 // The print_trace needs to be last to detect propagation from the objective.
1904 if (nested) {
1905 if (print_trace_ != nullptr) { // Was installed at the top level?
1906 print_trace_->Install(); // Propagates to nested search.
1907 }
1908 } else { // Top level search
1909 print_trace_ = nullptr; // Clears it first.
1910 if (parameters_.trace_propagation()) {
1911 print_trace_ = BuildPrintTrace(this);
1912 print_trace_->Install();
1913 } else if (parameters_.trace_search()) {
1914 // This is useful to trace the exact behavior of the search.
1915 // The '######## ' prefix is the same as the progagation trace.
1916 // Search trace is subsumed by propagation trace, thus only one
1917 // is necessary.
1918 SearchMonitor* const trace = MakeSearchTrace("######## ");
1919 trace->Install();
1920 }
1921 }
1922
1923 // ----- enters search -----
1924
1925 search->EnterSearch();
1926
1927 // Push sentinel and set decision builder.
1928 PushSentinel(INITIAL_SEARCH_SENTINEL);
1929 search->set_decision_builder(db);
1930}
1931
1932// Backtrack to the last open right branch in the search tree.
1933// It returns true in case the search tree has been completely explored.
1934bool Solver::BacktrackOneLevel(Decision** const fail_decision) {
1935 bool no_more_solutions = false;
1936 bool end_loop = false;
1937 while (!end_loop) {
1938 StateInfo info;
1939 Solver::MarkerType t = PopState(&info);
1940 switch (t) {
1941 case SENTINEL:
1942 CHECK_EQ(info.ptr_info, this) << "Wrong sentinel found";
1943 CHECK((info.int_info == ROOT_NODE_SENTINEL && SolveDepth() == 1) ||
1944 (info.int_info == INITIAL_SEARCH_SENTINEL && SolveDepth() > 1));
1945 searches_.back()->sentinel_pushed_--;
1946 no_more_solutions = true;
1947 end_loop = true;
1948 break;
1949 case SIMPLE_MARKER:
1950 LOG(ERROR) << "Simple markers should not be encountered during search";
1951 break;
1952 case CHOICE_POINT:
1953 if (info.int_info == 0) { // was left branch
1954 (*fail_decision) = reinterpret_cast<Decision*>(info.ptr_info);
1955 end_loop = true;
1956 searches_.back()->set_search_depth(info.depth);
1957 searches_.back()->set_search_left_depth(info.left_depth);
1958 }
1959 break;
1960 case REVERSIBLE_ACTION: {
1961 if (info.reversible_action != nullptr) {
1962 info.reversible_action(this);
1963 }
1964 break;
1965 }
1966 }
1967 }
1968 Search* const search = searches_.back();
1969 search->EndFail();
1970 fail_stamp_++;
1971 if (no_more_solutions) {
1972 search->NoMoreSolutions();
1973 }
1974 return no_more_solutions;
1975}
1976
1977void Solver::PushSentinel(int magic_code) {
1978 StateInfo info(this, magic_code);
1979 PushState(SENTINEL, info);
1980 // We do not count the sentinel pushed in the ctor.
1981 if (magic_code != SOLVER_CTOR_SENTINEL) {
1982 searches_.back()->sentinel_pushed_++;
1983 }
1984 const int pushed = searches_.back()->sentinel_pushed_;
1985 DCHECK((magic_code == SOLVER_CTOR_SENTINEL) ||
1986 (magic_code == INITIAL_SEARCH_SENTINEL && pushed == 1) ||
1987 (magic_code == ROOT_NODE_SENTINEL && pushed == 2));
1988}
1989
1991 Search* const search = searches_.back();
1992 CHECK_NE(0, search->sentinel_pushed_);
1993 if (SolveDepth() == 1) { // top level.
1994 if (search->sentinel_pushed_ > 1) {
1995 BacktrackToSentinel(ROOT_NODE_SENTINEL);
1996 }
1997 CHECK_EQ(1, search->sentinel_pushed_);
1998 PushSentinel(ROOT_NODE_SENTINEL);
1999 state_ = IN_SEARCH;
2000 } else {
2001 CHECK_EQ(IN_SEARCH, state_);
2002 if (search->sentinel_pushed_ > 0) {
2003 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2004 }
2005 CHECK_EQ(0, search->sentinel_pushed_);
2006 PushSentinel(INITIAL_SEARCH_SENTINEL);
2007 }
2008
2009 search->RestartSearch();
2010}
2011
2012// Backtrack to the initial search sentinel.
2013// Does not change the state, this should be done by the caller.
2014void Solver::BacktrackToSentinel(int magic_code) {
2015 Search* const search = searches_.back();
2016 bool end_loop = search->sentinel_pushed_ == 0;
2017 while (!end_loop) {
2018 StateInfo info;
2019 Solver::MarkerType t = PopState(&info);
2020 switch (t) {
2021 case SENTINEL: {
2022 CHECK_EQ(info.ptr_info, this) << "Wrong sentinel found";
2023 CHECK_GE(--search->sentinel_pushed_, 0);
2024 search->set_search_depth(0);
2025 search->set_search_left_depth(0);
2026
2027 if (info.int_info == magic_code) {
2028 end_loop = true;
2029 }
2030 break;
2031 }
2032 case SIMPLE_MARKER:
2033 break;
2034 case CHOICE_POINT:
2035 break;
2036 case REVERSIBLE_ACTION: {
2037 info.reversible_action(this);
2038 break;
2039 }
2040 }
2041 }
2042 fail_stamp_++;
2043}
2044
2045// Closes the current search without backtrack.
2046void Solver::JumpToSentinelWhenNested() {
2047 CHECK_GT(SolveDepth(), 1) << "calling JumpToSentinel from top level";
2048 Search* c = searches_.back();
2049 Search* p = ParentSearch();
2050 bool found = false;
2051 while (!c->marker_stack_.empty()) {
2052 StateMarker* const m = c->marker_stack_.back();
2053 if (m->type_ == REVERSIBLE_ACTION) {
2054 p->marker_stack_.push_back(m);
2055 } else {
2056 if (m->type_ == SENTINEL) {
2057 CHECK_EQ(c->marker_stack_.size(), 1) << "Sentinel found too early";
2058 found = true;
2059 }
2060 delete m;
2061 }
2062 c->marker_stack_.pop_back();
2063 }
2064 c->set_search_depth(0);
2065 c->set_search_left_depth(0);
2066 CHECK_EQ(found, true) << "Sentinel not found";
2067}
2068
2069namespace {
2070class ReverseDecision : public Decision {
2071 public:
2072 explicit ReverseDecision(Decision* const d) : decision_(d) {
2073 CHECK(d != nullptr);
2074 }
2075 ~ReverseDecision() override {}
2076
2077 void Apply(Solver* const s) override { decision_->Refute(s); }
2078
2079 void Refute(Solver* const s) override { decision_->Apply(s); }
2080
2081 void Accept(DecisionVisitor* const visitor) const override {
2082 decision_->Accept(visitor);
2083 }
2084
2085 std::string DebugString() const override {
2086 std::string str = "Reverse(";
2087 str += decision_->DebugString();
2088 str += ")";
2089 return str;
2090 }
2091
2092 private:
2093 Decision* const decision_;
2094};
2095} // namespace
2096
2097// Search for the next solution in the search tree.
2099 Search* const search = searches_.back();
2100 Decision* fd = nullptr;
2101 const int solve_depth = SolveDepth();
2102 const bool top_level = solve_depth <= 1;
2103
2104 if (solve_depth == 0 && !search->decision_builder()) {
2105 LOG(WARNING) << "NextSolution() called without a NewSearch before";
2106 return false;
2107 }
2108
2109 if (top_level) { // Manage top level state.
2110 switch (state_) {
2111 case PROBLEM_INFEASIBLE:
2112 return false;
2113 case NO_MORE_SOLUTIONS:
2114 return false;
2115 case AT_SOLUTION: {
2116 if (BacktrackOneLevel(&fd)) { // No more solutions.
2117 state_ = NO_MORE_SOLUTIONS;
2118 return false;
2119 }
2120 state_ = IN_SEARCH;
2121 break;
2122 }
2123 case OUTSIDE_SEARCH: {
2124 state_ = IN_ROOT_NODE;
2125 search->BeginInitialPropagation();
2126 CP_TRY(search) {
2127 ProcessConstraints();
2128 search->EndInitialPropagation();
2129 PushSentinel(ROOT_NODE_SENTINEL);
2130 state_ = IN_SEARCH;
2131 search->ClearBuffer();
2132 }
2133 CP_ON_FAIL {
2134 queue_->AfterFailure();
2135 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2136 state_ = PROBLEM_INFEASIBLE;
2137 return false;
2138 }
2139 break;
2140 }
2141 case IN_SEARCH: // Usually after a RestartSearch
2142 break;
2143 case IN_ROOT_NODE:
2144 LOG(FATAL) << "Should not happen";
2145 break;
2146 }
2147 }
2148
2149 volatile bool finish = false;
2150 volatile bool result = false;
2151 DecisionBuilder* const db = search->decision_builder();
2152
2153 while (!finish) {
2154 CP_TRY(search) {
2155 if (fd != nullptr) {
2156 StateInfo i1(fd, 1, search->search_depth(),
2157 search->left_search_depth()); // 1 for right branch
2159 search->RefuteDecision(fd);
2160 branches_++;
2161 fd->Refute(this);
2162 // Check the fail state that could have been set in the python/java/C#
2163 // layer.
2164 CheckFail();
2165 search->AfterDecision(fd, false);
2166 search->RightMove();
2167 fd = nullptr;
2168 }
2169 Decision* d = nullptr;
2170 for (;;) {
2171 search->BeginNextDecision(db);
2172 d = db->Next(this);
2173 search->EndNextDecision(db, d);
2174 if (d == fail_decision_.get()) {
2175 Fail(); // fail now instead of after 2 branches.
2176 }
2177 if (d != nullptr) {
2178 DecisionModification modification = search->ModifyDecision();
2179 switch (modification) {
2180 case SWITCH_BRANCHES: {
2181 d = RevAlloc(new ReverseDecision(d));
2182 // We reverse the decision and fall through the normal code.
2183 ABSL_FALLTHROUGH_INTENDED;
2184 }
2185 case NO_CHANGE: {
2186 decisions_++;
2187 StateInfo i2(d, 0, search->search_depth(),
2188 search->left_search_depth()); // 0 for left branch
2190 search->ApplyDecision(d);
2191 branches_++;
2192 d->Apply(this);
2193 CheckFail();
2194 search->AfterDecision(d, true);
2195 search->LeftMove();
2196 break;
2197 }
2198 case KEEP_LEFT: {
2199 search->ApplyDecision(d);
2200 d->Apply(this);
2201 CheckFail();
2202 search->AfterDecision(d, true);
2203 break;
2204 }
2205 case KEEP_RIGHT: {
2206 search->RefuteDecision(d);
2207 d->Refute(this);
2208 CheckFail();
2209 search->AfterDecision(d, false);
2210 break;
2211 }
2212 case KILL_BOTH: {
2213 Fail();
2214 }
2215 }
2216 } else {
2217 break;
2218 }
2219 }
2220 if (search->AcceptSolution()) {
2221 search->IncrementSolutionCounter();
2222 if (!search->AtSolution() || !CurrentlyInSolve()) {
2223 result = true;
2224 finish = true;
2225 } else {
2226 Fail();
2227 }
2228 } else {
2229 Fail();
2230 }
2231 }
2232 CP_ON_FAIL {
2233 queue_->AfterFailure();
2234 if (search->should_finish()) {
2235 fd = nullptr;
2236 BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
2237 : INITIAL_SEARCH_SENTINEL);
2238 result = false;
2239 finish = true;
2240 search->set_should_finish(false);
2241 search->set_should_restart(false);
2242 // We do not need to push back the sentinel as we are exiting anyway.
2243 } else if (search->should_restart()) {
2244 fd = nullptr;
2245 BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
2246 : INITIAL_SEARCH_SENTINEL);
2247 search->set_should_finish(false);
2248 search->set_should_restart(false);
2249 PushSentinel(top_level ? ROOT_NODE_SENTINEL : INITIAL_SEARCH_SENTINEL);
2250 search->RestartSearch();
2251 } else {
2252 if (BacktrackOneLevel(&fd)) { // no more solutions.
2253 result = false;
2254 finish = true;
2255 }
2256 }
2257 }
2258 }
2259 if (result) {
2260 search->ClearBuffer();
2261 }
2262 if (top_level) { // Manage state after NextSolution().
2263 state_ = (result ? AT_SOLUTION : NO_MORE_SOLUTIONS);
2264 }
2265 return result;
2266}
2267
2269 Search* const search = searches_.back();
2270 if (search->backtrack_at_the_end_of_the_search()) {
2271 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2272 } else {
2273 CHECK_GT(searches_.size(), 2);
2274 if (search->sentinel_pushed_ > 0) {
2275 JumpToSentinelWhenNested();
2276 }
2277 }
2278 search->ExitSearch();
2279 search->Clear();
2280 if (2 == searches_.size()) { // Ending top level search.
2281 // Restores the state.
2282 state_ = OUTSIDE_SEARCH;
2283 // Checks if we want to export the profile info.
2284 if (!parameters_.profile_file().empty()) {
2285 const std::string& file_name = parameters_.profile_file();
2286 LOG(INFO) << "Exporting profile to " << file_name;
2287 ExportProfilingOverview(file_name);
2288 }
2289 if (parameters_.print_local_search_profile()) {
2291 }
2292 } else { // We clean the nested Search.
2293 delete search;
2294 searches_.pop_back();
2295 }
2296}
2297
2299 CHECK(solution);
2300 if (state_ == IN_SEARCH || state_ == IN_ROOT_NODE) {
2301 LOG(FATAL) << "CheckAssignment is only available at the top level.";
2302 }
2303 // Check state and go to OUTSIDE_SEARCH.
2304 Search* const search = searches_.back();
2305 search->set_created_by_solve(false); // default behavior.
2306
2307 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2308 state_ = OUTSIDE_SEARCH;
2309
2310 // Push monitors and enter search.
2311 search->EnterSearch();
2312
2313 // Push sentinel and set decision builder.
2314 DCHECK_EQ(0, SolveDepth());
2315 DCHECK_EQ(2, searches_.size());
2316 PushSentinel(INITIAL_SEARCH_SENTINEL);
2317 search->BeginInitialPropagation();
2318 CP_TRY(search) {
2319 state_ = IN_ROOT_NODE;
2320 DecisionBuilder* const restore = MakeRestoreAssignment(solution);
2321 restore->Next(this);
2322 ProcessConstraints();
2323 search->EndInitialPropagation();
2324 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2325 search->ClearBuffer();
2326 state_ = OUTSIDE_SEARCH;
2327 return true;
2328 }
2329 CP_ON_FAIL {
2330 const int index =
2331 constraint_index_ < constraints_list_.size()
2332 ? constraint_index_
2333 : additional_constraints_parent_list_[additional_constraint_index_];
2334 Constraint* const ct = constraints_list_[index];
2335 if (ct->name().empty()) {
2336 LOG(INFO) << "Failing constraint = " << ct->DebugString();
2337 } else {
2338 LOG(INFO) << "Failing constraint = " << ct->name() << ":"
2339 << ct->DebugString();
2340 }
2341 queue_->AfterFailure();
2342 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2343 state_ = PROBLEM_INFEASIBLE;
2344 return false;
2345 }
2346}
2347
2348namespace {
2349class AddConstraintDecisionBuilder : public DecisionBuilder {
2350 public:
2351 explicit AddConstraintDecisionBuilder(Constraint* const ct)
2352 : constraint_(ct) {
2353 CHECK(ct != nullptr);
2354 }
2355
2356 ~AddConstraintDecisionBuilder() override {}
2357
2358 Decision* Next(Solver* const solver) override {
2359 solver->AddConstraint(constraint_);
2360 return nullptr;
2361 }
2362
2363 std::string DebugString() const override {
2364 return absl::StrFormat("AddConstraintDecisionBuilder(%s)",
2365 constraint_->DebugString());
2366 }
2367
2368 private:
2369 Constraint* const constraint_;
2370};
2371} // namespace
2372
2374 return RevAlloc(new AddConstraintDecisionBuilder(ct));
2375}
2376
2378 return Solve(MakeConstraintAdder(ct));
2379}
2380
2382 SearchMonitor* const m1) {
2383 std::vector<SearchMonitor*> monitors;
2384 monitors.push_back(m1);
2385 return SolveAndCommit(db, monitors);
2386}
2387
2389 std::vector<SearchMonitor*> monitors;
2390 return SolveAndCommit(db, monitors);
2391}
2392
2394 SearchMonitor* const m2) {
2395 std::vector<SearchMonitor*> monitors;
2396 monitors.push_back(m1);
2397 monitors.push_back(m2);
2398 return SolveAndCommit(db, monitors);
2399}
2400
2402 SearchMonitor* const m2, SearchMonitor* const m3) {
2403 std::vector<SearchMonitor*> monitors;
2404 monitors.push_back(m1);
2405 monitors.push_back(m2);
2406 monitors.push_back(m3);
2407 return SolveAndCommit(db, monitors);
2408}
2409
2411 const std::vector<SearchMonitor*>& monitors) {
2412 NewSearch(db, monitors);
2413 searches_.back()->set_created_by_solve(true); // Overwrites default.
2414 searches_.back()->set_backtrack_at_the_end_of_the_search(false);
2415 NextSolution();
2416 const bool solution_found = searches_.back()->solution_counter() > 0;
2417 EndSearch();
2418 return solution_found;
2419}
2420
2422 if (fail_intercept_) {
2423 fail_intercept_();
2424 return;
2425 }
2427 fails_++;
2428 searches_.back()->BeginFail();
2429 searches_.back()->JumpBack();
2430}
2431
2433 searches_.back()->set_should_finish(true);
2434}
2435
2437 searches_.back()->set_should_restart(true);
2438}
2439
2440// ----- Cast Expression -----
2441
2443 const IntegerCastInfo* const cast_info =
2444 gtl::FindOrNull(cast_information_, var);
2445 if (cast_info != nullptr) {
2446 return cast_info->expression;
2447 }
2448 return nullptr;
2449}
2450
2451// --- Propagation object names ---
2452
2453std::string Solver::GetName(const PropagationBaseObject* object) {
2454 const std::string* name = gtl::FindOrNull(propagation_object_names_, object);
2455 if (name != nullptr) {
2456 return *name;
2457 }
2458 const IntegerCastInfo* const cast_info =
2459 gtl::FindOrNull(cast_information_, object);
2460 if (cast_info != nullptr && cast_info->expression != nullptr) {
2461 if (cast_info->expression->HasName()) {
2462 return absl::StrFormat("Var<%s>", cast_info->expression->name());
2463 } else if (parameters_.name_cast_variables()) {
2464 return absl::StrFormat("Var<%s>", cast_info->expression->DebugString());
2465 } else {
2466 const std::string new_name =
2467 absl::StrFormat("CastVar<%d>", anonymous_variable_index_++);
2468 propagation_object_names_[object] = new_name;
2469 return new_name;
2470 }
2471 }
2472 const std::string base_name = object->BaseName();
2473 if (parameters_.name_all_variables() && !base_name.empty()) {
2474 const std::string new_name =
2475 absl::StrFormat("%s_%d", base_name, anonymous_variable_index_++);
2476 propagation_object_names_[object] = new_name;
2477 return new_name;
2478 }
2479 return empty_name_;
2480}
2481
2482void Solver::SetName(const PropagationBaseObject* object,
2483 const std::string& name) {
2484 if (parameters_.store_names() &&
2485 GetName(object) != name) { // in particular if name.empty()
2486 propagation_object_names_[object] = name;
2487 }
2488}
2489
2490bool Solver::HasName(const PropagationBaseObject* const object) const {
2491 return gtl::ContainsKey(propagation_object_names_,
2492 const_cast<PropagationBaseObject*>(object)) ||
2493 (!object->BaseName().empty() && parameters_.name_all_variables());
2494}
2495
2496// ------------------ Useful Operators ------------------
2497
2498std::ostream& operator<<(std::ostream& out, const Solver* const s) {
2499 out << s->DebugString();
2500 return out;
2501}
2502
2503std::ostream& operator<<(std::ostream& out, const BaseObject* const o) {
2504 out << o->DebugString();
2505 return out;
2506}
2507
2508// ---------- PropagationBaseObject ---------
2509
2510std::string PropagationBaseObject::name() const {
2511 return solver_->GetName(this);
2512}
2513
2514void PropagationBaseObject::set_name(const std::string& name) {
2515 solver_->SetName(this, name);
2516}
2517
2518bool PropagationBaseObject::HasName() const { return solver_->HasName(this); }
2519
2520std::string PropagationBaseObject::BaseName() const { return ""; }
2521
2523 solver_->ExecuteAll(demons);
2524}
2525
2527 solver_->EnqueueAll(demons);
2528}
2529
2530// ---------- Decision Builder ----------
2531
2532std::string DecisionBuilder::DebugString() const { return "DecisionBuilder"; }
2533
2535 Solver* const solver, std::vector<SearchMonitor*>* const extras) {}
2536
2537void DecisionBuilder::Accept(ModelVisitor* const visitor) const {}
2538
2539// ---------- Decision and DecisionVisitor ----------
2540
2541void Decision::Accept(DecisionVisitor* const visitor) const {
2542 visitor->VisitUnknownDecision();
2543}
2544
2547 bool lower) {}
2550 int64_t est) {}
2552 int64_t est) {}
2554 int index) {}
2555
2557 int index) {}
2558
2559// ---------- ModelVisitor ----------
2560
2561// Tags for constraints, arguments, extensions.
2562
2563const char ModelVisitor::kAbs[] = "Abs";
2564const char ModelVisitor::kAbsEqual[] = "AbsEqual";
2565const char ModelVisitor::kAllDifferent[] = "AllDifferent";
2566const char ModelVisitor::kAllowedAssignments[] = "AllowedAssignments";
2567const char ModelVisitor::kAtMost[] = "AtMost";
2568const char ModelVisitor::kBetween[] = "Between";
2569const char ModelVisitor::kConditionalExpr[] = "ConditionalExpr";
2570const char ModelVisitor::kCircuit[] = "Circuit";
2571const char ModelVisitor::kConvexPiecewise[] = "ConvexPiecewise";
2572const char ModelVisitor::kCountEqual[] = "CountEqual";
2573const char ModelVisitor::kCover[] = "Cover";
2574const char ModelVisitor::kCumulative[] = "Cumulative";
2575const char ModelVisitor::kDeviation[] = "Deviation";
2576const char ModelVisitor::kDifference[] = "Difference";
2577const char ModelVisitor::kDisjunctive[] = "Disjunctive";
2578const char ModelVisitor::kDistribute[] = "Distribute";
2579const char ModelVisitor::kDivide[] = "Divide";
2580const char ModelVisitor::kDurationExpr[] = "DurationExpression";
2581const char ModelVisitor::kElement[] = "Element";
2582const char ModelVisitor::kElementEqual[] = "ElementEqual";
2583const char ModelVisitor::kEndExpr[] = "EndExpression";
2584const char ModelVisitor::kEquality[] = "Equal";
2585const char ModelVisitor::kFalseConstraint[] = "FalseConstraint";
2586const char ModelVisitor::kGlobalCardinality[] = "GlobalCardinality";
2587const char ModelVisitor::kGreater[] = "Greater";
2588const char ModelVisitor::kGreaterOrEqual[] = "GreaterOrEqual";
2589const char ModelVisitor::kIndexOf[] = "IndexOf";
2590const char ModelVisitor::kIntegerVariable[] = "IntegerVariable";
2591const char ModelVisitor::kIntervalBinaryRelation[] = "IntervalBinaryRelation";
2592const char ModelVisitor::kIntervalDisjunction[] = "IntervalDisjunction";
2593const char ModelVisitor::kIntervalUnaryRelation[] = "IntervalUnaryRelation";
2594const char ModelVisitor::kIntervalVariable[] = "IntervalVariable";
2595const char ModelVisitor::kInversePermutation[] = "InversePermutation";
2596const char ModelVisitor::kIsBetween[] = "IsBetween;";
2597const char ModelVisitor::kIsDifferent[] = "IsDifferent";
2598const char ModelVisitor::kIsEqual[] = "IsEqual";
2599const char ModelVisitor::kIsGreater[] = "IsGreater";
2600const char ModelVisitor::kIsGreaterOrEqual[] = "IsGreaterOrEqual";
2601const char ModelVisitor::kIsLess[] = "IsLess";
2602const char ModelVisitor::kIsLessOrEqual[] = "IsLessOrEqual";
2603const char ModelVisitor::kIsMember[] = "IsMember;";
2604const char ModelVisitor::kLess[] = "Less";
2605const char ModelVisitor::kLessOrEqual[] = "LessOrEqual";
2606const char ModelVisitor::kLexLess[] = "LexLess";
2607const char ModelVisitor::kLinkExprVar[] = "CastExpressionIntoVariable";
2608const char ModelVisitor::kMapDomain[] = "MapDomain";
2609const char ModelVisitor::kMax[] = "Max";
2610const char ModelVisitor::kMaxEqual[] = "MaxEqual";
2611const char ModelVisitor::kMember[] = "Member";
2612const char ModelVisitor::kMin[] = "Min";
2613const char ModelVisitor::kMinEqual[] = "MinEqual";
2614const char ModelVisitor::kModulo[] = "Modulo";
2615const char ModelVisitor::kNoCycle[] = "NoCycle";
2616const char ModelVisitor::kNonEqual[] = "NonEqual";
2617const char ModelVisitor::kNotBetween[] = "NotBetween";
2618const char ModelVisitor::kNotMember[] = "NotMember";
2619const char ModelVisitor::kNullIntersect[] = "NullIntersect";
2620const char ModelVisitor::kOpposite[] = "Opposite";
2621const char ModelVisitor::kPack[] = "Pack";
2622const char ModelVisitor::kPathCumul[] = "PathCumul";
2623const char ModelVisitor::kDelayedPathCumul[] = "DelayedPathCumul";
2624const char ModelVisitor::kPerformedExpr[] = "PerformedExpression";
2625const char ModelVisitor::kPower[] = "Power";
2626const char ModelVisitor::kProduct[] = "Product";
2627const char ModelVisitor::kScalProd[] = "ScalarProduct";
2628const char ModelVisitor::kScalProdEqual[] = "ScalarProductEqual";
2630 "ScalarProductGreaterOrEqual";
2631const char ModelVisitor::kScalProdLessOrEqual[] = "ScalarProductLessOrEqual";
2632const char ModelVisitor::kSemiContinuous[] = "SemiContinuous";
2633const char ModelVisitor::kSequenceVariable[] = "SequenceVariable";
2634const char ModelVisitor::kSortingConstraint[] = "SortingConstraint";
2635const char ModelVisitor::kSquare[] = "Square";
2636const char ModelVisitor::kStartExpr[] = "StartExpression";
2637const char ModelVisitor::kSum[] = "Sum";
2638const char ModelVisitor::kSumEqual[] = "SumEqual";
2639const char ModelVisitor::kSumGreaterOrEqual[] = "SumGreaterOrEqual";
2640const char ModelVisitor::kSumLessOrEqual[] = "SumLessOrEqual";
2641const char ModelVisitor::kTransition[] = "Transition";
2642const char ModelVisitor::kTrace[] = "Trace";
2643const char ModelVisitor::kTrueConstraint[] = "TrueConstraint";
2644const char ModelVisitor::kVarBoundWatcher[] = "VarBoundWatcher";
2645const char ModelVisitor::kVarValueWatcher[] = "VarValueWatcher";
2646
2647const char ModelVisitor::kCountAssignedItemsExtension[] = "CountAssignedItems";
2648const char ModelVisitor::kCountUsedBinsExtension[] = "CountUsedBins";
2649const char ModelVisitor::kInt64ToBoolExtension[] = "Int64ToBoolFunction";
2650const char ModelVisitor::kInt64ToInt64Extension[] = "Int64ToInt64Function";
2651const char ModelVisitor::kObjectiveExtension[] = "Objective";
2652const char ModelVisitor::kSearchLimitExtension[] = "SearchLimit";
2653const char ModelVisitor::kUsageEqualVariableExtension[] = "UsageEqualVariable";
2654
2655const char ModelVisitor::kUsageLessConstantExtension[] = "UsageLessConstant";
2656const char ModelVisitor::kVariableGroupExtension[] = "VariableGroup";
2658 "VariableUsageLessConstant";
2660 "WeightedSumOfAssignedEqualVariable";
2661
2662const char ModelVisitor::kActiveArgument[] = "active";
2663const char ModelVisitor::kAssumePathsArgument[] = "assume_paths";
2664const char ModelVisitor::kBranchesLimitArgument[] = "branches_limit";
2665const char ModelVisitor::kCapacityArgument[] = "capacity";
2666const char ModelVisitor::kCardsArgument[] = "cardinalities";
2667const char ModelVisitor::kCoefficientsArgument[] = "coefficients";
2668const char ModelVisitor::kCountArgument[] = "count";
2669const char ModelVisitor::kCumulativeArgument[] = "cumulative";
2670const char ModelVisitor::kCumulsArgument[] = "cumuls";
2671const char ModelVisitor::kDemandsArgument[] = "demands";
2672const char ModelVisitor::kDurationMinArgument[] = "duration_min";
2673const char ModelVisitor::kDurationMaxArgument[] = "duration_max";
2674const char ModelVisitor::kEarlyCostArgument[] = "early_cost";
2675const char ModelVisitor::kEarlyDateArgument[] = "early_date";
2676const char ModelVisitor::kEndMinArgument[] = "end_min";
2677const char ModelVisitor::kEndMaxArgument[] = "end_max";
2678const char ModelVisitor::kEndsArgument[] = "ends";
2679const char ModelVisitor::kExpressionArgument[] = "expression";
2680const char ModelVisitor::kFailuresLimitArgument[] = "failures_limit";
2681const char ModelVisitor::kFinalStatesArgument[] = "final_states";
2682const char ModelVisitor::kFixedChargeArgument[] = "fixed_charge";
2683const char ModelVisitor::kIndex2Argument[] = "index2";
2684const char ModelVisitor::kIndexArgument[] = "index";
2685const char ModelVisitor::kInitialState[] = "initial_state";
2686const char ModelVisitor::kIntervalArgument[] = "interval";
2687const char ModelVisitor::kIntervalsArgument[] = "intervals";
2688const char ModelVisitor::kLateCostArgument[] = "late_cost";
2689const char ModelVisitor::kLateDateArgument[] = "late_date";
2690const char ModelVisitor::kLeftArgument[] = "left";
2691const char ModelVisitor::kMaxArgument[] = "max_value";
2692const char ModelVisitor::kMaximizeArgument[] = "maximize";
2693const char ModelVisitor::kMinArgument[] = "min_value";
2694const char ModelVisitor::kModuloArgument[] = "modulo";
2695const char ModelVisitor::kNextsArgument[] = "nexts";
2696const char ModelVisitor::kOptionalArgument[] = "optional";
2697const char ModelVisitor::kPartialArgument[] = "partial";
2698const char ModelVisitor::kPositionXArgument[] = "position_x";
2699const char ModelVisitor::kPositionYArgument[] = "position_y";
2700const char ModelVisitor::kRangeArgument[] = "range";
2701const char ModelVisitor::kRelationArgument[] = "relation";
2702const char ModelVisitor::kRightArgument[] = "right";
2703const char ModelVisitor::kSequenceArgument[] = "sequence";
2704const char ModelVisitor::kSequencesArgument[] = "sequences";
2705const char ModelVisitor::kSmartTimeCheckArgument[] = "smart_time_check";
2706const char ModelVisitor::kSizeArgument[] = "size";
2707const char ModelVisitor::kSizeXArgument[] = "size_x";
2708const char ModelVisitor::kSizeYArgument[] = "size_y";
2709const char ModelVisitor::kSolutionLimitArgument[] = "solutions_limit";
2710const char ModelVisitor::kStartMinArgument[] = "start_min";
2711const char ModelVisitor::kStartMaxArgument[] = "start_max";
2712const char ModelVisitor::kStartsArgument[] = "starts";
2713const char ModelVisitor::kStepArgument[] = "step";
2714const char ModelVisitor::kTargetArgument[] = "target_variable";
2715const char ModelVisitor::kTimeLimitArgument[] = "time_limit";
2716const char ModelVisitor::kTransitsArgument[] = "transits";
2717const char ModelVisitor::kTuplesArgument[] = "tuples";
2718const char ModelVisitor::kValueArgument[] = "value";
2719const char ModelVisitor::kValuesArgument[] = "values";
2720const char ModelVisitor::kVarsArgument[] = "variables";
2721const char ModelVisitor::kEvaluatorArgument[] = "evaluator";
2722
2723const char ModelVisitor::kVariableArgument[] = "variable";
2724
2725const char ModelVisitor::kMirrorOperation[] = "mirror";
2726const char ModelVisitor::kRelaxedMaxOperation[] = "relaxed_max";
2727const char ModelVisitor::kRelaxedMinOperation[] = "relaxed_min";
2728const char ModelVisitor::kSumOperation[] = "sum";
2729const char ModelVisitor::kDifferenceOperation[] = "difference";
2730const char ModelVisitor::kProductOperation[] = "product";
2731const char ModelVisitor::kStartSyncOnStartOperation[] = "start_synced_on_start";
2732const char ModelVisitor::kStartSyncOnEndOperation[] = "start_synced_on_end";
2733const char ModelVisitor::kTraceOperation[] = "trace";
2734
2735// Methods
2736
2738
2739void ModelVisitor::BeginVisitModel(const std::string& type_name) {}
2740void ModelVisitor::EndVisitModel(const std::string& type_name) {}
2741
2742void ModelVisitor::BeginVisitConstraint(const std::string& type_name,
2743 const Constraint* const constraint) {}
2744void ModelVisitor::EndVisitConstraint(const std::string& type_name,
2745 const Constraint* const constraint) {}
2746
2747void ModelVisitor::BeginVisitExtension(const std::string& type) {}
2748void ModelVisitor::EndVisitExtension(const std::string& type) {}
2749
2750void ModelVisitor::BeginVisitIntegerExpression(const std::string& type_name,
2751 const IntExpr* const expr) {}
2752void ModelVisitor::EndVisitIntegerExpression(const std::string& type_name,
2753 const IntExpr* const expr) {}
2754
2756 IntExpr* const delegate) {
2757 if (delegate != nullptr) {
2758 delegate->Accept(this);
2759 }
2760}
2761
2763 const std::string& operation,
2764 int64_t value, IntVar* const delegate) {
2765 if (delegate != nullptr) {
2766 delegate->Accept(this);
2767 }
2768}
2769
2771 const std::string& operation,
2772 int64_t value,
2773 IntervalVar* const delegate) {
2774 if (delegate != nullptr) {
2775 delegate->Accept(this);
2776 }
2777}
2778
2780 for (int i = 0; i < variable->size(); ++i) {
2781 variable->Interval(i)->Accept(this);
2782 }
2783}
2784
2785void ModelVisitor::VisitIntegerArgument(const std::string& arg_name,
2786 int64_t value) {}
2787
2789 const std::string& arg_name, const std::vector<int64_t>& values) {}
2790
2791void ModelVisitor::VisitIntegerMatrixArgument(const std::string& arg_name,
2792 const IntTupleSet& tuples) {}
2793
2794void ModelVisitor::VisitIntegerExpressionArgument(const std::string& arg_name,
2795 IntExpr* const argument) {
2796 argument->Accept(this);
2797}
2798
2800 const std::string& arg_name, const Solver::Int64ToIntVar& arguments) {}
2801
2803 const std::string& arg_name, const std::vector<IntVar*>& arguments) {
2804 ForAll(arguments, &IntVar::Accept, this);
2805}
2806
2807void ModelVisitor::VisitIntervalArgument(const std::string& arg_name,
2808 IntervalVar* const argument) {
2809 argument->Accept(this);
2810}
2811
2813 const std::string& arg_name, const std::vector<IntervalVar*>& arguments) {
2814 ForAll(arguments, &IntervalVar::Accept, this);
2815}
2816
2817void ModelVisitor::VisitSequenceArgument(const std::string& arg_name,
2818 SequenceVar* const argument) {
2819 argument->Accept(this);
2820}
2821
2823 const std::string& arg_name, const std::vector<SequenceVar*>& arguments) {
2824 ForAll(arguments, &SequenceVar::Accept, this);
2825}
2826
2827// ----- Helpers -----
2828
2830 int64_t index_min,
2831 int64_t index_max) {
2832 if (filter != nullptr) {
2833 std::vector<int64_t> cached_results;
2834 for (int i = index_min; i <= index_max; ++i) {
2835 cached_results.push_back(filter(i));
2836 }
2842 }
2843}
2844
2846 const Solver::IndexEvaluator1& eval, int64_t index_min, int64_t index_max) {
2847 CHECK(eval != nullptr);
2848 std::vector<int64_t> cached_results;
2849 for (int i = index_min; i <= index_max; ++i) {
2850 cached_results.push_back(eval(i));
2851 }
2857}
2858
2860 const std::string& arg_name,
2861 int64_t index_max) {
2862 CHECK(eval != nullptr);
2863 std::vector<int64_t> cached_results;
2864 for (int i = 0; i <= index_max; ++i) {
2865 cached_results.push_back(eval(i));
2866 }
2867 VisitIntegerArrayArgument(arg_name, cached_results);
2868}
2869
2870// ---------- Search Monitor ----------
2871
2877 Decision* const d) {}
2880void SearchMonitor::AfterDecision(Decision* const d, bool apply) {}
2885bool SearchMonitor::AcceptSolution() { return true; }
2886bool SearchMonitor::AtSolution() { return false; }
2888bool SearchMonitor::LocalOptimum() { return false; }
2890 return true;
2891}
2895void SearchMonitor::Accept(ModelVisitor* const visitor) const {}
2896// A search monitors adds itself on the active search.
2898 solver()->searches_.back()->push_monitor(this);
2899}
2900
2901// ---------- Propagation Monitor -----------
2903 : SearchMonitor(solver) {}
2904
2906
2907// A propagation monitor listens to search events as well as propagation events.
2911}
2912
2913// ---------- Local Search Monitor -----------
2915 : SearchMonitor(solver) {}
2916
2918
2919// A local search monitor listens to search events as well as local search
2920// events.
2924}
2925
2926// ---------- Trace ----------
2927
2929 public:
2930 explicit Trace(Solver* const s) : PropagationMonitor(s) {}
2931
2932 ~Trace() override {}
2933
2935 Constraint* const constraint) override {
2937 constraint);
2938 }
2939
2940 void EndConstraintInitialPropagation(Constraint* const constraint) override {
2942 constraint);
2943 }
2944
2946 Constraint* const parent, Constraint* const nested) override {
2947 ForAll(monitors_,
2949 nested);
2950 }
2951
2953 Constraint* const parent, Constraint* const nested) override {
2954 ForAll(monitors_,
2956 nested);
2957 }
2958
2959 void RegisterDemon(Demon* const demon) override {
2960 ForAll(monitors_, &PropagationMonitor::RegisterDemon, demon);
2961 }
2962
2963 void BeginDemonRun(Demon* const demon) override {
2964 ForAll(monitors_, &PropagationMonitor::BeginDemonRun, demon);
2965 }
2966
2967 void EndDemonRun(Demon* const demon) override {
2968 ForAll(monitors_, &PropagationMonitor::EndDemonRun, demon);
2969 }
2970
2973 }
2974
2977 }
2978
2979 void PushContext(const std::string& context) override {
2980 ForAll(monitors_, &PropagationMonitor::PushContext, context);
2981 }
2982
2983 void PopContext() override {
2984 ForAll(monitors_, &PropagationMonitor::PopContext);
2985 }
2986
2987 // IntExpr modifiers.
2988 void SetMin(IntExpr* const expr, int64_t new_min) override {
2989 for (PropagationMonitor* const monitor : monitors_) {
2990 monitor->SetMin(expr, new_min);
2991 }
2992 }
2993
2994 void SetMax(IntExpr* const expr, int64_t new_max) override {
2995 for (PropagationMonitor* const monitor : monitors_) {
2996 monitor->SetMax(expr, new_max);
2997 }
2998 }
2999
3000 void SetRange(IntExpr* const expr, int64_t new_min,
3001 int64_t new_max) override {
3002 for (PropagationMonitor* const monitor : monitors_) {
3003 monitor->SetRange(expr, new_min, new_max);
3004 }
3005 }
3006
3007 // IntVar modifiers.
3008 void SetMin(IntVar* const var, int64_t new_min) override {
3009 for (PropagationMonitor* const monitor : monitors_) {
3010 monitor->SetMin(var, new_min);
3011 }
3012 }
3013
3014 void SetMax(IntVar* const var, int64_t new_max) override {
3015 for (PropagationMonitor* const monitor : monitors_) {
3016 monitor->SetMax(var, new_max);
3017 }
3018 }
3019
3020 void SetRange(IntVar* const var, int64_t new_min, int64_t new_max) override {
3021 for (PropagationMonitor* const monitor : monitors_) {
3022 monitor->SetRange(var, new_min, new_max);
3023 }
3024 }
3025
3026 void RemoveValue(IntVar* const var, int64_t value) override {
3027 ForAll(monitors_, &PropagationMonitor::RemoveValue, var, value);
3028 }
3029
3030 void SetValue(IntVar* const var, int64_t value) override {
3031 ForAll(monitors_, &PropagationMonitor::SetValue, var, value);
3032 }
3033
3034 void RemoveInterval(IntVar* const var, int64_t imin, int64_t imax) override {
3035 ForAll(monitors_, &PropagationMonitor::RemoveInterval, var, imin, imax);
3036 }
3037
3038 void SetValues(IntVar* const var,
3039 const std::vector<int64_t>& values) override {
3040 ForAll(monitors_, &PropagationMonitor::SetValues, var, values);
3041 }
3042
3044 const std::vector<int64_t>& values) override {
3045 ForAll(monitors_, &PropagationMonitor::RemoveValues, var, values);
3046 }
3047
3048 // IntervalVar modifiers.
3049 void SetStartMin(IntervalVar* const var, int64_t new_min) override {
3050 ForAll(monitors_, &PropagationMonitor::SetStartMin, var, new_min);
3051 }
3052
3053 void SetStartMax(IntervalVar* const var, int64_t new_max) override {
3054 ForAll(monitors_, &PropagationMonitor::SetStartMax, var, new_max);
3055 }
3056
3057 void SetStartRange(IntervalVar* const var, int64_t new_min,
3058 int64_t new_max) override {
3059 ForAll(monitors_, &PropagationMonitor::SetStartRange, var, new_min,
3060 new_max);
3061 }
3062
3063 void SetEndMin(IntervalVar* const var, int64_t new_min) override {
3064 ForAll(monitors_, &PropagationMonitor::SetEndMin, var, new_min);
3065 }
3066
3067 void SetEndMax(IntervalVar* const var, int64_t new_max) override {
3068 ForAll(monitors_, &PropagationMonitor::SetEndMax, var, new_max);
3069 }
3070
3071 void SetEndRange(IntervalVar* const var, int64_t new_min,
3072 int64_t new_max) override {
3073 ForAll(monitors_, &PropagationMonitor::SetEndRange, var, new_min, new_max);
3074 }
3075
3076 void SetDurationMin(IntervalVar* const var, int64_t new_min) override {
3077 ForAll(monitors_, &PropagationMonitor::SetDurationMin, var, new_min);
3078 }
3079
3080 void SetDurationMax(IntervalVar* const var, int64_t new_max) override {
3081 ForAll(monitors_, &PropagationMonitor::SetDurationMax, var, new_max);
3082 }
3083
3084 void SetDurationRange(IntervalVar* const var, int64_t new_min,
3085 int64_t new_max) override {
3086 ForAll(monitors_, &PropagationMonitor::SetDurationRange, var, new_min,
3087 new_max);
3088 }
3089
3090 void SetPerformed(IntervalVar* const var, bool value) override {
3091 ForAll(monitors_, &PropagationMonitor::SetPerformed, var, value);
3092 }
3093
3094 void RankFirst(SequenceVar* const var, int index) override {
3095 ForAll(monitors_, &PropagationMonitor::RankFirst, var, index);
3096 }
3097
3098 void RankNotFirst(SequenceVar* const var, int index) override {
3099 ForAll(monitors_, &PropagationMonitor::RankNotFirst, var, index);
3100 }
3101
3102 void RankLast(SequenceVar* const var, int index) override {
3103 ForAll(monitors_, &PropagationMonitor::RankLast, var, index);
3104 }
3105
3106 void RankNotLast(SequenceVar* const var, int index) override {
3107 ForAll(monitors_, &PropagationMonitor::RankNotLast, var, index);
3108 }
3109
3110 void RankSequence(SequenceVar* const var, const std::vector<int>& rank_first,
3111 const std::vector<int>& rank_last,
3112 const std::vector<int>& unperformed) override {
3113 ForAll(monitors_, &PropagationMonitor::RankSequence, var, rank_first,
3114 rank_last, unperformed);
3115 }
3116
3117 // Does not take ownership of monitor.
3118 void Add(PropagationMonitor* const monitor) {
3119 if (monitor != nullptr) {
3120 monitors_.push_back(monitor);
3121 }
3122 }
3123
3124 // The trace will dispatch propagation events. It needs to listen to search
3125 // events.
3126 void Install() override { SearchMonitor::Install(); }
3127
3128 std::string DebugString() const override { return "Trace"; }
3129
3130 private:
3131 std::vector<PropagationMonitor*> monitors_;
3132};
3133
3134PropagationMonitor* BuildTrace(Solver* const s) { return new Trace(s); }
3135
3137 // TODO(user): Check solver state?
3138 reinterpret_cast<class Trace*>(propagation_monitor_.get())->Add(monitor);
3139}
3140
3142 return propagation_monitor_.get();
3143}
3144
3145// ---------- Local Search Monitor Master ----------
3146
3148 public:
3151
3152 void BeginOperatorStart() override {
3153 ForAll(monitors_, &LocalSearchMonitor::BeginOperatorStart);
3154 }
3155 void EndOperatorStart() override {
3156 ForAll(monitors_, &LocalSearchMonitor::EndOperatorStart);
3157 }
3159 ForAll(monitors_, &LocalSearchMonitor::BeginMakeNextNeighbor, op);
3160 }
3161 void EndMakeNextNeighbor(const LocalSearchOperator* op, bool neighbor_found,
3162 const Assignment* delta,
3163 const Assignment* deltadelta) override {
3164 ForAll(monitors_, &LocalSearchMonitor::EndMakeNextNeighbor, op,
3165 neighbor_found, delta, deltadelta);
3166 }
3167 void BeginFilterNeighbor(const LocalSearchOperator* op) override {
3168 ForAll(monitors_, &LocalSearchMonitor::BeginFilterNeighbor, op);
3169 }
3171 bool neighbor_found) override {
3172 ForAll(monitors_, &LocalSearchMonitor::EndFilterNeighbor, op,
3173 neighbor_found);
3174 }
3175 void BeginAcceptNeighbor(const LocalSearchOperator* op) override {
3176 ForAll(monitors_, &LocalSearchMonitor::BeginAcceptNeighbor, op);
3177 }
3179 bool neighbor_found) override {
3180 ForAll(monitors_, &LocalSearchMonitor::EndAcceptNeighbor, op,
3181 neighbor_found);
3182 }
3183 void BeginFiltering(const LocalSearchFilter* filter) override {
3184 ForAll(monitors_, &LocalSearchMonitor::BeginFiltering, filter);
3185 }
3186 void EndFiltering(const LocalSearchFilter* filter, bool reject) override {
3187 ForAll(monitors_, &LocalSearchMonitor::EndFiltering, filter, reject);
3188 }
3189
3190 // Does not take ownership of monitor.
3191 void Add(LocalSearchMonitor* monitor) {
3192 if (monitor != nullptr) {
3193 monitors_.push_back(monitor);
3194 }
3195 }
3196
3197 // The trace will dispatch propagation events. It needs to listen to search
3198 // events.
3199 void Install() override { SearchMonitor::Install(); }
3200
3201 std::string DebugString() const override {
3202 return "LocalSearchMonitorMaster";
3203 }
3204
3205 private:
3206 std::vector<LocalSearchMonitor*> monitors_;
3207};
3208
3210 return new LocalSearchMonitorMaster(s);
3211}
3212
3214 reinterpret_cast<class LocalSearchMonitorMaster*>(local_search_monitor_.get())
3215 ->Add(monitor);
3216}
3217
3219 return local_search_monitor_.get();
3220}
3221
3223 const std::string& search_context) {
3224 search->set_search_context(search_context);
3225}
3226
3227std::string Solver::SearchContext() const {
3228 return ActiveSearch()->search_context();
3229}
3230
3231std::string Solver::SearchContext(const Search* search) const {
3232 return search->search_context();
3233}
3234
3236 if (local_search_state_ == nullptr) {
3237 local_search_state_ = absl::make_unique<Assignment>(this);
3238 }
3239 return local_search_state_.get();
3240}
3241
3242// ----------------- Constraint class -------------------
3243
3244std::string Constraint::DebugString() const { return "Constraint"; }
3245
3247 FreezeQueue();
3248 Post();
3250 solver()->CheckFail();
3251 UnfreezeQueue();
3252}
3253
3254void Constraint::Accept(ModelVisitor* const visitor) const {
3255 visitor->BeginVisitConstraint("unknown", this);
3256 VLOG(3) << "Unknown constraint " << DebugString();
3257 visitor->EndVisitConstraint("unknown", this);
3258}
3259
3261 return gtl::ContainsKey(solver()->cast_constraints_, this);
3262}
3263
3264IntVar* Constraint::Var() { return nullptr; }
3265
3266// ----- Class IntExpr -----
3267
3268void IntExpr::Accept(ModelVisitor* const visitor) const {
3269 visitor->BeginVisitIntegerExpression("unknown", this);
3270 VLOG(3) << "Unknown expression " << DebugString();
3271 visitor->EndVisitIntegerExpression("unknown", this);
3272}
3273
3274#undef CP_TRY // We no longer need those.
3275#undef CP_ON_FAIL
3276#undef CP_DO_FAIL
3277
3278} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
#define CHECK(condition)
Definition: base/logging.h:491
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:888
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
#define CHECK_GE(val1, val2)
Definition: base/logging.h:702
#define CHECK_GT(val1, val2)
Definition: base/logging.h:703
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:890
#define CHECK_NE(val1, val2)
Definition: base/logging.h:699
#define DCHECK_GT(val1, val2)
Definition: base/logging.h:891
#define LOG(severity)
Definition: base/logging.h:416
#define DCHECK(condition)
Definition: base/logging.h:885
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
#define VLOG(verboselevel)
Definition: base/logging.h:979
An Assignment is a variable -> domains mapping, used to report solutions to the user.
A BaseObject is the root of all reversibly allocated objects.
virtual std::string DebugString() const
Cast constraints are special channeling constraints designed to keep a variable in sync with an expre...
A constraint is the main modeling object.
void PostAndPropagate()
Calls Post and then Propagate to initialize the constraints.
bool IsCastConstraint() const
Is the constraint created by a cast from expression to integer variable?
virtual void InitialPropagate()=0
This method performs the initial propagation of the constraint.
virtual void Accept(ModelVisitor *const visitor) const
Accepts the given visitor.
virtual IntVar * Var()
Creates a Boolean variable representing the status of the constraint (false = constraint is violated,...
std::string DebugString() const override
virtual void Post()=0
This method is called when the constraint is processed by the solver.
void set_compress_trail(::operations_research::ConstraintSolverParameters_TrailCompression value)
void set_profile_file(ArgT0 &&arg0, ArgT... args)
void set_trail_block_size(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_array_split_size(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_check_solution_period(::PROTOBUF_NAMESPACE_ID::int32 value)
::PROTOBUF_NAMESPACE_ID::int32 trail_block_size() const
ConstraintSolverParameters_TrailCompression TrailCompression
static constexpr TrailCompression COMPRESS_WITH_ZLIB
static constexpr TrailCompression NO_COMPRESSION
::operations_research::ConstraintSolverParameters_TrailCompression compress_trail() const
void set_max_edge_finder_size(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_num_branches(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_bytes_used(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_num_failures(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_num_solutions(::PROTOBUF_NAMESPACE_ID::int64 value)
A DecisionBuilder is responsible for creating the search tree.
virtual Decision * Next(Solver *const s)=0
This is the main method of the decision builder class.
virtual void Accept(ModelVisitor *const visitor) const
virtual void AppendMonitors(Solver *const solver, std::vector< SearchMonitor * > *const extras)
This method will be called at the start of the search.
std::string DebugString() const override
A Decision represents a choice point in the search tree.
virtual void Accept(DecisionVisitor *const visitor) const
Accepts the given visitor.
virtual void Apply(Solver *const s)=0
Apply will be called first when the decision is executed.
virtual void Refute(Solver *const s)=0
Refute will be called after a backtrack.
A DecisionVisitor is used to inspect a decision.
virtual void VisitSetVariableValue(IntVar *const var, int64_t value)
virtual void VisitSplitVariableDomain(IntVar *const var, int64_t value, bool start_with_lower_half)
virtual void VisitRankFirstInterval(SequenceVar *const sequence, int index)
virtual void VisitRankLastInterval(SequenceVar *const sequence, int index)
virtual void VisitScheduleOrPostpone(IntervalVar *const var, int64_t est)
virtual void VisitScheduleOrExpedite(IntervalVar *const var, int64_t est)
A Demon is the base element of a propagation queue.
void inhibit(Solver *const s)
This method inhibits the demon in the search tree below the current position.
void desinhibit(Solver *const s)
This method un-inhibits the demon that was previously inhibited.
virtual Solver::DemonPriority priority() const
This method returns the priority of the demon.
std::string DebugString() const override
virtual void Run(Solver *const s)=0
This is the main callback of the demon.
The class IntExpr is the base of all integer expressions in constraint programming.
virtual void Accept(ModelVisitor *const visitor) const
Accepts the given visitor.
The class IntVar is a subset of IntExpr.
void Accept(ModelVisitor *const visitor) const override
Accepts the given visitor.
Interval variables are often used in scheduling.
virtual void Accept(ModelVisitor *const visitor) const =0
Accepts the given visitor.
Local Search Filters are used for fast neighbor pruning.
virtual void EndMakeNextNeighbor(const LocalSearchOperator *op, bool neighbor_found, const Assignment *delta, const Assignment *deltadelta)=0
void Install() override
Install itself on the solver.
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
void BeginFiltering(const LocalSearchFilter *filter) override
void Install() override
Registers itself on the solver such that it gets notified of the search and propagation events.
void BeginOperatorStart() override
Local search operator events.
void EndMakeNextNeighbor(const LocalSearchOperator *op, bool neighbor_found, const Assignment *delta, const Assignment *deltadelta) override
void BeginMakeNextNeighbor(const LocalSearchOperator *op) override
void EndAcceptNeighbor(const LocalSearchOperator *op, bool neighbor_found) override
void BeginAcceptNeighbor(const LocalSearchOperator *op) override
void EndFilterNeighbor(const LocalSearchOperator *op, bool neighbor_found) override
void EndFiltering(const LocalSearchFilter *filter, bool reject) override
void BeginFilterNeighbor(const LocalSearchOperator *op) override
The base class for all local search operators.
static const char kSolutionLimitArgument[]
static const char kCountUsedBinsExtension[]
virtual void VisitIntegerArgument(const std::string &arg_name, int64_t value)
Visit integer arguments.
static const char kMirrorOperation[]
Operations.
static const char kAbs[]
Constraint and Expression types.
virtual void VisitSequenceVariable(const SequenceVar *const variable)
static const char kVariableUsageLessConstantExtension[]
virtual void VisitIntegerVariable(const IntVar *const variable, IntExpr *const delegate)
void VisitInt64ToInt64AsArray(const Solver::IndexEvaluator1 &eval, const std::string &arg_name, int64_t index_max)
Expands function as array when index min is 0.
virtual void VisitIntervalVariable(const IntervalVar *const variable, const std::string &operation, int64_t value, IntervalVar *const delegate)
void VisitInt64ToInt64Extension(const Solver::IndexEvaluator1 &eval, int64_t index_min, int64_t index_max)
static const char kActiveArgument[]
argument names:
void VisitInt64ToBoolExtension(Solver::IndexFilter1 filter, int64_t index_min, int64_t index_max)
Using SWIG on callbacks is troublesome, so we hide these methods during the wrapping.
virtual void VisitIntegerArrayArgument(const std::string &arg_name, const std::vector< int64_t > &values)
virtual void VisitIntervalArgument(const std::string &arg_name, IntervalVar *const argument)
Visit interval argument.
static const char kBranchesLimitArgument[]
static const char kIntervalUnaryRelation[]
virtual void BeginVisitIntegerExpression(const std::string &type_name, const IntExpr *const expr)
virtual void EndVisitIntegerExpression(const std::string &type_name, const IntExpr *const expr)
static const char kWeightedSumOfAssignedEqualVariableExtension[]
virtual void VisitIntegerVariableEvaluatorArgument(const std::string &arg_name, const Solver::Int64ToIntVar &arguments)
Helpers.
static const char kSmartTimeCheckArgument[]
virtual void EndVisitConstraint(const std::string &type_name, const Constraint *const constraint)
virtual void BeginVisitExtension(const std::string &type)
static const char kStartSyncOnStartOperation[]
static const char kUsageLessConstantExtension[]
virtual void EndVisitExtension(const std::string &type)
static const char kUsageEqualVariableExtension[]
virtual void EndVisitModel(const std::string &type_name)
virtual void VisitIntegerVariableArrayArgument(const std::string &arg_name, const std::vector< IntVar * > &arguments)
static const char kVariableGroupExtension[]
static const char kFailuresLimitArgument[]
static const char kScalProdGreaterOrEqual[]
virtual void VisitIntervalArrayArgument(const std::string &arg_name, const std::vector< IntervalVar * > &arguments)
static const char kIntervalBinaryRelation[]
virtual void VisitIntegerMatrixArgument(const std::string &arg_name, const IntTupleSet &tuples)
virtual void VisitIntegerExpressionArgument(const std::string &arg_name, IntExpr *const argument)
Visit integer expression argument.
virtual void VisitSequenceArrayArgument(const std::string &arg_name, const std::vector< SequenceVar * > &arguments)
static const char kInt64ToInt64Extension[]
static const char kStartSyncOnEndOperation[]
virtual void VisitSequenceArgument(const std::string &arg_name, SequenceVar *const argument)
Visit sequence argument.
virtual void BeginVisitModel(const std::string &type_name)
--— Virtual methods for visitors --—
virtual void BeginVisitConstraint(const std::string &type_name, const Constraint *const constraint)
static const char kCountAssignedItemsExtension[]
Extension names:
virtual std::string name() const
Object naming.
bool HasName() const
Returns whether the object has been named or not.
void ExecuteAll(const SimpleRevFIFO< Demon * > &demons)
void FreezeQueue()
This method freezes the propagation queue.
void EnqueueAll(const SimpleRevFIFO< Demon * > &demons)
virtual std::string BaseName() const
Returns a base name for automatic naming.
void UnfreezeQueue()
This method unfreezes the propagation queue.
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
void Install() override
Install itself on the solver.
virtual void RankLast(SequenceVar *const var, int index)=0
virtual void EndConstraintInitialPropagation(Constraint *const constraint)=0
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 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 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 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
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.
void EnqueueDelayedDemon(Demon *const demon)
static constexpr int64_t kTestPeriod
void set_action_on_fail(Solver::Action a)
void ExecuteAll(const SimpleRevFIFO< Demon * > &demons)
void EnqueueVar(Demon *const demon)
void AddConstraint(Constraint *const c)
void EnqueueAll(const SimpleRevFIFO< Demon * > &demons)
void set_variable_to_clean_on_fail(IntVar *var)
void ProcessOneDemon(Demon *const demon)
void RefuteDecision(Decision *const d)
void ApplyDecision(Decision *const d)
DecisionBuilder * decision_builder() const
void BeginNextDecision(DecisionBuilder *const db)
Search(Solver *const s, int)
std::string search_context() const
void SetBranchSelector(Solver::BranchSelector bs)
int64_t unchecked_solution_counter() const
bool backtrack_at_the_end_of_the_search() const
void AfterDecision(Decision *const d, bool apply)
void set_backtrack_at_the_end_of_the_search(bool restore)
Solver::DecisionModification ModifyDecision()
void push_monitor(SearchMonitor *const m)
void set_decision_builder(DecisionBuilder *const db)
bool AcceptDelta(Assignment *delta, Assignment *deltadelta)
void Accept(ModelVisitor *const visitor) const
void EndNextDecision(DecisionBuilder *const db, Decision *const d)
void set_search_context(const std::string &search_context)
A search monitor is a simple set of callbacks to monitor all search events.
virtual void RefuteDecision(Decision *const d)
Before refuting the decision.
virtual void ApplyDecision(Decision *const d)
Before applying the decision.
virtual void RestartSearch()
Restart the search.
virtual void ExitSearch()
End of the search.
virtual bool LocalOptimum()
When a local optimum is reached.
virtual void NoMoreSolutions()
When the search tree is finished.
virtual void BeginFail()
Just when the failure occurs.
virtual void AfterDecision(Decision *const d, bool apply)
Just after refuting or applying the decision, apply is true after Apply.
virtual void BeginInitialPropagation()
Before the initial propagation.
virtual void BeginNextDecision(DecisionBuilder *const b)
Before calling DecisionBuilder::Next.
virtual void PeriodicCheck()
Periodic call to check limits in long running methods.
virtual void EnterSearch()
Beginning of the search.
virtual void EndNextDecision(DecisionBuilder *const b, Decision *const d)
After calling DecisionBuilder::Next, along with the returned decision.
virtual void EndFail()
After completing the backtrack.
virtual void EndInitialPropagation()
After the initial propagation.
virtual void AcceptUncheckedNeighbor()
After accepting an unchecked neighbor during local search.
virtual bool AcceptDelta(Assignment *delta, Assignment *deltadelta)
virtual bool AtSolution()
This method is called when a valid solution is found.
virtual void Accept(ModelVisitor *const visitor) const
Accepts the given model visitor.
virtual void AcceptNeighbor()
After accepting a neighbor during local search.
virtual void Install()
Registers itself on the solver such that it gets notified of the search and propagation events.
virtual bool AcceptSolution()
This method is called when a solution is found.
A sequence variable is a variable whose domain is a set of possible orderings of the interval variabl...
IntervalVar * Interval(int index) const
Returns the index_th interval of the sequence.
Definition: sched_search.cc:52
int64_t size() const
Returns the number of interval vars in the sequence.
virtual void Accept(ModelVisitor *const visitor) const
Accepts the given visitor.
Definition: sched_search.cc:73
This iterator is not stable with respect to deletion.
This class represent a reversible FIFO structure.
DecisionModification
The Solver is responsible for creating the search tree.
@ NO_CHANGE
Keeps the default behavior, i.e.
@ SWITCH_BRANCHES
Applies right branch first.
@ KEEP_RIGHT
Left branches are ignored.
@ KEEP_LEFT
Right branches are ignored.
@ KILL_BOTH
Backtracks to the previous decisions, i.e.
bool HasName(const PropagationBaseObject *object) const
Returns whether the object has been named or not.
int64_t branches() const
The number of branches explored since the creation of the solver.
bool SolveAndCommit(DecisionBuilder *const db, const std::vector< SearchMonitor * > &monitors)
SolveAndCommit using a decision builder and up to three search monitors, usually one for the objectiv...
Constraint * MakeFalseConstraint()
This constraint always fails.
Definition: constraints.cc:523
ConstraintSolverStatistics GetConstraintSolverStatistics() const
Returns detailed cp search statistics.
static constexpr int kNumPriorities
Number of priorities for demons.
DemonPriority
This enum represents the three possible priorities for a demon in the Solver queue.
@ VAR_PRIORITY
VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.
@ DELAYED_PRIORITY
DELAYED_PRIORITY is the lowest priority: Demons will be processed after VAR_PRIORITY and NORMAL_PRIOR...
@ NORMAL_PRIORITY
NORMAL_PRIORITY is the highest priority: Demons will be processed first.
@ AT_SOLUTION
After successful NextSolution and before EndSearch.
@ PROBLEM_INFEASIBLE
After search, the model is infeasible.
@ OUTSIDE_SEARCH
Before search, after search.
@ IN_ROOT_NODE
Executing the root node.
@ NO_MORE_SOLUTIONS
After failed NextSolution and before EndSearch.
@ IN_SEARCH
Executing the search code.
std::string SearchContext() const
bool CheckAssignment(Assignment *const solution)
Checks whether the given assignment satisfies all relevant constraints.
absl::Time Now() const
The 'absolute time' as seen by the solver.
DecisionBuilder * MakeConstraintAdder(Constraint *const ct)
Returns a decision builder that will add the given constraint to the model.
Assignment * GetOrCreateLocalSearchState()
Returns (or creates) an assignment representing the state of local search.
bool IsProfilingEnabled() const
Returns whether we are profiling the solver.
void AddPropagationMonitor(PropagationMonitor *const monitor)
Adds the propagation monitor to the solver.
bool CheckConstraint(Constraint *const ct)
Checks whether adding this constraint will lead to an immediate failure.
void SetSearchContext(Search *search, const std::string &search_context)
void TopPeriodicCheck()
Performs PeriodicCheck on the top-level search; for instance, can be called from a nested solve to ch...
DecisionBuilder * MakeApplyBranchSelector(BranchSelector bs)
Creates a decision builder that will set the branch selector.
void AddConstraint(Constraint *const c)
Adds the constraint 'c' to the model.
int64_t wall_time() const
DEPRECATED: Use Now() instead.
std::function< bool(int64_t)> IndexFilter1
int SearchDepth() const
Gets the search depth of the current active search.
int64_t unchecked_solutions() const
The number of unchecked solutions found by local search.
void SaveAndSetValue(T *adr, T val)
All-in-one SaveAndSetValue.
void AddLocalSearchMonitor(LocalSearchMonitor *monitor)
Adds the local search monitor to the solver.
void PushState()
The PushState and PopState methods manipulates the states of the reversible objects.
bool IsLocalSearchProfilingEnabled() const
Returns whether we are profiling local search.
std::string DebugString() const
!defined(SWIG)
Search * ActiveSearch() const
Returns the active search, nullptr outside search.
int64_t failures() const
The number of failures encountered since the creation of the solver.
LocalSearchMonitor * GetLocalSearchMonitor() const
Returns the local search monitor.
static int64_t MemoryUsage()
Current memory usage in bytes.
int SolveDepth() const
Gets the number of nested searches.
PropagationMonitor * GetPropagationMonitor() const
Returns the propagation monitor.
bool Solve(DecisionBuilder *const db, const std::vector< SearchMonitor * > &monitors)
std::string model_name() const
Returns the name of the model.
bool InstrumentsVariables() const
Returns whether we are tracing variables.
SearchMonitor * MakeSearchTrace(const std::string &prefix)
Creates a search monitor that will trace precisely the behavior of the search.
Definition: search.cc:398
static ConstraintSolverParameters DefaultSolverParameters()
Create a ConstraintSolverParameters proto with all the default values.
std::string LocalSearchProfile() const
Returns local search profiling information in a human readable format.
void Accept(ModelVisitor *const visitor) const
Accepts the given model visitor.
int SearchLeftDepth() const
Gets the search left depth of the current active search.
void AddBacktrackAction(Action a, bool fast)
When SaveValue() is not the best way to go, one can create a reversible action that will be called up...
int TopProgressPercent()
Returns a percentage representing the propress of the search before reaching the limits of the top-le...
bool CurrentlyInSolve() const
Returns true whether the current search has been created using a Solve() call instead of a NewSearch ...
Solver(const std::string &name)
Solver API.
uint64_t stamp() const
The stamp indicates how many moves in the search tree we have performed.
bool NameAllVariables() const
Returns whether all variables should be named.
IntExpr * CastExpression(const IntVar *const var) const
!defined(SWIG)
uint64_t fail_stamp() const
The fail_stamp() is incremented after each backtrack.
void SetBranchSelector(BranchSelector bs)
Sets the given branch selector on the current active search.
ModelVisitor * MakePrintModelVisitor()
Prints the model.
Definition: utilities.cc:813
std::function< void(Solver *)> Action
void ExportProfilingOverview(const std::string &filename)
Exports the profiling information in a human readable overview.
MarkerType
This enum is used internally in private methods Solver::PushState and Solver::PopState to tag states ...
void AddCastConstraint(CastConstraint *const constraint, IntVar *const target_var, IntExpr *const expr)
Adds 'constraint' to the solver and marks it as a cast constraint, that is, a constraint created call...
std::function< int64_t(int64_t)> IndexEvaluator1
Callback typedefs.
std::function< DecisionModification()> BranchSelector
bool InstrumentsDemons() const
Returns whether we are instrumenting demons.
DecisionBuilder * MakeRestoreAssignment(Assignment *assignment)
Returns a DecisionBuilder which restores an Assignment (calls void Assignment::Restore())
void Fail()
Abandon the current branch in the search tree. A backtrack will follow.
int64_t solutions() const
The number of solutions found since the start of the search.
std::function< IntVar *(int64_t)> Int64ToIntVar
T * RevAlloc(T *object)
Registers the given object as being reversible.
void FinishCurrentSearch()
Tells the solver to kill or restart the current search.
void NewSearch(DecisionBuilder *const db, const std::vector< SearchMonitor * > &monitors)
ModelVisitor * MakeStatisticsModelVisitor()
Displays some nice statistics on the model.
Definition: utilities.cc:817
void SetDurationMax(IntervalVar *const var, int64_t new_max) override
void Install() override
Registers itself on the solver such that it gets notified of the search and propagation events.
void SetDurationRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override
void SetStartMax(IntervalVar *const var, int64_t new_max) override
void SetMin(IntVar *const var, int64_t new_min) override
IntVar modifiers.
void SetValue(IntVar *const var, int64_t value) override
void SetEndMax(IntervalVar *const var, int64_t new_max) override
void EndProcessingIntegerVariable(IntVar *const var) override
void SetStartMin(IntervalVar *const var, int64_t new_min) override
IntervalVar modifiers.
void SetEndRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override
void SetMin(IntExpr *const expr, int64_t new_min) override
IntExpr modifiers.
void SetPerformed(IntervalVar *const var, bool value) override
void BeginConstraintInitialPropagation(Constraint *const constraint) override
Propagation events.
void SetRange(IntVar *const var, int64_t new_min, int64_t new_max) override
void EndNestedConstraintInitialPropagation(Constraint *const parent, Constraint *const nested) override
void EndConstraintInitialPropagation(Constraint *const constraint) override
void SetMax(IntVar *const var, int64_t new_max) override
void StartProcessingIntegerVariable(IntVar *const var) override
void RegisterDemon(Demon *const demon) override
void EndDemonRun(Demon *const demon) override
void SetStartRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override
void RankSequence(SequenceVar *const var, const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed) override
void BeginDemonRun(Demon *const demon) override
void SetDurationMin(IntervalVar *const var, int64_t new_min) override
void RankLast(SequenceVar *const var, int index) override
void PushContext(const std::string &context) override
void Add(PropagationMonitor *const monitor)
void RankNotLast(SequenceVar *const var, int index) override
void RemoveValues(IntVar *const var, const std::vector< int64_t > &values) override
void BeginNestedConstraintInitialPropagation(Constraint *const parent, Constraint *const nested) override
void SetMax(IntExpr *const expr, int64_t new_max) override
void RemoveValue(IntVar *const var, int64_t value) override
void SetValues(IntVar *const var, const std::vector< int64_t > &values) override
void RankFirst(SequenceVar *const var, int index) override
SequenceVar modifiers.
void SetEndMin(IntervalVar *const var, int64_t new_min) override
void SetRange(IntExpr *const expr, int64_t new_min, int64_t new_max) override
std::string DebugString() const override
void RankNotFirst(SequenceVar *const var, int index) override
void RemoveInterval(IntVar *const var, int64_t imin, int64_t imax) override
int64_t b
int64_t a
Block * next
#define CP_ON_FAIL
#define CP_TRY(search)
#define CP_DO_FAIL(search)
ABSL_FLAG(bool, cp_trace_propagation, false, "Trace propagation events (constraint and demon executions," " variable modifications).")
void ConstraintSolverFailsHere()
std::string compressed
SatParameters parameters
const std::string name
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GurobiMPCallbackContext * context
const int WARNING
Definition: log_severity.h:31
const int INFO
Definition: log_severity.h:31
const int ERROR
Definition: log_severity.h:32
const int FATAL
Definition: log_severity.h:32
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
void STLDeleteElements(T *container)
Definition: stl_util.h:372
const Collection::value_type::second_type * FindOrNull(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition: map_util.h:60
bool ContainsKey(const Collection &collection, const Key &key)
Definition: map_util.h:200
Collection of objects used to extend the Constraint Solver library.
PropagationMonitor * BuildPrintTrace(Solver *const s)
Definition: trace.cc:878
void InternalSaveBooleanVarValue(Solver *const solver, IntVar *const var)
void InstallDemonProfiler(DemonProfiler *const monitor)
void InstallLocalSearchProfiler(LocalSearchProfiler *monitor)
void CleanVariableOnFail(IntVar *const var)
ModelCache * BuildModelCache(Solver *const solver)
Definition: model_cache.cc:846
int64_t GetProcessMemoryUsage()
Definition: base/sysinfo.cc:85
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
void DeleteLocalSearchProfiler(LocalSearchProfiler *monitor)
void RestoreBoolValue(IntVar *const var)
DemonProfiler * BuildDemonProfiler(Solver *const solver)
bool AcceptDelta(Search *const search, Assignment *delta, Assignment *deltadelta)
void AcceptNeighbor(Search *const search)
LocalSearchMonitor * BuildLocalSearchMonitorMaster(Solver *const s)
PropagationMonitor * BuildTrace(Solver *const s)
void DeleteDemonProfiler(DemonProfiler *const monitor)
bool LocalOptimumReached(Search *const search)
void AcceptUncheckedNeighbor(Search *const search)
LocalSearchProfiler * BuildLocalSearchProfiler(Solver *solver)
STL namespace.
int index
Definition: pack.cc:509
int64_t delta
Definition: resource.cc:1692
BaseVariableAssignmentSelector *const selector_
Definition: search.cc:1865
int64_t current_
Definition: search.cc:2968
Holds semantic information stating that the 'expression' has been cast into 'variable' using the Var(...
StateInfo(Solver::Action a, bool fast)
StateInfo(void *pinfo, int iinfo, int d, int ld)
StateInfo(void *pinfo, int iinfo)
StateMarker(Solver::MarkerType t, const StateInfo &info)
CompressedTrail< void * > rev_ptrs_
std::vector< double * > rev_double_memory_
std::vector< int64_t * > rev_int64_memory_
std::vector< int * > rev_int_memory_
std::vector< BaseObject * > rev_object_memory_
std::vector< IntVar * > rev_boolvar_list_
std::vector< void * > rev_memory_
Trail(int block_size, ConstraintSolverParameters::TrailCompression compression_level)
std::vector< bool > rev_bool_value_
void BacktrackTo(StateMarker *m)
std::vector< bool * > rev_bools_
std::vector< void ** > rev_memory_array_
CompressedTrail< int64_t > rev_int64s_
CompressedTrail< uint64_t > rev_uint64s_
CompressedTrail< double > rev_doubles_
std::vector< BaseObject ** > rev_object_array_memory_
CompressedTrail< int > rev_ints_