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