OR-Tools  8.0
search.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 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 #include <algorithm>
15 #include <functional>
16 #include <list>
17 #include <memory>
18 #include <queue>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/base/casts.h"
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/memory/memory.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_format.h"
28 #include "absl/strings/str_join.h"
29 #include "absl/time/time.h"
30 #include "ortools/base/bitmap.h"
32 #include "ortools/base/hash.h"
34 #include "ortools/base/logging.h"
35 #include "ortools/base/macros.h"
36 #include "ortools/base/map_util.h"
37 #include "ortools/base/mathutil.h"
38 #include "ortools/base/stl_util.h"
39 #include "ortools/base/timer.h"
44 
45 DEFINE_bool(cp_use_sparse_gls_penalties, false,
46  "Use sparse implementation to store Guided Local Search penalties");
47 DEFINE_bool(cp_log_to_vlog, false,
48  "Whether search related logging should be "
49  "vlog or info.");
50 DEFINE_int64(cp_large_domain_no_splitting_limit, 0xFFFFF,
51  "Size limit to allow holes in variables from the strategy.");
52 namespace operations_research {
53 
54 // ---------- Search Log ---------
55 
56 SearchLog::SearchLog(Solver* const s, OptimizeVar* const obj, IntVar* const var,
57  double scaling_factor, double offset,
58  std::function<std::string()> display_callback, int period)
59  : SearchMonitor(s),
60  period_(period),
61  timer_(new WallTimer),
62  var_(var),
63  obj_(obj),
64  scaling_factor_(scaling_factor),
65  offset_(offset),
66  display_callback_(std::move(display_callback)),
67  nsol_(0),
68  tick_(0),
69  objective_min_(kint64max),
70  objective_max_(kint64min),
71  min_right_depth_(kint32max),
72  max_depth_(0),
73  sliding_min_depth_(0),
74  sliding_max_depth_(0) {
75  CHECK(obj == nullptr || var == nullptr)
76  << "Either var or obj need to be nullptr.";
77 }
78 
80 
81 std::string SearchLog::DebugString() const { return "SearchLog"; }
82 
84  const std::string buffer =
85  absl::StrFormat("Start search (%s)", MemoryUsage());
86  OutputLine(buffer);
87  timer_->Restart();
88  min_right_depth_ = kint32max;
89 }
90 
92  const int64 branches = solver()->branches();
93  int64 ms = timer_->GetInMs();
94  if (ms == 0) {
95  ms = 1;
96  }
97  const std::string buffer = absl::StrFormat(
98  "End search (time = %d ms, branches = %d, failures = %d, %s, speed = %d "
99  "branches/s)",
100  ms, branches, solver()->failures(), MemoryUsage(), branches * 1000 / ms);
101  OutputLine(buffer);
102 }
103 
105  Maintain();
106  const int depth = solver()->SearchDepth();
107  std::string obj_str = "";
108  int64 current = 0;
109  bool objective_updated = false;
110  const auto scaled_str = [this](int64 value) {
111  if (scaling_factor_ != 1.0 || offset_ != 0.0) {
112  return absl::StrFormat("%d (%.8lf)", value,
113  scaling_factor_ * (value + offset_));
114  } else {
115  return absl::StrCat(value);
116  }
117  };
118  if (obj_ != nullptr && obj_->Var()->Bound()) {
119  current = obj_->Var()->Value();
120  obj_str = obj_->Print();
121  objective_updated = true;
122  } else if (var_ != nullptr && var_->Bound()) {
123  current = var_->Value();
124  absl::StrAppend(&obj_str, scaled_str(current), ", ");
125  objective_updated = true;
126  } else {
127  current = solver()->GetOrCreateLocalSearchState()->ObjectiveMin();
128  absl::StrAppend(&obj_str, scaled_str(current), ", ");
129  objective_updated = true;
130  }
131  if (objective_updated) {
132  if (current > objective_min_) {
133  absl::StrAppend(&obj_str,
134  "objective minimum = ", scaled_str(objective_min_), ", ");
135  } else {
136  objective_min_ = current;
137  }
138  if (current < objective_max_) {
139  absl::StrAppend(&obj_str,
140  "objective maximum = ", scaled_str(objective_max_), ", ");
141  } else {
142  objective_max_ = current;
143  }
144  }
145  std::string log;
146  absl::StrAppendFormat(&log,
147  "Solution #%d (%stime = %d ms, branches = %d,"
148  " failures = %d, depth = %d",
149  nsol_++, obj_str, timer_->GetInMs(),
150  solver()->branches(), solver()->failures(), depth);
151  if (!solver()->SearchContext().empty()) {
152  absl::StrAppendFormat(&log, ", %s", solver()->SearchContext());
153  }
154  if (solver()->neighbors() != 0) {
155  absl::StrAppendFormat(&log,
156  ", neighbors = %d, filtered neighbors = %d,"
157  " accepted neighbors = %d",
158  solver()->neighbors(), solver()->filtered_neighbors(),
159  solver()->accepted_neighbors());
160  }
161  absl::StrAppendFormat(&log, ", %s", MemoryUsage());
162  const int progress = solver()->TopProgressPercent();
163  if (progress != SearchMonitor::kNoProgress) {
164  absl::StrAppendFormat(&log, ", limit = %d%%", progress);
165  }
166  if (display_callback_) {
167  absl::StrAppendFormat(&log, ", %s", display_callback_());
168  }
169  log.append(")");
170  OutputLine(log);
171  return false;
172 }
173 
175 
177 
179  std::string buffer = absl::StrFormat(
180  "Finished search tree (time = %d ms, branches = %d,"
181  " failures = %d",
182  timer_->GetInMs(), solver()->branches(), solver()->failures());
183  if (solver()->neighbors() != 0) {
184  absl::StrAppendFormat(&buffer,
185  ", neighbors = %d, filtered neighbors = %d,"
186  " accepted neigbors = %d",
187  solver()->neighbors(), solver()->filtered_neighbors(),
188  solver()->accepted_neighbors());
189  }
190  absl::StrAppendFormat(&buffer, ", %s)", MemoryUsage());
191  OutputLine(buffer);
192 }
193 
194 void SearchLog::ApplyDecision(Decision* const decision) {
195  Maintain();
196  const int64 b = solver()->branches();
197  if (b % period_ == 0 && b > 0) {
198  OutputDecision();
199  }
200 }
201 
202 void SearchLog::RefuteDecision(Decision* const decision) {
203  min_right_depth_ = std::min(min_right_depth_, solver()->SearchDepth());
204  ApplyDecision(decision);
205 }
206 
208  std::string buffer =
209  absl::StrFormat("%d branches, %d ms, %d failures", solver()->branches(),
210  timer_->GetInMs(), solver()->failures());
211  if (min_right_depth_ != kint32max && max_depth_ != 0) {
212  const int depth = solver()->SearchDepth();
213  absl::StrAppendFormat(&buffer, ", tree pos=%d/%d/%d minref=%d max=%d",
214  sliding_min_depth_, depth, sliding_max_depth_,
215  min_right_depth_, max_depth_);
216  sliding_min_depth_ = depth;
217  sliding_max_depth_ = depth;
218  }
219  if (obj_ != nullptr && objective_min_ != kint64max &&
220  objective_max_ != kint64min) {
221  absl::StrAppendFormat(&buffer,
222  ", objective minimum = %d"
223  ", objective maximum = %d",
224  objective_min_, objective_max_);
225  }
226  const int progress = solver()->TopProgressPercent();
227  if (progress != SearchMonitor::kNoProgress) {
228  absl::StrAppendFormat(&buffer, ", limit = %d%%", progress);
229  }
230  OutputLine(buffer);
231 }
232 
234  const int current_depth = solver()->SearchDepth();
235  sliding_min_depth_ = std::min(current_depth, sliding_min_depth_);
236  sliding_max_depth_ = std::max(current_depth, sliding_max_depth_);
237  max_depth_ = std::max(current_depth, max_depth_);
238 }
239 
240 void SearchLog::BeginInitialPropagation() { tick_ = timer_->GetInMs(); }
241 
243  const int64 delta = std::max<int64>(timer_->GetInMs() - tick_, 0);
244  const std::string buffer = absl::StrFormat(
245  "Root node processed (time = %d ms, constraints = %d, %s)", delta,
246  solver()->constraints(), MemoryUsage());
247  OutputLine(buffer);
248 }
249 
250 void SearchLog::OutputLine(const std::string& line) {
251  if (FLAGS_cp_log_to_vlog) {
252  VLOG(1) << line;
253  } else {
254  LOG(INFO) << line;
255  }
256 }
257 
258 std::string SearchLog::MemoryUsage() {
259  static const int64 kDisplayThreshold = 2;
260  static const int64 kKiloByte = 1024;
261  static const int64 kMegaByte = kKiloByte * kKiloByte;
262  static const int64 kGigaByte = kMegaByte * kKiloByte;
263  const int64 memory_usage = Solver::MemoryUsage();
264  if (memory_usage > kDisplayThreshold * kGigaByte) {
265  return absl::StrFormat("memory used = %.2lf GB",
266  memory_usage * 1.0 / kGigaByte);
267  } else if (memory_usage > kDisplayThreshold * kMegaByte) {
268  return absl::StrFormat("memory used = %.2lf MB",
269  memory_usage * 1.0 / kMegaByte);
270  } else if (memory_usage > kDisplayThreshold * kKiloByte) {
271  return absl::StrFormat("memory used = %2lf KB",
272  memory_usage * 1.0 / kKiloByte);
273  } else {
274  return absl::StrFormat("memory used = %d", memory_usage);
275  }
276 }
277 
278 SearchMonitor* Solver::MakeSearchLog(int branch_period) {
279  return RevAlloc(
280  new SearchLog(this, nullptr, nullptr, 1.0, 0.0, nullptr, branch_period));
281 }
282 
283 SearchMonitor* Solver::MakeSearchLog(int branch_period, IntVar* const var) {
284  return RevAlloc(
285  new SearchLog(this, nullptr, var, 1.0, 0.0, nullptr, branch_period));
286 }
287 
288 SearchMonitor* Solver::MakeSearchLog(
289  int branch_period, std::function<std::string()> display_callback) {
290  return RevAlloc(new SearchLog(this, nullptr, nullptr, 1.0, 0.0,
291  std::move(display_callback), branch_period));
292 }
293 
294 SearchMonitor* Solver::MakeSearchLog(
295  int branch_period, IntVar* const var,
296  std::function<std::string()> display_callback) {
297  return RevAlloc(new SearchLog(this, nullptr, var, 1.0, 0.0,
298  std::move(display_callback), branch_period));
299 }
300 
301 SearchMonitor* Solver::MakeSearchLog(int branch_period,
302  OptimizeVar* const opt_var) {
303  return RevAlloc(
304  new SearchLog(this, opt_var, nullptr, 1.0, 0.0, nullptr, branch_period));
305 }
306 
307 SearchMonitor* Solver::MakeSearchLog(
308  int branch_period, OptimizeVar* const opt_var,
309  std::function<std::string()> display_callback) {
310  return RevAlloc(new SearchLog(this, opt_var, nullptr, 1.0, 0.0,
311  std::move(display_callback), branch_period));
312 }
313 
314 SearchMonitor* Solver::MakeSearchLog(SearchLogParameters parameters) {
315  return RevAlloc(new SearchLog(this, parameters.objective, parameters.variable,
316  parameters.scaling_factor, parameters.offset,
317  std::move(parameters.display_callback),
318  parameters.branch_period));
319 }
320 
321 // ---------- Search Trace ----------
322 namespace {
323 class SearchTrace : public SearchMonitor {
324  public:
325  SearchTrace(Solver* const s, const std::string& prefix)
326  : SearchMonitor(s), prefix_(prefix) {}
327  ~SearchTrace() override {}
328 
329  void EnterSearch() override {
330  LOG(INFO) << prefix_ << " EnterSearch(" << solver()->SolveDepth() << ")";
331  }
332  void RestartSearch() override {
333  LOG(INFO) << prefix_ << " RestartSearch(" << solver()->SolveDepth() << ")";
334  }
335  void ExitSearch() override {
336  LOG(INFO) << prefix_ << " ExitSearch(" << solver()->SolveDepth() << ")";
337  }
338  void BeginNextDecision(DecisionBuilder* const b) override {
339  LOG(INFO) << prefix_ << " BeginNextDecision(" << b << ") ";
340  }
341  void EndNextDecision(DecisionBuilder* const b, Decision* const d) override {
342  if (d) {
343  LOG(INFO) << prefix_ << " EndNextDecision(" << b << ", " << d << ") ";
344  } else {
345  LOG(INFO) << prefix_ << " EndNextDecision(" << b << ") ";
346  }
347  }
348  void ApplyDecision(Decision* const d) override {
349  LOG(INFO) << prefix_ << " ApplyDecision(" << d << ") ";
350  }
351  void RefuteDecision(Decision* const d) override {
352  LOG(INFO) << prefix_ << " RefuteDecision(" << d << ") ";
353  }
354  void AfterDecision(Decision* const d, bool apply) override {
355  LOG(INFO) << prefix_ << " AfterDecision(" << d << ", " << apply << ") ";
356  }
357  void BeginFail() override {
358  LOG(INFO) << prefix_ << " BeginFail(" << solver()->SearchDepth() << ")";
359  }
360  void EndFail() override {
361  LOG(INFO) << prefix_ << " EndFail(" << solver()->SearchDepth() << ")";
362  }
363  void BeginInitialPropagation() override {
364  LOG(INFO) << prefix_ << " BeginInitialPropagation()";
365  }
366  void EndInitialPropagation() override {
367  LOG(INFO) << prefix_ << " EndInitialPropagation()";
368  }
369  bool AtSolution() override {
370  LOG(INFO) << prefix_ << " AtSolution()";
371  return false;
372  }
373  bool AcceptSolution() override {
374  LOG(INFO) << prefix_ << " AcceptSolution()";
375  return true;
376  }
377  void NoMoreSolutions() override {
378  LOG(INFO) << prefix_ << " NoMoreSolutions()";
379  }
380 
381  std::string DebugString() const override { return "SearchTrace"; }
382 
383  private:
384  const std::string prefix_;
385 };
386 } // namespace
387 
388 SearchMonitor* Solver::MakeSearchTrace(const std::string& prefix) {
389  return RevAlloc(new SearchTrace(this, prefix));
390 }
391 
392 // ---------- Callback-based search monitors ----------
393 namespace {
394 class AtSolutionCallback : public SearchMonitor {
395  public:
396  AtSolutionCallback(Solver* const solver, std::function<void()> callback)
397  : SearchMonitor(solver), callback_(std::move(callback)) {}
398  ~AtSolutionCallback() override {}
399  bool AtSolution() override;
400 
401  private:
402  const std::function<void()> callback_;
403 };
404 
405 bool AtSolutionCallback::AtSolution() {
406  callback_();
407  return false;
408 }
409 
410 } // namespace
411 
412 SearchMonitor* Solver::MakeAtSolutionCallback(std::function<void()> callback) {
413  return RevAlloc(new AtSolutionCallback(this, std::move(callback)));
414 }
415 
416 namespace {
417 class EnterSearchCallback : public SearchMonitor {
418  public:
419  EnterSearchCallback(Solver* const solver, std::function<void()> callback)
420  : SearchMonitor(solver), callback_(std::move(callback)) {}
421  ~EnterSearchCallback() override {}
422  void EnterSearch() override;
423 
424  private:
425  const std::function<void()> callback_;
426 };
427 
428 void EnterSearchCallback::EnterSearch() { callback_(); }
429 
430 } // namespace
431 
432 SearchMonitor* Solver::MakeEnterSearchCallback(std::function<void()> callback) {
433  return RevAlloc(new EnterSearchCallback(this, std::move(callback)));
434 }
435 
436 namespace {
437 class ExitSearchCallback : public SearchMonitor {
438  public:
439  ExitSearchCallback(Solver* const solver, std::function<void()> callback)
440  : SearchMonitor(solver), callback_(std::move(callback)) {}
441  ~ExitSearchCallback() override {}
442  void ExitSearch() override;
443 
444  private:
445  const std::function<void()> callback_;
446 };
447 
448 void ExitSearchCallback::ExitSearch() { callback_(); }
449 
450 } // namespace
451 
452 SearchMonitor* Solver::MakeExitSearchCallback(std::function<void()> callback) {
453  return RevAlloc(new ExitSearchCallback(this, std::move(callback)));
454 }
455 
456 // ---------- Composite Decision Builder --------
457 
458 namespace {
459 class CompositeDecisionBuilder : public DecisionBuilder {
460  public:
461  CompositeDecisionBuilder();
462  explicit CompositeDecisionBuilder(const std::vector<DecisionBuilder*>& dbs);
463  ~CompositeDecisionBuilder() override;
464  void Add(DecisionBuilder* const db);
465  void AppendMonitors(Solver* const solver,
466  std::vector<SearchMonitor*>* const monitors) override;
467  void Accept(ModelVisitor* const visitor) const override;
468 
469  protected:
470  std::vector<DecisionBuilder*> builders_;
471 };
472 
473 CompositeDecisionBuilder::CompositeDecisionBuilder() {}
474 
475 CompositeDecisionBuilder::CompositeDecisionBuilder(
476  const std::vector<DecisionBuilder*>& dbs) {
477  for (int i = 0; i < dbs.size(); ++i) {
478  Add(dbs[i]);
479  }
480 }
481 
482 CompositeDecisionBuilder::~CompositeDecisionBuilder() {}
483 
484 void CompositeDecisionBuilder::Add(DecisionBuilder* const db) {
485  if (db != nullptr) {
486  builders_.push_back(db);
487  }
488 }
489 
490 void CompositeDecisionBuilder::AppendMonitors(
491  Solver* const solver, std::vector<SearchMonitor*>* const monitors) {
492  for (DecisionBuilder* const db : builders_) {
493  db->AppendMonitors(solver, monitors);
494  }
495 }
496 
497 void CompositeDecisionBuilder::Accept(ModelVisitor* const visitor) const {
498  for (DecisionBuilder* const db : builders_) {
499  db->Accept(visitor);
500  }
501 }
502 } // namespace
503 
504 // ---------- Compose Decision Builder ----------
505 
506 namespace {
507 class ComposeDecisionBuilder : public CompositeDecisionBuilder {
508  public:
509  ComposeDecisionBuilder();
510  explicit ComposeDecisionBuilder(const std::vector<DecisionBuilder*>& dbs);
511  ~ComposeDecisionBuilder() override;
512  Decision* Next(Solver* const s) override;
513  std::string DebugString() const override;
514 
515  private:
516  int start_index_;
517 };
518 
519 ComposeDecisionBuilder::ComposeDecisionBuilder() : start_index_(0) {}
520 
521 ComposeDecisionBuilder::ComposeDecisionBuilder(
522  const std::vector<DecisionBuilder*>& dbs)
523  : CompositeDecisionBuilder(dbs), start_index_(0) {}
524 
525 ComposeDecisionBuilder::~ComposeDecisionBuilder() {}
526 
527 Decision* ComposeDecisionBuilder::Next(Solver* const s) {
528  const int size = builders_.size();
529  for (int i = start_index_; i < size; ++i) {
530  Decision* d = builders_[i]->Next(s);
531  if (d != nullptr) {
532  s->SaveAndSetValue(&start_index_, i);
533  return d;
534  }
535  }
536  s->SaveAndSetValue(&start_index_, size);
537  return nullptr;
538 }
539 
540 std::string ComposeDecisionBuilder::DebugString() const {
541  return absl::StrFormat("ComposeDecisionBuilder(%s)",
543 }
544 } // namespace
545 
546 DecisionBuilder* Solver::Compose(DecisionBuilder* const db1,
547  DecisionBuilder* const db2) {
548  ComposeDecisionBuilder* c = RevAlloc(new ComposeDecisionBuilder());
549  c->Add(db1);
550  c->Add(db2);
551  return c;
552 }
553 
554 DecisionBuilder* Solver::Compose(DecisionBuilder* const db1,
555  DecisionBuilder* const db2,
556  DecisionBuilder* const db3) {
557  ComposeDecisionBuilder* c = RevAlloc(new ComposeDecisionBuilder());
558  c->Add(db1);
559  c->Add(db2);
560  c->Add(db3);
561  return c;
562 }
563 
564 DecisionBuilder* Solver::Compose(DecisionBuilder* const db1,
565  DecisionBuilder* const db2,
566  DecisionBuilder* const db3,
567  DecisionBuilder* const db4) {
568  ComposeDecisionBuilder* c = RevAlloc(new ComposeDecisionBuilder());
569  c->Add(db1);
570  c->Add(db2);
571  c->Add(db3);
572  c->Add(db4);
573  return c;
574 }
575 
576 DecisionBuilder* Solver::Compose(const std::vector<DecisionBuilder*>& dbs) {
577  if (dbs.size() == 1) {
578  return dbs[0];
579  }
580  return RevAlloc(new ComposeDecisionBuilder(dbs));
581 }
582 
583 // ---------- ClosureDecision ---------
584 
585 namespace {
586 class ClosureDecision : public Decision {
587  public:
588  ClosureDecision(Solver::Action apply, Solver::Action refute)
589  : apply_(std::move(apply)), refute_(std::move(refute)) {}
590  ~ClosureDecision() override {}
591 
592  void Apply(Solver* const s) override { apply_(s); }
593 
594  void Refute(Solver* const s) override { refute_(s); }
595 
596  std::string DebugString() const override { return "ClosureDecision"; }
597 
598  private:
599  Solver::Action apply_;
600  Solver::Action refute_;
601 };
602 } // namespace
603 
604 Decision* Solver::MakeDecision(Action apply, Action refute) {
605  return RevAlloc(new ClosureDecision(std::move(apply), std::move(refute)));
606 }
607 
608 // ---------- Try Decision Builder ----------
609 
610 namespace {
611 
612 class TryDecisionBuilder;
613 
614 class TryDecision : public Decision {
615  public:
616  explicit TryDecision(TryDecisionBuilder* const try_builder);
617  ~TryDecision() override;
618  void Apply(Solver* const solver) override;
619  void Refute(Solver* const solver) override;
620  std::string DebugString() const override { return "TryDecision"; }
621 
622  private:
623  TryDecisionBuilder* const try_builder_;
624 };
625 
626 class TryDecisionBuilder : public CompositeDecisionBuilder {
627  public:
628  TryDecisionBuilder();
629  explicit TryDecisionBuilder(const std::vector<DecisionBuilder*>& dbs);
630  ~TryDecisionBuilder() override;
631  Decision* Next(Solver* const solver) override;
632  std::string DebugString() const override;
633  void AdvanceToNextBuilder(Solver* const solver);
634 
635  private:
636  TryDecision try_decision_;
637  int current_builder_;
638  bool start_new_builder_;
639 };
640 
641 TryDecision::TryDecision(TryDecisionBuilder* const try_builder)
642  : try_builder_(try_builder) {}
643 
644 TryDecision::~TryDecision() {}
645 
646 void TryDecision::Apply(Solver* const solver) {}
647 
648 void TryDecision::Refute(Solver* const solver) {
649  try_builder_->AdvanceToNextBuilder(solver);
650 }
651 
652 TryDecisionBuilder::TryDecisionBuilder()
653  : CompositeDecisionBuilder(),
654  try_decision_(this),
655  current_builder_(-1),
656  start_new_builder_(true) {}
657 
658 TryDecisionBuilder::TryDecisionBuilder(const std::vector<DecisionBuilder*>& dbs)
659  : CompositeDecisionBuilder(dbs),
660  try_decision_(this),
661  current_builder_(-1),
662  start_new_builder_(true) {}
663 
664 TryDecisionBuilder::~TryDecisionBuilder() {}
665 
666 Decision* TryDecisionBuilder::Next(Solver* const solver) {
667  if (current_builder_ < 0) {
668  solver->SaveAndSetValue(&current_builder_, 0);
669  start_new_builder_ = true;
670  }
671  if (start_new_builder_) {
672  start_new_builder_ = false;
673  return &try_decision_;
674  } else {
675  return builders_[current_builder_]->Next(solver);
676  }
677 }
678 
679 std::string TryDecisionBuilder::DebugString() const {
680  return absl::StrFormat("TryDecisionBuilder(%s)",
682 }
683 
684 void TryDecisionBuilder::AdvanceToNextBuilder(Solver* const solver) {
685  ++current_builder_;
686  start_new_builder_ = true;
687  if (current_builder_ >= builders_.size()) {
688  solver->Fail();
689  }
690 }
691 
692 } // namespace
693 
694 DecisionBuilder* Solver::Try(DecisionBuilder* const db1,
695  DecisionBuilder* const db2) {
696  TryDecisionBuilder* try_db = RevAlloc(new TryDecisionBuilder());
697  try_db->Add(db1);
698  try_db->Add(db2);
699  return try_db;
700 }
701 
702 DecisionBuilder* Solver::Try(DecisionBuilder* const db1,
703  DecisionBuilder* const db2,
704  DecisionBuilder* const db3) {
705  TryDecisionBuilder* try_db = RevAlloc(new TryDecisionBuilder());
706  try_db->Add(db1);
707  try_db->Add(db2);
708  try_db->Add(db3);
709  return try_db;
710 }
711 
712 DecisionBuilder* Solver::Try(DecisionBuilder* const db1,
713  DecisionBuilder* const db2,
714  DecisionBuilder* const db3,
715  DecisionBuilder* const db4) {
716  TryDecisionBuilder* try_db = RevAlloc(new TryDecisionBuilder());
717  try_db->Add(db1);
718  try_db->Add(db2);
719  try_db->Add(db3);
720  try_db->Add(db4);
721  return try_db;
722 }
723 
724 DecisionBuilder* Solver::Try(const std::vector<DecisionBuilder*>& dbs) {
725  return RevAlloc(new TryDecisionBuilder(dbs));
726 }
727 
728 // ---------- Variable Assignments ----------
729 
730 // ----- BaseAssignmentSelector -----
731 
732 namespace {
733 class BaseVariableAssignmentSelector : public BaseObject {
734  public:
735  BaseVariableAssignmentSelector(Solver* solver,
736  const std::vector<IntVar*>& vars)
737  : solver_(solver),
738  vars_(vars),
739  first_unbound_(0),
740  last_unbound_(vars.size() - 1) {}
741 
742  ~BaseVariableAssignmentSelector() override {}
743 
744  virtual int64 SelectValue(const IntVar* v, int64 id) = 0;
745 
746  // Returns -1 if no variable are suitable.
747  virtual int64 ChooseVariable() = 0;
748 
749  int64 ChooseVariableWrapper() {
750  int64 i;
751  for (i = first_unbound_.Value(); i <= last_unbound_.Value(); ++i) {
752  if (!vars_[i]->Bound()) {
753  break;
754  }
755  }
756  first_unbound_.SetValue(solver_, i);
757  if (i > last_unbound_.Value()) {
758  return -1;
759  }
760  for (i = last_unbound_.Value(); i >= first_unbound_.Value(); --i) {
761  if (!vars_[i]->Bound()) {
762  break;
763  }
764  }
765  last_unbound_.SetValue(solver_, i);
766  return ChooseVariable();
767  }
768 
769  void Accept(ModelVisitor* const visitor) const {
770  visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
771  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
772  vars_);
773  visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
774  }
775 
776  const std::vector<IntVar*>& vars() const { return vars_; }
777 
778  protected:
779  Solver* const solver_;
780  std::vector<IntVar*> vars_;
781  Rev<int64> first_unbound_;
782  Rev<int64> last_unbound_;
783 };
784 
785 // ----- Choose first unbound --
786 
787 int64 ChooseFirstUnbound(Solver* solver, const std::vector<IntVar*>& vars,
788  int64 first_unbound, int64 last_unbound) {
789  for (int64 i = first_unbound; i <= last_unbound; ++i) {
790  if (!vars[i]->Bound()) {
791  return i;
792  }
793  }
794  return -1;
795 }
796 
797 // ----- Choose Min Size Lowest Min -----
798 
799 int64 ChooseMinSizeLowestMin(Solver* solver, const std::vector<IntVar*>& vars,
800  int64 first_unbound, int64 last_unbound) {
801  uint64 best_size = kuint64max;
802  int64 best_min = kint64max;
803  int64 best_index = -1;
804  for (int64 i = first_unbound; i <= last_unbound; ++i) {
805  IntVar* const var = vars[i];
806  if (!var->Bound()) {
807  if (var->Size() < best_size ||
808  (var->Size() == best_size && var->Min() < best_min)) {
809  best_size = var->Size();
810  best_min = var->Min();
811  best_index = i;
812  }
813  }
814  }
815  return best_index;
816 }
817 
818 // ----- Choose Min Size Highest Min -----
819 
820 int64 ChooseMinSizeHighestMin(Solver* solver, const std::vector<IntVar*>& vars,
821  int64 first_unbound, int64 last_unbound) {
822  uint64 best_size = kuint64max;
823  int64 best_min = kint64min;
824  int64 best_index = -1;
825  for (int64 i = first_unbound; i <= last_unbound; ++i) {
826  IntVar* const var = vars[i];
827  if (!var->Bound()) {
828  if (var->Size() < best_size ||
829  (var->Size() == best_size && var->Min() > best_min)) {
830  best_size = var->Size();
831  best_min = var->Min();
832  best_index = i;
833  }
834  }
835  }
836  return best_index;
837 }
838 
839 // ----- Choose Min Size Lowest Max -----
840 
841 int64 ChooseMinSizeLowestMax(Solver* solver, const std::vector<IntVar*>& vars,
842  int64 first_unbound, int64 last_unbound) {
843  uint64 best_size = kuint64max;
844  int64 best_max = kint64max;
845  int64 best_index = -1;
846  for (int64 i = first_unbound; i <= last_unbound; ++i) {
847  IntVar* const var = vars[i];
848  if (!var->Bound()) {
849  if (var->Size() < best_size ||
850  (var->Size() == best_size && var->Max() < best_max)) {
851  best_size = var->Size();
852  best_max = var->Max();
853  best_index = i;
854  }
855  }
856  }
857  return best_index;
858 }
859 
860 // ----- Choose Min Size Highest Max -----
861 
862 int64 ChooseMinSizeHighestMax(Solver* solver, const std::vector<IntVar*>& vars,
863  int64 first_unbound, int64 last_unbound) {
864  uint64 best_size = kuint64max;
865  int64 best_max = kint64min;
866  int64 best_index = -1;
867  for (int64 i = first_unbound; i <= last_unbound; ++i) {
868  IntVar* const var = vars[i];
869  if (!var->Bound()) {
870  if (var->Size() < best_size ||
871  (var->Size() == best_size && var->Max() > best_max)) {
872  best_size = var->Size();
873  best_max = var->Max();
874  best_index = i;
875  }
876  }
877  }
878  return best_index;
879 }
880 
881 // ----- Choose Lowest Min --
882 
883 int64 ChooseLowestMin(Solver* solver, const std::vector<IntVar*>& vars,
884  int64 first_unbound, int64 last_unbound) {
885  int64 best_min = kint64max;
886  int64 best_index = -1;
887  for (int64 i = first_unbound; i <= last_unbound; ++i) {
888  IntVar* const var = vars[i];
889  if (!var->Bound()) {
890  if (var->Min() < best_min) {
891  best_min = var->Min();
892  best_index = i;
893  }
894  }
895  }
896  return best_index;
897 }
898 
899 // ----- Choose Highest Max -----
900 
901 int64 ChooseHighestMax(Solver* solver, const std::vector<IntVar*>& vars,
902  int64 first_unbound, int64 last_unbound) {
903  int64 best_max = kint64min;
904  int64 best_index = -1;
905  for (int64 i = first_unbound; i <= last_unbound; ++i) {
906  IntVar* const var = vars[i];
907  if (!var->Bound()) {
908  if (var->Max() > best_max) {
909  best_max = var->Max();
910  best_index = i;
911  }
912  }
913  }
914  return best_index;
915 }
916 
917 // ----- Choose Lowest Size --
918 
919 int64 ChooseMinSize(Solver* solver, const std::vector<IntVar*>& vars,
920  int64 first_unbound, int64 last_unbound) {
921  uint64 best_size = kuint64max;
922  int64 best_index = -1;
923  for (int64 i = first_unbound; i <= last_unbound; ++i) {
924  IntVar* const var = vars[i];
925  if (!var->Bound()) {
926  if (var->Size() < best_size) {
927  best_size = var->Size();
928  best_index = i;
929  }
930  }
931  }
932  return best_index;
933 }
934 
935 // ----- Choose Highest Size -----
936 
937 int64 ChooseMaxSize(Solver* solver, const std::vector<IntVar*>& vars,
938  int64 first_unbound, int64 last_unbound) {
939  uint64 best_size = 0;
940  int64 best_index = -1;
941  for (int64 i = first_unbound; i <= last_unbound; ++i) {
942  IntVar* const var = vars[i];
943  if (!var->Bound()) {
944  if (var->Size() > best_size) {
945  best_size = var->Size();
946  best_index = i;
947  }
948  }
949  }
950  return best_index;
951 }
952 
953 // ----- Choose Highest Regret -----
954 
955 class HighestRegretSelectorOnMin : public BaseObject {
956  public:
957  explicit HighestRegretSelectorOnMin(const std::vector<IntVar*>& vars)
958  : iterators_(vars.size()) {
959  for (int64 i = 0; i < vars.size(); ++i) {
960  iterators_[i] = vars[i]->MakeDomainIterator(true);
961  }
962  }
963  ~HighestRegretSelectorOnMin() override {}
964  int64 Choose(Solver* const s, const std::vector<IntVar*>& vars,
965  int64 first_unbound, int64 last_unbound);
966  std::string DebugString() const override { return "MaxRegretSelector"; }
967 
968  int64 ComputeRegret(IntVar* var, int64 index) const {
969  DCHECK(!var->Bound());
970  const int64 vmin = var->Min();
971  IntVarIterator* const iterator = iterators_[index];
972  iterator->Init();
973  iterator->Next();
974  return iterator->Value() - vmin;
975  }
976 
977  private:
978  std::vector<IntVarIterator*> iterators_;
979 };
980 
981 int64 HighestRegretSelectorOnMin::Choose(Solver* const s,
982  const std::vector<IntVar*>& vars,
983  int64 first_unbound,
984  int64 last_unbound) {
985  int64 best_regret = 0;
986  int64 index = -1;
987  for (int64 i = first_unbound; i <= last_unbound; ++i) {
988  IntVar* const var = vars[i];
989  if (!var->Bound()) {
990  const int64 regret = ComputeRegret(var, i);
991  if (regret > best_regret) {
992  best_regret = regret;
993  index = i;
994  }
995  }
996  }
997  return index;
998 }
999 
1000 // ----- Choose random unbound --
1001 
1002 int64 ChooseRandom(Solver* solver, const std::vector<IntVar*>& vars,
1003  int64 first_unbound, int64 last_unbound) {
1004  const int64 span = last_unbound - first_unbound + 1;
1005  const int64 shift = solver->Rand32(span);
1006  for (int64 i = 0; i < span; ++i) {
1007  const int64 index = (i + shift) % span + first_unbound;
1008  if (!vars[index]->Bound()) {
1009  return index;
1010  }
1011  }
1012  return -1;
1013 }
1014 
1015 // ----- Choose min eval -----
1016 
1017 class CheapestVarSelector : public BaseObject {
1018  public:
1019  explicit CheapestVarSelector(std::function<int64(int64)> var_evaluator)
1020  : var_evaluator_(std::move(var_evaluator)) {}
1021  ~CheapestVarSelector() override {}
1022  int64 Choose(Solver* const s, const std::vector<IntVar*>& vars,
1023  int64 first_unbound, int64 last_unbound);
1024  std::string DebugString() const override { return "CheapestVarSelector"; }
1025 
1026  private:
1027  std::function<int64(int64)> var_evaluator_;
1028 };
1029 
1030 int64 CheapestVarSelector::Choose(Solver* const s,
1031  const std::vector<IntVar*>& vars,
1032  int64 first_unbound, int64 last_unbound) {
1033  int64 best_eval = kint64max;
1034  int64 index = -1;
1035  for (int64 i = first_unbound; i <= last_unbound; ++i) {
1036  if (!vars[i]->Bound()) {
1037  const int64 eval = var_evaluator_(i);
1038  if (eval < best_eval) {
1039  best_eval = eval;
1040  index = i;
1041  }
1042  }
1043  }
1044  return index;
1045 }
1046 
1047 // ----- Path selector -----
1048 // Follow path, where var[i] is represents the next of i
1049 
1050 class PathSelector : public BaseObject {
1051  public:
1052  PathSelector() : first_(kint64max) {}
1053  ~PathSelector() override {}
1054  int64 Choose(Solver* const s, const std::vector<IntVar*>& vars,
1055  int64 first_unbound, int64 last_unbound);
1056  std::string DebugString() const override { return "ChooseNextOnPath"; }
1057 
1058  private:
1059  bool UpdateIndex(const std::vector<IntVar*>& vars, int64* index) const;
1060  bool FindPathStart(const std::vector<IntVar*>& vars, int64* index) const;
1061 
1062  Rev<int64> first_;
1063 };
1064 
1065 int64 PathSelector::Choose(Solver* const s, const std::vector<IntVar*>& vars,
1066  int64 first_unbound, int64 last_unbound) {
1067  int64 index = first_.Value();
1068  if (!UpdateIndex(vars, &index)) {
1069  return -1;
1070  }
1071  int64 count = 0;
1072  while (vars[index]->Bound()) {
1073  index = vars[index]->Value();
1074  if (!UpdateIndex(vars, &index)) {
1075  return -1;
1076  }
1077  ++count;
1078  if (count >= vars.size() &&
1079  !FindPathStart(vars, &index)) { // Cycle detected
1080  return -1;
1081  }
1082  }
1083  first_.SetValue(s, index);
1084  return index;
1085 }
1086 
1087 bool PathSelector::UpdateIndex(const std::vector<IntVar*>& vars,
1088  int64* index) const {
1089  if (*index >= vars.size()) {
1090  if (!FindPathStart(vars, index)) {
1091  return false;
1092  }
1093  }
1094  return true;
1095 }
1096 
1097 // Select variables on a path:
1098 // 1. Try to extend an existing route: look for an unbound variable, to which
1099 // some other variable points.
1100 // 2. If no such road is found, try to find a start node of a route: look for
1101 // an unbound variable, to which no other variable can point.
1102 // 3. If everything else fails, pick the first unbound variable.
1103 bool PathSelector::FindPathStart(const std::vector<IntVar*>& vars,
1104  int64* index) const {
1105  // Try to extend an existing path
1106  for (int64 i = vars.size() - 1; i >= 0; --i) {
1107  if (vars[i]->Bound()) {
1108  const int64 next = vars[i]->Value();
1109  if (next < vars.size() && !vars[next]->Bound()) {
1110  *index = next;
1111  return true;
1112  }
1113  }
1114  }
1115  // Pick path start
1116  for (int64 i = vars.size() - 1; i >= 0; --i) {
1117  if (!vars[i]->Bound()) {
1118  bool has_possible_prev = false;
1119  for (int64 j = 0; j < vars.size(); ++j) {
1120  if (vars[j]->Contains(i)) {
1121  has_possible_prev = true;
1122  break;
1123  }
1124  }
1125  if (!has_possible_prev) {
1126  *index = i;
1127  return true;
1128  }
1129  }
1130  }
1131  // Pick first unbound
1132  for (int64 i = 0; i < vars.size(); ++i) {
1133  if (!vars[i]->Bound()) {
1134  *index = i;
1135  return true;
1136  }
1137  }
1138  return false;
1139 }
1140 
1141 // ----- Select min -----
1142 
1143 int64 SelectMinValue(const IntVar* v, int64 id) { return v->Min(); }
1144 
1145 // ----- Select max -----
1146 
1147 int64 SelectMaxValue(const IntVar* v, int64 id) { return v->Max(); }
1148 
1149 // ----- Select random -----
1150 
1151 int64 SelectRandomValue(const IntVar* v, int64 id) {
1152  const uint64 span = v->Max() - v->Min() + 1;
1153  if (span > FLAGS_cp_large_domain_no_splitting_limit) {
1154  // Do not create holes in large domains.
1155  return v->Min();
1156  }
1157  const uint64 size = v->Size();
1158  Solver* const s = v->solver();
1159  if (size > span / 4) { // Dense enough, we can try to find the
1160  // value randomly.
1161  for (;;) {
1162  const int64 value = v->Min() + s->Rand64(span);
1163  if (v->Contains(value)) {
1164  return value;
1165  }
1166  }
1167  } else { // Not dense enough, we will count.
1168  int64 index = s->Rand64(size);
1169  if (index <= size / 2) {
1170  for (int64 i = v->Min(); i <= v->Max(); ++i) {
1171  if (v->Contains(i)) {
1172  if (--index == 0) {
1173  return i;
1174  }
1175  }
1176  }
1177  CHECK_LE(index, 0);
1178  } else {
1179  for (int64 i = v->Max(); i > v->Min(); --i) {
1180  if (v->Contains(i)) {
1181  if (--index == 0) {
1182  return i;
1183  }
1184  }
1185  }
1186  CHECK_LE(index, 0);
1187  }
1188  }
1189  return 0;
1190 }
1191 
1192 // ----- Select center -----
1193 
1194 int64 SelectCenterValue(const IntVar* v, int64 id) {
1195  const int64 vmin = v->Min();
1196  const int64 vmax = v->Max();
1197  if (vmax - vmin > FLAGS_cp_large_domain_no_splitting_limit) {
1198  // Do not create holes in large domains.
1199  return vmin;
1200  }
1201  const int64 mid = (vmin + vmax) / 2;
1202  if (v->Contains(mid)) {
1203  return mid;
1204  }
1205  const int64 diameter = vmax - mid; // always greater than mid - vmix.
1206  for (int64 i = 1; i <= diameter; ++i) {
1207  if (v->Contains(mid - i)) {
1208  return mid - i;
1209  }
1210  if (v->Contains(mid + i)) {
1211  return mid + i;
1212  }
1213  }
1214  return 0;
1215 }
1216 
1217 // ----- Select center -----
1218 
1219 int64 SelectSplitValue(const IntVar* v, int64 id) {
1220  const int64 vmin = v->Min();
1221  const int64 vmax = v->Max();
1222  const uint64 delta = vmax - vmin;
1223  const int64 mid = vmin + delta / 2;
1224  return mid;
1225 }
1226 
1227 // ----- Select the value yielding the cheapest "eval" for a var -----
1228 
1229 class CheapestValueSelector : public BaseObject {
1230  public:
1231  CheapestValueSelector(std::function<int64(int64, int64)> eval,
1232  std::function<int64(int64)> tie_breaker)
1233  : eval_(std::move(eval)), tie_breaker_(std::move(tie_breaker)) {}
1234  ~CheapestValueSelector() override {}
1235  int64 Select(const IntVar* v, int64 id);
1236  std::string DebugString() const override { return "CheapestValue"; }
1237 
1238  private:
1239  std::function<int64(int64, int64)> eval_;
1240  std::function<int64(int64)> tie_breaker_;
1241  std::vector<int64> cache_;
1242 };
1243 
1244 int64 CheapestValueSelector::Select(const IntVar* v, int64 id) {
1245  cache_.clear();
1246  int64 best = kint64max;
1247  std::unique_ptr<IntVarIterator> it(v->MakeDomainIterator(false));
1248  for (const int64 i : InitAndGetValues(it.get())) {
1249  int64 eval = eval_(id, i);
1250  if (eval < best) {
1251  best = eval;
1252  cache_.clear();
1253  cache_.push_back(i);
1254  } else if (eval == best) {
1255  cache_.push_back(i);
1256  }
1257  }
1258  DCHECK_GT(cache_.size(), 0);
1259  if (tie_breaker_ == nullptr || cache_.size() == 1) {
1260  return cache_.back();
1261  } else {
1262  return cache_[tie_breaker_(cache_.size())];
1263  }
1264 }
1265 
1266 // ----- Select the best value for the var, based on a comparator callback -----
1267 
1268 // The comparator should be a total order, but does not have to be a strict
1269 // ordering. If there is a tie between two values val1 and val2, i.e. if
1270 // !comparator(var_id, val1, val2) && !comparator(var_id, val2, val1), then
1271 // the lowest value wins.
1272 // comparator(var_id, val1, val2) == true means than val1 should be preferred
1273 // over val2 for variable var_id.
1274 class BestValueByComparisonSelector : public BaseObject {
1275  public:
1276  explicit BestValueByComparisonSelector(
1277  Solver::VariableValueComparator comparator)
1278  : comparator_(std::move(comparator)) {}
1279  ~BestValueByComparisonSelector() override {}
1280  int64 Select(const IntVar* v, int64 id);
1281  std::string DebugString() const override {
1282  return "BestValueByComparisonSelector";
1283  }
1284 
1285  private:
1286  Solver::VariableValueComparator comparator_;
1287 };
1288 
1289 int64 BestValueByComparisonSelector::Select(const IntVar* v, int64 id) {
1290  std::unique_ptr<IntVarIterator> it(v->MakeDomainIterator(false));
1291  it->Init();
1292  DCHECK(it->Ok()); // At least one value.
1293  int64 best_value = it->Value();
1294  for (it->Next(); it->Ok(); it->Next()) {
1295  const int64 candidate_value = it->Value();
1296  if (comparator_(id, candidate_value, best_value)) {
1297  best_value = candidate_value;
1298  }
1299  }
1300  return best_value;
1301 }
1302 
1303 // ----- VariableAssignmentSelector -----
1304 
1305 class VariableAssignmentSelector : public BaseVariableAssignmentSelector {
1306  public:
1307  VariableAssignmentSelector(Solver* solver, const std::vector<IntVar*>& vars,
1308  Solver::VariableIndexSelector var_selector,
1309  Solver::VariableValueSelector value_selector,
1310  const std::string& name)
1311  : BaseVariableAssignmentSelector(solver, vars),
1312  var_selector_(std::move(var_selector)),
1313  value_selector_(std::move(value_selector)),
1314  name_(name) {}
1315  ~VariableAssignmentSelector() override {}
1316  int64 SelectValue(const IntVar* var, int64 id) override {
1317  return value_selector_(var, id);
1318  }
1319  int64 ChooseVariable() override {
1320  return var_selector_(solver_, vars_, first_unbound_.Value(),
1321  last_unbound_.Value());
1322  }
1323  std::string DebugString() const override;
1324 
1325  private:
1326  Solver::VariableIndexSelector var_selector_;
1327  Solver::VariableValueSelector value_selector_;
1328  const std::string name_;
1329 };
1330 
1331 std::string VariableAssignmentSelector::DebugString() const {
1332  return absl::StrFormat("%s(%s)", name_, JoinDebugStringPtr(vars_, ", "));
1333 }
1334 
1335 // ----- Base Global Evaluator-based selector -----
1336 
1337 class BaseEvaluatorSelector : public BaseVariableAssignmentSelector {
1338  public:
1339  BaseEvaluatorSelector(Solver* solver, const std::vector<IntVar*>& vars,
1340  std::function<int64(int64, int64)> evaluator);
1341  ~BaseEvaluatorSelector() override {}
1342 
1343  protected:
1344  struct Element {
1345  Element() : var(0), value(0) {}
1346  Element(int64 i, int64 j) : var(i), value(j) {}
1349  };
1350 
1351  std::string DebugStringInternal(const std::string& name) const {
1352  return absl::StrFormat("%s(%s)", name, JoinDebugStringPtr(vars_, ", "));
1353  }
1354 
1355  std::function<int64(int64, int64)> evaluator_;
1356 };
1357 
1358 BaseEvaluatorSelector::BaseEvaluatorSelector(
1359  Solver* solver, const std::vector<IntVar*>& vars,
1360  std::function<int64(int64, int64)> evaluator)
1361  : BaseVariableAssignmentSelector(solver, vars),
1362  evaluator_(std::move(evaluator)) {}
1363 
1364 // ----- Global Dynamic Evaluator-based selector -----
1365 
1366 class DynamicEvaluatorSelector : public BaseEvaluatorSelector {
1367  public:
1368  DynamicEvaluatorSelector(Solver* solver, const std::vector<IntVar*>& vars,
1369  std::function<int64(int64, int64)> evaluator,
1370  std::function<int64(int64)> tie_breaker);
1371  ~DynamicEvaluatorSelector() override {}
1372  int64 SelectValue(const IntVar* var, int64 id) override;
1373  int64 ChooseVariable() override;
1374  std::string DebugString() const override;
1375 
1376  private:
1377  int64 first_;
1378  std::function<int64(int64)> tie_breaker_;
1379  std::vector<Element> cache_;
1380 };
1381 
1382 DynamicEvaluatorSelector::DynamicEvaluatorSelector(
1383  Solver* solver, const std::vector<IntVar*>& vars,
1384  std::function<int64(int64, int64)> evaluator,
1385  std::function<int64(int64)> tie_breaker)
1386  : BaseEvaluatorSelector(solver, vars, std::move(evaluator)),
1387  first_(-1),
1388  tie_breaker_(std::move(tie_breaker)) {}
1389 
1390 int64 DynamicEvaluatorSelector::SelectValue(const IntVar* var, int64 id) {
1391  return cache_[first_].value;
1392 }
1393 
1394 int64 DynamicEvaluatorSelector::ChooseVariable() {
1395  int64 best_evaluation = kint64max;
1396  cache_.clear();
1397  for (int64 i = 0; i < vars_.size(); ++i) {
1398  const IntVar* const var = vars_[i];
1399  if (!var->Bound()) {
1400  std::unique_ptr<IntVarIterator> it(var->MakeDomainIterator(false));
1401  for (const int64 j : InitAndGetValues(it.get())) {
1402  const int64 value = evaluator_(i, j);
1403  if (value < best_evaluation) {
1404  best_evaluation = value;
1405  cache_.clear();
1406  cache_.push_back(Element(i, j));
1407  } else if (value == best_evaluation && tie_breaker_) {
1408  cache_.push_back(Element(i, j));
1409  }
1410  }
1411  }
1412  }
1413 
1414  if (cache_.empty()) {
1415  return -1;
1416  }
1417 
1418  if (tie_breaker_ == nullptr || cache_.size() == 1) {
1419  first_ = 0;
1420  return cache_.front().var;
1421  } else {
1422  first_ = tie_breaker_(cache_.size());
1423  return cache_[first_].var;
1424  }
1425 }
1426 
1427 std::string DynamicEvaluatorSelector::DebugString() const {
1428  return DebugStringInternal("AssignVariablesOnDynamicEvaluator");
1429 }
1430 
1431 // ----- Global Dynamic Evaluator-based selector -----
1432 
1433 class StaticEvaluatorSelector : public BaseEvaluatorSelector {
1434  public:
1435  StaticEvaluatorSelector(Solver* solver, const std::vector<IntVar*>& vars,
1436  const std::function<int64(int64, int64)>& evaluator);
1437  ~StaticEvaluatorSelector() override {}
1438  int64 SelectValue(const IntVar* var, int64 id) override;
1439  int64 ChooseVariable() override;
1440  std::string DebugString() const override;
1441 
1442  private:
1443  class Compare {
1444  public:
1445  explicit Compare(std::function<int64(int64, int64)> evaluator)
1446  : evaluator_(std::move(evaluator)) {}
1447  bool operator()(const Element& lhs, const Element& rhs) const {
1448  const int64 value_lhs = Value(lhs);
1449  const int64 value_rhs = Value(rhs);
1450  return value_lhs < value_rhs ||
1451  (value_lhs == value_rhs &&
1452  (lhs.var < rhs.var ||
1453  (lhs.var == rhs.var && lhs.value < rhs.value)));
1454  }
1455  int64 Value(const Element& element) const {
1456  return evaluator_(element.var, element.value);
1457  }
1458 
1459  private:
1460  std::function<int64(int64, int64)> evaluator_;
1461  };
1462 
1463  Compare comp_;
1464  std::vector<Element> elements_;
1465  int64 first_;
1466 };
1467 
1468 StaticEvaluatorSelector::StaticEvaluatorSelector(
1469  Solver* solver, const std::vector<IntVar*>& vars,
1470  const std::function<int64(int64, int64)>& evaluator)
1471  : BaseEvaluatorSelector(solver, vars, evaluator),
1472  comp_(evaluator),
1473  first_(-1) {}
1474 
1475 int64 StaticEvaluatorSelector::SelectValue(const IntVar* var, int64 id) {
1476  return elements_[first_].value;
1477 }
1478 
1479 int64 StaticEvaluatorSelector::ChooseVariable() {
1480  if (first_ == -1) { // first call to select. update assignment costs
1481  // Two phases: compute size then filland sort
1482  int64 element_size = 0;
1483  for (int64 i = 0; i < vars_.size(); ++i) {
1484  if (!vars_[i]->Bound()) {
1485  element_size += vars_[i]->Size();
1486  }
1487  }
1488  elements_.resize(element_size);
1489  int count = 0;
1490  for (int i = 0; i < vars_.size(); ++i) {
1491  const IntVar* const var = vars_[i];
1492  if (!var->Bound()) {
1493  std::unique_ptr<IntVarIterator> it(var->MakeDomainIterator(false));
1494  for (const int64 value : InitAndGetValues(it.get())) {
1495  elements_[count++] = Element(i, value);
1496  }
1497  }
1498  }
1499  // Sort is stable here given the tie-breaking rules in comp_.
1500  std::sort(elements_.begin(), elements_.end(), comp_);
1501  solver_->SaveAndSetValue<int64>(&first_, 0);
1502  }
1503  for (int64 i = first_; i < elements_.size(); ++i) {
1504  const Element& element = elements_[i];
1505  IntVar* const var = vars_[element.var];
1506  if (!var->Bound() && var->Contains(element.value)) {
1507  solver_->SaveAndSetValue(&first_, i);
1508  return element.var;
1509  }
1510  }
1511  solver_->SaveAndSetValue(&first_, static_cast<int64>(elements_.size()));
1512  return -1;
1513 }
1514 
1515 std::string StaticEvaluatorSelector::DebugString() const {
1516  return DebugStringInternal("AssignVariablesOnStaticEvaluator");
1517 }
1518 
1519 // ----- AssignOneVariableValue decision -----
1520 
1521 class AssignOneVariableValue : public Decision {
1522  public:
1523  AssignOneVariableValue(IntVar* const v, int64 val);
1524  ~AssignOneVariableValue() override {}
1525  void Apply(Solver* const s) override;
1526  void Refute(Solver* const s) override;
1527  std::string DebugString() const override;
1528  void Accept(DecisionVisitor* const visitor) const override {
1529  visitor->VisitSetVariableValue(var_, value_);
1530  }
1531 
1532  private:
1533  IntVar* const var_;
1534  int64 value_;
1535 };
1536 
1537 AssignOneVariableValue::AssignOneVariableValue(IntVar* const v, int64 val)
1538  : var_(v), value_(val) {}
1539 
1540 std::string AssignOneVariableValue::DebugString() const {
1541  return absl::StrFormat("[%s == %d] or [%s != %d]", var_->DebugString(),
1542  value_, var_->DebugString(), value_);
1543 }
1544 
1545 void AssignOneVariableValue::Apply(Solver* const s) { var_->SetValue(value_); }
1546 
1547 void AssignOneVariableValue::Refute(Solver* const s) {
1548  var_->RemoveValue(value_);
1549 }
1550 } // namespace
1551 
1552 Decision* Solver::MakeAssignVariableValue(IntVar* const var, int64 val) {
1553  return RevAlloc(new AssignOneVariableValue(var, val));
1554 }
1555 
1556 // ----- AssignOneVariableValueOrFail decision -----
1557 
1558 namespace {
1559 class AssignOneVariableValueOrFail : public Decision {
1560  public:
1561  AssignOneVariableValueOrFail(IntVar* const v, int64 value);
1562  ~AssignOneVariableValueOrFail() override {}
1563  void Apply(Solver* const s) override;
1564  void Refute(Solver* const s) override;
1565  std::string DebugString() const override;
1566  void Accept(DecisionVisitor* const visitor) const override {
1567  visitor->VisitSetVariableValue(var_, value_);
1568  }
1569 
1570  private:
1571  IntVar* const var_;
1572  const int64 value_;
1573 };
1574 
1575 AssignOneVariableValueOrFail::AssignOneVariableValueOrFail(IntVar* const v,
1576  int64 value)
1577  : var_(v), value_(value) {}
1578 
1579 std::string AssignOneVariableValueOrFail::DebugString() const {
1580  return absl::StrFormat("[%s == %d] or fail", var_->DebugString(), value_);
1581 }
1582 
1583 void AssignOneVariableValueOrFail::Apply(Solver* const s) {
1584  var_->SetValue(value_);
1585 }
1586 
1587 void AssignOneVariableValueOrFail::Refute(Solver* const s) { s->Fail(); }
1588 } // namespace
1589 
1590 Decision* Solver::MakeAssignVariableValueOrFail(IntVar* const var,
1591  int64 value) {
1592  return RevAlloc(new AssignOneVariableValueOrFail(var, value));
1593 }
1594 
1595 // ----- AssignOneVariableValueOrDoNothing decision -----
1596 
1597 namespace {
1598 class AssignOneVariableValueDoNothing : public Decision {
1599  public:
1600  AssignOneVariableValueDoNothing(IntVar* const v, int64 value)
1601  : var_(v), value_(value) {}
1602  ~AssignOneVariableValueDoNothing() override {}
1603  void Apply(Solver* const s) override { var_->SetValue(value_); }
1604  void Refute(Solver* const s) override {}
1605  std::string DebugString() const override {
1606  return absl::StrFormat("[%s == %d] or []", var_->DebugString(), value_);
1607  }
1608  void Accept(DecisionVisitor* const visitor) const override {
1609  visitor->VisitSetVariableValue(var_, value_);
1610  }
1611 
1612  private:
1613  IntVar* const var_;
1614  const int64 value_;
1615 };
1616 
1617 } // namespace
1618 
1619 Decision* Solver::MakeAssignVariableValueOrDoNothing(IntVar* const var,
1620  int64 value) {
1621  return RevAlloc(new AssignOneVariableValueDoNothing(var, value));
1622 }
1623 
1624 // ----- AssignOneVariableValue decision -----
1625 
1626 namespace {
1627 class SplitOneVariable : public Decision {
1628  public:
1629  SplitOneVariable(IntVar* const v, int64 val, bool start_with_lower_half);
1630  ~SplitOneVariable() override {}
1631  void Apply(Solver* const s) override;
1632  void Refute(Solver* const s) override;
1633  std::string DebugString() const override;
1634  void Accept(DecisionVisitor* const visitor) const override {
1635  visitor->VisitSplitVariableDomain(var_, value_, start_with_lower_half_);
1636  }
1637 
1638  private:
1639  IntVar* const var_;
1640  const int64 value_;
1641  const bool start_with_lower_half_;
1642 };
1643 
1644 SplitOneVariable::SplitOneVariable(IntVar* const v, int64 val,
1645  bool start_with_lower_half)
1646  : var_(v), value_(val), start_with_lower_half_(start_with_lower_half) {}
1647 
1648 std::string SplitOneVariable::DebugString() const {
1649  if (start_with_lower_half_) {
1650  return absl::StrFormat("[%s <= %d]", var_->DebugString(), value_);
1651  } else {
1652  return absl::StrFormat("[%s >= %d]", var_->DebugString(), value_);
1653  }
1654 }
1655 
1656 void SplitOneVariable::Apply(Solver* const s) {
1657  if (start_with_lower_half_) {
1658  var_->SetMax(value_);
1659  } else {
1660  var_->SetMin(value_ + 1);
1661  }
1662 }
1663 
1664 void SplitOneVariable::Refute(Solver* const s) {
1665  if (start_with_lower_half_) {
1666  var_->SetMin(value_ + 1);
1667  } else {
1668  var_->SetMax(value_);
1669  }
1670 }
1671 } // namespace
1672 
1673 Decision* Solver::MakeSplitVariableDomain(IntVar* const var, int64 val,
1674  bool start_with_lower_half) {
1675  return RevAlloc(new SplitOneVariable(var, val, start_with_lower_half));
1676 }
1677 
1678 Decision* Solver::MakeVariableLessOrEqualValue(IntVar* const var, int64 value) {
1679  return MakeSplitVariableDomain(var, value, true);
1680 }
1681 
1682 Decision* Solver::MakeVariableGreaterOrEqualValue(IntVar* const var,
1683  int64 value) {
1684  return MakeSplitVariableDomain(var, value, false);
1685 }
1686 
1687 // ----- AssignVariablesValues decision -----
1688 
1689 namespace {
1690 class AssignVariablesValues : public Decision {
1691  public:
1692  AssignVariablesValues(const std::vector<IntVar*>& vars,
1693  const std::vector<int64>& values);
1694  ~AssignVariablesValues() override {}
1695  void Apply(Solver* const s) override;
1696  void Refute(Solver* const s) override;
1697  std::string DebugString() const override;
1698  void Accept(DecisionVisitor* const visitor) const override {
1699  for (int i = 0; i < vars_.size(); ++i) {
1700  visitor->VisitSetVariableValue(vars_[i], values_[i]);
1701  }
1702  }
1703 
1704  virtual void Accept(ModelVisitor* const visitor) const {
1705  visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
1706  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1707  vars_);
1708  visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
1709  }
1710 
1711  private:
1712  const std::vector<IntVar*> vars_;
1713  const std::vector<int64> values_;
1714 };
1715 
1716 AssignVariablesValues::AssignVariablesValues(const std::vector<IntVar*>& vars,
1717  const std::vector<int64>& values)
1718  : vars_(vars), values_(values) {}
1719 
1720 std::string AssignVariablesValues::DebugString() const {
1721  std::string out;
1722  for (int i = 0; i < vars_.size(); ++i) {
1723  absl::StrAppendFormat(&out, "[%s == %d]", vars_[i]->DebugString(),
1724  values_[i]);
1725  }
1726  return out;
1727 }
1728 
1729 void AssignVariablesValues::Apply(Solver* const s) {
1730  for (int i = 0; i < vars_.size(); ++i) {
1731  vars_[i]->SetValue(values_[i]);
1732  }
1733 }
1734 
1735 void AssignVariablesValues::Refute(Solver* const s) {
1736  std::vector<IntVar*> terms;
1737  for (int i = 0; i < vars_.size(); ++i) {
1738  IntVar* term = s->MakeBoolVar();
1739  s->MakeIsDifferentCstCt(vars_[i], values_[i], term);
1740  terms.push_back(term);
1741  }
1742  s->AddConstraint(s->MakeSumGreaterOrEqual(terms, 1));
1743 }
1744 } // namespace
1745 
1746 Decision* Solver::MakeAssignVariablesValues(const std::vector<IntVar*>& vars,
1747  const std::vector<int64>& values) {
1748  CHECK_EQ(vars.size(), values.size());
1749  return RevAlloc(new AssignVariablesValues(vars, values));
1750 }
1751 
1752 // ----- AssignAllVariables -----
1753 
1754 namespace {
1755 class BaseAssignVariables : public DecisionBuilder {
1756  public:
1757  enum Mode {
1758  ASSIGN,
1759  SPLIT_LOWER,
1760  SPLIT_UPPER,
1761  };
1762 
1763  BaseAssignVariables(BaseVariableAssignmentSelector* const selector, Mode mode)
1764  : selector_(selector), mode_(mode) {}
1765 
1766  ~BaseAssignVariables() override;
1767  Decision* Next(Solver* const s) override;
1768  std::string DebugString() const override;
1769  static BaseAssignVariables* MakePhase(
1770  Solver* const s, const std::vector<IntVar*>& vars,
1771  Solver::VariableIndexSelector var_selector,
1772  Solver::VariableValueSelector value_selector,
1773  const std::string& value_selector_name, BaseAssignVariables::Mode mode);
1774 
1775  static Solver::VariableIndexSelector MakeVariableSelector(
1776  Solver* const s, const std::vector<IntVar*>& vars,
1777  Solver::IntVarStrategy str) {
1778  switch (str) {
1779  case Solver::INT_VAR_DEFAULT:
1780  case Solver::INT_VAR_SIMPLE:
1781  case Solver::CHOOSE_FIRST_UNBOUND:
1782  return ChooseFirstUnbound;
1783  case Solver::CHOOSE_RANDOM:
1784  return ChooseRandom;
1785  case Solver::CHOOSE_MIN_SIZE_LOWEST_MIN:
1786  return ChooseMinSizeLowestMin;
1787  case Solver::CHOOSE_MIN_SIZE_HIGHEST_MIN:
1788  return ChooseMinSizeHighestMin;
1789  case Solver::CHOOSE_MIN_SIZE_LOWEST_MAX:
1790  return ChooseMinSizeLowestMax;
1791  case Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX:
1792  return ChooseMinSizeHighestMax;
1793  case Solver::CHOOSE_LOWEST_MIN:
1794  return ChooseLowestMin;
1795  case Solver::CHOOSE_HIGHEST_MAX:
1796  return ChooseHighestMax;
1797  case Solver::CHOOSE_MIN_SIZE:
1798  return ChooseMinSize;
1799  case Solver::CHOOSE_MAX_SIZE:
1800  return ChooseMaxSize;
1801  case Solver::CHOOSE_MAX_REGRET_ON_MIN: {
1802  HighestRegretSelectorOnMin* const selector =
1803  s->RevAlloc(new HighestRegretSelectorOnMin(vars));
1804  return [selector](Solver* solver, const std::vector<IntVar*>& vars,
1805  int first_unbound, int last_unbound) {
1806  return selector->Choose(solver, vars, first_unbound, last_unbound);
1807  };
1808  }
1809  case Solver::CHOOSE_PATH: {
1810  PathSelector* const selector = s->RevAlloc(new PathSelector());
1811  return [selector](Solver* solver, const std::vector<IntVar*>& vars,
1812  int first_unbound, int last_unbound) {
1813  return selector->Choose(solver, vars, first_unbound, last_unbound);
1814  };
1815  }
1816  default:
1817  LOG(FATAL) << "Unknown int var strategy " << str;
1818  return nullptr;
1819  }
1820  }
1821 
1822  static Solver::VariableValueSelector MakeValueSelector(
1823  Solver* const s, Solver::IntValueStrategy val_str) {
1824  switch (val_str) {
1825  case Solver::INT_VALUE_DEFAULT:
1826  case Solver::INT_VALUE_SIMPLE:
1827  case Solver::ASSIGN_MIN_VALUE:
1828  return SelectMinValue;
1829  case Solver::ASSIGN_MAX_VALUE:
1830  return SelectMaxValue;
1831  case Solver::ASSIGN_RANDOM_VALUE:
1832  return SelectRandomValue;
1833  case Solver::ASSIGN_CENTER_VALUE:
1834  return SelectCenterValue;
1835  case Solver::SPLIT_LOWER_HALF:
1836  return SelectSplitValue;
1837  case Solver::SPLIT_UPPER_HALF:
1838  return SelectSplitValue;
1839  default:
1840  LOG(FATAL) << "Unknown int value strategy " << val_str;
1841  return nullptr;
1842  }
1843  }
1844 
1845  void Accept(ModelVisitor* const visitor) const override {
1846  selector_->Accept(visitor);
1847  }
1848 
1849  protected:
1850  BaseVariableAssignmentSelector* const selector_;
1851  const Mode mode_;
1852 };
1853 
1854 BaseAssignVariables::~BaseAssignVariables() {}
1855 
1856 Decision* BaseAssignVariables::Next(Solver* const s) {
1857  const std::vector<IntVar*>& vars = selector_->vars();
1858  int id = selector_->ChooseVariableWrapper();
1859  if (id >= 0 && id < vars.size()) {
1860  IntVar* const var = vars[id];
1861  const int64 value = selector_->SelectValue(var, id);
1862  switch (mode_) {
1863  case ASSIGN:
1864  return s->RevAlloc(new AssignOneVariableValue(var, value));
1865  case SPLIT_LOWER:
1866  return s->RevAlloc(new SplitOneVariable(var, value, true));
1867  case SPLIT_UPPER:
1868  return s->RevAlloc(new SplitOneVariable(var, value, false));
1869  }
1870  }
1871  return nullptr;
1872 }
1873 
1874 std::string BaseAssignVariables::DebugString() const {
1875  return selector_->DebugString();
1876 }
1877 
1878 BaseAssignVariables* BaseAssignVariables::MakePhase(
1879  Solver* const s, const std::vector<IntVar*>& vars,
1880  Solver::VariableIndexSelector var_selector,
1881  Solver::VariableValueSelector value_selector,
1882  const std::string& value_selector_name, BaseAssignVariables::Mode mode) {
1883  BaseVariableAssignmentSelector* const selector =
1884  s->RevAlloc(new VariableAssignmentSelector(
1885  s, vars, std::move(var_selector), std::move(value_selector),
1886  value_selector_name));
1887  return s->RevAlloc(new BaseAssignVariables(selector, mode));
1888 }
1889 
1890 std::string ChooseVariableName(Solver::IntVarStrategy var_str) {
1891  switch (var_str) {
1892  case Solver::INT_VAR_DEFAULT:
1893  case Solver::INT_VAR_SIMPLE:
1894  case Solver::CHOOSE_FIRST_UNBOUND:
1895  return "ChooseFirstUnbound";
1896  case Solver::CHOOSE_RANDOM:
1897  return "ChooseRandom";
1898  case Solver::CHOOSE_MIN_SIZE_LOWEST_MIN:
1899  return "ChooseMinSizeLowestMin";
1900  case Solver::CHOOSE_MIN_SIZE_HIGHEST_MIN:
1901  return "ChooseMinSizeHighestMin";
1902  case Solver::CHOOSE_MIN_SIZE_LOWEST_MAX:
1903  return "ChooseMinSizeLowestMax";
1904  case Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX:
1905  return "ChooseMinSizeHighestMax";
1906  case Solver::CHOOSE_LOWEST_MIN:
1907  return "ChooseLowestMin";
1908  case Solver::CHOOSE_HIGHEST_MAX:
1909  return "ChooseHighestMax";
1910  case Solver::CHOOSE_MIN_SIZE:
1911  return "ChooseMinSize";
1912  case Solver::CHOOSE_MAX_SIZE:
1913  return "ChooseMaxSize;";
1914  case Solver::CHOOSE_MAX_REGRET_ON_MIN:
1915  return "HighestRegretSelectorOnMin";
1916  case Solver::CHOOSE_PATH:
1917  return "PathSelector";
1918  default:
1919  LOG(FATAL) << "Unknown int var strategy " << var_str;
1920  return "";
1921  }
1922 }
1923 
1924 std::string SelectValueName(Solver::IntValueStrategy val_str) {
1925  switch (val_str) {
1926  case Solver::INT_VALUE_DEFAULT:
1927  case Solver::INT_VALUE_SIMPLE:
1928  case Solver::ASSIGN_MIN_VALUE:
1929  return "SelectMinValue";
1930  case Solver::ASSIGN_MAX_VALUE:
1931  return "SelectMaxValue";
1932  case Solver::ASSIGN_RANDOM_VALUE:
1933  return "SelectRandomValue";
1934  case Solver::ASSIGN_CENTER_VALUE:
1935  return "SelectCenterValue";
1936  case Solver::SPLIT_LOWER_HALF:
1937  return "SelectSplitValue";
1938  case Solver::SPLIT_UPPER_HALF:
1939  return "SelectSplitValue";
1940  default:
1941  LOG(FATAL) << "Unknown int value strategy " << val_str;
1942  return "";
1943  }
1944 }
1945 
1946 std::string BuildHeuristicsName(Solver::IntVarStrategy var_str,
1947  Solver::IntValueStrategy val_str) {
1948  return ChooseVariableName(var_str) + "_" + SelectValueName(val_str);
1949 }
1950 } // namespace
1951 
1952 DecisionBuilder* Solver::MakePhase(IntVar* const v0,
1953  Solver::IntVarStrategy var_str,
1954  Solver::IntValueStrategy val_str) {
1955  std::vector<IntVar*> vars(1);
1956  vars[0] = v0;
1957  return MakePhase(vars, var_str, val_str);
1958 }
1959 
1960 DecisionBuilder* Solver::MakePhase(IntVar* const v0, IntVar* const v1,
1961  Solver::IntVarStrategy var_str,
1962  Solver::IntValueStrategy val_str) {
1963  std::vector<IntVar*> vars(2);
1964  vars[0] = v0;
1965  vars[1] = v1;
1966  return MakePhase(vars, var_str, val_str);
1967 }
1968 
1969 DecisionBuilder* Solver::MakePhase(IntVar* const v0, IntVar* const v1,
1970  IntVar* const v2,
1971  Solver::IntVarStrategy var_str,
1972  Solver::IntValueStrategy val_str) {
1973  std::vector<IntVar*> vars(3);
1974  vars[0] = v0;
1975  vars[1] = v1;
1976  vars[2] = v2;
1977  return MakePhase(vars, var_str, val_str);
1978 }
1979 
1980 DecisionBuilder* Solver::MakePhase(IntVar* const v0, IntVar* const v1,
1981  IntVar* const v2, IntVar* const v3,
1982  Solver::IntVarStrategy var_str,
1983  Solver::IntValueStrategy val_str) {
1984  std::vector<IntVar*> vars(4);
1985  vars[0] = v0;
1986  vars[1] = v1;
1987  vars[2] = v2;
1988  vars[3] = v3;
1989  return MakePhase(vars, var_str, val_str);
1990 }
1991 
1992 BaseAssignVariables::Mode ChooseMode(Solver::IntValueStrategy val_str) {
1993  BaseAssignVariables::Mode mode = BaseAssignVariables::ASSIGN;
1994  if (val_str == Solver::SPLIT_LOWER_HALF) {
1995  mode = BaseAssignVariables::SPLIT_LOWER;
1996  } else if (val_str == Solver::SPLIT_UPPER_HALF) {
1997  mode = BaseAssignVariables::SPLIT_UPPER;
1998  }
1999  return mode;
2000 }
2001 
2002 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2003  Solver::IntVarStrategy var_str,
2004  Solver::IntValueStrategy val_str) {
2005  Solver::VariableIndexSelector var_selector =
2006  BaseAssignVariables::MakeVariableSelector(this, vars, var_str);
2007  Solver::VariableValueSelector value_selector =
2008  BaseAssignVariables::MakeValueSelector(this, val_str);
2009  const std::string name = BuildHeuristicsName(var_str, val_str);
2010  return BaseAssignVariables::MakePhase(
2011  this, vars, var_selector, value_selector, name, ChooseMode(val_str));
2012 }
2013 
2014 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2015  Solver::IndexEvaluator1 var_evaluator,
2016  Solver::IntValueStrategy val_str) {
2017  CHECK(var_evaluator != nullptr);
2018  CheapestVarSelector* const var_selector =
2019  RevAlloc(new CheapestVarSelector(std::move(var_evaluator)));
2020  Solver::VariableIndexSelector choose_variable =
2021  [var_selector](Solver* solver, const std::vector<IntVar*>& vars,
2022  int first_unbound, int last_unbound) {
2023  return var_selector->Choose(solver, vars, first_unbound, last_unbound);
2024  };
2025  Solver::VariableValueSelector select_value =
2026  BaseAssignVariables::MakeValueSelector(this, val_str);
2027  const std::string name = "ChooseCheapestVariable_" + SelectValueName(val_str);
2028  return BaseAssignVariables::MakePhase(
2029  this, vars, choose_variable, select_value, name, ChooseMode(val_str));
2030 }
2031 
2032 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2033  Solver::IntVarStrategy var_str,
2034  Solver::IndexEvaluator2 value_evaluator) {
2035  Solver::VariableIndexSelector choose_variable =
2036  BaseAssignVariables::MakeVariableSelector(this, vars, var_str);
2037  CheapestValueSelector* const value_selector =
2038  RevAlloc(new CheapestValueSelector(std::move(value_evaluator), nullptr));
2039  Solver::VariableValueSelector select_value =
2040  [value_selector](const IntVar* var, int64 id) {
2041  return value_selector->Select(var, id);
2042  };
2043  const std::string name = ChooseVariableName(var_str) + "_SelectCheapestValue";
2044  return BaseAssignVariables::MakePhase(this, vars, choose_variable,
2045  select_value, name,
2046  BaseAssignVariables::ASSIGN);
2047 }
2048 
2049 DecisionBuilder* Solver::MakePhase(
2050  const std::vector<IntVar*>& vars, IntVarStrategy var_str,
2051  VariableValueComparator var_val1_val2_comparator) {
2052  Solver::VariableIndexSelector choose_variable =
2053  BaseAssignVariables::MakeVariableSelector(this, vars, var_str);
2054  BestValueByComparisonSelector* const value_selector = RevAlloc(
2055  new BestValueByComparisonSelector(std::move(var_val1_val2_comparator)));
2056  Solver::VariableValueSelector select_value =
2057  [value_selector](const IntVar* var, int64 id) {
2058  return value_selector->Select(var, id);
2059  };
2060  return BaseAssignVariables::MakePhase(this, vars, choose_variable,
2061  select_value, "CheapestValue",
2062  BaseAssignVariables::ASSIGN);
2063 }
2064 
2065 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2066  Solver::IndexEvaluator1 var_evaluator,
2067  Solver::IndexEvaluator2 value_evaluator) {
2068  CheapestVarSelector* const var_selector =
2069  RevAlloc(new CheapestVarSelector(std::move(var_evaluator)));
2070  Solver::VariableIndexSelector choose_variable =
2071  [var_selector](Solver* solver, const std::vector<IntVar*>& vars,
2072  int first_unbound, int last_unbound) {
2073  return var_selector->Choose(solver, vars, first_unbound, last_unbound);
2074  };
2075  CheapestValueSelector* value_selector =
2076  RevAlloc(new CheapestValueSelector(std::move(value_evaluator), nullptr));
2077  Solver::VariableValueSelector select_value =
2078  [value_selector](const IntVar* var, int64 id) {
2079  return value_selector->Select(var, id);
2080  };
2081  return BaseAssignVariables::MakePhase(this, vars, choose_variable,
2082  select_value, "CheapestValue",
2083  BaseAssignVariables::ASSIGN);
2084 }
2085 
2086 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2087  Solver::IntVarStrategy var_str,
2088  Solver::IndexEvaluator2 value_evaluator,
2089  Solver::IndexEvaluator1 tie_breaker) {
2090  Solver::VariableIndexSelector choose_variable =
2091  BaseAssignVariables::MakeVariableSelector(this, vars, var_str);
2092  CheapestValueSelector* value_selector = RevAlloc(new CheapestValueSelector(
2093  std::move(value_evaluator), std::move(tie_breaker)));
2094  Solver::VariableValueSelector select_value =
2095  [value_selector](const IntVar* var, int64 id) {
2096  return value_selector->Select(var, id);
2097  };
2098  return BaseAssignVariables::MakePhase(this, vars, choose_variable,
2099  select_value, "CheapestValue",
2100  BaseAssignVariables::ASSIGN);
2101 }
2102 
2103 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2104  Solver::IndexEvaluator1 var_evaluator,
2105  Solver::IndexEvaluator2 value_evaluator,
2106  Solver::IndexEvaluator1 tie_breaker) {
2107  CheapestVarSelector* const var_selector =
2108  RevAlloc(new CheapestVarSelector(std::move(var_evaluator)));
2109  Solver::VariableIndexSelector choose_variable =
2110  [var_selector](Solver* solver, const std::vector<IntVar*>& vars,
2111  int first_unbound, int last_unbound) {
2112  return var_selector->Choose(solver, vars, first_unbound, last_unbound);
2113  };
2114  CheapestValueSelector* value_selector = RevAlloc(new CheapestValueSelector(
2115  std::move(value_evaluator), std::move(tie_breaker)));
2116  Solver::VariableValueSelector select_value =
2117  [value_selector](const IntVar* var, int64 id) {
2118  return value_selector->Select(var, id);
2119  };
2120  return BaseAssignVariables::MakePhase(this, vars, choose_variable,
2121  select_value, "CheapestValue",
2122  BaseAssignVariables::ASSIGN);
2123 }
2124 
2125 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2126  Solver::IndexEvaluator2 eval,
2127  Solver::EvaluatorStrategy str) {
2128  return MakePhase(vars, std::move(eval), nullptr, str);
2129 }
2130 
2131 DecisionBuilder* Solver::MakePhase(const std::vector<IntVar*>& vars,
2132  Solver::IndexEvaluator2 eval,
2133  Solver::IndexEvaluator1 tie_breaker,
2134  Solver::EvaluatorStrategy str) {
2135  BaseVariableAssignmentSelector* selector = nullptr;
2136  switch (str) {
2137  case Solver::CHOOSE_STATIC_GLOBAL_BEST: {
2138  // TODO(user): support tie breaker
2139  selector = RevAlloc(new StaticEvaluatorSelector(this, vars, eval));
2140  break;
2141  }
2142  case Solver::CHOOSE_DYNAMIC_GLOBAL_BEST: {
2143  selector = RevAlloc(new DynamicEvaluatorSelector(this, vars, eval,
2144  std::move(tie_breaker)));
2145  break;
2146  }
2147  }
2148  return RevAlloc(
2149  new BaseAssignVariables(selector, BaseAssignVariables::ASSIGN));
2150 }
2151 
2152 // ----- AssignAllVariablesFromAssignment decision builder -----
2153 
2154 namespace {
2155 class AssignVariablesFromAssignment : public DecisionBuilder {
2156  public:
2157  AssignVariablesFromAssignment(const Assignment* const assignment,
2158  DecisionBuilder* const db,
2159  const std::vector<IntVar*>& vars)
2160  : assignment_(assignment), db_(db), vars_(vars), iter_(0) {}
2161 
2162  ~AssignVariablesFromAssignment() override {}
2163 
2164  Decision* Next(Solver* const s) override {
2165  if (iter_ < vars_.size()) {
2166  IntVar* const var = vars_[iter_++];
2167  return s->RevAlloc(
2168  new AssignOneVariableValue(var, assignment_->Value(var)));
2169  } else {
2170  return db_->Next(s);
2171  }
2172  }
2173 
2174  void Accept(ModelVisitor* const visitor) const override {
2175  visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
2176  visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
2177  vars_);
2178  visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
2179  }
2180 
2181  private:
2182  const Assignment* const assignment_;
2183  DecisionBuilder* const db_;
2184  const std::vector<IntVar*> vars_;
2185  int iter_;
2186 };
2187 } // namespace
2188 
2189 DecisionBuilder* Solver::MakeDecisionBuilderFromAssignment(
2190  Assignment* const assignment, DecisionBuilder* const db,
2191  const std::vector<IntVar*>& vars) {
2192  return RevAlloc(new AssignVariablesFromAssignment(assignment, db, vars));
2193 }
2194 
2195 // ---------- Solution Collectors -----------
2196 
2197 // ----- Base Class -----
2198 
2199 SolutionCollector::SolutionCollector(Solver* const solver,
2200  const Assignment* const assignment)
2201  : SearchMonitor(solver),
2202  prototype_(assignment == nullptr ? nullptr : new Assignment(assignment)) {
2203 }
2204 
2205 SolutionCollector::SolutionCollector(Solver* const solver)
2206  : SearchMonitor(solver), prototype_(new Assignment(solver)) {}
2207 
2208 SolutionCollector::~SolutionCollector() {
2209  for (auto& data : solution_data_) {
2210  delete data.solution;
2211  }
2212  gtl::STLDeleteElements(&recycle_solutions_);
2213 }
2214 
2215 void SolutionCollector::Add(IntVar* const var) {
2216  if (prototype_ != nullptr) {
2217  prototype_->Add(var);
2218  }
2219 }
2220 
2221 void SolutionCollector::Add(const std::vector<IntVar*>& vars) {
2222  if (prototype_ != nullptr) {
2223  prototype_->Add(vars);
2224  }
2225 }
2226 
2227 void SolutionCollector::Add(IntervalVar* const var) {
2228  if (prototype_ != nullptr) {
2229  prototype_->Add(var);
2230  }
2231 }
2232 
2233 void SolutionCollector::Add(const std::vector<IntervalVar*>& vars) {
2234  if (prototype_ != nullptr) {
2235  prototype_->Add(vars);
2236  }
2237 }
2238 
2239 void SolutionCollector::Add(SequenceVar* const var) {
2240  if (prototype_ != nullptr) {
2241  prototype_->Add(var);
2242  }
2243 }
2244 
2245 void SolutionCollector::Add(const std::vector<SequenceVar*>& vars) {
2246  if (prototype_ != nullptr) {
2247  prototype_->Add(vars);
2248  }
2249 }
2250 
2251 void SolutionCollector::AddObjective(IntVar* const objective) {
2252  if (prototype_ != nullptr && objective != nullptr) {
2253  prototype_->AddObjective(objective);
2254  }
2255 }
2256 
2257 void SolutionCollector::EnterSearch() {
2258  for (auto& data : solution_data_) {
2259  delete data.solution;
2260  }
2261  gtl::STLDeleteElements(&recycle_solutions_);
2262  solution_data_.clear();
2263  recycle_solutions_.clear();
2264 }
2265 
2266 void SolutionCollector::PushSolution() {
2267  Push(BuildSolutionDataForCurrentState());
2268 }
2269 
2270 void SolutionCollector::PopSolution() {
2271  if (!solution_data_.empty()) {
2272  FreeSolution(solution_data_.back().solution);
2273  solution_data_.pop_back();
2274  }
2275 }
2276 
2277 SolutionCollector::SolutionData
2278 SolutionCollector::BuildSolutionDataForCurrentState() {
2279  Assignment* solution = nullptr;
2280  if (prototype_ != nullptr) {
2281  if (!recycle_solutions_.empty()) {
2282  solution = recycle_solutions_.back();
2283  DCHECK(solution != nullptr);
2284  recycle_solutions_.pop_back();
2285  } else {
2286  solution = new Assignment(prototype_.get());
2287  }
2288  solution->Store();
2289  }
2290  SolutionData data;
2291  data.solution = solution;
2292  data.time = solver()->wall_time();
2293  data.branches = solver()->branches();
2294  data.failures = solver()->failures();
2295  if (solution != nullptr) {
2296  data.objective_value = solution->ObjectiveValue();
2297  } else {
2298  data.objective_value = 0;
2299  }
2300  return data;
2301 }
2302 
2303 void SolutionCollector::FreeSolution(Assignment* solution) {
2304  if (solution != nullptr) {
2305  recycle_solutions_.push_back(solution);
2306  }
2307 }
2308 
2309 void SolutionCollector::check_index(int n) const {
2310  CHECK_GE(n, 0) << "wrong index in solution getter";
2311  CHECK_LT(n, solution_data_.size()) << "wrong index in solution getter";
2312 }
2313 
2314 Assignment* SolutionCollector::solution(int n) const {
2315  check_index(n);
2316  return solution_data_[n].solution;
2317 }
2318 
2319 int SolutionCollector::solution_count() const { return solution_data_.size(); }
2320 
2321 int64 SolutionCollector::wall_time(int n) const {
2322  check_index(n);
2323  return solution_data_[n].time;
2324 }
2325 
2326 int64 SolutionCollector::branches(int n) const {
2327  check_index(n);
2328  return solution_data_[n].branches;
2329 }
2330 
2331 int64 SolutionCollector::failures(int n) const {
2332  check_index(n);
2333  return solution_data_[n].failures;
2334 }
2335 
2336 int64 SolutionCollector::objective_value(int n) const {
2337  check_index(n);
2338  return solution_data_[n].objective_value;
2339 }
2340 
2341 int64 SolutionCollector::Value(int n, IntVar* const var) const {
2342  return solution(n)->Value(var);
2343 }
2344 
2345 int64 SolutionCollector::StartValue(int n, IntervalVar* const var) const {
2346  return solution(n)->StartValue(var);
2347 }
2348 
2349 int64 SolutionCollector::DurationValue(int n, IntervalVar* const var) const {
2350  return solution(n)->DurationValue(var);
2351 }
2352 
2353 int64 SolutionCollector::EndValue(int n, IntervalVar* const var) const {
2354  return solution(n)->EndValue(var);
2355 }
2356 
2357 int64 SolutionCollector::PerformedValue(int n, IntervalVar* const var) const {
2358  return solution(n)->PerformedValue(var);
2359 }
2360 
2361 const std::vector<int>& SolutionCollector::ForwardSequence(
2362  int n, SequenceVar* const var) const {
2363  return solution(n)->ForwardSequence(var);
2364 }
2365 
2366 const std::vector<int>& SolutionCollector::BackwardSequence(
2367  int n, SequenceVar* const var) const {
2368  return solution(n)->BackwardSequence(var);
2369 }
2370 
2371 const std::vector<int>& SolutionCollector::Unperformed(
2372  int n, SequenceVar* const var) const {
2373  return solution(n)->Unperformed(var);
2374 }
2375 
2376 namespace {
2377 // ----- First Solution Collector -----
2378 
2379 // Collect first solution, useful when looking satisfaction problems
2380 class FirstSolutionCollector : public SolutionCollector {
2381  public:
2382  FirstSolutionCollector(Solver* const s, const Assignment* const a);
2383  explicit FirstSolutionCollector(Solver* const s);
2384  ~FirstSolutionCollector() override;
2385  void EnterSearch() override;
2386  bool AtSolution() override;
2387  std::string DebugString() const override;
2388 
2389  private:
2390  bool done_;
2391 };
2392 
2393 FirstSolutionCollector::FirstSolutionCollector(Solver* const s,
2394  const Assignment* const a)
2395  : SolutionCollector(s, a), done_(false) {}
2396 
2397 FirstSolutionCollector::FirstSolutionCollector(Solver* const s)
2398  : SolutionCollector(s), done_(false) {}
2399 
2400 FirstSolutionCollector::~FirstSolutionCollector() {}
2401 
2402 void FirstSolutionCollector::EnterSearch() {
2403  SolutionCollector::EnterSearch();
2404  done_ = false;
2405 }
2406 
2407 bool FirstSolutionCollector::AtSolution() {
2408  if (!done_) {
2409  PushSolution();
2410  done_ = true;
2411  }
2412  return false;
2413 }
2414 
2415 std::string FirstSolutionCollector::DebugString() const {
2416  if (prototype_ == nullptr) {
2417  return "FirstSolutionCollector()";
2418  } else {
2419  return "FirstSolutionCollector(" + prototype_->DebugString() + ")";
2420  }
2421 }
2422 } // namespace
2423 
2424 SolutionCollector* Solver::MakeFirstSolutionCollector(
2425  const Assignment* const assignment) {
2426  return RevAlloc(new FirstSolutionCollector(this, assignment));
2427 }
2428 
2429 SolutionCollector* Solver::MakeFirstSolutionCollector() {
2430  return RevAlloc(new FirstSolutionCollector(this));
2431 }
2432 
2433 // ----- Last Solution Collector -----
2434 
2435 // Collect last solution, useful when optimizing
2436 namespace {
2437 class LastSolutionCollector : public SolutionCollector {
2438  public:
2439  LastSolutionCollector(Solver* const s, const Assignment* const a);
2440  explicit LastSolutionCollector(Solver* const s);
2441  ~LastSolutionCollector() override;
2442  bool AtSolution() override;
2443  std::string DebugString() const override;
2444 };
2445 
2446 LastSolutionCollector::LastSolutionCollector(Solver* const s,
2447  const Assignment* const a)
2448  : SolutionCollector(s, a) {}
2449 
2450 LastSolutionCollector::LastSolutionCollector(Solver* const s)
2451  : SolutionCollector(s) {}
2452 
2453 LastSolutionCollector::~LastSolutionCollector() {}
2454 
2455 bool LastSolutionCollector::AtSolution() {
2456  PopSolution();
2457  PushSolution();
2458  return true;
2459 }
2460 
2461 std::string LastSolutionCollector::DebugString() const {
2462  if (prototype_ == nullptr) {
2463  return "LastSolutionCollector()";
2464  } else {
2465  return "LastSolutionCollector(" + prototype_->DebugString() + ")";
2466  }
2467 }
2468 } // namespace
2469 
2470 SolutionCollector* Solver::MakeLastSolutionCollector(
2471  const Assignment* const assignment) {
2472  return RevAlloc(new LastSolutionCollector(this, assignment));
2473 }
2474 
2475 SolutionCollector* Solver::MakeLastSolutionCollector() {
2476  return RevAlloc(new LastSolutionCollector(this));
2477 }
2478 
2479 // ----- Best Solution Collector -----
2480 
2481 namespace {
2482 class BestValueSolutionCollector : public SolutionCollector {
2483  public:
2484  BestValueSolutionCollector(Solver* const s, const Assignment* const a,
2485  bool maximize);
2486  BestValueSolutionCollector(Solver* const s, bool maximize);
2487  ~BestValueSolutionCollector() override {}
2488  void EnterSearch() override;
2489  bool AtSolution() override;
2490  std::string DebugString() const override;
2491 
2492  public:
2493  const bool maximize_;
2495 };
2496 
2497 BestValueSolutionCollector::BestValueSolutionCollector(
2498  Solver* const s, const Assignment* const a, bool maximize)
2499  : SolutionCollector(s, a),
2500  maximize_(maximize),
2501  best_(maximize ? kint64min : kint64max) {}
2502 
2503 BestValueSolutionCollector::BestValueSolutionCollector(Solver* const s,
2504  bool maximize)
2505  : SolutionCollector(s),
2506  maximize_(maximize),
2507  best_(maximize ? kint64min : kint64max) {}
2508 
2509 void BestValueSolutionCollector::EnterSearch() {
2510  SolutionCollector::EnterSearch();
2512 }
2513 
2514 bool BestValueSolutionCollector::AtSolution() {
2515  if (prototype_ != nullptr) {
2516  const IntVar* objective = prototype_->Objective();
2517  if (objective != nullptr) {
2518  if (maximize_ && (solution_count() == 0 || objective->Max() > best_)) {
2519  PopSolution();
2520  PushSolution();
2521  best_ = objective->Max();
2522  } else if (!maximize_ &&
2523  (solution_count() == 0 || objective->Min() < best_)) {
2524  PopSolution();
2525  PushSolution();
2526  best_ = objective->Min();
2527  }
2528  }
2529  }
2530  return true;
2531 }
2532 
2533 std::string BestValueSolutionCollector::DebugString() const {
2534  if (prototype_ == nullptr) {
2535  return "BestValueSolutionCollector()";
2536  } else {
2537  return "BestValueSolutionCollector(" + prototype_->DebugString() + ")";
2538  }
2539 }
2540 } // namespace
2541 
2542 SolutionCollector* Solver::MakeBestValueSolutionCollector(
2543  const Assignment* const assignment, bool maximize) {
2544  return RevAlloc(new BestValueSolutionCollector(this, assignment, maximize));
2545 }
2546 
2547 SolutionCollector* Solver::MakeBestValueSolutionCollector(bool maximize) {
2548  return RevAlloc(new BestValueSolutionCollector(this, maximize));
2549 }
2550 
2551 // ----- N Best Solution Collector -----
2552 
2553 namespace {
2554 class NBestValueSolutionCollector : public SolutionCollector {
2555  public:
2556  NBestValueSolutionCollector(Solver* const solver,
2557  const Assignment* const assignment,
2558  int solution_count, bool maximize);
2559  NBestValueSolutionCollector(Solver* const solver, int solution_count,
2560  bool maximize);
2561  ~NBestValueSolutionCollector() override { Clear(); }
2562  void EnterSearch() override;
2563  void ExitSearch() override;
2564  bool AtSolution() override;
2565  std::string DebugString() const override;
2566 
2567  public:
2568  void Clear();
2569 
2570  const bool maximize_;
2571  std::priority_queue<std::pair<int64, SolutionData>> solutions_pq_;
2572  const int solution_count_;
2573 };
2574 
2575 NBestValueSolutionCollector::NBestValueSolutionCollector(
2576  Solver* const solver, const Assignment* const assignment,
2577  int solution_count, bool maximize)
2578  : SolutionCollector(solver, assignment),
2579  maximize_(maximize),
2580  solution_count_(solution_count) {}
2581 
2582 NBestValueSolutionCollector::NBestValueSolutionCollector(Solver* const solver,
2583  int solution_count,
2584  bool maximize)
2585  : SolutionCollector(solver),
2586  maximize_(maximize),
2587  solution_count_(solution_count) {}
2588 
2589 void NBestValueSolutionCollector::EnterSearch() {
2590  SolutionCollector::EnterSearch();
2591  // TODO(user): Remove this when fast local search works with
2592  // multiple solutions collected.
2593  if (solution_count_ > 1) {
2594  solver()->SetUseFastLocalSearch(false);
2595  }
2596  Clear();
2597 }
2598 
2599 void NBestValueSolutionCollector::ExitSearch() {
2600  while (!solutions_pq_.empty()) {
2601  Push(solutions_pq_.top().second);
2602  solutions_pq_.pop();
2603  }
2604 }
2605 
2606 bool NBestValueSolutionCollector::AtSolution() {
2607  if (prototype_ != nullptr) {
2608  const IntVar* objective = prototype_->Objective();
2609  if (objective != nullptr) {
2610  const int64 objective_value =
2611  maximize_ ? CapSub(0, objective->Max()) : objective->Min();
2612  if (solutions_pq_.size() < solution_count_) {
2613  solutions_pq_.push(
2614  {objective_value, BuildSolutionDataForCurrentState()});
2615  } else if (!solutions_pq_.empty()) {
2616  const auto& top = solutions_pq_.top();
2617  if (top.first > objective_value) {
2618  FreeSolution(solutions_pq_.top().second.solution);
2619  solutions_pq_.pop();
2620  solutions_pq_.push(
2621  {objective_value, BuildSolutionDataForCurrentState()});
2622  }
2623  }
2624  }
2625  }
2626  return true;
2627 }
2628 
2629 std::string NBestValueSolutionCollector::DebugString() const {
2630  if (prototype_ == nullptr) {
2631  return "NBestValueSolutionCollector()";
2632  } else {
2633  return "NBestValueSolutionCollector(" + prototype_->DebugString() + ")";
2634  }
2635 }
2636 
2637 void NBestValueSolutionCollector::Clear() {
2638  while (!solutions_pq_.empty()) {
2639  delete solutions_pq_.top().second.solution;
2640  solutions_pq_.pop();
2641  }
2642 }
2643 
2644 } // namespace
2645 
2646 SolutionCollector* Solver::MakeNBestValueSolutionCollector(
2647  const Assignment* const assignment, int solution_count, bool maximize) {
2648  if (solution_count == 1) {
2649  return MakeBestValueSolutionCollector(assignment, maximize);
2650  }
2651  return RevAlloc(new NBestValueSolutionCollector(this, assignment,
2652  solution_count, maximize));
2653 }
2654 
2655 SolutionCollector* Solver::MakeNBestValueSolutionCollector(int solution_count,
2656  bool maximize) {
2657  if (solution_count == 1) {
2658  return MakeBestValueSolutionCollector(maximize);
2659  }
2660  return RevAlloc(
2661  new NBestValueSolutionCollector(this, solution_count, maximize));
2662 }
2663 
2664 // ----- All Solution Collector -----
2665 
2666 // collect all solutions
2667 namespace {
2668 class AllSolutionCollector : public SolutionCollector {
2669  public:
2670  AllSolutionCollector(Solver* const s, const Assignment* const a);
2671  explicit AllSolutionCollector(Solver* const s);
2672  ~AllSolutionCollector() override;
2673  bool AtSolution() override;
2674  std::string DebugString() const override;
2675 };
2676 
2677 AllSolutionCollector::AllSolutionCollector(Solver* const s,
2678  const Assignment* const a)
2679  : SolutionCollector(s, a) {}
2680 
2681 AllSolutionCollector::AllSolutionCollector(Solver* const s)
2682  : SolutionCollector(s) {}
2683 
2684 AllSolutionCollector::~AllSolutionCollector() {}
2685 
2686 bool AllSolutionCollector::AtSolution() {
2687  PushSolution();
2688  return true;
2689 }
2690 
2691 std::string AllSolutionCollector::DebugString() const {
2692  if (prototype_ == nullptr) {
2693  return "AllSolutionCollector()";
2694  } else {
2695  return "AllSolutionCollector(" + prototype_->DebugString() + ")";
2696  }
2697 }
2698 } // namespace
2699 
2700 SolutionCollector* Solver::MakeAllSolutionCollector(
2701  const Assignment* const assignment) {
2702  return RevAlloc(new AllSolutionCollector(this, assignment));
2703 }
2704 
2705 SolutionCollector* Solver::MakeAllSolutionCollector() {
2706  return RevAlloc(new AllSolutionCollector(this));
2707 }
2708 
2709 // ---------- Objective Management ----------
2710 
2711 OptimizeVar::OptimizeVar(Solver* const s, bool maximize, IntVar* const a,
2712  int64 step)
2713  : SearchMonitor(s),
2714  var_(a),
2715  step_(step),
2716  best_(kint64max),
2717  maximize_(maximize),
2718  found_initial_solution_(false) {
2719  CHECK_GT(step_, 0);
2720  // TODO(user): Store optimization direction in Solver. Besides making the
2721  // code simpler it would also having two monitors optimizing in opposite
2722  // directions.
2723  if (maximize) {
2724  s->set_optimization_direction(Solver::MAXIMIZATION);
2725  } else {
2726  s->set_optimization_direction(Solver::MINIMIZATION);
2727  }
2728 }
2729 
2730 OptimizeVar::~OptimizeVar() {}
2731 
2732 void OptimizeVar::EnterSearch() {
2733  found_initial_solution_ = false;
2734  if (maximize_) {
2735  best_ = kint64min;
2736  } else {
2737  best_ = kint64max;
2738  }
2739 }
2740 
2741 void OptimizeVar::BeginNextDecision(DecisionBuilder* const db) {
2742  if (solver()->SearchDepth() == 0) { // after a restart.
2743  ApplyBound();
2744  }
2745 }
2746 
2747 void OptimizeVar::ApplyBound() {
2748  if (found_initial_solution_) {
2749  if (maximize_) {
2750  var_->SetMin(best_ + step_);
2751  } else {
2752  var_->SetMax(best_ - step_);
2753  }
2754  }
2755 }
2756 
2757 void OptimizeVar::RefuteDecision(Decision* const d) { ApplyBound(); }
2758 
2759 bool OptimizeVar::AcceptSolution() {
2760  const int64 val = var_->Value();
2761  if (!found_initial_solution_) {
2762  return true;
2763  } else {
2764  // This code should never return false in sequential mode because
2765  // ApplyBound should have been called before. In parallel, this is
2766  // no longer true. That is why we keep it there, just in case.
2767  return (maximize_ && val > best_) || (!maximize_ && val < best_);
2768  }
2769 }
2770 
2771 bool OptimizeVar::AtSolution() {
2772  int64 val = var_->Value();
2773  if (maximize_) {
2774  CHECK(!found_initial_solution_ || val > best_);
2775  best_ = val;
2776  } else {
2777  CHECK(!found_initial_solution_ || val < best_);
2778  best_ = val;
2779  }
2780  found_initial_solution_ = true;
2781  return true;
2782 }
2783 
2784 bool OptimizeVar::AcceptDelta(Assignment* delta, Assignment* deltadelta) {
2785  if (delta != nullptr) {
2786  const bool delta_has_objective = delta->HasObjective();
2787  if (!delta_has_objective) {
2788  delta->AddObjective(var_);
2789  }
2790  if (delta->Objective() == var_) {
2791  const Assignment* const local_search_state =
2792  solver()->GetOrCreateLocalSearchState();
2793  if (maximize_) {
2794  const int64 delta_min_objective =
2795  delta_has_objective ? delta->ObjectiveMin() : kint64min;
2796  const int64 min_objective =
2797  local_search_state->HasObjective()
2798  ? CapAdd(local_search_state->ObjectiveMin(), step_)
2799  : kint64min;
2800  delta->SetObjectiveMin(
2801  std::max({var_->Min(), min_objective, delta_min_objective}));
2802 
2803  } else {
2804  const int64 delta_max_objective =
2805  delta_has_objective ? delta->ObjectiveMax() : kint64max;
2806  const int64 max_objective =
2807  local_search_state->HasObjective()
2808  ? CapSub(local_search_state->ObjectiveMax(), step_)
2809  : kint64max;
2810  delta->SetObjectiveMax(
2811  std::min({var_->Max(), max_objective, delta_max_objective}));
2812  }
2813  }
2814  }
2815  return true;
2816 }
2817 
2818 std::string OptimizeVar::Print() const {
2819  return absl::StrFormat("objective value = %d, ", var_->Value());
2820 }
2821 
2822 std::string OptimizeVar::DebugString() const {
2823  std::string out;
2824  if (maximize_) {
2825  out = "MaximizeVar(";
2826  } else {
2827  out = "MinimizeVar(";
2828  }
2829  absl::StrAppendFormat(&out, "%s, step = %d, best = %d)", var_->DebugString(),
2830  step_, best_);
2831  return out;
2832 }
2833 
2834 void OptimizeVar::Accept(ModelVisitor* const visitor) const {
2835  visitor->BeginVisitExtension(ModelVisitor::kObjectiveExtension);
2836  visitor->VisitIntegerArgument(ModelVisitor::kMaximizeArgument, maximize_);
2837  visitor->VisitIntegerArgument(ModelVisitor::kStepArgument, step_);
2838  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
2839  var_);
2840  visitor->EndVisitExtension(ModelVisitor::kObjectiveExtension);
2841 }
2842 
2843 OptimizeVar* Solver::MakeMinimize(IntVar* const v, int64 step) {
2844  return RevAlloc(new OptimizeVar(this, false, v, step));
2845 }
2846 
2847 OptimizeVar* Solver::MakeMaximize(IntVar* const v, int64 step) {
2848  return RevAlloc(new OptimizeVar(this, true, v, step));
2849 }
2850 
2851 OptimizeVar* Solver::MakeOptimize(bool maximize, IntVar* const v, int64 step) {
2852  return RevAlloc(new OptimizeVar(this, maximize, v, step));
2853 }
2854 
2855 namespace {
2856 class WeightedOptimizeVar : public OptimizeVar {
2857  public:
2858  WeightedOptimizeVar(Solver* solver, bool maximize,
2859  const std::vector<IntVar*>& sub_objectives,
2860  const std::vector<int64>& weights, int64 step)
2861  : OptimizeVar(solver, maximize,
2862  solver->MakeScalProd(sub_objectives, weights)->Var(), step),
2863  sub_objectives_(sub_objectives),
2864  weights_(weights) {
2865  CHECK_EQ(sub_objectives.size(), weights.size());
2866  }
2867 
2868  ~WeightedOptimizeVar() override {}
2869  std::string Print() const override;
2870 
2871  private:
2872  const std::vector<IntVar*> sub_objectives_;
2873  const std::vector<int64> weights_;
2874 
2875  DISALLOW_COPY_AND_ASSIGN(WeightedOptimizeVar);
2876 };
2877 
2878 std::string WeightedOptimizeVar::Print() const {
2879  std::string result(OptimizeVar::Print());
2880  result.append("\nWeighted Objective:\n");
2881  for (int i = 0; i < sub_objectives_.size(); ++i) {
2882  absl::StrAppendFormat(&result, "Variable %s,\tvalue %d,\tweight %d\n",
2883  sub_objectives_[i]->name(),
2884  sub_objectives_[i]->Value(), weights_[i]);
2885  }
2886  return result;
2887 }
2888 } // namespace
2889 
2890 OptimizeVar* Solver::MakeWeightedOptimize(
2891  bool maximize, const std::vector<IntVar*>& sub_objectives,
2892  const std::vector<int64>& weights, int64 step) {
2893  return RevAlloc(
2894  new WeightedOptimizeVar(this, maximize, sub_objectives, weights, step));
2895 }
2896 
2897 OptimizeVar* Solver::MakeWeightedMinimize(
2898  const std::vector<IntVar*>& sub_objectives,
2899  const std::vector<int64>& weights, int64 step) {
2900  return RevAlloc(
2901  new WeightedOptimizeVar(this, false, sub_objectives, weights, step));
2902 }
2903 
2904 OptimizeVar* Solver::MakeWeightedMaximize(
2905  const std::vector<IntVar*>& sub_objectives,
2906  const std::vector<int64>& weights, int64 step) {
2907  return RevAlloc(
2908  new WeightedOptimizeVar(this, true, sub_objectives, weights, step));
2909 }
2910 
2911 OptimizeVar* Solver::MakeWeightedOptimize(
2912  bool maximize, const std::vector<IntVar*>& sub_objectives,
2913  const std::vector<int>& weights, int64 step) {
2914  return MakeWeightedOptimize(maximize, sub_objectives, ToInt64Vector(weights),
2915  step);
2916 }
2917 
2918 OptimizeVar* Solver::MakeWeightedMinimize(
2919  const std::vector<IntVar*>& sub_objectives, const std::vector<int>& weights,
2920  int64 step) {
2921  return MakeWeightedMinimize(sub_objectives, ToInt64Vector(weights), step);
2922 }
2923 
2924 OptimizeVar* Solver::MakeWeightedMaximize(
2925  const std::vector<IntVar*>& sub_objectives, const std::vector<int>& weights,
2926  int64 step) {
2927  return MakeWeightedMaximize(sub_objectives, ToInt64Vector(weights), step);
2928 }
2929 
2930 // ---------- Metaheuristics ---------
2931 
2932 namespace {
2933 class Metaheuristic : public SearchMonitor {
2934  public:
2935  Metaheuristic(Solver* const solver, bool maximize, IntVar* objective,
2936  int64 step);
2937  ~Metaheuristic() override {}
2938 
2939  bool AtSolution() override;
2940  void EnterSearch() override;
2941  void RefuteDecision(Decision* const d) override;
2942  bool AcceptDelta(Assignment* delta, Assignment* deltadelta) override;
2943 
2944  protected:
2945  IntVar* const objective_;
2948  int64 best_;
2949  bool maximize_;
2950 };
2951 
2952 Metaheuristic::Metaheuristic(Solver* const solver, bool maximize,
2953  IntVar* objective, int64 step)
2954  : SearchMonitor(solver),
2955  objective_(objective),
2956  step_(step),
2958  best_(kint64max),
2959  maximize_(maximize) {}
2960 
2961 bool Metaheuristic::AtSolution() {
2962  current_ = objective_->Value();
2963  if (maximize_) {
2965  } else {
2967  }
2968  return true;
2969 }
2970 
2971 void Metaheuristic::EnterSearch() {
2972  // TODO(user): Remove this when fast local search works with
2973  // metaheuristics.
2974  solver()->SetUseFastLocalSearch(false);
2975  if (maximize_) {
2976  best_ = objective_->Min();
2977  current_ = kint64min;
2978  } else {
2979  best_ = objective_->Max();
2980  current_ = kint64max;
2981  }
2982 }
2983 
2984 void Metaheuristic::RefuteDecision(Decision* d) {
2985  if (maximize_) {
2986  if (objective_->Max() < best_ + step_) {
2987  solver()->Fail();
2988  }
2989  } else if (objective_->Min() > best_ - step_) {
2990  solver()->Fail();
2991  }
2992 }
2993 
2994 bool Metaheuristic::AcceptDelta(Assignment* delta, Assignment* deltadelta) {
2995  if (delta != nullptr) {
2996  if (!delta->HasObjective()) {
2997  delta->AddObjective(objective_);
2998  }
2999  if (delta->Objective() == objective_) {
3000  if (maximize_) {
3001  delta->SetObjectiveMin(
3002  std::max(objective_->Min(), delta->ObjectiveMin()));
3003  } else {
3004  delta->SetObjectiveMax(
3005  std::min(objective_->Max(), delta->ObjectiveMax()));
3006  }
3007  }
3008  }
3009  return true;
3010 }
3011 
3012 // ---------- Tabu Search ----------
3013 
3014 class TabuSearch : public Metaheuristic {
3015  public:
3016  TabuSearch(Solver* const s, bool maximize, IntVar* objective, int64 step,
3017  const std::vector<IntVar*>& vars, int64 keep_tenure,
3018  int64 forbid_tenure, double tabu_factor);
3019  ~TabuSearch() override {}
3020  void EnterSearch() override;
3021  void ApplyDecision(Decision* d) override;
3022  bool AtSolution() override;
3023  bool LocalOptimum() override;
3024  void AcceptNeighbor() override;
3025  std::string DebugString() const override { return "Tabu Search"; }
3026 
3027  protected:
3028  struct VarValue {
3029  VarValue(IntVar* const var, int64 value, int64 stamp)
3030  : var_(var), value_(value), stamp_(stamp) {}
3031  IntVar* const var_;
3032  const int64 value_;
3033  const int64 stamp_;
3034  };
3035  typedef std::list<VarValue> TabuList;
3036 
3037  virtual std::vector<IntVar*> CreateTabuVars();
3038  const TabuList& forbid_tabu_list() { return forbid_tabu_list_; }
3039 
3040  private:
3041  void AgeList(int64 tenure, TabuList* list);
3042  void AgeLists();
3043 
3044  const std::vector<IntVar*> vars_;
3045  Assignment assignment_;
3046  int64 last_;
3047  TabuList keep_tabu_list_;
3048  int64 keep_tenure_;
3049  TabuList forbid_tabu_list_;
3050  int64 forbid_tenure_;
3051  double tabu_factor_;
3052  int64 stamp_;
3053  bool found_initial_solution_;
3054 
3055  DISALLOW_COPY_AND_ASSIGN(TabuSearch);
3056 };
3057 
3058 TabuSearch::TabuSearch(Solver* const s, bool maximize, IntVar* objective,
3059  int64 step, const std::vector<IntVar*>& vars,
3060  int64 keep_tenure, int64 forbid_tenure,
3061  double tabu_factor)
3062  : Metaheuristic(s, maximize, objective, step),
3063  vars_(vars),
3064  assignment_(s),
3065  last_(kint64max),
3066  keep_tenure_(keep_tenure),
3067  forbid_tenure_(forbid_tenure),
3068  tabu_factor_(tabu_factor),
3069  stamp_(0),
3070  found_initial_solution_(false) {
3071  assignment_.Add(vars_);
3072 }
3073 
3074 void TabuSearch::EnterSearch() {
3075  Metaheuristic::EnterSearch();
3076  found_initial_solution_ = false;
3077 }
3078 
3079 void TabuSearch::ApplyDecision(Decision* const d) {
3080  Solver* const s = solver();
3081  if (d == s->balancing_decision()) {
3082  return;
3083  }
3084  // Aspiration criterion
3085  // Accept a neighbor if it improves the best solution found so far
3086  IntVar* aspiration = s->MakeBoolVar();
3087  if (maximize_) {
3088  s->AddConstraint(s->MakeIsGreaterOrEqualCstCt(
3089  objective_, CapAdd(best_, step_), aspiration));
3090  } else {
3091  s->AddConstraint(s->MakeIsLessOrEqualCstCt(objective_, CapSub(best_, step_),
3092  aspiration));
3093  }
3094 
3095  IntVar* tabu_var = nullptr;
3096  {
3097  // Creating the vector in a scope to make sure it gets deleted before
3098  // adding further constraints which could fail and lead to a leak.
3099  const std::vector<IntVar*> tabu_vars = CreateTabuVars();
3100  if (!tabu_vars.empty()) {
3101  tabu_var = s->MakeIsGreaterOrEqualCstVar(s->MakeSum(tabu_vars)->Var(),
3102  tabu_vars.size() * tabu_factor_);
3103  }
3104  }
3105 
3106  if (tabu_var != nullptr) {
3107  s->AddConstraint(
3108  s->MakeGreaterOrEqual(s->MakeSum(aspiration, tabu_var), int64{1}));
3109  }
3110 
3111  // Go downhill to the next local optimum
3112  if (maximize_) {
3113  const int64 bound = (current_ > kint64min) ? current_ + step_ : current_;
3114  s->AddConstraint(s->MakeGreaterOrEqual(objective_, bound));
3115  } else {
3116  const int64 bound = (current_ < kint64max) ? current_ - step_ : current_;
3117  s->AddConstraint(s->MakeLessOrEqual(objective_, bound));
3118  }
3119 
3120  // Avoid cost plateau's which lead to tabu cycles
3121  if (found_initial_solution_) {
3122  s->AddConstraint(s->MakeNonEquality(objective_, last_));
3123  }
3124 }
3125 
3126 std::vector<IntVar*> TabuSearch::CreateTabuVars() {
3127  Solver* const s = solver();
3128 
3129  // Tabu criterion
3130  // A variable in the "keep" list must keep its value, a variable in the
3131  // "forbid" list must not take its value in the list. The tabu criterion is
3132  // softened by the tabu factor which gives the number of violations to
3133  // the tabu criterion which is tolerated; a factor of 1 means no violations
3134  // allowed, a factor of 0 means all violations allowed.
3135  std::vector<IntVar*> tabu_vars;
3136  for (const VarValue& vv : keep_tabu_list_) {
3137  tabu_vars.push_back(s->MakeIsEqualCstVar(vv.var_, vv.value_));
3138  }
3139  for (const VarValue& vv : forbid_tabu_list_) {
3140  tabu_vars.push_back(s->MakeIsDifferentCstVar(vv.var_, vv.value_));
3141  }
3142  return tabu_vars;
3143 }
3144 
3145 bool TabuSearch::AtSolution() {
3146  if (!Metaheuristic::AtSolution()) {
3147  return false;
3148  }
3149  found_initial_solution_ = true;
3150  last_ = current_;
3151 
3152  // New solution found: add new assignments to tabu lists; this is only
3153  // done after the first local optimum (stamp_ != 0)
3154  if (0 != stamp_) {
3155  for (int i = 0; i < vars_.size(); ++i) {
3156  IntVar* const var = vars_[i];
3157  const int64 old_value = assignment_.Value(var);
3158  const int64 new_value = var->Value();
3159  if (old_value != new_value) {
3160  if (keep_tenure_ > 0) {
3161  VarValue keep_value(var, new_value, stamp_);
3162  keep_tabu_list_.push_front(keep_value);
3163  }
3164  if (forbid_tenure_ > 0) {
3165  VarValue forbid_value(var, old_value, stamp_);
3166  forbid_tabu_list_.push_front(forbid_value);
3167  }
3168  }
3169  }
3170  }
3171  assignment_.Store();
3172 
3173  return true;
3174 }
3175 
3176 bool TabuSearch::LocalOptimum() {
3177  AgeLists();
3178  if (maximize_) {
3179  current_ = kint64min;
3180  } else {
3181  current_ = kint64max;
3182  }
3183  return found_initial_solution_;
3184 }
3185 
3187  if (0 != stamp_) {
3188  AgeLists();
3189  }
3190 }
3191 
3192 void TabuSearch::AgeList(int64 tenure, TabuList* list) {
3193  while (!list->empty() && list->back().stamp_ < stamp_ - tenure) {
3194  list->pop_back();
3195  }
3196 }
3197 
3198 void TabuSearch::AgeLists() {
3199  AgeList(keep_tenure_, &keep_tabu_list_);
3200  AgeList(forbid_tenure_, &forbid_tabu_list_);
3201  ++stamp_;
3202 }
3203 
3204 class GenericTabuSearch : public TabuSearch {
3205  public:
3206  GenericTabuSearch(Solver* const s, bool maximize, IntVar* objective,
3207  int64 step, const std::vector<IntVar*>& vars,
3208  int64 forbid_tenure)
3209  : TabuSearch(s, maximize, objective, step, vars, 0, forbid_tenure, 1) {}
3210  std::string DebugString() const override { return "Generic Tabu Search"; }
3211 
3212  protected:
3213  std::vector<IntVar*> CreateTabuVars() override;
3214 };
3215 
3216 std::vector<IntVar*> GenericTabuSearch::CreateTabuVars() {
3217  Solver* const s = solver();
3218 
3219  // Tabu criterion
3220  // At least one element of the forbid_tabu_list must change value.
3221  std::vector<IntVar*> forbid_values;
3222  for (const VarValue& vv : forbid_tabu_list()) {
3223  forbid_values.push_back(s->MakeIsDifferentCstVar(vv.var_, vv.value_));
3224  }
3225  std::vector<IntVar*> tabu_vars;
3226  if (!forbid_values.empty()) {
3227  tabu_vars.push_back(s->MakeIsGreaterCstVar(s->MakeSum(forbid_values), 0));
3228  }
3229  return tabu_vars;
3230 }
3231 
3232 } // namespace
3233 
3234 SearchMonitor* Solver::MakeTabuSearch(bool maximize, IntVar* const v,
3235  int64 step,
3236  const std::vector<IntVar*>& vars,
3237  int64 keep_tenure, int64 forbid_tenure,
3238  double tabu_factor) {
3239  return RevAlloc(new TabuSearch(this, maximize, v, step, vars, keep_tenure,
3240  forbid_tenure, tabu_factor));
3241 }
3242 
3243 SearchMonitor* Solver::MakeGenericTabuSearch(
3244  bool maximize, IntVar* const v, int64 step,
3245  const std::vector<IntVar*>& tabu_vars, int64 forbid_tenure) {
3246  return RevAlloc(
3247  new GenericTabuSearch(this, maximize, v, step, tabu_vars, forbid_tenure));
3248 }
3249 
3250 // ---------- Simulated Annealing ----------
3251 
3252 namespace {
3253 class SimulatedAnnealing : public Metaheuristic {
3254  public:
3255  SimulatedAnnealing(Solver* const s, bool maximize, IntVar* objective,
3256  int64 step, int64 initial_temperature);
3257  ~SimulatedAnnealing() override {}
3258  void EnterSearch() override;
3259  void ApplyDecision(Decision* d) override;
3260  bool AtSolution() override;
3261  bool LocalOptimum() override;
3262  void AcceptNeighbor() override;
3263  std::string DebugString() const override { return "Simulated Annealing"; }
3264 
3265  private:
3266  double Temperature() const;
3267 
3268  const int64 temperature0_;
3269  int64 iteration_;
3270  std::mt19937 rand_;
3271  bool found_initial_solution_;
3272 
3273  DISALLOW_COPY_AND_ASSIGN(SimulatedAnnealing);
3274 };
3275 
3276 SimulatedAnnealing::SimulatedAnnealing(Solver* const s, bool maximize,
3277  IntVar* objective, int64 step,
3278  int64 initial_temperature)
3279  : Metaheuristic(s, maximize, objective, step),
3280  temperature0_(initial_temperature),
3281  iteration_(0),
3282  rand_(CpRandomSeed()),
3283  found_initial_solution_(false) {}
3284 
3285 void SimulatedAnnealing::EnterSearch() {
3286  Metaheuristic::EnterSearch();
3287  found_initial_solution_ = false;
3288 }
3289 
3290 void SimulatedAnnealing::ApplyDecision(Decision* const d) {
3291  Solver* const s = solver();
3292  if (d == s->balancing_decision()) {
3293  return;
3294  }
3295  const double rand_double = absl::Uniform<double>(rand_, 0.0, 1.0);
3296 #if defined(_MSC_VER) || defined(__ANDROID__)
3297  const double rand_log2_double = log(rand_double) / log(2.0L);
3298 #else
3299  const double rand_log2_double = log2(rand_double);
3300 #endif
3301  const int64 energy_bound = Temperature() * rand_log2_double;
3302  if (maximize_) {
3303  const int64 bound =
3304  (current_ > kint64min) ? current_ + step_ + energy_bound : current_;
3305  s->AddConstraint(s->MakeGreaterOrEqual(objective_, bound));
3306  } else {
3307  const int64 bound =
3308  (current_ < kint64max) ? current_ - step_ - energy_bound : current_;
3309  s->AddConstraint(s->MakeLessOrEqual(objective_, bound));
3310  }
3311 }
3312 
3313 bool SimulatedAnnealing::AtSolution() {
3314  if (!Metaheuristic::AtSolution()) {
3315  return false;
3316  }
3317  found_initial_solution_ = true;
3318  return true;
3319 }
3320 
3321 bool SimulatedAnnealing::LocalOptimum() {
3322  if (maximize_) {
3323  current_ = kint64min;
3324  } else {
3325  current_ = kint64max;
3326  }
3327  ++iteration_;
3328  return found_initial_solution_ && Temperature() > 0;
3329 }
3330 
3332  if (iteration_ > 0) {
3333  ++iteration_;
3334  }
3335 }
3336 
3337 double SimulatedAnnealing::Temperature() const {
3338  if (iteration_ > 0) {
3339  return (1.0 * temperature0_) / iteration_; // Cauchy annealing
3340  } else {
3341  return 0.;
3342  }
3343 }
3344 } // namespace
3345 
3346 SearchMonitor* Solver::MakeSimulatedAnnealing(bool maximize, IntVar* const v,
3347  int64 step,
3348  int64 initial_temperature) {
3349  return RevAlloc(
3350  new SimulatedAnnealing(this, maximize, v, step, initial_temperature));
3351 }
3352 
3353 // ---------- Guided Local Search ----------
3354 
3355 typedef std::pair<int64, int64> Arc;
3356 
3357 namespace {
3358 // Base GLS penalties abstract class. Maintains the penalty frequency for each
3359 // (variable, value) arc.
3360 class GuidedLocalSearchPenalties {
3361  public:
3362  virtual ~GuidedLocalSearchPenalties() {}
3363  virtual bool HasValues() const = 0;
3364  virtual void Increment(const Arc& arc) = 0;
3365  virtual int64 Value(const Arc& arc) const = 0;
3366  virtual void Reset() = 0;
3367 };
3368 
3369 // Dense GLS penalties implementation using a matrix to store penalties.
3370 class GuidedLocalSearchPenaltiesTable : public GuidedLocalSearchPenalties {
3371  public:
3372  explicit GuidedLocalSearchPenaltiesTable(int size);
3373  ~GuidedLocalSearchPenaltiesTable() override {}
3374  bool HasValues() const override { return has_values_; }
3375  void Increment(const Arc& arc) override;
3376  int64 Value(const Arc& arc) const override;
3377  void Reset() override;
3378 
3379  private:
3380  std::vector<std::vector<int64>> penalties_;
3381  bool has_values_;
3382 };
3383 
3384 GuidedLocalSearchPenaltiesTable::GuidedLocalSearchPenaltiesTable(int size)
3385  : penalties_(size), has_values_(false) {}
3386 
3387 void GuidedLocalSearchPenaltiesTable::Increment(const Arc& arc) {
3388  std::vector<int64>& first_penalties = penalties_[arc.first];
3389  const int64 second = arc.second;
3390  if (second >= first_penalties.size()) {
3391  first_penalties.resize(second + 1, 0);
3392  }
3393  ++first_penalties[second];
3394  has_values_ = true;
3395 }
3396 
3397 void GuidedLocalSearchPenaltiesTable::Reset() {
3398  has_values_ = false;
3399  for (int i = 0; i < penalties_.size(); ++i) {
3400  penalties_[i].clear();
3401  }
3402 }
3403 
3405  const std::vector<int64>& first_penalties = penalties_[arc.first];
3406  const int64 second = arc.second;
3407  if (second >= first_penalties.size()) {
3408  return 0;
3409  } else {
3410  return first_penalties[second];
3411  }
3412 }
3413 
3414 // Sparse GLS penalties implementation using hash_map to store penalties.
3415 class GuidedLocalSearchPenaltiesMap : public GuidedLocalSearchPenalties {
3416  public:
3417  explicit GuidedLocalSearchPenaltiesMap(int size);
3418  ~GuidedLocalSearchPenaltiesMap() override {}
3419  bool HasValues() const override { return (!penalties_.empty()); }
3420  void Increment(const Arc& arc) override;
3421  int64 Value(const Arc& arc) const override;
3422  void Reset() override;
3423 
3424  private:
3425  Bitmap penalized_;
3426  absl::flat_hash_map<Arc, int64> penalties_;
3427 };
3428 
3429 GuidedLocalSearchPenaltiesMap::GuidedLocalSearchPenaltiesMap(int size)
3430  : penalized_(size, false) {}
3431 
3432 void GuidedLocalSearchPenaltiesMap::Increment(const Arc& arc) {
3433  ++penalties_[arc];
3434  penalized_.Set(arc.first, true);
3435 }
3436 
3437 void GuidedLocalSearchPenaltiesMap::Reset() {
3438  penalties_.clear();
3439  penalized_.Clear();
3440 }
3441 
3443  if (penalized_.Get(arc.first)) {
3444  return gtl::FindWithDefault(penalties_, arc, 0);
3445  }
3446  return 0;
3447 }
3448 
3449 class GuidedLocalSearch : public Metaheuristic {
3450  public:
3451  GuidedLocalSearch(Solver* const s, IntVar* objective, bool maximize,
3452  int64 step, const std::vector<IntVar*>& vars,
3453  double penalty_factor);
3454  ~GuidedLocalSearch() override {}
3455  bool AcceptDelta(Assignment* delta, Assignment* deltadelta) override;
3456  void ApplyDecision(Decision* d) override;
3457  bool AtSolution() override;
3458  void EnterSearch() override;
3459  bool LocalOptimum() override;
3460  virtual int64 AssignmentElementPenalty(const Assignment& assignment,
3461  int index) = 0;
3462  virtual int64 AssignmentPenalty(const Assignment& assignment, int index,
3463  int64 next) = 0;
3464  virtual bool EvaluateElementValue(const Assignment::IntContainer& container,
3465  int64 index, int* container_index,
3466  int64* penalty) = 0;
3467  virtual IntExpr* MakeElementPenalty(int index) = 0;
3468  std::string DebugString() const override { return "Guided Local Search"; }
3469 
3470  protected:
3471  struct Comparator {
3472  bool operator()(const std::pair<Arc, double>& i,
3473  const std::pair<Arc, double>& j) {
3474  return i.second > j.second;
3475  }
3476  };
3477 
3478  int64 Evaluate(const Assignment* delta, int64 current_penalty,
3479  const int64* const out_values, bool cache_delta_values);
3480 
3482  Assignment assignment_;
3485  const std::vector<IntVar*> vars_;
3486  absl::flat_hash_map<const IntVar*, int64> indices_;
3487  const double penalty_factor_;
3488  std::unique_ptr<GuidedLocalSearchPenalties> penalties_;
3489  std::unique_ptr<int64[]> current_penalized_values_;
3490  std::unique_ptr<int64[]> delta_cache_;
3492 };
3493 
3494 GuidedLocalSearch::GuidedLocalSearch(Solver* const s, IntVar* objective,
3495  bool maximize, int64 step,
3496  const std::vector<IntVar*>& vars,
3497  double penalty_factor)
3498  : Metaheuristic(s, maximize, objective, step),
3499  penalized_objective_(nullptr),
3500  assignment_(s),
3503  vars_(vars),
3504  penalty_factor_(penalty_factor),
3505  incremental_(false) {
3506  if (!vars.empty()) {
3507  // TODO(user): Remove scoped_array.
3508  assignment_.Add(vars_);
3509  current_penalized_values_ = absl::make_unique<int64[]>(vars_.size());
3510  delta_cache_ = absl::make_unique<int64[]>(vars_.size());
3511  memset(current_penalized_values_.get(), 0,
3512  vars_.size() * sizeof(*current_penalized_values_.get()));
3513  }
3514  for (int i = 0; i < vars_.size(); ++i) {
3515  indices_[vars_[i]] = i;
3516  }
3517  if (FLAGS_cp_use_sparse_gls_penalties) {
3518  penalties_ = absl::make_unique<GuidedLocalSearchPenaltiesMap>(vars_.size());
3519  } else {
3520  penalties_ =
3521  absl::make_unique<GuidedLocalSearchPenaltiesTable>(vars_.size());
3522  }
3523 }
3524 
3525 // Add the following constraint (includes aspiration criterion):
3526 // if minimizing,
3527 // objective =< Max(current penalized cost - penalized_objective - step,
3528 // best solution cost - step)
3529 // if maximizing,
3530 // objective >= Min(current penalized cost - penalized_objective + step,
3531 // best solution cost + step)
3532 void GuidedLocalSearch::ApplyDecision(Decision* const d) {
3533  if (d == solver()->balancing_decision()) {
3534  return;
3535  }
3537  if (penalties_->HasValues()) {
3538  // Computing sum of penalties expression.
3539  // Scope needed to avoid potential leak of elements.
3540  {
3541  std::vector<IntVar*> elements;
3542  for (int i = 0; i < vars_.size(); ++i) {
3543  elements.push_back(MakeElementPenalty(i)->Var());
3544  const int64 penalty = AssignmentElementPenalty(assignment_, i);
3545  current_penalized_values_[i] = penalty;
3546  delta_cache_[i] = penalty;
3549  }
3550  penalized_objective_ = solver()->MakeSum(elements)->Var();
3551  }
3553  incremental_ = false;
3554  if (maximize_) {
3555  IntExpr* min_pen_exp =
3556  solver()->MakeDifference(current_ + step_, penalized_objective_);
3557  IntVar* min_exp = solver()->MakeMin(min_pen_exp, best_ + step_)->Var();
3558  solver()->AddConstraint(
3559  solver()->MakeGreaterOrEqual(objective_, min_exp));
3560  } else {
3561  IntExpr* max_pen_exp =
3562  solver()->MakeDifference(current_ - step_, penalized_objective_);
3563  IntVar* max_exp = solver()->MakeMax(max_pen_exp, best_ - step_)->Var();
3564  solver()->AddConstraint(solver()->MakeLessOrEqual(objective_, max_exp));
3565  }
3566  } else {
3567  penalized_objective_ = nullptr;
3568  if (maximize_) {
3569  const int64 bound = (current_ > kint64min) ? current_ + step_ : current_;
3570  objective_->SetMin(bound);
3571  } else {
3572  const int64 bound = (current_ < kint64max) ? current_ - step_ : current_;
3573  objective_->SetMax(bound);
3574  }
3575  }
3576 }
3577 
3578 bool GuidedLocalSearch::AtSolution() {
3579  if (!Metaheuristic::AtSolution()) {
3580  return false;
3581  }
3582  if (penalized_objective_ != nullptr) { // In case no move has been found
3583  current_ += penalized_objective_->Value();
3584  }
3585  assignment_.Store();
3586  return true;
3587 }
3588 
3589 void GuidedLocalSearch::EnterSearch() {
3590  Metaheuristic::EnterSearch();
3591  penalized_objective_ = nullptr;
3594  memset(current_penalized_values_.get(), 0,
3595  vars_.size() * sizeof(*current_penalized_values_.get()));
3596  penalties_->Reset();
3597 }
3598 
3599 // GLS filtering; compute the penalized value corresponding to the delta and
3600 // modify objective bound accordingly.
3601 bool GuidedLocalSearch::AcceptDelta(Assignment* delta, Assignment* deltadelta) {
3602  if (delta != nullptr || deltadelta != nullptr) {
3603  if (!penalties_->HasValues()) {
3604  return Metaheuristic::AcceptDelta(delta, deltadelta);
3605  }
3606  int64 penalty = 0;
3607  if (!deltadelta->Empty()) {
3608  if (!incremental_) {
3609  penalty = Evaluate(delta, assignment_penalized_value_,
3610  current_penalized_values_.get(), true);
3611  } else {
3612  penalty = Evaluate(deltadelta, old_penalized_value_, delta_cache_.get(),
3613  true);
3614  }
3615  incremental_ = true;
3616  } else {
3617  if (incremental_) {
3618  for (int i = 0; i < vars_.size(); ++i) {
3620  }
3622  }
3623  incremental_ = false;
3624  penalty = Evaluate(delta, assignment_penalized_value_,
3625  current_penalized_values_.get(), false);
3626  }
3627  old_penalized_value_ = penalty;
3628  if (!delta->HasObjective()) {
3629  delta->AddObjective(objective_);
3630  }
3631  if (delta->Objective() == objective_) {
3632  if (maximize_) {
3633  delta->SetObjectiveMin(
3635  CapAdd(best_, step_)),
3636  delta->ObjectiveMin()));
3637  } else {
3638  delta->SetObjectiveMax(
3640  CapSub(best_, step_)),
3641  delta->ObjectiveMax()));
3642  }
3643  }
3644  }
3645  return true;
3646 }
3647 
3648 int64 GuidedLocalSearch::Evaluate(const Assignment* delta,
3649  int64 current_penalty,
3650  const int64* const out_values,
3651  bool cache_delta_values) {
3652  int64 penalty = current_penalty;
3653  const Assignment::IntContainer& container = delta->IntVarContainer();
3654  const int size = container.Size();
3655  for (int i = 0; i < size; ++i) {
3656  const IntVarElement& new_element = container.Element(i);
3657  IntVar* var = new_element.Var();
3658  int64 index = -1;
3659  if (gtl::FindCopy(indices_, var, &index)) {
3660  penalty = CapSub(penalty, out_values[index]);
3661  int64 new_penalty = 0;
3662  if (EvaluateElementValue(container, index, &i, &new_penalty)) {
3663  penalty = CapAdd(penalty, new_penalty);
3664  if (cache_delta_values) {
3665  delta_cache_[index] = new_penalty;
3666  }
3667  }
3668  }
3669  }
3670  return penalty;
3671 }
3672 
3673 // Penalize all the most expensive arcs (var, value) according to their utility:
3674 // utility(i, j) = cost(i, j) / (1 + penalty(i, j))
3675 bool GuidedLocalSearch::LocalOptimum() {
3676  std::vector<std::pair<Arc, double>> utility(vars_.size());
3677  for (int i = 0; i < vars_.size(); ++i) {
3678  if (!assignment_.Bound(vars_[i])) {
3679  // Never synced with a solution, problem infeasible.
3680  return false;
3681  }
3682  const int64 var_value = assignment_.Value(vars_[i]);
3683  const int64 value =
3684  (var_value != i) ? AssignmentPenalty(assignment_, i, var_value) : 0;
3685  const Arc arc(i, var_value);
3686  const int64 penalty = penalties_->Value(arc);
3687  utility[i] = std::pair<Arc, double>(arc, value / (penalty + 1.0));
3688  }
3689  Comparator comparator;
3690  std::sort(utility.begin(), utility.end(), comparator);
3691  int64 utility_value = utility[0].second;
3692  penalties_->Increment(utility[0].first);
3693  for (int i = 1; i < utility.size() && utility_value == utility[i].second;
3694  ++i) {
3695  penalties_->Increment(utility[i].first);
3696  }
3697  if (maximize_) {
3698  current_ = kint64min;
3699  } else {
3700  current_ = kint64max;
3701  }
3702  return true;
3703 }
3704 
3705 class BinaryGuidedLocalSearch : public GuidedLocalSearch {
3706  public:
3707  BinaryGuidedLocalSearch(Solver* const solver, IntVar* const objective,
3708  std::function<int64(int64, int64)> objective_function,
3709  bool maximize, int64 step,
3710  const std::vector<IntVar*>& vars,
3711  double penalty_factor);
3712  ~BinaryGuidedLocalSearch() override {}
3713  IntExpr* MakeElementPenalty(int index) override;
3714  int64 AssignmentElementPenalty(const Assignment& assignment,
3715  int index) override;
3716  int64 AssignmentPenalty(const Assignment& assignment, int index,
3717  int64 next) override;
3718  bool EvaluateElementValue(const Assignment::IntContainer& container,
3719  int64 index, int* container_index,
3720  int64* penalty) override;
3721 
3722  private:
3723  int64 PenalizedValue(int64 i, int64 j);
3724  std::function<int64(int64, int64)> objective_function_;
3725 };
3726 
3727 BinaryGuidedLocalSearch::BinaryGuidedLocalSearch(
3728  Solver* const solver, IntVar* const objective,
3729  std::function<int64(int64, int64)> objective_function, bool maximize,
3730  int64 step, const std::vector<IntVar*>& vars, double penalty_factor)
3731  : GuidedLocalSearch(solver, objective, maximize, step, vars,
3732  penalty_factor),
3733  objective_function_(std::move(objective_function)) {}
3734 
3735 IntExpr* BinaryGuidedLocalSearch::MakeElementPenalty(int index) {
3736  return solver()->MakeElement(
3737  [this, index](int64 i) { return PenalizedValue(index, i); },
3738  vars_[index]);
3739 }
3740 
3741 int64 BinaryGuidedLocalSearch::AssignmentElementPenalty(
3742  const Assignment& assignment, int index) {
3743  return PenalizedValue(index, assignment.Value(vars_[index]));
3744 }
3745 
3746 int64 BinaryGuidedLocalSearch::AssignmentPenalty(const Assignment& assignment,
3747  int index, int64 next) {
3748  return objective_function_(index, next);
3749 }
3750 
3751 bool BinaryGuidedLocalSearch::EvaluateElementValue(
3752  const Assignment::IntContainer& container, int64 index,
3753  int* container_index, int64* penalty) {
3754  const IntVarElement& element = container.Element(*container_index);
3755  if (element.Activated()) {
3756  *penalty = PenalizedValue(index, element.Value());
3757  return true;
3758  }
3759  return false;
3760 }
3761 
3762 // Penalized value for (i, j) = penalty_factor_ * penalty(i, j) * cost (i, j)
3763 int64 BinaryGuidedLocalSearch::PenalizedValue(int64 i, int64 j) {
3764  const Arc arc(i, j);
3765  const int64 penalty = penalties_->Value(arc);
3766  if (penalty != 0) { // objective_function_->Run(i, j) can be costly
3767  const double penalized_value_fp =
3768  penalty_factor_ * penalty * objective_function_(i, j);
3769  const int64 penalized_value = (penalized_value_fp <= kint64max)
3770  ? static_cast<int64>(penalized_value_fp)
3771  : kint64max;
3772  if (maximize_) {
3773  return -penalized_value;
3774  } else {
3775  return penalized_value;
3776  }
3777  } else {
3778  return 0;
3779  }
3780 }
3781 
3782 class TernaryGuidedLocalSearch : public GuidedLocalSearch {
3783  public:
3784  TernaryGuidedLocalSearch(
3785  Solver* const solver, IntVar* const objective,
3786  std::function<int64(int64, int64, int64)> objective_function,
3787  bool maximize, int64 step, const std::vector<IntVar*>& vars,
3788  const std::vector<IntVar*>& secondary_vars, double penalty_factor);
3789  ~TernaryGuidedLocalSearch() override {}
3790  IntExpr* MakeElementPenalty(int index) override;
3791  int64 AssignmentElementPenalty(const Assignment& assignment,
3792  int index) override;
3793  int64 AssignmentPenalty(const Assignment& assignment, int index,
3794  int64 next) override;
3795  bool EvaluateElementValue(const Assignment::IntContainer& container,
3796  int64 index, int* container_index,
3797  int64* penalty) override;
3798 
3799  private:
3800  int64 PenalizedValue(int64 i, int64 j, int64 k);
3801  int64 GetAssignmentSecondaryValue(const Assignment::IntContainer& container,
3802  int index, int* container_index) const;
3803 
3804  const std::vector<IntVar*> secondary_vars_;
3805  std::function<int64(int64, int64, int64)> objective_function_;
3806 };
3807 
3808 TernaryGuidedLocalSearch::TernaryGuidedLocalSearch(
3809  Solver* const solver, IntVar* const objective,
3810  std::function<int64(int64, int64, int64)> objective_function, bool maximize,
3811  int64 step, const std::vector<IntVar*>& vars,
3812  const std::vector<IntVar*>& secondary_vars, double penalty_factor)
3813  : GuidedLocalSearch(solver, objective, maximize, step, vars,
3814  penalty_factor),
3815  secondary_vars_(secondary_vars),
3816  objective_function_(std::move(objective_function)) {
3817  if (!secondary_vars.empty()) {
3818  assignment_.Add(secondary_vars);
3819  }
3820 }
3821 
3822 IntExpr* TernaryGuidedLocalSearch::MakeElementPenalty(int index) {
3823  return solver()->MakeElement(
3824  [this, index](int64 i, int64 j) { return PenalizedValue(index, i, j); },
3825  vars_[index], secondary_vars_[index]);
3826 }
3827 
3828 int64 TernaryGuidedLocalSearch::AssignmentElementPenalty(
3829  const Assignment& assignment, int index) {
3830  return PenalizedValue(index, assignment.Value(vars_[index]),
3831  assignment.Value(secondary_vars_[index]));
3832 }
3833 
3834 int64 TernaryGuidedLocalSearch::AssignmentPenalty(const Assignment& assignment,
3835  int index, int64 next) {
3836  return objective_function_(index, next,
3837  assignment.Value(secondary_vars_[index]));
3838 }
3839 
3840 bool TernaryGuidedLocalSearch::EvaluateElementValue(
3841  const Assignment::IntContainer& container, int64 index,
3842  int* container_index, int64* penalty) {
3843  const IntVarElement& element = container.Element(*container_index);
3844  if (element.Activated()) {
3845  *penalty = PenalizedValue(
3846  index, element.Value(),
3847  GetAssignmentSecondaryValue(container, index, container_index));
3848  return true;
3849  }
3850  return false;
3851 }
3852 
3853 // Penalized value for (i, j) = penalty_factor_ * penalty(i, j) * cost (i, j)
3854 int64 TernaryGuidedLocalSearch::PenalizedValue(int64 i, int64 j, int64 k) {
3855  const Arc arc(i, j);
3856  const int64 penalty = penalties_->Value(arc);
3857  if (penalty != 0) { // objective_function_(i, j, k) can be costly
3858  const double penalized_value_fp =
3859  penalty_factor_ * penalty * objective_function_(i, j, k);
3860  const int64 penalized_value = (penalized_value_fp <= kint64max)
3861  ? static_cast<int64>(penalized_value_fp)
3862  : kint64max;
3863  if (maximize_) {
3864  return -penalized_value;
3865  } else {
3866  return penalized_value;
3867  }
3868  } else {
3869  return 0;
3870  }
3871 }
3872 
3873 int64 TernaryGuidedLocalSearch::GetAssignmentSecondaryValue(
3874  const Assignment::IntContainer& container, int index,
3875  int* container_index) const {
3876  const IntVar* secondary_var = secondary_vars_[index];
3877  int hint_index = *container_index + 1;
3878  if (hint_index > 0 && hint_index < container.Size() &&
3879  secondary_var == container.Element(hint_index).Var()) {
3880  *container_index = hint_index;
3881  return container.Element(hint_index).Value();
3882  } else {
3883  return container.Element(secondary_var).Value();
3884  }
3885 }
3886 } // namespace
3887 
3888 SearchMonitor* Solver::MakeGuidedLocalSearch(
3889  bool maximize, IntVar* const objective,
3890  Solver::IndexEvaluator2 objective_function, int64 step,
3891  const std::vector<IntVar*>& vars, double penalty_factor) {
3892  return RevAlloc(new BinaryGuidedLocalSearch(
3893  this, objective, std::move(objective_function), maximize, step, vars,
3894  penalty_factor));
3895 }
3896 
3897 SearchMonitor* Solver::MakeGuidedLocalSearch(
3898  bool maximize, IntVar* const objective,
3899  Solver::IndexEvaluator3 objective_function, int64 step,
3900  const std::vector<IntVar*>& vars,
3901  const std::vector<IntVar*>& secondary_vars, double penalty_factor) {
3902  return RevAlloc(new TernaryGuidedLocalSearch(
3903  this, objective, std::move(objective_function), maximize, step, vars,
3904  secondary_vars, penalty_factor));
3905 }
3906 
3907 // ---------- Search Limits ----------
3908 
3909 // ----- Base Class -----
3910 
3911 SearchLimit::~SearchLimit() {}
3912 
3913 void SearchLimit::EnterSearch() {
3914  crossed_ = false;
3915  Init();
3916 }
3917 
3918 void SearchLimit::BeginNextDecision(DecisionBuilder* const b) {
3919  PeriodicCheck();
3920  TopPeriodicCheck();
3921 }
3922 
3923 void SearchLimit::RefuteDecision(Decision* const d) {
3924  PeriodicCheck();
3925  TopPeriodicCheck();
3926 }
3927 
3928 void SearchLimit::PeriodicCheck() {
3929  if (crossed_ || Check()) {
3930  crossed_ = true;
3931  solver()->Fail();
3932  }
3933 }
3934 
3935 void SearchLimit::TopPeriodicCheck() {
3936  if (solver()->TopLevelSearch() != solver()->ActiveSearch()) {
3937  solver()->TopPeriodicCheck();
3938  }
3939 }
3940 
3941 // ----- Regular Limit -----
3942 
3943 RegularLimit::RegularLimit(Solver* const s, absl::Duration time, int64 branches,
3944  int64 failures, int64 solutions,
3945  bool smart_time_check, bool cumulative)
3946  : SearchLimit(s),
3947  duration_limit_(time),
3948  solver_time_at_limit_start_(s->Now()),
3949  last_time_elapsed_(absl::ZeroDuration()),
3950  check_count_(0),
3951  next_check_(0),
3952  smart_time_check_(smart_time_check),
3953  branches_(branches),
3954  branches_offset_(0),
3955  failures_(failures),
3956  failures_offset_(0),
3957  solutions_(solutions),
3958  solutions_offset_(0),
3959  cumulative_(cumulative) {}
3960 
3961 RegularLimit::~RegularLimit() {}
3962 
3963 void RegularLimit::Copy(const SearchLimit* const limit) {
3964  const RegularLimit* const regular =
3965  reinterpret_cast<const RegularLimit* const>(limit);
3966  duration_limit_ = regular->duration_limit_;
3967  branches_ = regular->branches_;
3968  failures_ = regular->failures_;
3969  solutions_ = regular->solutions_;
3970  smart_time_check_ = regular->smart_time_check_;
3971  cumulative_ = regular->cumulative_;
3972 }
3973 
3974 SearchLimit* RegularLimit::MakeClone() const { return MakeIdenticalClone(); }
3975 
3976 RegularLimit* RegularLimit::MakeIdenticalClone() const {
3977  Solver* const s = solver();
3978  return s->MakeLimit(wall_time(), branches_, failures_, solutions_,
3979  smart_time_check_);
3980 }
3981 
3982 bool RegularLimit::Check() {
3983  Solver* const s = solver();
3984  // Warning limits might be kint64max, do not move the offset to the rhs
3985  return s->branches() - branches_offset_ >= branches_ ||
3986  s->failures() - failures_offset_ >= failures_ || CheckTime() ||
3987  s->solutions() - solutions_offset_ >= solutions_;
3988 }
3989 
3990 int RegularLimit::ProgressPercent() {
3991  Solver* const s = solver();
3992  int64 progress = GetPercent(s->branches(), branches_offset_, branches_);
3993  progress = std::max(progress,
3994  GetPercent(s->failures(), failures_offset_, failures_));
3995  progress = std::max(
3996  progress, GetPercent(s->solutions(), solutions_offset_, solutions_));
3997  if (duration_limit() != absl::InfiniteDuration()) {
3998  progress = std::max(progress, (100 * TimeElapsed()) / duration_limit());
3999  }
4000  return progress;
4001 }
4002 
4003 void RegularLimit::Init() {
4004  Solver* const s = solver();
4005  branches_offset_ = s->branches();
4006  failures_offset_ = s->failures();
4007  solver_time_at_limit_start_ = s->Now();
4008  last_time_elapsed_ = absl::ZeroDuration();
4009  solutions_offset_ = s->solutions();
4010  check_count_ = 0;
4011  next_check_ = 0;
4012 }
4013 
4014 void RegularLimit::ExitSearch() {
4015  if (cumulative_) {
4016  // Reduce the limits by the amount consumed during this search
4017  Solver* const s = solver();
4018  branches_ -= s->branches() - branches_offset_;
4019  failures_ -= s->failures() - failures_offset_;
4020  duration_limit_ -= s->Now() - solver_time_at_limit_start_;
4021  solutions_ -= s->solutions() - solutions_offset_;
4022  }
4023 }
4024 
4025 void RegularLimit::UpdateLimits(absl::Duration time, int64 branches,
4026  int64 failures, int64 solutions) {
4027  duration_limit_ = time;
4028  branches_ = branches;
4029  failures_ = failures;
4030  solutions_ = solutions;
4031 }
4032 
4033 bool RegularLimit::IsUncheckedSolutionLimitReached() {
4034  Solver* const s = solver();
4035  return s->solutions() + s->unchecked_solutions() - solutions_offset_ >=
4036  solutions_;
4037 }
4038 
4039 std::string RegularLimit::DebugString() const {
4040  return absl::StrFormat(
4041  "RegularLimit(crossed = %i, duration_limit = %s, "
4042  "branches = %d, failures = %d, solutions = %d cumulative = %s",
4043  crossed(), absl::FormatDuration(duration_limit()), branches_, failures_,
4044  solutions_, (cumulative_ ? "true" : "false"));
4045 }
4046 
4047 void RegularLimit::Accept(ModelVisitor* const visitor) const {
4048  visitor->BeginVisitExtension(ModelVisitor::kSearchLimitExtension);
4049  visitor->VisitIntegerArgument(ModelVisitor::kTimeLimitArgument, wall_time());
4050  visitor->VisitIntegerArgument(ModelVisitor::kBranchesLimitArgument,
4051  branches_);
4052  visitor->VisitIntegerArgument(ModelVisitor::kFailuresLimitArgument,
4053  failures_);
4054  visitor->VisitIntegerArgument(ModelVisitor::kSolutionLimitArgument,
4055  solutions_);
4056  visitor->VisitIntegerArgument(ModelVisitor::kSmartTimeCheckArgument,
4057  smart_time_check_);
4058  visitor->VisitIntegerArgument(ModelVisitor::kCumulativeArgument, cumulative_);
4059  visitor->EndVisitExtension(ModelVisitor::kObjectiveExtension);
4060 }
4061 
4062 bool RegularLimit::CheckTime() { return TimeElapsed() >= duration_limit(); }
4063 
4064 absl::Duration RegularLimit::TimeElapsed() {
4065  const int64 kMaxSkip = 100;
4066  const int64 kCheckWarmupIterations = 100;
4067  ++check_count_;
4068  if (duration_limit() != absl::InfiniteDuration() &&
4069  next_check_ <= check_count_) {
4070  Solver* const s = solver();
4071  absl::Duration elapsed = s->Now() - solver_time_at_limit_start_;
4072  if (smart_time_check_ && check_count_ > kCheckWarmupIterations &&
4073  elapsed > absl::ZeroDuration()) {
4074  const int64 estimated_check_count_at_limit = MathUtil::FastInt64Round(
4075  check_count_ * absl::FDivDuration(duration_limit_, elapsed));
4076  next_check_ =
4077  std::min(check_count_ + kMaxSkip, estimated_check_count_at_limit);
4078  }
4079  last_time_elapsed_ = elapsed;
4080  }
4081  return last_time_elapsed_;
4082 }
4083 
4084 RegularLimit* Solver::MakeTimeLimit(absl::Duration time) {
4085  return MakeLimit(time, kint64max, kint64max, kint64max,
4086  /*smart_time_check=*/false, /*cumulative=*/false);
4087 }
4088 
4089 RegularLimit* Solver::MakeBranchesLimit(int64 branches) {
4090  return MakeLimit(absl::InfiniteDuration(), branches, kint64max, kint64max,
4091  /*smart_time_check=*/false, /*cumulative=*/false);
4092 }
4093 
4094 RegularLimit* Solver::MakeFailuresLimit(int64 failures) {
4095  return MakeLimit(absl::InfiniteDuration(), kint64max, failures, kint64max,
4096  /*smart_time_check=*/false, /*cumulative=*/false);
4097 }
4098 
4099 RegularLimit* Solver::MakeSolutionsLimit(int64 solutions) {
4100  return MakeLimit(absl::InfiniteDuration(), kint64max, kint64max, solutions,
4101  /*smart_time_check=*/false, /*cumulative=*/false);
4102 }
4103 
4104 RegularLimit* Solver::MakeLimit(int64 time, int64 branches, int64 failures,
4105  int64 solutions, bool smart_time_check,
4106  bool cumulative) {
4107  return MakeLimit(absl::Milliseconds(time), branches, failures, solutions,
4108  smart_time_check, cumulative);
4109 }
4110 
4111 RegularLimit* Solver::MakeLimit(absl::Duration time, int64 branches,
4112  int64 failures, int64 solutions,
4113  bool smart_time_check, bool cumulative) {
4114  return RevAlloc(new RegularLimit(this, time, branches, failures, solutions,
4115  smart_time_check, cumulative));
4116 }
4117 
4118 RegularLimit* Solver::MakeLimit(const RegularLimitParameters& proto) {
4119  return MakeLimit(proto.time() == kint64max ? absl::InfiniteDuration()
4120  : absl::Milliseconds(proto.time()),
4121  proto.branches(), proto.failures(), proto.solutions(),
4122  proto.smart_time_check(), proto.cumulative());
4123 }
4124 
4125 RegularLimitParameters Solver::MakeDefaultRegularLimitParameters() const {
4126  RegularLimitParameters proto;
4127  proto.set_time(kint64max);
4128  proto.set_branches(kint64max);
4129  proto.set_failures(kint64max);
4130  proto.set_solutions(kint64max);
4131  proto.set_smart_time_check(false);
4132  proto.set_cumulative(false);
4133  return proto;
4134 }
4135 
4136 // A limit whose Check function is the OR of two underlying limits.
4137 namespace {
4138 class ORLimit : public SearchLimit {
4139  public:
4140  ORLimit(SearchLimit* limit_1, SearchLimit* limit_2)
4141  : SearchLimit(limit_1->solver()), limit_1_(limit_1), limit_2_(limit_2) {
4142  CHECK(limit_1 != nullptr);
4143  CHECK(limit_2 != nullptr);
4144  CHECK_EQ(limit_1->solver(), limit_2->solver())
4145  << "Illegal arguments: cannot combines limits that belong to different "
4146  << "solvers, because the reversible allocations could delete one and "
4147  << "not the other.";
4148  }
4149 
4150  bool Check() override {
4151  // Check being non-const, there may be side effects. So we always call both
4152  // checks.
4153  const bool check_1 = limit_1_->Check();
4154  const bool check_2 = limit_2_->Check();
4155  return check_1 || check_2;
4156  }
4157 
4158  void Init() override {
4159  limit_1_->Init();
4160  limit_2_->Init();
4161  }
4162 
4163  void Copy(const SearchLimit* const limit) override {
4164  LOG(FATAL) << "Not implemented.";
4165  }
4166 
4167  SearchLimit* MakeClone() const override {
4168  // Deep cloning: the underlying limits are cloned, too.
4169  return solver()->MakeLimit(limit_1_->MakeClone(), limit_2_->MakeClone());
4170  }
4171 
4172  void EnterSearch() override {
4173  limit_1_->EnterSearch();
4174  limit_2_->EnterSearch();
4175  }
4176  void BeginNextDecision(DecisionBuilder* const b) override {
4177  limit_1_->BeginNextDecision(b);
4178  limit_2_->BeginNextDecision(b);
4179  }
4180  void PeriodicCheck() override {
4181  limit_1_->PeriodicCheck();
4182  limit_2_->PeriodicCheck();
4183  }
4184  void RefuteDecision(Decision* const d) override {
4185  limit_1_->RefuteDecision(d);
4186  limit_2_->RefuteDecision(d);
4187  }
4188  std::string DebugString() const override {
4189  return absl::StrCat("OR limit (", limit_1_->DebugString(), " OR ",
4190  limit_2_->DebugString(), ")");
4191  }
4192 
4193  private:
4194  SearchLimit* const limit_1_;
4195  SearchLimit* const limit_2_;
4196 };
4197 } // namespace
4198 
4199 SearchLimit* Solver::MakeLimit(SearchLimit* const limit_1,
4200  SearchLimit* const limit_2) {
4201  return RevAlloc(new ORLimit(limit_1, limit_2));
4202 }
4203 
4204 namespace {
4205 class CustomLimit : public SearchLimit {
4206  public:
4207  CustomLimit(Solver* const s, std::function<bool()> limiter);
4208  bool Check() override;
4209  void Init() override;
4210  void Copy(const SearchLimit* const limit) override;
4211  SearchLimit* MakeClone() const override;
4212 
4213  private:
4214  std::function<bool()> limiter_;
4215 };
4216 
4217 CustomLimit::CustomLimit(Solver* const s, std::function<bool()> limiter)
4218  : SearchLimit(s), limiter_(std::move(limiter)) {}
4219 
4220 bool CustomLimit::Check() {
4221  if (limiter_) return limiter_();
4222  return false;
4223 }
4224 
4225 void CustomLimit::Init() {}
4226 
4227 void CustomLimit::Copy(const SearchLimit* const limit) {
4228  const CustomLimit* const custom =
4229  reinterpret_cast<const CustomLimit* const>(limit);
4230  limiter_ = custom->limiter_;
4231 }
4232 
4233 SearchLimit* CustomLimit::MakeClone() const {
4234  return solver()->RevAlloc(new CustomLimit(solver(), limiter_));
4235 }
4236 } // namespace
4237 
4238 SearchLimit* Solver::MakeCustomLimit(std::function<bool()> limiter) {
4239  return RevAlloc(new CustomLimit(this, std::move(limiter)));
4240 }
4241 
4242 // ---------- SolveOnce ----------
4243 
4244 namespace {
4245 class SolveOnce : public DecisionBuilder {
4246  public:
4247  explicit SolveOnce(DecisionBuilder* const db) : db_(db) {
4248  CHECK(db != nullptr);
4249  }
4250 
4251  SolveOnce(DecisionBuilder* const db,
4252  const std::vector<SearchMonitor*>& monitors)
4253  : db_(db), monitors_(monitors) {
4254  CHECK(db != nullptr);
4255  }
4256 
4257  ~SolveOnce() override {}
4258 
4259  Decision* Next(Solver* s) override {
4260  bool res = s->SolveAndCommit(db_, monitors_);
4261  if (!res) {
4262  s->Fail();
4263  }
4264  return nullptr;
4265  }
4266 
4267  std::string DebugString() const override {
4268  return absl::StrFormat("SolveOnce(%s)", db_->DebugString());
4269  }
4270 
4271  void Accept(ModelVisitor* const visitor) const override {
4272  db_->Accept(visitor);
4273  }
4274 
4275  private:
4276  DecisionBuilder* const db_;
4277  std::vector<SearchMonitor*> monitors_;
4278 };
4279 } // namespace
4280 
4281 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder* const db) {
4282  return RevAlloc(new SolveOnce(db));
4283 }
4284 
4285 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder* const db,
4286  SearchMonitor* const monitor1) {
4287  std::vector<SearchMonitor*> monitors;
4288  monitors.push_back(monitor1);
4289  return RevAlloc(new SolveOnce(db, monitors));
4290 }
4291 
4292 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder* const db,
4293  SearchMonitor* const monitor1,
4294  SearchMonitor* const monitor2) {
4295  std::vector<SearchMonitor*> monitors;
4296  monitors.push_back(monitor1);
4297  monitors.push_back(monitor2);
4298  return RevAlloc(new SolveOnce(db, monitors));
4299 }
4300 
4301 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder* const db,
4302  SearchMonitor* const monitor1,
4303  SearchMonitor* const monitor2,
4304  SearchMonitor* const monitor3) {
4305  std::vector<SearchMonitor*> monitors;
4306  monitors.push_back(monitor1);
4307  monitors.push_back(monitor2);
4308  monitors.push_back(monitor3);
4309  return RevAlloc(new SolveOnce(db, monitors));
4310 }
4311 
4312 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder* const db,
4313  SearchMonitor* const monitor1,
4314  SearchMonitor* const monitor2,
4315  SearchMonitor* const monitor3,
4316  SearchMonitor* const monitor4) {
4317  std::vector<SearchMonitor*> monitors;
4318  monitors.push_back(monitor1);
4319  monitors.push_back(monitor2);
4320  monitors.push_back(monitor3);
4321  monitors.push_back(monitor4);
4322  return RevAlloc(new SolveOnce(db, monitors));
4323 }
4324 
4325 DecisionBuilder* Solver::MakeSolveOnce(
4326  DecisionBuilder* const db, const std::vector<SearchMonitor*>& monitors) {
4327  return RevAlloc(new SolveOnce(db, monitors));
4328 }
4329 
4330 // ---------- NestedOptimize ----------
4331 
4332 namespace {
4333 class NestedOptimize : public DecisionBuilder {
4334  public:
4335  NestedOptimize(DecisionBuilder* const db, Assignment* const solution,
4336  bool maximize, int64 step)
4337  : db_(db),
4338  solution_(solution),
4339  maximize_(maximize),
4340  step_(step),
4341  collector_(nullptr) {
4342  CHECK(db != nullptr);
4343  CHECK(solution != nullptr);
4344  CHECK(solution->HasObjective());
4345  AddMonitors();
4346  }
4347 
4348  NestedOptimize(DecisionBuilder* const db, Assignment* const solution,
4349  bool maximize, int64 step,
4350  const std::vector<SearchMonitor*>& monitors)
4351  : db_(db),
4352  solution_(solution),
4353  maximize_(maximize),
4354  step_(step),
4355  monitors_(monitors),
4356  collector_(nullptr) {
4357  CHECK(db != nullptr);
4358  CHECK(solution != nullptr);
4359  CHECK(solution->HasObjective());
4360  AddMonitors();
4361  }
4362 
4363  void AddMonitors() {
4364  Solver* const solver = solution_->solver();
4365  collector_ = solver->MakeLastSolutionCollector(solution_);
4366  monitors_.push_back(collector_);
4367  OptimizeVar* const optimize =
4368  solver->MakeOptimize(maximize_, solution_->Objective(), step_);
4369  monitors_.push_back(optimize);
4370  }
4371 
4372  Decision* Next(Solver* solver) override {
4373  solver->Solve(db_, monitors_);
4374  if (collector_->solution_count() == 0) {
4375  solver->Fail();
4376  }
4377  collector_->solution(0)->Restore();
4378  return nullptr;
4379  }
4380 
4381  std::string DebugString() const override {
4382  return absl::StrFormat("NestedOptimize(db = %s, maximize = %d, step = %d)",
4383  db_->DebugString(), maximize_, step_);
4384  }
4385 
4386  void Accept(ModelVisitor* const visitor) const override {
4387  db_->Accept(visitor);
4388  }
4389 
4390  private:
4391  DecisionBuilder* const db_;
4392  Assignment* const solution_;
4393  const bool maximize_;
4394  const int64 step_;
4395  std::vector<SearchMonitor*> monitors_;
4396  SolutionCollector* collector_;
4397 };
4398 } // namespace
4399 
4400 DecisionBuilder* Solver::MakeNestedOptimize(DecisionBuilder* const db,
4401  Assignment* const solution,
4402  bool maximize, int64 step) {
4403  return RevAlloc(new NestedOptimize(db, solution, maximize, step));
4404 }
4405 
4406 DecisionBuilder* Solver::MakeNestedOptimize(DecisionBuilder* const db,
4407  Assignment* const solution,
4408  bool maximize, int64 step,
4409  SearchMonitor* const monitor1) {
4410  std::vector<SearchMonitor*> monitors;
4411  monitors.push_back(monitor1);
4412  return RevAlloc(new NestedOptimize(db, solution, maximize, step, monitors));
4413 }
4414 
4415 DecisionBuilder* Solver::MakeNestedOptimize(DecisionBuilder* const db,
4416  Assignment* const solution,
4417  bool maximize, int64 step,
4418  SearchMonitor* const monitor1,
4419  SearchMonitor* const monitor2) {
4420  std::vector<SearchMonitor*> monitors;
4421  monitors.push_back(monitor1);
4422  monitors.push_back(monitor2);
4423  return RevAlloc(new NestedOptimize(db, solution, maximize, step, monitors));
4424 }
4425 
4426 DecisionBuilder* Solver::MakeNestedOptimize(DecisionBuilder* const db,
4427  Assignment* const solution,
4428  bool maximize, int64 step,
4429  SearchMonitor* const monitor1,
4430  SearchMonitor* const monitor2,
4431  SearchMonitor* const monitor3) {
4432  std::vector<SearchMonitor*> monitors;
4433  monitors.push_back(monitor1);
4434  monitors.push_back(monitor2);
4435  monitors.push_back(monitor3);
4436  return RevAlloc(new NestedOptimize(db, solution, maximize, step, monitors));
4437 }
4438 
4439 DecisionBuilder* Solver::MakeNestedOptimize(
4440  DecisionBuilder* const db, Assignment* const solution, bool maximize,
4441  int64 step, SearchMonitor* const monitor1, SearchMonitor* const monitor2,
4442  SearchMonitor* const monitor3, SearchMonitor* const monitor4) {
4443  std::vector<SearchMonitor*> monitors;
4444  monitors.push_back(monitor1);
4445  monitors.push_back(monitor2);
4446  monitors.push_back(monitor3);
4447  monitors.push_back(monitor4);
4448  return RevAlloc(new NestedOptimize(db, solution, maximize, step, monitors));
4449 }
4450 
4451 DecisionBuilder* Solver::MakeNestedOptimize(
4452  DecisionBuilder* const db, Assignment* const solution, bool maximize,
4453  int64 step, const std::vector<SearchMonitor*>& monitors) {
4454  return RevAlloc(new NestedOptimize(db, solution, maximize, step, monitors));
4455 }
4456 
4457 // ---------- Restart ----------
4458 
4459 namespace {
4460 // Luby Strategy
4461 int64 NextLuby(int i) {
4462  DCHECK_GT(i, 0);
4463  DCHECK_LT(i, kint32max);
4464  int64 power;
4465 
4466  // let's find the least power of 2 >= (i+1).
4467  power = 2;
4468  // Cannot overflow, because bounded by kint32max + 1.
4469  while (power < (i + 1)) {
4470  power <<= 1;
4471  }
4472  if (power == i + 1) {
4473  return (power / 2);
4474  }
4475  return NextLuby(i - (power / 2) + 1);
4476 }
4477 
4478 class LubyRestart : public SearchMonitor {
4479  public:
4480  LubyRestart(Solver* const s, int scale_factor)
4481  : SearchMonitor(s),
4482  scale_factor_(scale_factor),
4483  iteration_(1),
4484  current_fails_(0),
4485  next_step_(scale_factor) {
4486  CHECK_GE(scale_factor, 1);
4487  }
4488 
4489  ~LubyRestart() override {}
4490 
4491  void BeginFail() override {
4492  if (++current_fails_ >= next_step_) {
4493  current_fails_ = 0;
4494  next_step_ = NextLuby(++iteration_) * scale_factor_;
4495  solver()->RestartCurrentSearch();
4496  }
4497  }
4498 
4499  std::string DebugString() const override {
4500  return absl::StrFormat("LubyRestart(%i)", scale_factor_);
4501  }
4502 
4503  private:
4504  const int scale_factor_;
4505  int iteration_;
4506  int64 current_fails_;
4507  int64 next_step_;
4508 };
4509 } // namespace
4510 
4511 SearchMonitor* Solver::MakeLubyRestart(int scale_factor) {
4512  return RevAlloc(new LubyRestart(this, scale_factor));
4513 }
4514 
4515 // ----- Constant Restart -----
4516 
4517 namespace {
4518 class ConstantRestart : public SearchMonitor {
4519  public:
4520  ConstantRestart(Solver* const s, int frequency)
4521  : SearchMonitor(s), frequency_(frequency), current_fails_(0) {
4522  CHECK_GE(frequency, 1);
4523  }
4524 
4525  ~ConstantRestart() override {}
4526 
4527  void BeginFail() override {
4528  if (++current_fails_ >= frequency_) {
4529  current_fails_ = 0;
4530  solver()->RestartCurrentSearch();
4531  }
4532  }
4533 
4534  std::string DebugString() const override {
4535  return absl::StrFormat("ConstantRestart(%i)", frequency_);
4536  }
4537 
4538  private:
4539  const int frequency_;
4540  int64 current_fails_;
4541 };
4542 } // namespace
4543 
4544 SearchMonitor* Solver::MakeConstantRestart(int frequency) {
4545  return RevAlloc(new ConstantRestart(this, frequency));
4546 }
4547 
4548 // ---------- Symmetry Breaking ----------
4549 
4550 // The symmetry manager maintains a list of problem symmetries. Each
4551 // symmetry is called on each decision and should return a term
4552 // representing the boolean status of the symmetrical decision.
4553 // e.g. : the decision is x == 3, the symmetrical decision is y == 5
4554 // then the symmetry breaker should use
4555 // AddIntegerVariableEqualValueClause(y, 5). Once this is done, upon
4556 // refutation, for each symmetry breaker, the system adds a constraint
4557 // that will forbid the symmetrical variation of the current explored
4558 // search tree. This constraint can be expressed very simply just by
4559 // keeping the list of current symmetrical decisions.
4560 //
4561 // This is called Symmetry Breaking During Search (Ian Gent, Barbara
4562 // Smith, ECAI 2000).
4563 // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.3788&rep=rep1&type=pdf
4564 //
4565 class SymmetryManager : public SearchMonitor {
4566  public:
4567  SymmetryManager(Solver* const s,
4568  const std::vector<SymmetryBreaker*>& visitors)
4569  : SearchMonitor(s),
4570  visitors_(visitors),
4571  clauses_(visitors.size()),
4572  decisions_(visitors.size()),
4573  directions_(visitors.size()) { // false = left.
4574  for (int i = 0; i < visitors_.size(); ++i) {
4575  visitors_[i]->set_symmetry_manager_and_index(this, i);
4576  }
4577  }
4578 
4579  ~SymmetryManager() override {}
4580 
4581  void EndNextDecision(DecisionBuilder* const db, Decision* const d) override {
4582  if (d) {
4583  for (int i = 0; i < visitors_.size(); ++i) {
4584  const void* const last = clauses_[i].Last();
4585  d->Accept(visitors_[i]);
4586  if (last != clauses_[i].Last()) {
4587  // Synchroneous push of decision as marker.
4588  decisions_[i].Push(solver(), d);
4589  directions_[i].Push(solver(), false);
4590  }
4591  }
4592  }
4593  }
4594 
4595  void RefuteDecision(Decision* d) override {
4596  for (int i = 0; i < visitors_.size(); ++i) {
4597  if (decisions_[i].Last() != nullptr && decisions_[i].LastValue() == d) {
4598  CheckSymmetries(i);
4599  }
4600  }
4601  }
4602 
4603  // TODO(user) : Improve speed, cache previous min and build them
4604  // incrementally.
4606  SimpleRevFIFO<IntVar*>::Iterator tmp(&clauses_[index]);
4607  SimpleRevFIFO<bool>::Iterator tmp_dir(&directions_[index]);
4608  Constraint* ct = nullptr;
4609  {
4610  std::vector<IntVar*> guard;
4611  // keep the last entry for later, if loop doesn't exit.
4612  ++tmp;
4613  ++tmp_dir;
4614  while (tmp.ok()) {
4615  IntVar* const term = *tmp;
4616  if (!*tmp_dir) {
4617  if (term->Max() == 0) {
4618  // Premise is wrong. The clause will never apply.
4619  return;
4620  }
4621  if (term->Min() == 0) {
4622  DCHECK_EQ(1, term->Max());
4623  // Premise may be true. Adding to guard vector.
4624  guard.push_back(term);
4625  }
4626  }
4627  ++tmp;
4628  ++tmp_dir;
4629  }
4630  guard.push_back(clauses_[index].LastValue());
4631  directions_[index].SetLastValue(true);
4632  // Given premises: xi = ai
4633  // and a term y != b
4634  // The following is equivalent to
4635  // And(xi == a1) => y != b.
4636  ct = solver()->MakeEquality(solver()->MakeMin(guard), Zero());
4637  }
4638  DCHECK(ct != nullptr);
4639  solver()->AddConstraint(ct);
4640  }
4641 
4642  void AddTermToClause(SymmetryBreaker* const visitor, IntVar* const term) {
4643  clauses_[visitor->index_in_symmetry_manager()].Push(solver(), term);
4644  }
4645 
4646  std::string DebugString() const override { return "SymmetryManager"; }
4647 
4648  private:
4649  const std::vector<SymmetryBreaker*> visitors_;
4650  std::vector<SimpleRevFIFO<IntVar*>> clauses_;
4651  std::vector<SimpleRevFIFO<Decision*>> decisions_;
4652  std::vector<SimpleRevFIFO<bool>> directions_;
4653 };
4654 
4655 // ----- Symmetry Breaker -----
4656 
4657 void SymmetryBreaker::AddIntegerVariableEqualValueClause(IntVar* const var,
4658  int64 value) {
4659  CHECK(var != nullptr);
4660  Solver* const solver = var->solver();
4661  IntVar* const term = solver->MakeIsEqualCstVar(var, value);
4662  symmetry_manager()->AddTermToClause(this, term);
4663 }
4664 
4665 void SymmetryBreaker::AddIntegerVariableGreaterOrEqualValueClause(
4666  IntVar* const var, int64 value) {
4667  CHECK(var != nullptr);
4668  Solver* const solver = var->solver();
4669  IntVar* const term = solver->MakeIsGreaterOrEqualCstVar(var, value);
4670  symmetry_manager()->AddTermToClause(this, term);
4671 }
4672 
4673 void SymmetryBreaker::AddIntegerVariableLessOrEqualValueClause(
4674  IntVar* const var, int64 value) {
4675  CHECK(var != nullptr);
4676  Solver* const solver = var->solver();
4677  IntVar* const term = solver->MakeIsLessOrEqualCstVar(var, value);
4678  symmetry_manager()->AddTermToClause(this, term);
4679 }
4680 
4681 // ----- API -----
4682 
4683 SearchMonitor* Solver::MakeSymmetryManager(
4684  const std::vector<SymmetryBreaker*>& visitors) {
4685  return RevAlloc(new SymmetryManager(this, visitors));
4686 }
4687 
4688 SearchMonitor* Solver::MakeSymmetryManager(SymmetryBreaker* const v1) {
4689  std::vector<SymmetryBreaker*> visitors;
4690  visitors.push_back(v1);
4691  return MakeSymmetryManager(visitors);
4692 }
4693 
4694 SearchMonitor* Solver::MakeSymmetryManager(SymmetryBreaker* const v1,
4695  SymmetryBreaker* const v2) {
4696  std::vector<SymmetryBreaker*> visitors;
4697  visitors.push_back(v1);
4698  visitors.push_back(v2);
4699  return MakeSymmetryManager(visitors);
4700 }
4701 
4702 SearchMonitor* Solver::MakeSymmetryManager(SymmetryBreaker* const v1,
4703  SymmetryBreaker* const v2,
4704  SymmetryBreaker* const v3) {
4705  std::vector<SymmetryBreaker*> visitors;
4706  visitors.push_back(v1);
4707  visitors.push_back(v2);
4708  visitors.push_back(v3);
4709  return MakeSymmetryManager(visitors);
4710 }
4711 
4712 SearchMonitor* Solver::MakeSymmetryManager(SymmetryBreaker* const v1,
4713  SymmetryBreaker* const v2,
4714  SymmetryBreaker* const v3,
4715  SymmetryBreaker* const v4) {
4716  std::vector<SymmetryBreaker*> visitors;
4717  visitors.push_back(v1);
4718  visitors.push_back(v2);
4719  visitors.push_back(v3);
4720  visitors.push_back(v4);
4721  return MakeSymmetryManager(visitors);
4722 }
4723 } // namespace operations_research
operations_research::SearchLog::OutputLine
virtual void OutputLine(const std::string &line)
Definition: search.cc:250
operations_research::ToInt64Vector
std::vector< int64 > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:822
operations_research::SearchLog::EndInitialPropagation
void EndInitialPropagation() override
Definition: search.cc:242
min
int64 min
Definition: alldiff_cst.cc:138
integral_types.h
map_util.h
operations_research::Arc
std::pair< int64, int64 > Arc
Definition: search.cc:3355
penalized_objective_
IntVar * penalized_objective_
Definition: search.cc:3481
operations_research::CapSub
int64 CapSub(int64 x, int64 y)
Definition: saturated_arithmetic.h:154
max
int64 max
Definition: alldiff_cst.cc:139
current_
int64 current_
Definition: search.cc:2947
operations_research::SymmetryManager
Definition: search.cc:4565
bound
int64 bound
Definition: routing_search.cc:972
builders_
std::vector< DecisionBuilder * > builders_
Definition: search.cc:470
bitmap.h
operations_research::SearchLog::~SearchLog
~SearchLog() override
Definition: search.cc:79
delta_cache_
std::unique_ptr< int64[]> delta_cache_
Definition: search.cc:3490
logging.h
last_unbound_
Rev< int64 > last_unbound_
Definition: search.cc:782
operations_research::SearchLog::OutputDecision
void OutputDecision()
Definition: search.cc:207
stamp_
const int64 stamp_
Definition: search.cc:3033
DEFINE_int64
DEFINE_int64(cp_large_domain_no_splitting_limit, 0xFFFFF, "Size limit to allow holes in variables from the strategy.")
kuint64max
static const uint64 kuint64max
Definition: integral_types.h:52
operations_research::AcceptNeighbor
void AcceptNeighbor(Search *const search)
Definition: constraint_solver.cc:1346
macros.h
gtl::FindWithDefault
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
Definition: map_util.h:26
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
solutions_pq_
std::priority_queue< std::pair< int64, SolutionData > > solutions_pq_
Definition: search.cc:2571
kint64min
static const int64 kint64min
Definition: integral_types.h:60
operations_research::SearchLog::AtSolution
bool AtSolution() override
Definition: search.cc:104
operations_research::SearchLog::BeginFail
void BeginFail() override
Definition: search.cc:176
int64
int64_t int64
Definition: integral_types.h:34
constraint_solveri.h
operations_research::SearchLog::RefuteDecision
void RefuteDecision(Decision *const decision) override
Definition: search.cc:202
index
int index
Definition: pack.cc:508
offset_
const int64 offset_
Definition: interval.cc:2076
operations_research::SymmetryManager::~SymmetryManager
~SymmetryManager() override
Definition: search.cc:4579
operations_research::SearchLog::NoMoreSolutions
void NoMoreSolutions() override
Definition: search.cc:178
evaluator_
std::function< int64(int64, int64)> evaluator_
Definition: search.cc:1355
value
int64 value
Definition: search.cc:1348
old_penalized_value_
int64 old_penalized_value_
Definition: search.cc:3484
a
int64 a
Definition: constraint_solver/table.cc:42
constraint_solver.h
solution_count_
const int solution_count_
Definition: search.cc:2572
operations_research::SymmetryManager::RefuteDecision
void RefuteDecision(Decision *d) override
Definition: search.cc:4595
operations_research::SearchLog::BeginInitialPropagation
void BeginInitialPropagation() override
Definition: search.cc:240
string_array.h
first_unbound_
Rev< int64 > first_unbound_
Definition: search.cc:781
kint32max
static const int32 kint32max
Definition: integral_types.h:59
operations_research::SearchLog::SearchLog
SearchLog(Solver *const s, OptimizeVar *const obj, IntVar *const var, double scaling_factor, double offset, std::function< std::string()> display_callback, int period)
Definition: search.cc:56
operations_research::SearchLog::DebugString
std::string DebugString() const override
Definition: search.cc:81
operations_research::CapAdd
int64 CapAdd(int64 x, int64 y)
Definition: saturated_arithmetic.h:124
timer.h
operations_research::SymmetryManager::SymmetryManager
SymmetryManager(Solver *const s, const std::vector< SymmetryBreaker * > &visitors)
Definition: search.cc:4567
operations_research::SymmetryManager::CheckSymmetries
void CheckSymmetries(int index)
Definition: search.cc:4605
DEFINE_bool
DEFINE_bool(cp_use_sparse_gls_penalties, false, "Use sparse implementation to store Guided Local Search penalties")
var
int64 var
Definition: search.cc:1347
operations_research::SymmetryManager::AddTermToClause
void AddTermToClause(SymmetryBreaker *const visitor, IntVar *const term)
Definition: search.cc:4642
iterators_
std::vector< IntVarIterator * > iterators_
Definition: constraint_solver/table.cc:225
mathutil.h
search_limit.pb.h
WallTimer
Definition: timer.h:23
objective_
IntVar *const objective_
Definition: search.cc:2945
ct
const Constraint * ct
Definition: demon_profiler.cc:42
indices_
absl::flat_hash_map< const IntVar *, int64 > indices_
Definition: search.cc:3486
operations_research::SearchLog::ExitSearch
void ExitSearch() override
Definition: search.cc:91
operations_research::AcceptDelta
bool AcceptDelta(Search *const search, Assignment *delta, Assignment *deltadelta)
Definition: constraint_solver.cc:1341
uint64
uint64_t uint64
Definition: integral_types.h:39
operations_research::sat::Value
std::function< int64(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1396
operations_research::ChooseMode
BaseAssignVariables::Mode ChooseMode(Solver::IntValueStrategy val_str)
Definition: search.cc:1992
best_
int64 best_
Definition: search.cc:2494
callback
MPCallback * callback
Definition: gurobi_interface.cc:440
operations_research::SymmetryBreaker
A symmetry breaker is an object that will visit a decision and create the 'symmetrical' decision in r...
Definition: constraint_solveri.h:1996
operations_research::SearchLog::EnterSearch
void EnterSearch() override
Definition: search.cc:83
operations_research::SearchLog::AcceptUncheckedNeighbor
void AcceptUncheckedNeighbor() override
Definition: search.cc:174
operations_research::SearchLog::Maintain
void Maintain()
Definition: search.cc:233
vars_
std::vector< IntVar * > vars_
Definition: search.cc:780
stl_util.h
operations_research::SimpleRevFIFO
This class represent a reversible FIFO structure.
Definition: constraint_solveri.h:145
operations_research::SearchLog::ApplyDecision
void ApplyDecision(Decision *const decision) override
Definition: search.cc:194
operations_research::Bitmap
Definition: bitmap.h:38
penalty_factor_
const double penalty_factor_
Definition: search.cc:3487
hash.h
maximize_
const bool maximize_
Definition: search.cc:2493
delta
int64 delta
Definition: resource.cc:1684
b
int64 b
Definition: constraint_solver/table.cc:43
DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
next
Block * next
Definition: constraint_solver.cc:667
selector_
BaseVariableAssignmentSelector *const selector_
Definition: search.cc:1850
absl
Definition: cleanup.h:22
gtl::STLDeleteElements
void STLDeleteElements(T *container)
Definition: stl_util.h:372
proto
CpModelProto proto
Definition: cp_model_fz_solver.cc:106
assignment_penalized_value_
int64 assignment_penalized_value_
Definition: search.cc:3483
solver_
Solver *const solver_
Definition: search.cc:779
gtl::FindCopy
bool FindCopy(const Collection &collection, const Key &key, Value *const value)
Definition: map_util.h:155
operations_research::SymmetryManager::DebugString
std::string DebugString() const override
Definition: search.cc:4646
current_penalized_values_
std::unique_ptr< int64[]> current_penalized_values_
Definition: search.cc:3489
step_
int64 step_
Definition: search.cc:2946
commandlineflags.h
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:107
MemoryUsage
int64 MemoryUsage(int unused)
Definition: base/sysinfo.h:24
operations_research::SymmetryManager::EndNextDecision
void EndNextDecision(DecisionBuilder *const db, Decision *const d) override
Definition: search.cc:4581
name
const std::string name
Definition: default_search.cc:807
operations_research::JoinDebugStringPtr
std::string JoinDebugStringPtr(const std::vector< T > &v, const std::string &separator)
Definition: string_array.h:45
mode_
const Mode mode_
Definition: search.cc:1851
kint64max
static const int64 kint64max
Definition: integral_types.h:62
time
int64 time
Definition: resource.cc:1683
incremental_
bool incremental_
Definition: search.cc:3491