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