27 #include "absl/memory/memory.h"
28 #include "absl/time/clock.h"
29 #include "absl/time/time.h"
44 "Trace propagation events (constraint and demon executions,"
45 " variable modifications).");
48 "show all constraints added to the solver.");
50 "use PrintModelVisitor on model before solving.");
52 "use StatisticsModelVisitor on model before solving.");
54 "Force failure at the beginning of a search.");
55 DEFINE_string(cp_profile_file,
"",
"Export profiling overview to file.");
57 "Print local search profiling data after solving.");
58 DEFINE_bool(cp_name_variables,
false,
"Force all variables to have names.");
60 "Name variables casted from expressions");
62 "Use small compact table constraint when possible.");
64 "Use the O(n log n) cumulative edge finding algorithm described "
65 "in 'Edge Finding Filtering Algorithm for Discrete Cumulative "
66 "Resources in O(kn log n)' by Petr Vilim, CP 2009.");
68 "Use a O(n^2) cumulative time table propagation algorithm.");
70 "Use a synchronized O(n^2 log n) cumulative time table propagation "
73 "Use a sequence constraints for cumulative tasks that have a "
74 "demand greater than half of the capacity of the resource.");
76 "Post temporal disjunctions for all pairs of tasks sharing a "
77 "cumulative resource and that cannot overlap because the sum of "
78 "their demand exceeds the capacity.");
80 "Do not post the edge finder in the cumulative constraints if "
81 "it contains more than this number of tasks");
83 "Diffn constraint adds redundant cumulative constraint");
85 "If true, rmq's will be used in element expressions.");
87 "Number of solutions explored between two solution checks during "
90 "Random seed used in several (but not all) random number "
91 "generators used by the CP solver. Use -1 to auto-generate an"
92 "undeterministic random seed.");
96 #if defined(_MSC_VER) // WINDOWS
97 #pragma warning(disable : 4351 4355)
105 template <
typename T,
typename MethodPointer,
typename... Args>
106 void ForAll(
const std::vector<T*>& objects, MethodPointer method,
107 const Args&... args) {
108 for (T*
const object : objects) {
109 DCHECK(
object !=
nullptr);
110 (
object->*method)(args...);
117 ConstraintSolverParameters Solver::DefaultSolverParameters() {
118 ConstraintSolverParameters params;
119 params.set_compress_trail(ConstraintSolverParameters::NO_COMPRESSION);
120 params.set_trail_block_size(8000);
121 params.set_array_split_size(16);
122 params.set_store_names(
true);
123 params.set_profile_propagation(!FLAGS_cp_profile_file.empty());
124 params.set_trace_propagation(FLAGS_cp_trace_propagation);
125 params.set_trace_search(FLAGS_cp_trace_search);
126 params.set_name_all_variables(FLAGS_cp_name_variables);
127 params.set_profile_file(FLAGS_cp_profile_file);
128 params.set_profile_local_search(FLAGS_cp_print_local_search_profile);
129 params.set_print_local_search_profile(FLAGS_cp_print_local_search_profile);
130 params.set_print_model(FLAGS_cp_print_model);
131 params.set_print_model_stats(FLAGS_cp_model_stats);
132 params.set_disable_solve(FLAGS_cp_disable_solve);
133 params.set_name_cast_variables(FLAGS_cp_name_cast_variables);
134 params.set_print_added_constraints(FLAGS_cp_print_added_constraints);
135 params.set_use_small_table(FLAGS_cp_use_small_table);
136 params.set_use_cumulative_edge_finder(FLAGS_cp_use_cumulative_edge_finder);
137 params.set_use_cumulative_time_table(FLAGS_cp_use_cumulative_time_table);
138 params.set_use_cumulative_time_table_sync(
139 FLAGS_cp_use_cumulative_time_table_sync);
140 params.set_use_sequence_high_demand_tasks(
141 FLAGS_cp_use_sequence_high_demand_tasks);
142 params.set_use_all_possible_disjunctions(
143 FLAGS_cp_use_all_possible_disjunctions);
144 params.set_max_edge_finder_size(FLAGS_cp_max_edge_finder_size);
145 params.set_diffn_use_cumulative(FLAGS_cp_diffn_use_cumulative);
146 params.set_use_element_rmq(FLAGS_cp_use_element_rmq);
147 params.set_check_solution_period(FLAGS_cp_check_solution_period);
162 bool Solver::InstrumentsDemons()
const {
163 return IsProfilingEnabled() || InstrumentsVariables();
166 bool Solver::IsProfilingEnabled()
const {
167 return parameters_.profile_propagation() ||
168 !parameters_.profile_file().empty();
171 bool Solver::IsLocalSearchProfilingEnabled()
const {
172 return parameters_.profile_local_search() ||
173 parameters_.print_local_search_profile();
176 bool Solver::InstrumentsVariables()
const {
177 return parameters_.trace_propagation();
180 bool Solver::NameAllVariables()
const {
181 return parameters_.name_all_variables();
186 Solver::DemonPriority Demon::priority()
const {
187 return Solver::NORMAL_PRIORITY;
190 std::string Demon::DebugString()
const {
return "Demon"; }
192 void Demon::inhibit(Solver*
const s) {
198 void Demon::desinhibit(Solver*
const s) {
200 s->SaveAndSetValue(&
stamp_, s->stamp() - 1);
217 clean_action_(nullptr),
218 clean_variable_(nullptr),
220 instruments_demons_(s->InstrumentsDemons()) {}
230 if (--freeze_level_ == 0) {
236 demon->set_stamp(stamp_ - 1);
237 if (!instruments_demons_) {
238 if (++solver_->demon_runs_[demon->priority()] %
kTestPeriod == 0) {
239 solver_->TopPeriodicCheck();
242 solver_->CheckFail();
244 solver_->GetPropagationMonitor()->BeginDemonRun(demon);
245 if (++solver_->demon_runs_[demon->priority()] %
kTestPeriod == 0) {
246 solver_->TopPeriodicCheck();
249 solver_->CheckFail();
250 solver_->GetPropagationMonitor()->EndDemonRun(demon);
257 while (!var_queue_.empty() || !delayed_queue_.empty()) {
258 if (!var_queue_.empty()) {
259 Demon*
const demon = var_queue_.front();
260 var_queue_.pop_front();
263 DCHECK(!delayed_queue_.empty());
264 Demon*
const demon = delayed_queue_.front();
265 delayed_queue_.pop_front();
274 if (!instruments_demons_) {
276 Demon*
const demon = *it;
277 if (demon->stamp() < stamp_) {
278 DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
279 if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] %
kTestPeriod ==
281 solver_->TopPeriodicCheck();
284 solver_->CheckFail();
289 Demon*
const demon = *it;
290 if (demon->stamp() < stamp_) {
291 DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
292 solver_->GetPropagationMonitor()->BeginDemonRun(demon);
293 if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] %
kTestPeriod ==
295 solver_->TopPeriodicCheck();
298 solver_->CheckFail();
299 solver_->GetPropagationMonitor()->EndDemonRun(demon);
312 DCHECK(demon->priority() == Solver::VAR_PRIORITY);
313 if (demon->stamp() < stamp_) {
314 demon->set_stamp(stamp_);
315 var_queue_.push_back(demon);
316 if (freeze_level_ == 0) {
323 DCHECK(demon->priority() == Solver::DELAYED_PRIORITY);
324 if (demon->stamp() < stamp_) {
325 demon->set_stamp(stamp_);
326 delayed_queue_.push_back(demon);
333 delayed_queue_.clear();
336 if (clean_action_ !=
nullptr) {
337 clean_action_(solver_);
338 clean_action_ =
nullptr;
339 }
else if (clean_variable_ !=
nullptr) {
341 clean_variable_ =
nullptr;
355 DCHECK(clean_variable_ ==
nullptr);
356 clean_action_ = std::move(
a);
360 DCHECK(clean_action_ ==
nullptr);
361 clean_variable_ =
var;
365 DCHECK(clean_variable_ ==
nullptr);
366 clean_action_ =
nullptr;
370 to_add_.push_back(c);
380 for (
int counter = 0; counter < to_add_.size(); ++counter) {
381 Constraint*
const constraint = to_add_[counter];
383 constraint->PostAndPropagate();
391 Solver*
const solver_;
392 std::deque<Demon*> var_queue_;
393 std::deque<Demon*> delayed_queue_;
399 Solver::Action clean_action_;
400 IntVar* clean_variable_;
401 std::vector<Constraint*> to_add_;
403 const bool instruments_demons_;
450 Solver::MarkerType type_;
452 int rev_int64_index_;
453 int rev_uint64_index_;
454 int rev_double_index_;
456 int rev_boolvar_list_index_;
457 int rev_bools_index_;
458 int rev_int_memory_index_;
459 int rev_int64_memory_index_;
460 int rev_double_memory_index_;
461 int rev_object_memory_index_;
462 int rev_object_array_memory_index_;
463 int rev_memory_index_;
464 int rev_memory_array_index_;
472 rev_uint64_index_(0),
473 rev_double_index_(0),
475 rev_boolvar_list_index_(0),
477 rev_int_memory_index_(0),
478 rev_int64_memory_index_(0),
479 rev_double_memory_index_(0),
480 rev_object_memory_index_(0),
481 rev_object_array_memory_index_(0),
494 addrval() : address_(nullptr) {}
495 explicit addrval(T* adr) : address_(adr), old_value_(*adr) {}
496 void restore()
const { (*address_) = old_value_; }
511 explicit TrailPacker(
int block_size) : block_size_(block_size) {}
512 virtual ~TrailPacker() {}
513 int input_size()
const {
return block_size_ *
sizeof(addrval<T>); }
514 virtual void Pack(
const addrval<T>* block, std::string* packed_block) = 0;
515 virtual void Unpack(
const std::string& packed_block, addrval<T>* block) = 0;
518 const int block_size_;
523 class NoCompressionTrailPacker :
public TrailPacker<T> {
525 explicit NoCompressionTrailPacker(
int block_size)
526 : TrailPacker<T>(block_size) {}
527 ~NoCompressionTrailPacker()
override {}
528 void Pack(
const addrval<T>* block, std::string* packed_block)
override {
529 DCHECK(block !=
nullptr);
530 DCHECK(packed_block !=
nullptr);
531 absl::string_view block_str(
reinterpret_cast<const char*
>(block),
533 packed_block->assign(block_str.data(), block_str.size());
535 void Unpack(
const std::string& packed_block, addrval<T>* block)
override {
536 DCHECK(block !=
nullptr);
537 memcpy(block, packed_block.c_str(), packed_block.size());
545 class ZlibTrailPacker :
public TrailPacker<T> {
547 explicit ZlibTrailPacker(
int block_size)
548 : TrailPacker<T>(block_size),
549 tmp_size_(compressBound(this->input_size())),
550 tmp_block_(new char[tmp_size_]) {}
552 ~ZlibTrailPacker()
override {}
554 void Pack(
const addrval<T>* block, std::string* packed_block)
override {
555 DCHECK(block !=
nullptr);
556 DCHECK(packed_block !=
nullptr);
557 uLongf size = tmp_size_;
559 compress(
reinterpret_cast<Bytef*
>(tmp_block_.get()), &size,
560 reinterpret_cast<const Bytef*
>(block), this->input_size());
561 CHECK_EQ(Z_OK, result);
562 absl::string_view block_str;
563 block_str = absl::string_view(tmp_block_.get(), size);
564 packed_block->assign(block_str.data(), block_str.size());
567 void Unpack(
const std::string& packed_block, addrval<T>* block)
override {
568 DCHECK(block !=
nullptr);
569 uLongf size = this->input_size();
571 uncompress(
reinterpret_cast<Bytef*
>(block), &size,
572 reinterpret_cast<const Bytef*
>(packed_block.c_str()),
573 packed_block.size());
574 CHECK_EQ(Z_OK, result);
579 std::unique_ptr<char[]> tmp_block_;
584 class CompressedTrail {
588 ConstraintSolverParameters::TrailCompression compression_level)
589 : block_size_(block_size),
591 free_blocks_(nullptr),
592 data_(new addrval<T>[block_size]),
593 buffer_(new addrval<T>[block_size]),
597 switch (compression_level) {
598 case ConstraintSolverParameters::NO_COMPRESSION: {
599 packer_.reset(
new NoCompressionTrailPacker<T>(block_size));
602 case ConstraintSolverParameters::COMPRESS_WITH_ZLIB: {
603 packer_.reset(
new ZlibTrailPacker<T>(block_size));
607 LOG(ERROR) <<
"Should not be here";
616 memset(data_.get(), 0,
sizeof(*data_.get()) * block_size);
617 memset(buffer_.get(), 0,
sizeof(*buffer_.get()) * block_size);
621 FreeBlocks(free_blocks_);
623 const addrval<T>& Back()
const {
635 buffer_used_ =
false;
636 }
else if (blocks_ !=
nullptr) {
637 packer_->Unpack(blocks_->compressed, data_.get());
645 void PushBack(
const addrval<T>& addr_val) {
649 packer_->Pack(buffer_.get(), &blocks_->compressed);
662 int64 size()
const {
return size_; }
670 void FreeTopBlock() {
671 Block* block = blocks_;
672 blocks_ = block->next;
673 block->compressed.clear();
674 block->next = free_blocks_;
675 free_blocks_ = block;
678 Block* block =
nullptr;
679 if (free_blocks_ !=
nullptr) {
680 block = free_blocks_;
681 free_blocks_ = block->next;
685 block->next = blocks_;
688 void FreeBlocks(Block* blocks) {
689 while (
nullptr != blocks) {
690 Block*
next = blocks->next;
696 std::unique_ptr<TrailPacker<T> > packer_;
697 const int block_size_;
700 std::unique_ptr<addrval<T>[]> data_;
701 std::unique_ptr<addrval<T>[]> buffer_;
734 ConstraintSolverParameters::TrailCompression compression_level)
735 :
rev_ints_(block_size, compression_level),
739 rev_ptrs_(block_size, compression_level) {}
742 int target = m->rev_int_index_;
743 for (
int curr =
rev_ints_.size(); curr > target; --curr) {
744 const addrval<int>& cell =
rev_ints_.Back();
750 target = m->rev_int64_index_;
751 for (
int curr =
rev_int64s_.size(); curr > target; --curr) {
758 target = m->rev_uint64_index_;
759 for (
int curr =
rev_uint64s_.size(); curr > target; --curr) {
766 target = m->rev_double_index_;
767 for (
int curr =
rev_doubles_.size(); curr > target; --curr) {
774 target = m->rev_ptr_index_;
775 for (
int curr =
rev_ptrs_.size(); curr > target; --curr) {
776 const addrval<void*>& cell =
rev_ptrs_.Back();
782 target = m->rev_boolvar_list_index_;
790 target = m->rev_bools_index_;
791 for (
int curr =
rev_bools_.size() - 1; curr >= target; --curr) {
797 target = m->rev_int_memory_index_;
803 target = m->rev_int64_memory_index_;
809 target = m->rev_double_memory_index_;
815 target = m->rev_object_memory_index_;
821 target = m->rev_object_array_memory_index_;
828 target = m->rev_memory_index_;
829 for (
int curr =
rev_memory_.size() - 1; curr >= target; --curr) {
831 ::operator
delete(
reinterpret_cast<char*
>(
rev_memory_[curr]));
840 target = m->rev_memory_array_index_;
849 void Solver::InternalSaveValue(
int* valptr) {
850 trail_->rev_ints_.PushBack(addrval<int>(valptr));
853 void Solver::InternalSaveValue(
int64* valptr) {
854 trail_->rev_int64s_.PushBack(addrval<int64>(valptr));
857 void Solver::InternalSaveValue(
uint64* valptr) {
858 trail_->rev_uint64s_.PushBack(addrval<uint64>(valptr));
861 void Solver::InternalSaveValue(
double* valptr) {
862 trail_->rev_doubles_.PushBack(addrval<double>(valptr));
865 void Solver::InternalSaveValue(
void** valptr) {
866 trail_->rev_ptrs_.PushBack(addrval<void*>(valptr));
872 void Solver::InternalSaveValue(
bool* valptr) {
873 trail_->rev_bools_.push_back(valptr);
874 trail_->rev_bool_value_.push_back(*valptr);
877 BaseObject* Solver::SafeRevAlloc(BaseObject* ptr) {
879 trail_->rev_object_memory_.push_back(ptr);
883 int* Solver::SafeRevAllocArray(
int* ptr) {
885 trail_->rev_int_memory_.push_back(ptr);
889 int64* Solver::SafeRevAllocArray(
int64* ptr) {
891 trail_->rev_int64_memory_.push_back(ptr);
895 double* Solver::SafeRevAllocArray(
double* ptr) {
897 trail_->rev_double_memory_.push_back(ptr);
903 trail_->rev_int64_memory_.push_back(
reinterpret_cast<int64*
>(ptr));
907 BaseObject** Solver::SafeRevAllocArray(BaseObject** ptr) {
909 trail_->rev_object_array_memory_.push_back(ptr);
913 IntVar** Solver::SafeRevAllocArray(IntVar** ptr) {
914 BaseObject** in = SafeRevAllocArray(
reinterpret_cast<BaseObject**
>(ptr));
915 return reinterpret_cast<IntVar**
>(in);
918 IntExpr** Solver::SafeRevAllocArray(IntExpr** ptr) {
919 BaseObject** in = SafeRevAllocArray(
reinterpret_cast<BaseObject**
>(ptr));
920 return reinterpret_cast<IntExpr**
>(in);
923 Constraint** Solver::SafeRevAllocArray(Constraint** ptr) {
924 BaseObject** in = SafeRevAllocArray(
reinterpret_cast<BaseObject**
>(ptr));
925 return reinterpret_cast<Constraint**
>(in);
928 void* Solver::UnsafeRevAllocAux(
void* ptr) {
930 trail_->rev_memory_.push_back(ptr);
934 void** Solver::UnsafeRevAllocArrayAux(
void** ptr) {
936 trail_->rev_memory_array_.push_back(ptr);
941 solver->trail_->rev_boolvar_list_.push_back(
var);
952 solution_counter_(0),
953 unchecked_solution_counter_(0),
954 decision_builder_(nullptr),
955 created_by_solve_(false),
957 left_search_depth_(0),
958 should_restart_(false),
959 should_finish_(false),
961 jmpbuf_filled_(false),
962 backtrack_at_the_end_of_the_search_(true) {}
971 solution_counter_(0),
972 unchecked_solution_counter_(0),
973 decision_builder_(nullptr),
974 created_by_solve_(false),
976 left_search_depth_(-1),
977 should_restart_(false),
978 should_finish_(false),
980 jmpbuf_filled_(false),
981 backtrack_at_the_end_of_the_search_(true) {}
1007 void Accept(ModelVisitor*
const visitor)
const;
1014 return unchecked_solution_counter_;
1017 decision_builder_ = db;
1026 left_search_depth_++;
1030 return backtrack_at_the_end_of_the_search_;
1033 backtrack_at_the_end_of_the_search_ = restore;
1044 if (should_finish_ || should_restart_) {
1057 void ClearBuffer() {
1058 CHECK(jmpbuf_filled_) <<
"Internal error in backtracking";
1059 jmpbuf_filled_ =
false;
1063 std::vector<StateMarker*> marker_stack_;
1064 std::vector<SearchMonitor*> monitors_;
1065 jmp_buf fail_buffer_;
1066 int64 solution_counter_;
1067 int64 unchecked_solution_counter_;
1068 DecisionBuilder* decision_builder_;
1069 bool created_by_solve_;
1072 int left_search_depth_;
1073 bool should_restart_;
1074 bool should_finish_;
1075 int sentinel_pushed_;
1076 bool jmpbuf_filled_;
1077 bool backtrack_at_the_end_of_the_search_;
1078 std::string search_context_;
1091 #ifndef CP_USE_EXCEPTIONS_FOR_BACKTRACK
1094 #define CP_TRY(search) \
1095 CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
1096 search->jmpbuf_filled_ = true; \
1097 if (setjmp(search->fail_buffer_) == 0)
1098 #define CP_ON_FAIL else
1099 #define CP_DO_FAIL(search) longjmp(search->fail_buffer_, 1)
1100 #else // CP_USE_EXCEPTIONS_FOR_BACKTRACK
1101 class FailException {};
1102 #define CP_TRY(search) \
1103 CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
1104 search->jmpbuf_filled_ = true; \
1106 #define CP_ON_FAIL catch (FailException&)
1107 #define CP_DO_FAIL(search) throw FailException()
1108 #endif // CP_USE_EXCEPTIONS_FOR_BACKTRACK
1110 void Search::JumpBack() {
1111 if (jmpbuf_filled_) {
1112 jmpbuf_filled_ =
false;
1115 std::string explanation =
"Failure outside of search";
1116 solver_->AddConstraint(solver_->MakeFalseConstraint(explanation));
1120 Search* Solver::ActiveSearch()
const {
return searches_.back(); }
1123 class ApplyBranchSelector :
public DecisionBuilder {
1125 explicit ApplyBranchSelector(Solver::BranchSelector bs)
1127 ~ApplyBranchSelector()
override {}
1129 Decision* Next(Solver*
const s)
override {
1134 std::string DebugString()
const override {
return "Apply(BranchSelector)"; }
1142 selector_ = std::move(bs);
1145 void Solver::SetBranchSelector(BranchSelector bs) {
1149 const int solve_depth = SolveDepth();
1151 [solve_depth](Solver* s) {
1152 if (s->SolveDepth() == solve_depth) {
1153 s->ActiveSearch()->SetBranchSelector(nullptr);
1157 searches_.back()->SetBranchSelector(std::move(bs));
1160 DecisionBuilder* Solver::MakeApplyBranchSelector(BranchSelector bs) {
1161 return RevAlloc(
new ApplyBranchSelector(std::move(bs)));
1164 int Solver::SolveDepth()
const {
1165 return state_ == OUTSIDE_SEARCH ? 0 : searches_.size() - 1;
1168 int Solver::SearchDepth()
const {
return searches_.back()->search_depth(); }
1170 int Solver::SearchLeftDepth()
const {
1171 return searches_.back()->left_search_depth();
1175 if (selector_ !=
nullptr) {
1178 return Solver::NO_CHANGE;
1183 monitors_.push_back(m);
1190 left_search_depth_ = 0;
1191 selector_ =
nullptr;
1192 backtrack_at_the_end_of_the_search_ =
true;
1199 solution_counter_ = 0;
1200 unchecked_solution_counter_ = 0;
1202 ForAll(monitors_, &SearchMonitor::EnterSearch);
1207 ForAll(monitors_, &SearchMonitor::ExitSearch);
1211 ForAll(monitors_, &SearchMonitor::RestartSearch);
1215 ForAll(monitors_, &SearchMonitor::BeginNextDecision, db);
1220 ForAll(monitors_, &SearchMonitor::EndNextDecision, db, d);
1225 ForAll(monitors_, &SearchMonitor::ApplyDecision, d);
1230 ForAll(monitors_, &SearchMonitor::AfterDecision, d, apply);
1235 ForAll(monitors_, &SearchMonitor::RefuteDecision, d);
1244 ForAll(monitors_, &SearchMonitor::BeginInitialPropagation);
1248 ForAll(monitors_, &SearchMonitor::EndInitialPropagation);
1253 for (SearchMonitor*
const monitor : monitors_) {
1254 if (!monitor->AcceptSolution()) {
1265 bool should_continue =
false;
1266 for (SearchMonitor*
const monitor : monitors_) {
1267 if (monitor->AtSolution()) {
1271 should_continue =
true;
1274 return should_continue;
1278 ForAll(monitors_, &SearchMonitor::NoMoreSolutions);
1283 for (SearchMonitor*
const monitor : monitors_) {
1284 if (monitor->LocalOptimum()) {
1293 for (SearchMonitor*
const monitor : monitors_) {
1294 if (!monitor->AcceptDelta(
delta, deltadelta)) {
1310 for (SearchMonitor*
const monitor : monitors_) {
1311 if (monitor->IsUncheckedSolutionLimitReached()) {
1319 ForAll(monitors_, &SearchMonitor::PeriodicCheck);
1323 int progress = SearchMonitor::kNoProgress;
1324 for (SearchMonitor*
const monitor : monitors_) {
1325 progress =
std::max(progress, monitor->ProgressPercent());
1331 ForAll(monitors_, &SearchMonitor::Accept, visitor);
1332 if (decision_builder_ !=
nullptr) {
1333 decision_builder_->Accept(visitor);
1342 Assignment* deltadelta) {
1356 class FailDecision :
public Decision {
1358 void Apply(Solver*
const s)
override { s->Fail(); }
1359 void Refute(Solver*
const s)
override { s->Fail(); }
1364 class BalancingDecision :
public Decision {
1366 ~BalancingDecision()
override {}
1367 void Apply(Solver*
const s)
override {}
1368 void Refute(Solver*
const s)
override {}
1372 Decision* Solver::MakeFailDecision() {
return fail_decision_.get(); }
1379 enum SentinelMarker {
1380 INITIAL_SEARCH_SENTINEL = 10000000,
1381 ROOT_NODE_SENTINEL = 20000000,
1382 SOLVER_CTOR_SENTINEL = 40000000
1386 extern PropagationMonitor*
BuildTrace(Solver*
const s);
1390 std::string Solver::model_name()
const {
return name_; }
1393 void CheckSolverParameters(
const ConstraintSolverParameters&
parameters) {
1395 <<
"Were parameters built using Solver::DefaultSolverParameters() ?";
1399 Solver::Solver(
const std::string&
name,
1400 const ConstraintSolverParameters&
parameters)
1403 random_(CpRandomSeed()),
1405 use_fast_local_search_(true),
1410 Solver::Solver(
const std::string&
name)
1412 parameters_(DefaultSolverParameters()),
1413 random_(CpRandomSeed()),
1415 use_fast_local_search_(true),
1420 void Solver::Init() {
1421 CheckSolverParameters(parameters_);
1422 queue_ = absl::make_unique<Queue>(
this);
1423 trail_ = absl::make_unique<Trail>(parameters_.trail_block_size(),
1424 parameters_.compress_trail());
1425 state_ = OUTSIDE_SEARCH;
1430 filtered_neighbors_ = 0;
1431 accepted_neighbors_ = 0;
1432 optimization_direction_ = NOT_SET;
1433 timer_ = absl::make_unique<ClockTimer>();
1434 searches_.assign(1,
new Search(
this, 0));
1436 balancing_decision_ = absl::make_unique<BalancingDecision>();
1437 fail_intercept_ =
nullptr;
1438 true_constraint_ =
nullptr;
1439 false_constraint_ =
nullptr;
1440 fail_decision_ = absl::make_unique<FailDecision>();
1441 constraint_index_ = 0;
1442 additional_constraint_index_ = 0;
1444 propagation_monitor_.reset(
BuildTrace(
this));
1446 print_trace_ =
nullptr;
1447 anonymous_variable_index_ = 0;
1448 should_fail_ =
false;
1450 for (
int i = 0; i < kNumPriorities; ++i) {
1453 searches_.push_back(
new Search(
this));
1454 PushSentinel(SOLVER_CTOR_SENTINEL);
1455 InitCachedIntConstants();
1456 InitCachedConstraint();
1459 AddPropagationMonitor(
reinterpret_cast<PropagationMonitor*
>(demon_profiler_));
1460 AddLocalSearchMonitor(
1461 reinterpret_cast<LocalSearchMonitor*
>(local_search_profiler_));
1466 CHECK_EQ(2, searches_.size());
1467 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
1470 Solver::MarkerType finalType = PopState(&info);
1472 DCHECK_EQ(finalType, SENTINEL);
1474 DCHECK_EQ(info.int_info, SOLVER_CTOR_SENTINEL);
1480 std::string Solver::DebugString()
const {
1481 std::string out =
"Solver(name = \"" + name_ +
"\", state = ";
1483 case OUTSIDE_SEARCH:
1484 out +=
"OUTSIDE_SEARCH";
1487 out +=
"IN_ROOT_NODE";
1493 out +=
"AT_SOLUTION";
1495 case NO_MORE_SOLUTIONS:
1496 out +=
"NO_MORE_SOLUTIONS";
1498 case PROBLEM_INFEASIBLE:
1499 out +=
"PROBLEM_INFEASIBLE";
1502 absl::StrAppendFormat(
1504 ", branches = %d, fails = %d, decisions = %d, delayed demon runs = %d, "
1505 "var demon runs = %d, normal demon runs = %d, Run time = %d ms)",
1506 branches_, fails_, decisions_, demon_runs_[DELAYED_PRIORITY],
1507 demon_runs_[VAR_PRIORITY], demon_runs_[NORMAL_PRIORITY], wall_time());
1513 int64 Solver::wall_time()
const {
1514 return absl::ToInt64Milliseconds(timer_->GetDuration());
1517 absl::Time Solver::Now()
const {
1518 return absl::FromUnixSeconds(0) + timer_->GetDuration();
1521 int64 Solver::solutions()
const {
return TopLevelSearch()->solution_counter(); }
1523 int64 Solver::unchecked_solutions()
const {
1524 return TopLevelSearch()->unchecked_solution_counter();
1527 void Solver::IncrementUncheckedSolutionCounter() {
1528 TopLevelSearch()->IncrementUncheckedSolutionCounter();
1531 bool Solver::IsUncheckedSolutionLimitReached() {
1532 return TopLevelSearch()->IsUncheckedSolutionLimitReached();
1535 void Solver::TopPeriodicCheck() { TopLevelSearch()->PeriodicCheck(); }
1537 int Solver::TopProgressPercent() {
return TopLevelSearch()->ProgressPercent(); }
1539 void Solver::PushState() {
1541 PushState(SIMPLE_MARKER, info);
1544 void Solver::PopState() {
1546 Solver::MarkerType t = PopState(&info);
1547 CHECK_EQ(SIMPLE_MARKER, t);
1550 void Solver::PushState(Solver::MarkerType t,
const StateInfo& info) {
1551 StateMarker* m =
new StateMarker(t, info);
1552 if (t != REVERSIBLE_ACTION || info.int_info == 0) {
1553 m->rev_int_index_ = trail_->rev_ints_.size();
1554 m->rev_int64_index_ = trail_->rev_int64s_.size();
1555 m->rev_uint64_index_ = trail_->rev_uint64s_.size();
1556 m->rev_double_index_ = trail_->rev_doubles_.size();
1557 m->rev_ptr_index_ = trail_->rev_ptrs_.size();
1558 m->rev_boolvar_list_index_ = trail_->rev_boolvar_list_.size();
1559 m->rev_bools_index_ = trail_->rev_bools_.size();
1560 m->rev_int_memory_index_ = trail_->rev_int_memory_.size();
1561 m->rev_int64_memory_index_ = trail_->rev_int64_memory_.size();
1562 m->rev_double_memory_index_ = trail_->rev_double_memory_.size();
1563 m->rev_object_memory_index_ = trail_->rev_object_memory_.size();
1564 m->rev_object_array_memory_index_ = trail_->rev_object_array_memory_.size();
1565 m->rev_memory_index_ = trail_->rev_memory_.size();
1566 m->rev_memory_array_index_ = trail_->rev_memory_array_.size();
1568 searches_.back()->marker_stack_.push_back(m);
1569 queue_->increase_stamp();
1572 void Solver::AddBacktrackAction(Action
a,
bool fast) {
1573 StateInfo info(std::move(
a), fast);
1574 PushState(REVERSIBLE_ACTION, info);
1577 Solver::MarkerType Solver::PopState(StateInfo* info) {
1578 CHECK(!searches_.back()->marker_stack_.empty())
1579 <<
"PopState() on an empty stack";
1580 CHECK(info !=
nullptr);
1581 StateMarker*
const m = searches_.back()->marker_stack_.back();
1582 if (m->type_ != REVERSIBLE_ACTION || m->info_.int_info == 0) {
1583 trail_->BacktrackTo(m);
1585 Solver::MarkerType t = m->type_;
1587 searches_.back()->marker_stack_.pop_back();
1589 queue_->increase_stamp();
1593 void Solver::check_alloc_state() {
1595 case OUTSIDE_SEARCH:
1598 case NO_MORE_SOLUTIONS:
1599 case PROBLEM_INFEASIBLE:
1602 LOG(FATAL) <<
"allocating at a leaf node";
1604 LOG(FATAL) <<
"This switch was supposed to be exhaustive, but it is not!";
1608 void Solver::FreezeQueue() { queue_->Freeze(); }
1610 void Solver::UnfreezeQueue() { queue_->Unfreeze(); }
1612 void Solver::EnqueueVar(Demon*
const d) { queue_->EnqueueVar(d); }
1614 void Solver::EnqueueDelayedDemon(Demon*
const d) {
1615 queue_->EnqueueDelayedDemon(d);
1618 void Solver::ExecuteAll(
const SimpleRevFIFO<Demon*>& demons) {
1619 queue_->ExecuteAll(demons);
1622 void Solver::EnqueueAll(
const SimpleRevFIFO<Demon*>& demons) {
1623 queue_->EnqueueAll(demons);
1626 uint64 Solver::stamp()
const {
return queue_->stamp(); }
1628 uint64 Solver::fail_stamp()
const {
return fail_stamp_; }
1630 void Solver::set_action_on_fail(Action
a) {
1631 queue_->set_action_on_fail(std::move(
a));
1634 void Solver::set_variable_to_clean_on_fail(IntVar* v) {
1635 queue_->set_variable_to_clean_on_fail(v);
1638 void Solver::reset_action_on_fail() { queue_->reset_action_on_fail(); }
1640 void Solver::AddConstraint(Constraint*
const c) {
1641 DCHECK(c !=
nullptr);
1642 if (c == true_constraint_) {
1645 if (state_ == IN_SEARCH) {
1646 queue_->AddConstraint(c);
1647 }
else if (state_ == IN_ROOT_NODE) {
1648 DCHECK_GE(constraint_index_, 0);
1649 DCHECK_LE(constraint_index_, constraints_list_.size());
1650 const int constraint_parent =
1651 constraint_index_ == constraints_list_.size()
1652 ? additional_constraints_parent_list_[additional_constraint_index_]
1653 : constraint_index_;
1654 additional_constraints_list_.push_back(c);
1655 additional_constraints_parent_list_.push_back(constraint_parent);
1657 if (parameters_.print_added_constraints()) {
1658 LOG(INFO) << c->DebugString();
1660 constraints_list_.push_back(c);
1664 void Solver::AddCastConstraint(CastConstraint*
const constraint,
1665 IntVar*
const target_var, IntExpr*
const expr) {
1666 if (constraint !=
nullptr) {
1667 if (state_ != IN_SEARCH) {
1668 cast_constraints_.insert(constraint);
1669 cast_information_[target_var] =
1670 Solver::IntegerCastInfo(target_var, expr, constraint);
1672 AddConstraint(constraint);
1676 void Solver::Accept(ModelVisitor*
const visitor)
const {
1677 visitor->BeginVisitModel(name_);
1678 ForAll(constraints_list_, &Constraint::Accept, visitor);
1679 visitor->EndVisitModel(name_);
1682 void Solver::ProcessConstraints() {
1685 if (parameters_.print_model()) {
1686 ModelVisitor*
const visitor = MakePrintModelVisitor();
1689 if (parameters_.print_model_stats()) {
1690 ModelVisitor*
const visitor = MakeStatisticsModelVisitor();
1694 if (parameters_.disable_solve()) {
1695 LOG(INFO) <<
"Forcing early failure";
1700 const int constraints_size = constraints_list_.size();
1701 additional_constraints_list_.clear();
1702 additional_constraints_parent_list_.clear();
1704 for (constraint_index_ = 0; constraint_index_ < constraints_size;
1705 ++constraint_index_) {
1706 Constraint*
const constraint = constraints_list_[constraint_index_];
1707 propagation_monitor_->BeginConstraintInitialPropagation(constraint);
1708 constraint->PostAndPropagate();
1709 propagation_monitor_->EndConstraintInitialPropagation(constraint);
1711 CHECK_EQ(constraints_list_.size(), constraints_size);
1714 for (
int additional_constraint_index_ = 0;
1715 additional_constraint_index_ < additional_constraints_list_.size();
1716 ++additional_constraint_index_) {
1717 Constraint*
const nested =
1718 additional_constraints_list_[additional_constraint_index_];
1719 const int parent_index =
1720 additional_constraints_parent_list_[additional_constraint_index_];
1721 Constraint*
const parent = constraints_list_[parent_index];
1722 propagation_monitor_->BeginNestedConstraintInitialPropagation(parent,
1724 nested->PostAndPropagate();
1725 propagation_monitor_->EndNestedConstraintInitialPropagation(parent, nested);
1729 bool Solver::CurrentlyInSolve()
const {
1730 DCHECK_GT(SolveDepth(), 0);
1731 DCHECK(searches_.back() !=
nullptr);
1732 return searches_.back()->created_by_solve();
1735 bool Solver::Solve(DecisionBuilder*
const db, SearchMonitor*
const m1) {
1736 std::vector<SearchMonitor*> monitors;
1737 monitors.push_back(m1);
1738 return Solve(db, monitors);
1742 std::vector<SearchMonitor*> monitors;
1743 return Solve(db, monitors);
1746 bool Solver::Solve(DecisionBuilder*
const db, SearchMonitor*
const m1,
1747 SearchMonitor*
const m2) {
1748 std::vector<SearchMonitor*> monitors;
1749 monitors.push_back(m1);
1750 monitors.push_back(m2);
1751 return Solve(db, monitors);
1754 bool Solver::Solve(DecisionBuilder*
const db, SearchMonitor*
const m1,
1755 SearchMonitor*
const m2, SearchMonitor*
const m3) {
1756 std::vector<SearchMonitor*> monitors;
1757 monitors.push_back(m1);
1758 monitors.push_back(m2);
1759 monitors.push_back(m3);
1760 return Solve(db, monitors);
1763 bool Solver::Solve(DecisionBuilder*
const db, SearchMonitor*
const m1,
1764 SearchMonitor*
const m2, SearchMonitor*
const m3,
1765 SearchMonitor*
const m4) {
1766 std::vector<SearchMonitor*> monitors;
1767 monitors.push_back(m1);
1768 monitors.push_back(m2);
1769 monitors.push_back(m3);
1770 monitors.push_back(m4);
1771 return Solve(db, monitors);
1775 const std::vector<SearchMonitor*>& monitors) {
1776 NewSearch(db, monitors);
1777 searches_.back()->set_created_by_solve(
true);
1779 const bool solution_found = searches_.back()->solution_counter() > 0;
1781 return solution_found;
1784 void Solver::NewSearch(DecisionBuilder*
const db, SearchMonitor*
const m1) {
1785 std::vector<SearchMonitor*> monitors;
1786 monitors.push_back(m1);
1787 return NewSearch(db, monitors);
1790 void Solver::NewSearch(DecisionBuilder*
const db) {
1791 std::vector<SearchMonitor*> monitors;
1792 return NewSearch(db, monitors);
1795 void Solver::NewSearch(DecisionBuilder*
const db, SearchMonitor*
const m1,
1796 SearchMonitor*
const m2) {
1797 std::vector<SearchMonitor*> monitors;
1798 monitors.push_back(m1);
1799 monitors.push_back(m2);
1800 return NewSearch(db, monitors);
1803 void Solver::NewSearch(DecisionBuilder*
const db, SearchMonitor*
const m1,
1804 SearchMonitor*
const m2, SearchMonitor*
const m3) {
1805 std::vector<SearchMonitor*> monitors;
1806 monitors.push_back(m1);
1807 monitors.push_back(m2);
1808 monitors.push_back(m3);
1809 return NewSearch(db, monitors);
1812 void Solver::NewSearch(DecisionBuilder*
const db, SearchMonitor*
const m1,
1813 SearchMonitor*
const m2, SearchMonitor*
const m3,
1814 SearchMonitor*
const m4) {
1815 std::vector<SearchMonitor*> monitors;
1816 monitors.push_back(m1);
1817 monitors.push_back(m2);
1818 monitors.push_back(m3);
1819 monitors.push_back(m4);
1820 return NewSearch(db, monitors);
1826 void Solver::NewSearch(DecisionBuilder*
const db,
1827 const std::vector<SearchMonitor*>& monitors) {
1830 CHECK(db !=
nullptr);
1831 const bool nested = state_ == IN_SEARCH;
1833 if (state_ == IN_ROOT_NODE) {
1834 LOG(FATAL) <<
"Cannot start new searches here.";
1837 Search*
const search = nested ?
new Search(
this) : searches_.back();
1838 search->set_created_by_solve(
false);
1844 DCHECK_GE(searches_.size(), 2);
1845 searches_.push_back(search);
1849 DCHECK_EQ(2, searches_.size());
1851 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
1852 state_ = OUTSIDE_SEARCH;
1858 propagation_monitor_->Install();
1859 if (demon_profiler_ !=
nullptr) {
1862 local_search_monitor_->Install();
1863 if (local_search_profiler_ !=
nullptr) {
1868 for (SearchMonitor*
const monitor : monitors) {
1869 if (monitor !=
nullptr) {
1873 std::vector<SearchMonitor*> extras;
1874 db->AppendMonitors(
this, &extras);
1875 for (SearchMonitor*
const monitor : extras) {
1876 if (monitor !=
nullptr) {
1883 if (print_trace_ !=
nullptr) {
1884 print_trace_->Install();
1887 print_trace_ =
nullptr;
1888 if (parameters_.trace_propagation()) {
1890 print_trace_->Install();
1891 }
else if (parameters_.trace_search()) {
1896 SearchMonitor*
const trace = MakeSearchTrace(
"######## ");
1903 search->EnterSearch();
1906 PushSentinel(INITIAL_SEARCH_SENTINEL);
1907 search->set_decision_builder(db);
1912 bool Solver::BacktrackOneLevel(Decision**
const fail_decision) {
1913 bool no_more_solutions =
false;
1914 bool end_loop =
false;
1917 Solver::MarkerType t = PopState(&info);
1920 CHECK_EQ(info.ptr_info,
this) <<
"Wrong sentinel found";
1921 CHECK((info.int_info == ROOT_NODE_SENTINEL && SolveDepth() == 1) ||
1922 (info.int_info == INITIAL_SEARCH_SENTINEL && SolveDepth() > 1));
1923 searches_.back()->sentinel_pushed_--;
1924 no_more_solutions =
true;
1928 LOG(ERROR) <<
"Simple markers should not be encountered during search";
1931 if (info.int_info == 0) {
1932 (*fail_decision) =
reinterpret_cast<Decision*
>(info.ptr_info);
1934 searches_.back()->set_search_depth(info.depth);
1935 searches_.back()->set_search_left_depth(info.left_depth);
1938 case REVERSIBLE_ACTION: {
1939 if (info.reversible_action !=
nullptr) {
1940 info.reversible_action(
this);
1946 Search*
const search = searches_.back();
1949 if (no_more_solutions) {
1950 search->NoMoreSolutions();
1952 return no_more_solutions;
1955 void Solver::PushSentinel(
int magic_code) {
1956 StateInfo info(
this, magic_code);
1957 PushState(SENTINEL, info);
1959 if (magic_code != SOLVER_CTOR_SENTINEL) {
1960 searches_.back()->sentinel_pushed_++;
1962 const int pushed = searches_.back()->sentinel_pushed_;
1963 DCHECK((magic_code == SOLVER_CTOR_SENTINEL) ||
1964 (magic_code == INITIAL_SEARCH_SENTINEL && pushed == 1) ||
1965 (magic_code == ROOT_NODE_SENTINEL && pushed == 2));
1968 void Solver::RestartSearch() {
1969 Search*
const search = searches_.back();
1970 CHECK_NE(0, search->sentinel_pushed_);
1971 if (SolveDepth() == 1) {
1972 if (search->sentinel_pushed_ > 1) {
1973 BacktrackToSentinel(ROOT_NODE_SENTINEL);
1975 CHECK_EQ(1, search->sentinel_pushed_);
1976 PushSentinel(ROOT_NODE_SENTINEL);
1979 CHECK_EQ(IN_SEARCH, state_);
1980 if (search->sentinel_pushed_ > 0) {
1981 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
1983 CHECK_EQ(0, search->sentinel_pushed_);
1984 PushSentinel(INITIAL_SEARCH_SENTINEL);
1987 search->RestartSearch();
1992 void Solver::BacktrackToSentinel(
int magic_code) {
1993 Search*
const search = searches_.back();
1994 bool end_loop = search->sentinel_pushed_ == 0;
1997 Solver::MarkerType t = PopState(&info);
2000 CHECK_EQ(info.ptr_info,
this) <<
"Wrong sentinel found";
2001 CHECK_GE(--search->sentinel_pushed_, 0);
2002 search->set_search_depth(0);
2003 search->set_search_left_depth(0);
2005 if (info.int_info == magic_code) {
2014 case REVERSIBLE_ACTION: {
2015 info.reversible_action(
this);
2024 void Solver::JumpToSentinelWhenNested() {
2025 CHECK_GT(SolveDepth(), 1) <<
"calling JumpToSentinel from top level";
2026 Search* c = searches_.back();
2027 Search* p = ParentSearch();
2029 while (!c->marker_stack_.empty()) {
2030 StateMarker*
const m = c->marker_stack_.back();
2031 if (m->type_ == REVERSIBLE_ACTION) {
2032 p->marker_stack_.push_back(m);
2034 if (m->type_ == SENTINEL) {
2035 CHECK_EQ(c->marker_stack_.size(), 1) <<
"Sentinel found too early";
2040 c->marker_stack_.pop_back();
2042 c->set_search_depth(0);
2043 c->set_search_left_depth(0);
2044 CHECK_EQ(found,
true) <<
"Sentinel not found";
2048 class ReverseDecision :
public Decision {
2050 explicit ReverseDecision(Decision*
const d) : decision_(d) {
2051 CHECK(d !=
nullptr);
2053 ~ReverseDecision()
override {}
2055 void Apply(Solver*
const s)
override { decision_->Refute(s); }
2057 void Refute(Solver*
const s)
override { decision_->Apply(s); }
2059 void Accept(DecisionVisitor*
const visitor)
const override {
2060 decision_->Accept(visitor);
2063 std::string DebugString()
const override {
2064 std::string str =
"Reverse(";
2065 str += decision_->DebugString();
2071 Decision*
const decision_;
2076 bool Solver::NextSolution() {
2077 Search*
const search = searches_.back();
2078 Decision* fd =
nullptr;
2079 const int solve_depth = SolveDepth();
2080 const bool top_level = solve_depth <= 1;
2082 if (solve_depth == 0 && !search->decision_builder()) {
2083 LOG(WARNING) <<
"NextSolution() called without a NewSearch before";
2089 case PROBLEM_INFEASIBLE:
2091 case NO_MORE_SOLUTIONS:
2094 if (BacktrackOneLevel(&fd)) {
2095 state_ = NO_MORE_SOLUTIONS;
2101 case OUTSIDE_SEARCH: {
2102 state_ = IN_ROOT_NODE;
2103 search->BeginInitialPropagation();
2105 ProcessConstraints();
2106 search->EndInitialPropagation();
2107 PushSentinel(ROOT_NODE_SENTINEL);
2109 search->ClearBuffer();
2112 queue_->AfterFailure();
2113 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2114 state_ = PROBLEM_INFEASIBLE;
2122 LOG(FATAL) <<
"Should not happen";
2127 volatile bool finish =
false;
2128 volatile bool result =
false;
2129 DecisionBuilder*
const db = search->decision_builder();
2133 if (fd !=
nullptr) {
2134 StateInfo i1(fd, 1, search->search_depth(),
2135 search->left_search_depth());
2136 PushState(CHOICE_POINT, i1);
2137 search->RefuteDecision(fd);
2143 search->AfterDecision(fd,
false);
2144 search->RightMove();
2147 Decision* d =
nullptr;
2149 search->BeginNextDecision(db);
2151 search->EndNextDecision(db, d);
2152 if (d == fail_decision_.get()) {
2156 DecisionModification modification = search->ModifyDecision();
2157 switch (modification) {
2158 case SWITCH_BRANCHES: {
2159 d = RevAlloc(
new ReverseDecision(d));
2161 ABSL_FALLTHROUGH_INTENDED;
2165 StateInfo i2(d, 0, search->search_depth(),
2166 search->left_search_depth());
2167 PushState(CHOICE_POINT, i2);
2168 search->ApplyDecision(d);
2172 search->AfterDecision(d,
true);
2177 search->ApplyDecision(d);
2180 search->AfterDecision(d,
true);
2184 search->RefuteDecision(d);
2187 search->AfterDecision(d,
false);
2198 if (search->AcceptSolution()) {
2199 search->IncrementSolutionCounter();
2200 if (!search->AtSolution() || !CurrentlyInSolve()) {
2211 queue_->AfterFailure();
2212 if (search->should_finish()) {
2214 BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
2215 : INITIAL_SEARCH_SENTINEL);
2218 search->set_should_finish(
false);
2219 search->set_should_restart(
false);
2221 }
else if (search->should_restart()) {
2223 BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
2224 : INITIAL_SEARCH_SENTINEL);
2225 search->set_should_finish(
false);
2226 search->set_should_restart(
false);
2227 PushSentinel(top_level ? ROOT_NODE_SENTINEL : INITIAL_SEARCH_SENTINEL);
2228 search->RestartSearch();
2230 if (BacktrackOneLevel(&fd)) {
2238 search->ClearBuffer();
2241 state_ = (result ? AT_SOLUTION : NO_MORE_SOLUTIONS);
2246 void Solver::EndSearch() {
2247 Search*
const search = searches_.back();
2248 if (search->backtrack_at_the_end_of_the_search()) {
2249 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2251 CHECK_GT(searches_.size(), 2);
2252 if (search->sentinel_pushed_ > 0) {
2253 JumpToSentinelWhenNested();
2256 search->ExitSearch();
2258 if (2 == searches_.size()) {
2260 state_ = OUTSIDE_SEARCH;
2262 if (!parameters_.profile_file().empty()) {
2263 const std::string& file_name = parameters_.profile_file();
2264 LOG(INFO) <<
"Exporting profile to " << file_name;
2265 ExportProfilingOverview(file_name);
2267 if (parameters_.print_local_search_profile()) {
2268 LOG(INFO) << LocalSearchProfile();
2272 searches_.pop_back();
2276 bool Solver::CheckAssignment(Assignment*
const solution) {
2278 if (state_ == IN_SEARCH || state_ == IN_ROOT_NODE) {
2279 LOG(FATAL) <<
"CheckAssignment is only available at the top level.";
2282 Search*
const search = searches_.back();
2283 search->set_created_by_solve(
false);
2285 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2286 state_ = OUTSIDE_SEARCH;
2289 search->EnterSearch();
2292 DCHECK_EQ(0, SolveDepth());
2293 DCHECK_EQ(2, searches_.size());
2294 PushSentinel(INITIAL_SEARCH_SENTINEL);
2295 search->BeginInitialPropagation();
2297 state_ = IN_ROOT_NODE;
2298 DecisionBuilder*
const restore = MakeRestoreAssignment(solution);
2299 restore->Next(
this);
2300 ProcessConstraints();
2301 search->EndInitialPropagation();
2302 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2303 search->ClearBuffer();
2304 state_ = OUTSIDE_SEARCH;
2309 constraint_index_ < constraints_list_.size()
2311 : additional_constraints_parent_list_[additional_constraint_index_];
2312 Constraint*
const ct = constraints_list_[
index];
2313 if (
ct->name().empty()) {
2314 LOG(INFO) <<
"Failing constraint = " <<
ct->DebugString();
2316 LOG(INFO) <<
"Failing constraint = " <<
ct->name() <<
":"
2317 <<
ct->DebugString();
2319 queue_->AfterFailure();
2320 BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
2321 state_ = PROBLEM_INFEASIBLE;
2327 class AddConstraintDecisionBuilder :
public DecisionBuilder {
2329 explicit AddConstraintDecisionBuilder(Constraint*
const ct)
2331 CHECK(
ct !=
nullptr);
2334 ~AddConstraintDecisionBuilder()
override {}
2336 Decision* Next(Solver*
const solver)
override {
2337 solver->AddConstraint(constraint_);
2341 std::string DebugString()
const override {
2342 return absl::StrFormat(
"AddConstraintDecisionBuilder(%s)",
2343 constraint_->DebugString());
2347 Constraint*
const constraint_;
2351 DecisionBuilder* Solver::MakeConstraintAdder(Constraint*
const ct) {
2352 return RevAlloc(
new AddConstraintDecisionBuilder(
ct));
2355 bool Solver::CheckConstraint(Constraint*
const ct) {
2356 return Solve(MakeConstraintAdder(
ct));
2359 bool Solver::SolveAndCommit(DecisionBuilder*
const db,
2360 SearchMonitor*
const m1) {
2361 std::vector<SearchMonitor*> monitors;
2362 monitors.push_back(m1);
2363 return SolveAndCommit(db, monitors);
2366 bool Solver::SolveAndCommit(DecisionBuilder*
const db) {
2367 std::vector<SearchMonitor*> monitors;
2368 return SolveAndCommit(db, monitors);
2371 bool Solver::SolveAndCommit(DecisionBuilder*
const db, SearchMonitor*
const m1,
2372 SearchMonitor*
const m2) {
2373 std::vector<SearchMonitor*> monitors;
2374 monitors.push_back(m1);
2375 monitors.push_back(m2);
2376 return SolveAndCommit(db, monitors);
2379 bool Solver::SolveAndCommit(DecisionBuilder*
const db, SearchMonitor*
const m1,
2380 SearchMonitor*
const m2, SearchMonitor*
const m3) {
2381 std::vector<SearchMonitor*> monitors;
2382 monitors.push_back(m1);
2383 monitors.push_back(m2);
2384 monitors.push_back(m3);
2385 return SolveAndCommit(db, monitors);
2388 bool Solver::SolveAndCommit(DecisionBuilder*
const db,
2389 const std::vector<SearchMonitor*>& monitors) {
2390 NewSearch(db, monitors);
2391 searches_.back()->set_created_by_solve(
true);
2392 searches_.back()->set_backtrack_at_the_end_of_the_search(
false);
2394 const bool solution_found = searches_.back()->solution_counter() > 0;
2396 return solution_found;
2399 void Solver::Fail() {
2400 if (fail_intercept_) {
2406 searches_.back()->BeginFail();
2407 searches_.back()->JumpBack();
2410 void Solver::FinishCurrentSearch() {
2411 searches_.back()->set_should_finish(
true);
2414 void Solver::RestartCurrentSearch() {
2415 searches_.back()->set_should_restart(
true);
2420 IntExpr* Solver::CastExpression(
const IntVar*
const var)
const {
2421 const IntegerCastInfo*
const cast_info =
2423 if (cast_info !=
nullptr) {
2424 return cast_info->expression;
2431 std::string Solver::GetName(
const PropagationBaseObject*
object) {
2433 if (
name !=
nullptr) {
2436 const IntegerCastInfo*
const cast_info =
2438 if (cast_info !=
nullptr && cast_info->expression !=
nullptr) {
2439 if (cast_info->expression->HasName()) {
2440 return absl::StrFormat(
"Var<%s>", cast_info->expression->name());
2441 }
else if (parameters_.name_cast_variables()) {
2442 return absl::StrFormat(
"Var<%s>", cast_info->expression->DebugString());
2444 const std::string new_name =
2445 absl::StrFormat(
"CastVar<%d>", anonymous_variable_index_++);
2446 propagation_object_names_[object] = new_name;
2450 const std::string base_name =
object->BaseName();
2451 if (parameters_.name_all_variables() && !base_name.empty()) {
2452 const std::string new_name =
2453 absl::StrFormat(
"%s_%d", base_name, anonymous_variable_index_++);
2454 propagation_object_names_[object] = new_name;
2460 void Solver::SetName(
const PropagationBaseObject*
object,
2461 const std::string&
name) {
2462 if (parameters_.store_names() &&
2463 GetName(
object) !=
name) {
2464 propagation_object_names_[object] =
name;
2468 bool Solver::HasName(
const PropagationBaseObject*
const object)
const {
2470 const_cast<PropagationBaseObject*
>(
object)) ||
2471 (!
object->BaseName().empty() && parameters_.name_all_variables());
2476 std::ostream&
operator<<(std::ostream& out,
const Solver*
const s) {
2477 out << s->DebugString();
2481 std::ostream&
operator<<(std::ostream& out,
const BaseObject*
const o) {
2482 out << o->DebugString();
2489 return solver_->GetName(
this);
2492 void PropagationBaseObject::set_name(
const std::string&
name) {
2493 solver_->SetName(
this,
name);
2496 bool PropagationBaseObject::HasName()
const {
return solver_->HasName(
this); }
2498 std::string PropagationBaseObject::BaseName()
const {
return ""; }
2500 void PropagationBaseObject::ExecuteAll(
const SimpleRevFIFO<Demon*>& demons) {
2501 solver_->ExecuteAll(demons);
2504 void PropagationBaseObject::EnqueueAll(
const SimpleRevFIFO<Demon*>& demons) {
2505 solver_->EnqueueAll(demons);
2510 std::string DecisionBuilder::DebugString()
const {
return "DecisionBuilder"; }
2512 void DecisionBuilder::AppendMonitors(
2513 Solver*
const solver, std::vector<SearchMonitor*>*
const extras) {}
2515 void DecisionBuilder::Accept(ModelVisitor*
const visitor)
const {}
2519 void Decision::Accept(DecisionVisitor*
const visitor)
const {
2520 visitor->VisitUnknownDecision();
2523 void DecisionVisitor::VisitSetVariableValue(IntVar*
const var,
int64 value) {}
2524 void DecisionVisitor::VisitSplitVariableDomain(IntVar*
const var,
int64 value,
2526 void DecisionVisitor::VisitUnknownDecision() {}
2527 void DecisionVisitor::VisitScheduleOrPostpone(IntervalVar*
const var,
2529 void DecisionVisitor::VisitScheduleOrExpedite(IntervalVar*
const var,
2531 void DecisionVisitor::VisitRankFirstInterval(SequenceVar*
const sequence,
2534 void DecisionVisitor::VisitRankLastInterval(SequenceVar*
const sequence,
2541 const char ModelVisitor::kAbs[] =
"Abs";
2542 const char ModelVisitor::kAbsEqual[] =
"AbsEqual";
2543 const char ModelVisitor::kAllDifferent[] =
"AllDifferent";
2544 const char ModelVisitor::kAllowedAssignments[] =
"AllowedAssignments";
2545 const char ModelVisitor::kAtMost[] =
"AtMost";
2546 const char ModelVisitor::kBetween[] =
"Between";
2547 const char ModelVisitor::kConditionalExpr[] =
"ConditionalExpr";
2548 const char ModelVisitor::kCircuit[] =
"Circuit";
2549 const char ModelVisitor::kConvexPiecewise[] =
"ConvexPiecewise";
2550 const char ModelVisitor::kCountEqual[] =
"CountEqual";
2551 const char ModelVisitor::kCover[] =
"Cover";
2552 const char ModelVisitor::kCumulative[] =
"Cumulative";
2553 const char ModelVisitor::kDeviation[] =
"Deviation";
2554 const char ModelVisitor::kDifference[] =
"Difference";
2555 const char ModelVisitor::kDisjunctive[] =
"Disjunctive";
2556 const char ModelVisitor::kDistribute[] =
"Distribute";
2557 const char ModelVisitor::kDivide[] =
"Divide";
2558 const char ModelVisitor::kDurationExpr[] =
"DurationExpression";
2559 const char ModelVisitor::kElement[] =
"Element";
2560 const char ModelVisitor::kElementEqual[] =
"ElementEqual";
2561 const char ModelVisitor::kEndExpr[] =
"EndExpression";
2562 const char ModelVisitor::kEquality[] =
"Equal";
2563 const char ModelVisitor::kFalseConstraint[] =
"FalseConstraint";
2564 const char ModelVisitor::kGlobalCardinality[] =
"GlobalCardinality";
2565 const char ModelVisitor::kGreater[] =
"Greater";
2566 const char ModelVisitor::kGreaterOrEqual[] =
"GreaterOrEqual";
2567 const char ModelVisitor::kIndexOf[] =
"IndexOf";
2568 const char ModelVisitor::kIntegerVariable[] =
"IntegerVariable";
2569 const char ModelVisitor::kIntervalBinaryRelation[] =
"IntervalBinaryRelation";
2570 const char ModelVisitor::kIntervalDisjunction[] =
"IntervalDisjunction";
2571 const char ModelVisitor::kIntervalUnaryRelation[] =
"IntervalUnaryRelation";
2572 const char ModelVisitor::kIntervalVariable[] =
"IntervalVariable";
2573 const char ModelVisitor::kInversePermutation[] =
"InversePermutation";
2574 const char ModelVisitor::kIsBetween[] =
"IsBetween;";
2575 const char ModelVisitor::kIsDifferent[] =
"IsDifferent";
2576 const char ModelVisitor::kIsEqual[] =
"IsEqual";
2577 const char ModelVisitor::kIsGreater[] =
"IsGreater";
2578 const char ModelVisitor::kIsGreaterOrEqual[] =
"IsGreaterOrEqual";
2579 const char ModelVisitor::kIsLess[] =
"IsLess";
2580 const char ModelVisitor::kIsLessOrEqual[] =
"IsLessOrEqual";
2581 const char ModelVisitor::kIsMember[] =
"IsMember;";
2582 const char ModelVisitor::kLess[] =
"Less";
2583 const char ModelVisitor::kLessOrEqual[] =
"LessOrEqual";
2584 const char ModelVisitor::kLexLess[] =
"LexLess";
2585 const char ModelVisitor::kLinkExprVar[] =
"CastExpressionIntoVariable";
2586 const char ModelVisitor::kMapDomain[] =
"MapDomain";
2587 const char ModelVisitor::kMax[] =
"Max";
2588 const char ModelVisitor::kMaxEqual[] =
"MaxEqual";
2589 const char ModelVisitor::kMember[] =
"Member";
2590 const char ModelVisitor::kMin[] =
"Min";
2591 const char ModelVisitor::kMinEqual[] =
"MinEqual";
2592 const char ModelVisitor::kModulo[] =
"Modulo";
2593 const char ModelVisitor::kNoCycle[] =
"NoCycle";
2594 const char ModelVisitor::kNonEqual[] =
"NonEqual";
2595 const char ModelVisitor::kNotBetween[] =
"NotBetween";
2596 const char ModelVisitor::kNotMember[] =
"NotMember";
2597 const char ModelVisitor::kNullIntersect[] =
"NullIntersect";
2598 const char ModelVisitor::kOpposite[] =
"Opposite";
2599 const char ModelVisitor::kPack[] =
"Pack";
2600 const char ModelVisitor::kPathCumul[] =
"PathCumul";
2601 const char ModelVisitor::kDelayedPathCumul[] =
"DelayedPathCumul";
2602 const char ModelVisitor::kPerformedExpr[] =
"PerformedExpression";
2603 const char ModelVisitor::kPower[] =
"Power";
2604 const char ModelVisitor::kProduct[] =
"Product";
2605 const char ModelVisitor::kScalProd[] =
"ScalarProduct";
2606 const char ModelVisitor::kScalProdEqual[] =
"ScalarProductEqual";
2607 const char ModelVisitor::kScalProdGreaterOrEqual[] =
2608 "ScalarProductGreaterOrEqual";
2609 const char ModelVisitor::kScalProdLessOrEqual[] =
"ScalarProductLessOrEqual";
2610 const char ModelVisitor::kSemiContinuous[] =
"SemiContinuous";
2611 const char ModelVisitor::kSequenceVariable[] =
"SequenceVariable";
2612 const char ModelVisitor::kSortingConstraint[] =
"SortingConstraint";
2613 const char ModelVisitor::kSquare[] =
"Square";
2614 const char ModelVisitor::kStartExpr[] =
"StartExpression";
2615 const char ModelVisitor::kSum[] =
"Sum";
2616 const char ModelVisitor::kSumEqual[] =
"SumEqual";
2617 const char ModelVisitor::kSumGreaterOrEqual[] =
"SumGreaterOrEqual";
2618 const char ModelVisitor::kSumLessOrEqual[] =
"SumLessOrEqual";
2619 const char ModelVisitor::kTransition[] =
"Transition";
2620 const char ModelVisitor::kTrace[] =
"Trace";
2621 const char ModelVisitor::kTrueConstraint[] =
"TrueConstraint";
2622 const char ModelVisitor::kVarBoundWatcher[] =
"VarBoundWatcher";
2623 const char ModelVisitor::kVarValueWatcher[] =
"VarValueWatcher";
2625 const char ModelVisitor::kCountAssignedItemsExtension[] =
"CountAssignedItems";
2626 const char ModelVisitor::kCountUsedBinsExtension[] =
"CountUsedBins";
2627 const char ModelVisitor::kInt64ToBoolExtension[] =
"Int64ToBoolFunction";
2628 const char ModelVisitor::kInt64ToInt64Extension[] =
"Int64ToInt64Function";
2629 const char ModelVisitor::kObjectiveExtension[] =
"Objective";
2630 const char ModelVisitor::kSearchLimitExtension[] =
"SearchLimit";
2631 const char ModelVisitor::kUsageEqualVariableExtension[] =
"UsageEqualVariable";
2633 const char ModelVisitor::kUsageLessConstantExtension[] =
"UsageLessConstant";
2634 const char ModelVisitor::kVariableGroupExtension[] =
"VariableGroup";
2635 const char ModelVisitor::kVariableUsageLessConstantExtension[] =
2636 "VariableUsageLessConstant";
2637 const char ModelVisitor::kWeightedSumOfAssignedEqualVariableExtension[] =
2638 "WeightedSumOfAssignedEqualVariable";
2640 const char ModelVisitor::kActiveArgument[] =
"active";
2641 const char ModelVisitor::kAssumePathsArgument[] =
"assume_paths";
2642 const char ModelVisitor::kBranchesLimitArgument[] =
"branches_limit";
2643 const char ModelVisitor::kCapacityArgument[] =
"capacity";
2644 const char ModelVisitor::kCardsArgument[] =
"cardinalities";
2645 const char ModelVisitor::kCoefficientsArgument[] =
"coefficients";
2646 const char ModelVisitor::kCountArgument[] =
"count";
2647 const char ModelVisitor::kCumulativeArgument[] =
"cumulative";
2648 const char ModelVisitor::kCumulsArgument[] =
"cumuls";
2649 const char ModelVisitor::kDemandsArgument[] =
"demands";
2650 const char ModelVisitor::kDurationMinArgument[] =
"duration_min";
2651 const char ModelVisitor::kDurationMaxArgument[] =
"duration_max";
2652 const char ModelVisitor::kEarlyCostArgument[] =
"early_cost";
2653 const char ModelVisitor::kEarlyDateArgument[] =
"early_date";
2654 const char ModelVisitor::kEndMinArgument[] =
"end_min";
2655 const char ModelVisitor::kEndMaxArgument[] =
"end_max";
2656 const char ModelVisitor::kEndsArgument[] =
"ends";
2657 const char ModelVisitor::kExpressionArgument[] =
"expression";
2658 const char ModelVisitor::kFailuresLimitArgument[] =
"failures_limit";
2659 const char ModelVisitor::kFinalStatesArgument[] =
"final_states";
2660 const char ModelVisitor::kFixedChargeArgument[] =
"fixed_charge";
2661 const char ModelVisitor::kIndex2Argument[] =
"index2";
2662 const char ModelVisitor::kIndexArgument[] =
"index";
2663 const char ModelVisitor::kInitialState[] =
"initial_state";
2664 const char ModelVisitor::kIntervalArgument[] =
"interval";
2665 const char ModelVisitor::kIntervalsArgument[] =
"intervals";
2666 const char ModelVisitor::kLateCostArgument[] =
"late_cost";
2667 const char ModelVisitor::kLateDateArgument[] =
"late_date";
2668 const char ModelVisitor::kLeftArgument[] =
"left";
2669 const char ModelVisitor::kMaxArgument[] =
"max_value";
2670 const char ModelVisitor::kMaximizeArgument[] =
"maximize";
2671 const char ModelVisitor::kMinArgument[] =
"min_value";
2672 const char ModelVisitor::kModuloArgument[] =
"modulo";
2673 const char ModelVisitor::kNextsArgument[] =
"nexts";
2674 const char ModelVisitor::kOptionalArgument[] =
"optional";
2675 const char ModelVisitor::kPartialArgument[] =
"partial";
2676 const char ModelVisitor::kPositionXArgument[] =
"position_x";
2677 const char ModelVisitor::kPositionYArgument[] =
"position_y";
2678 const char ModelVisitor::kRangeArgument[] =
"range";
2679 const char ModelVisitor::kRelationArgument[] =
"relation";
2680 const char ModelVisitor::kRightArgument[] =
"right";
2681 const char ModelVisitor::kSequenceArgument[] =
"sequence";
2682 const char ModelVisitor::kSequencesArgument[] =
"sequences";
2683 const char ModelVisitor::kSmartTimeCheckArgument[] =
"smart_time_check";
2684 const char ModelVisitor::kSizeArgument[] =
"size";
2685 const char ModelVisitor::kSizeXArgument[] =
"size_x";
2686 const char ModelVisitor::kSizeYArgument[] =
"size_y";
2687 const char ModelVisitor::kSolutionLimitArgument[] =
"solutions_limit";
2688 const char ModelVisitor::kStartMinArgument[] =
"start_min";
2689 const char ModelVisitor::kStartMaxArgument[] =
"start_max";
2690 const char ModelVisitor::kStartsArgument[] =
"starts";
2691 const char ModelVisitor::kStepArgument[] =
"step";
2692 const char ModelVisitor::kTargetArgument[] =
"target_variable";
2693 const char ModelVisitor::kTimeLimitArgument[] =
"time_limit";
2694 const char ModelVisitor::kTransitsArgument[] =
"transits";
2695 const char ModelVisitor::kTuplesArgument[] =
"tuples";
2696 const char ModelVisitor::kValueArgument[] =
"value";
2697 const char ModelVisitor::kValuesArgument[] =
"values";
2698 const char ModelVisitor::kVarsArgument[] =
"variables";
2699 const char ModelVisitor::kEvaluatorArgument[] =
"evaluator";
2701 const char ModelVisitor::kVariableArgument[] =
"variable";
2703 const char ModelVisitor::kMirrorOperation[] =
"mirror";
2704 const char ModelVisitor::kRelaxedMaxOperation[] =
"relaxed_max";
2705 const char ModelVisitor::kRelaxedMinOperation[] =
"relaxed_min";
2706 const char ModelVisitor::kSumOperation[] =
"sum";
2707 const char ModelVisitor::kDifferenceOperation[] =
"difference";
2708 const char ModelVisitor::kProductOperation[] =
"product";
2709 const char ModelVisitor::kStartSyncOnStartOperation[] =
"start_synced_on_start";
2710 const char ModelVisitor::kStartSyncOnEndOperation[] =
"start_synced_on_end";
2711 const char ModelVisitor::kTraceOperation[] =
"trace";
2715 ModelVisitor::~ModelVisitor() {}
2717 void ModelVisitor::BeginVisitModel(
const std::string& type_name) {}
2718 void ModelVisitor::EndVisitModel(
const std::string& type_name) {}
2720 void ModelVisitor::BeginVisitConstraint(
const std::string& type_name,
2721 const Constraint*
const constraint) {}
2722 void ModelVisitor::EndVisitConstraint(
const std::string& type_name,
2723 const Constraint*
const constraint) {}
2725 void ModelVisitor::BeginVisitExtension(
const std::string& type) {}
2726 void ModelVisitor::EndVisitExtension(
const std::string& type) {}
2728 void ModelVisitor::BeginVisitIntegerExpression(
const std::string& type_name,
2729 const IntExpr*
const expr) {}
2730 void ModelVisitor::EndVisitIntegerExpression(
const std::string& type_name,
2731 const IntExpr*
const expr) {}
2733 void ModelVisitor::VisitIntegerVariable(
const IntVar*
const variable,
2734 IntExpr*
const delegate) {
2735 if (delegate !=
nullptr) {
2736 delegate->Accept(
this);
2740 void ModelVisitor::VisitIntegerVariable(
const IntVar*
const variable,
2741 const std::string& operation,
2743 if (delegate !=
nullptr) {
2744 delegate->Accept(
this);
2748 void ModelVisitor::VisitIntervalVariable(
const IntervalVar*
const variable,
2749 const std::string& operation,
2751 IntervalVar*
const delegate) {
2752 if (delegate !=
nullptr) {
2753 delegate->Accept(
this);
2757 void ModelVisitor::VisitSequenceVariable(
const SequenceVar*
const variable) {
2758 for (
int i = 0; i < variable->size(); ++i) {
2759 variable->Interval(i)->Accept(
this);
2763 void ModelVisitor::VisitIntegerArgument(
const std::string& arg_name,
2766 void ModelVisitor::VisitIntegerArrayArgument(
const std::string& arg_name,
2767 const std::vector<int64>& values) {
2770 void ModelVisitor::VisitIntegerMatrixArgument(
const std::string& arg_name,
2771 const IntTupleSet& tuples) {}
2773 void ModelVisitor::VisitIntegerExpressionArgument(
const std::string& arg_name,
2774 IntExpr*
const argument) {
2775 argument->Accept(
this);
2778 void ModelVisitor::VisitIntegerVariableEvaluatorArgument(
2779 const std::string& arg_name,
const Solver::Int64ToIntVar& arguments) {}
2781 void ModelVisitor::VisitIntegerVariableArrayArgument(
2782 const std::string& arg_name,
const std::vector<IntVar*>& arguments) {
2783 ForAll(arguments, &IntVar::Accept,
this);
2786 void ModelVisitor::VisitIntervalArgument(
const std::string& arg_name,
2787 IntervalVar*
const argument) {
2788 argument->Accept(
this);
2791 void ModelVisitor::VisitIntervalArrayArgument(
2792 const std::string& arg_name,
const std::vector<IntervalVar*>& arguments) {
2793 ForAll(arguments, &IntervalVar::Accept,
this);
2796 void ModelVisitor::VisitSequenceArgument(
const std::string& arg_name,
2797 SequenceVar*
const argument) {
2798 argument->Accept(
this);
2801 void ModelVisitor::VisitSequenceArrayArgument(
2802 const std::string& arg_name,
const std::vector<SequenceVar*>& arguments) {
2803 ForAll(arguments, &SequenceVar::Accept,
this);
2808 void ModelVisitor::VisitInt64ToBoolExtension(Solver::IndexFilter1 filter,
2810 if (filter !=
nullptr) {
2811 std::vector<int64> cached_results;
2812 for (
int i = index_min; i <= index_max; ++i) {
2813 cached_results.push_back(filter(i));
2815 BeginVisitExtension(kInt64ToBoolExtension);
2816 VisitIntegerArgument(kMinArgument, index_min);
2817 VisitIntegerArgument(kMaxArgument, index_max);
2818 VisitIntegerArrayArgument(kValuesArgument, cached_results);
2819 EndVisitExtension(kInt64ToBoolExtension);
2823 void ModelVisitor::VisitInt64ToInt64Extension(
2824 const Solver::IndexEvaluator1& eval,
int64 index_min,
int64 index_max) {
2825 CHECK(eval !=
nullptr);
2826 std::vector<int64> cached_results;
2827 for (
int i = index_min; i <= index_max; ++i) {
2828 cached_results.push_back(eval(i));
2830 BeginVisitExtension(kInt64ToInt64Extension);
2831 VisitIntegerArgument(kMinArgument, index_min);
2832 VisitIntegerArgument(kMaxArgument, index_max);
2833 VisitIntegerArrayArgument(kValuesArgument, cached_results);
2834 EndVisitExtension(kInt64ToInt64Extension);
2837 void ModelVisitor::VisitInt64ToInt64AsArray(
const Solver::IndexEvaluator1& eval,
2838 const std::string& arg_name,
2840 CHECK(eval !=
nullptr);
2841 std::vector<int64> cached_results;
2842 for (
int i = 0; i <= index_max; ++i) {
2843 cached_results.push_back(eval(i));
2845 VisitIntegerArrayArgument(arg_name, cached_results);
2850 void SearchMonitor::EnterSearch() {}
2851 void SearchMonitor::RestartSearch() {}
2852 void SearchMonitor::ExitSearch() {}
2853 void SearchMonitor::BeginNextDecision(DecisionBuilder*
const b) {}
2854 void SearchMonitor::EndNextDecision(DecisionBuilder*
const b,
2855 Decision*
const d) {}
2856 void SearchMonitor::ApplyDecision(Decision*
const d) {}
2857 void SearchMonitor::RefuteDecision(Decision*
const d) {}
2858 void SearchMonitor::AfterDecision(Decision*
const d,
bool apply) {}
2859 void SearchMonitor::BeginFail() {}
2860 void SearchMonitor::EndFail() {}
2861 void SearchMonitor::BeginInitialPropagation() {}
2862 void SearchMonitor::EndInitialPropagation() {}
2863 bool SearchMonitor::AcceptSolution() {
return true; }
2864 bool SearchMonitor::AtSolution() {
return false; }
2865 void SearchMonitor::NoMoreSolutions() {}
2866 bool SearchMonitor::LocalOptimum() {
return false; }
2872 void SearchMonitor::PeriodicCheck() {}
2873 void SearchMonitor::Accept(ModelVisitor*
const visitor)
const {}
2875 void SearchMonitor::Install() {
2876 solver()->searches_.back()->push_monitor(
this);
2880 PropagationMonitor::PropagationMonitor(Solver*
const solver)
2881 : SearchMonitor(solver) {}
2887 SearchMonitor::Install();
2888 solver()->AddPropagationMonitor(
this);
2893 : SearchMonitor(solver) {}
2900 SearchMonitor::Install();
2901 solver()->AddLocalSearchMonitor(
this);
2913 Constraint*
const constraint)
override {
2924 Constraint*
const parent, Constraint*
const nested)
override {
2931 Constraint*
const parent, Constraint*
const nested)
override {
2968 monitor->SetMin(expr, new_min);
2974 monitor->SetMax(expr, new_max);
2980 monitor->SetRange(expr, new_min, new_max);
2987 monitor->SetMin(
var, new_min);
2993 monitor->SetMax(
var, new_max);
2999 monitor->SetRange(
var, new_min, new_max);
3015 void SetValues(IntVar*
const var,
const std::vector<int64>& values)
override {
3020 const std::vector<int64>& values)
override {
3034 int64 new_max)
override {
3048 int64 new_max)
override {
3061 int64 new_max)
override {
3087 const std::vector<int>& rank_last,
3088 const std::vector<int>& unperformed)
override {
3090 rank_last, unperformed);
3095 if (monitor !=
nullptr) {
3096 monitors_.push_back(monitor);
3102 void Install()
override { SearchMonitor::Install(); }
3107 std::vector<PropagationMonitor*> monitors_;
3112 void Solver::AddPropagationMonitor(PropagationMonitor*
const monitor) {
3114 reinterpret_cast<class Trace*
>(propagation_monitor_.get())->Add(monitor);
3117 PropagationMonitor* Solver::GetPropagationMonitor()
const {
3118 return propagation_monitor_.get();
3138 const Assignment*
delta,
3139 const Assignment* deltadelta)
override {
3141 neighbor_found,
delta, deltadelta);
3147 bool neighbor_found)
override {
3155 bool neighbor_found)
override {
3168 if (monitor !=
nullptr) {
3169 monitors_.push_back(monitor);
3175 void Install()
override { SearchMonitor::Install(); }
3178 return "LocalSearchMonitorMaster";
3182 std::vector<LocalSearchMonitor*> monitors_;
3189 void Solver::AddLocalSearchMonitor(LocalSearchMonitor*
const monitor) {
3190 reinterpret_cast<class LocalSearchMonitorMaster*
>(local_search_monitor_.get())
3194 LocalSearchMonitor* Solver::GetLocalSearchMonitor()
const {
3195 return local_search_monitor_.get();
3198 void Solver::SetSearchContext(Search* search,
3199 const std::string& search_context) {
3200 search->set_search_context(search_context);
3203 std::string Solver::SearchContext()
const {
3204 return ActiveSearch()->search_context();
3207 std::string Solver::SearchContext(
const Search* search)
const {
3208 return search->search_context();
3211 Assignment* Solver::GetOrCreateLocalSearchState() {
3212 if (local_search_state_ ==
nullptr) {
3213 local_search_state_ = absl::make_unique<Assignment>(
this);
3215 return local_search_state_.get();
3220 std::string Constraint::DebugString()
const {
return "Constraint"; }
3222 void Constraint::PostAndPropagate() {
3226 solver()->CheckFail();
3230 void Constraint::Accept(ModelVisitor*
const visitor)
const {
3231 visitor->BeginVisitConstraint(
"unknown",
this);
3232 VLOG(3) <<
"Unknown constraint " << DebugString();
3233 visitor->EndVisitConstraint(
"unknown",
this);
3236 bool Constraint::IsCastConstraint()
const {
3240 IntVar* Constraint::Var() {
return nullptr; }
3244 void IntExpr::Accept(ModelVisitor*
const visitor)
const {
3245 visitor->BeginVisitIntegerExpression(
"unknown",
this);
3246 VLOG(3) <<
"Unknown expression " << DebugString();
3247 visitor->EndVisitIntegerExpression(
"unknown",
this);
3250 #undef CP_TRY // We no longer need those.