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