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"
46 "Use sparse implementation to store Guided Local Search penalties");
48 "Whether search related logging should be "
51 "Size limit to allow holes in variables from the strategy.");
57 double scaling_factor,
double offset,
58 std::function<std::string()> display_callback,
int period)
64 scaling_factor_(scaling_factor),
66 display_callback_(std::move(display_callback)),
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.";
84 const std::string buffer =
85 absl::StrFormat(
"Start search (%s)", MemoryUsage());
92 const int64 branches = solver()->branches();
93 int64 ms = timer_->GetInMs();
97 const std::string buffer = absl::StrFormat(
98 "End search (time = %d ms, branches = %d, failures = %d, %s, speed = %d "
100 ms, branches, solver()->failures(), MemoryUsage(), branches * 1000 / ms);
106 const int depth = solver()->SearchDepth();
107 std::string obj_str =
"";
109 bool objective_updated =
false;
111 if (scaling_factor_ != 1.0 || offset_ != 0.0) {
112 return absl::StrFormat(
"%d (%.8lf)",
value,
113 scaling_factor_ * (
value + offset_));
115 return absl::StrCat(
value);
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;
127 current = solver()->GetOrCreateLocalSearchState()->ObjectiveMin();
128 absl::StrAppend(&obj_str, scaled_str(current),
", ");
129 objective_updated =
true;
131 if (objective_updated) {
132 if (current > objective_min_) {
133 absl::StrAppend(&obj_str,
134 "objective minimum = ", scaled_str(objective_min_),
", ");
136 objective_min_ = current;
138 if (current < objective_max_) {
139 absl::StrAppend(&obj_str,
140 "objective maximum = ", scaled_str(objective_max_),
", ");
142 objective_max_ = current;
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());
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());
161 absl::StrAppendFormat(&log,
", %s", MemoryUsage());
162 const int progress = solver()->TopProgressPercent();
163 if (progress != SearchMonitor::kNoProgress) {
164 absl::StrAppendFormat(&log,
", limit = %d%%", progress);
166 if (display_callback_) {
167 absl::StrAppendFormat(&log,
", %s", display_callback_());
179 std::string buffer = absl::StrFormat(
180 "Finished search tree (time = %d ms, branches = %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());
190 absl::StrAppendFormat(&buffer,
", %s)", MemoryUsage());
196 const int64 b = solver()->branches();
197 if (
b % period_ == 0 &&
b > 0) {
203 min_right_depth_ =
std::min(min_right_depth_, solver()->SearchDepth());
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;
219 if (obj_ !=
nullptr && objective_min_ !=
kint64max &&
221 absl::StrAppendFormat(&buffer,
222 ", objective minimum = %d"
223 ", objective maximum = %d",
224 objective_min_, objective_max_);
226 const int progress = solver()->TopProgressPercent();
227 if (progress != SearchMonitor::kNoProgress) {
228 absl::StrAppendFormat(&buffer,
", limit = %d%%", progress);
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_);
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());
251 if (FLAGS_cp_log_to_vlog) {
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;
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);
274 return absl::StrFormat(
"memory used = %d", memory_usage);
278 SearchMonitor* Solver::MakeSearchLog(
int branch_period) {
280 new SearchLog(
this,
nullptr,
nullptr, 1.0, 0.0,
nullptr, branch_period));
283 SearchMonitor* Solver::MakeSearchLog(
int branch_period, IntVar*
const var) {
285 new SearchLog(
this,
nullptr,
var, 1.0, 0.0,
nullptr, branch_period));
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));
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));
301 SearchMonitor* Solver::MakeSearchLog(
int branch_period,
302 OptimizeVar*
const opt_var) {
304 new SearchLog(
this, opt_var,
nullptr, 1.0, 0.0,
nullptr, branch_period));
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));
314 SearchMonitor* Solver::MakeSearchLog(SearchLogParameters
parameters) {
323 class SearchTrace :
public SearchMonitor {
325 SearchTrace(Solver*
const s,
const std::string& prefix)
326 : SearchMonitor(s), prefix_(prefix) {}
327 ~SearchTrace()
override {}
329 void EnterSearch()
override {
330 LOG(INFO) << prefix_ <<
" EnterSearch(" << solver()->SolveDepth() <<
")";
332 void RestartSearch()
override {
333 LOG(INFO) << prefix_ <<
" RestartSearch(" << solver()->SolveDepth() <<
")";
335 void ExitSearch()
override {
336 LOG(INFO) << prefix_ <<
" ExitSearch(" << solver()->SolveDepth() <<
")";
338 void BeginNextDecision(DecisionBuilder*
const b)
override {
339 LOG(INFO) << prefix_ <<
" BeginNextDecision(" <<
b <<
") ";
341 void EndNextDecision(DecisionBuilder*
const b, Decision*
const d)
override {
343 LOG(INFO) << prefix_ <<
" EndNextDecision(" <<
b <<
", " << d <<
") ";
345 LOG(INFO) << prefix_ <<
" EndNextDecision(" <<
b <<
") ";
348 void ApplyDecision(Decision*
const d)
override {
349 LOG(INFO) << prefix_ <<
" ApplyDecision(" << d <<
") ";
351 void RefuteDecision(Decision*
const d)
override {
352 LOG(INFO) << prefix_ <<
" RefuteDecision(" << d <<
") ";
354 void AfterDecision(Decision*
const d,
bool apply)
override {
355 LOG(INFO) << prefix_ <<
" AfterDecision(" << d <<
", " << apply <<
") ";
357 void BeginFail()
override {
358 LOG(INFO) << prefix_ <<
" BeginFail(" << solver()->SearchDepth() <<
")";
360 void EndFail()
override {
361 LOG(INFO) << prefix_ <<
" EndFail(" << solver()->SearchDepth() <<
")";
363 void BeginInitialPropagation()
override {
364 LOG(INFO) << prefix_ <<
" BeginInitialPropagation()";
366 void EndInitialPropagation()
override {
367 LOG(INFO) << prefix_ <<
" EndInitialPropagation()";
369 bool AtSolution()
override {
370 LOG(INFO) << prefix_ <<
" AtSolution()";
373 bool AcceptSolution()
override {
374 LOG(INFO) << prefix_ <<
" AcceptSolution()";
377 void NoMoreSolutions()
override {
378 LOG(INFO) << prefix_ <<
" NoMoreSolutions()";
381 std::string DebugString()
const override {
return "SearchTrace"; }
384 const std::string prefix_;
388 SearchMonitor* Solver::MakeSearchTrace(
const std::string& prefix) {
389 return RevAlloc(
new SearchTrace(
this, prefix));
394 class AtSolutionCallback :
public SearchMonitor {
396 AtSolutionCallback(Solver*
const solver, std::function<
void()>
callback)
397 : SearchMonitor(solver), callback_(std::move(
callback)) {}
398 ~AtSolutionCallback()
override {}
399 bool AtSolution()
override;
402 const std::function<void()> callback_;
405 bool AtSolutionCallback::AtSolution() {
412 SearchMonitor* Solver::MakeAtSolutionCallback(std::function<
void()>
callback) {
413 return RevAlloc(
new AtSolutionCallback(
this, std::move(
callback)));
417 class EnterSearchCallback :
public SearchMonitor {
419 EnterSearchCallback(Solver*
const solver, std::function<
void()>
callback)
420 : SearchMonitor(solver), callback_(std::move(
callback)) {}
421 ~EnterSearchCallback()
override {}
422 void EnterSearch()
override;
425 const std::function<void()> callback_;
428 void EnterSearchCallback::EnterSearch() { callback_(); }
432 SearchMonitor* Solver::MakeEnterSearchCallback(std::function<
void()>
callback) {
433 return RevAlloc(
new EnterSearchCallback(
this, std::move(
callback)));
437 class ExitSearchCallback :
public SearchMonitor {
439 ExitSearchCallback(Solver*
const solver, std::function<
void()>
callback)
440 : SearchMonitor(solver), callback_(std::move(
callback)) {}
441 ~ExitSearchCallback()
override {}
442 void ExitSearch()
override;
445 const std::function<void()> callback_;
448 void ExitSearchCallback::ExitSearch() { callback_(); }
452 SearchMonitor* Solver::MakeExitSearchCallback(std::function<
void()>
callback) {
453 return RevAlloc(
new ExitSearchCallback(
this, std::move(
callback)));
459 class CompositeDecisionBuilder :
public DecisionBuilder {
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;
473 CompositeDecisionBuilder::CompositeDecisionBuilder() {}
475 CompositeDecisionBuilder::CompositeDecisionBuilder(
476 const std::vector<DecisionBuilder*>& dbs) {
477 for (
int i = 0; i < dbs.size(); ++i) {
482 CompositeDecisionBuilder::~CompositeDecisionBuilder() {}
484 void CompositeDecisionBuilder::Add(DecisionBuilder*
const db) {
490 void CompositeDecisionBuilder::AppendMonitors(
491 Solver*
const solver, std::vector<SearchMonitor*>*
const monitors) {
492 for (DecisionBuilder*
const db :
builders_) {
493 db->AppendMonitors(solver, monitors);
497 void CompositeDecisionBuilder::Accept(ModelVisitor*
const visitor)
const {
498 for (DecisionBuilder*
const db :
builders_) {
507 class ComposeDecisionBuilder :
public CompositeDecisionBuilder {
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;
519 ComposeDecisionBuilder::ComposeDecisionBuilder() : start_index_(0) {}
521 ComposeDecisionBuilder::ComposeDecisionBuilder(
522 const std::vector<DecisionBuilder*>& dbs)
523 : CompositeDecisionBuilder(dbs), start_index_(0) {}
525 ComposeDecisionBuilder::~ComposeDecisionBuilder() {}
527 Decision* ComposeDecisionBuilder::Next(Solver*
const s) {
529 for (
int i = start_index_; i < size; ++i) {
532 s->SaveAndSetValue(&start_index_, i);
536 s->SaveAndSetValue(&start_index_, size);
540 std::string ComposeDecisionBuilder::DebugString()
const {
541 return absl::StrFormat(
"ComposeDecisionBuilder(%s)",
546 DecisionBuilder* Solver::Compose(DecisionBuilder*
const db1,
547 DecisionBuilder*
const db2) {
548 ComposeDecisionBuilder* c = RevAlloc(
new ComposeDecisionBuilder());
554 DecisionBuilder* Solver::Compose(DecisionBuilder*
const db1,
555 DecisionBuilder*
const db2,
556 DecisionBuilder*
const db3) {
557 ComposeDecisionBuilder* c = RevAlloc(
new ComposeDecisionBuilder());
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());
576 DecisionBuilder* Solver::Compose(
const std::vector<DecisionBuilder*>& dbs) {
577 if (dbs.size() == 1) {
580 return RevAlloc(
new ComposeDecisionBuilder(dbs));
586 class ClosureDecision :
public Decision {
588 ClosureDecision(Solver::Action apply, Solver::Action refute)
589 : apply_(std::move(apply)), refute_(std::move(refute)) {}
590 ~ClosureDecision()
override {}
592 void Apply(Solver*
const s)
override { apply_(s); }
594 void Refute(Solver*
const s)
override { refute_(s); }
596 std::string DebugString()
const override {
return "ClosureDecision"; }
599 Solver::Action apply_;
600 Solver::Action refute_;
604 Decision* Solver::MakeDecision(Action apply, Action refute) {
605 return RevAlloc(
new ClosureDecision(std::move(apply), std::move(refute)));
612 class TryDecisionBuilder;
614 class TryDecision :
public Decision {
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"; }
623 TryDecisionBuilder*
const try_builder_;
626 class TryDecisionBuilder :
public CompositeDecisionBuilder {
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);
636 TryDecision try_decision_;
637 int current_builder_;
638 bool start_new_builder_;
641 TryDecision::TryDecision(TryDecisionBuilder*
const try_builder)
642 : try_builder_(try_builder) {}
644 TryDecision::~TryDecision() {}
646 void TryDecision::Apply(Solver*
const solver) {}
648 void TryDecision::Refute(Solver*
const solver) {
649 try_builder_->AdvanceToNextBuilder(solver);
652 TryDecisionBuilder::TryDecisionBuilder()
653 : CompositeDecisionBuilder(),
655 current_builder_(-1),
656 start_new_builder_(true) {}
658 TryDecisionBuilder::TryDecisionBuilder(
const std::vector<DecisionBuilder*>& dbs)
659 : CompositeDecisionBuilder(dbs),
661 current_builder_(-1),
662 start_new_builder_(true) {}
664 TryDecisionBuilder::~TryDecisionBuilder() {}
666 Decision* TryDecisionBuilder::Next(Solver*
const solver) {
667 if (current_builder_ < 0) {
668 solver->SaveAndSetValue(¤t_builder_, 0);
669 start_new_builder_ =
true;
671 if (start_new_builder_) {
672 start_new_builder_ =
false;
673 return &try_decision_;
675 return builders_[current_builder_]->Next(solver);
679 std::string TryDecisionBuilder::DebugString()
const {
680 return absl::StrFormat(
"TryDecisionBuilder(%s)",
684 void TryDecisionBuilder::AdvanceToNextBuilder(Solver*
const solver) {
686 start_new_builder_ =
true;
687 if (current_builder_ >=
builders_.size()) {
694 DecisionBuilder* Solver::Try(DecisionBuilder*
const db1,
695 DecisionBuilder*
const db2) {
696 TryDecisionBuilder* try_db = RevAlloc(
new TryDecisionBuilder());
702 DecisionBuilder* Solver::Try(DecisionBuilder*
const db1,
703 DecisionBuilder*
const db2,
704 DecisionBuilder*
const db3) {
705 TryDecisionBuilder* try_db = RevAlloc(
new TryDecisionBuilder());
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());
724 DecisionBuilder* Solver::Try(
const std::vector<DecisionBuilder*>& dbs) {
725 return RevAlloc(
new TryDecisionBuilder(dbs));
733 class BaseVariableAssignmentSelector :
public BaseObject {
735 BaseVariableAssignmentSelector(Solver* solver,
736 const std::vector<IntVar*>& vars)
742 ~BaseVariableAssignmentSelector()
override {}
744 virtual int64 SelectValue(
const IntVar* v,
int64 id) = 0;
747 virtual int64 ChooseVariable() = 0;
749 int64 ChooseVariableWrapper() {
752 if (!
vars_[i]->Bound()) {
761 if (!
vars_[i]->Bound()) {
766 return ChooseVariable();
769 void Accept(ModelVisitor*
const visitor)
const {
770 visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
771 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
773 visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
776 const std::vector<IntVar*>& vars()
const {
return vars_; }
787 int64 ChooseFirstUnbound(Solver* solver,
const std::vector<IntVar*>& vars,
789 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
790 if (!vars[i]->Bound()) {
799 int64 ChooseMinSizeLowestMin(Solver* solver,
const std::vector<IntVar*>& vars,
803 int64 best_index = -1;
804 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
805 IntVar*
const var = vars[i];
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();
820 int64 ChooseMinSizeHighestMin(Solver* solver,
const std::vector<IntVar*>& vars,
824 int64 best_index = -1;
825 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
826 IntVar*
const var = vars[i];
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();
841 int64 ChooseMinSizeLowestMax(Solver* solver,
const std::vector<IntVar*>& vars,
845 int64 best_index = -1;
846 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
847 IntVar*
const var = vars[i];
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();
862 int64 ChooseMinSizeHighestMax(Solver* solver,
const std::vector<IntVar*>& vars,
866 int64 best_index = -1;
867 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
868 IntVar*
const var = vars[i];
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();
883 int64 ChooseLowestMin(Solver* solver,
const std::vector<IntVar*>& vars,
886 int64 best_index = -1;
887 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
888 IntVar*
const var = vars[i];
890 if (
var->Min() < best_min) {
891 best_min =
var->Min();
901 int64 ChooseHighestMax(Solver* solver,
const std::vector<IntVar*>& vars,
904 int64 best_index = -1;
905 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
906 IntVar*
const var = vars[i];
908 if (
var->Max() > best_max) {
909 best_max =
var->Max();
919 int64 ChooseMinSize(Solver* solver,
const std::vector<IntVar*>& vars,
922 int64 best_index = -1;
923 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
924 IntVar*
const var = vars[i];
926 if (
var->Size() < best_size) {
927 best_size =
var->Size();
937 int64 ChooseMaxSize(Solver* solver,
const std::vector<IntVar*>& vars,
940 int64 best_index = -1;
941 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
942 IntVar*
const var = vars[i];
944 if (
var->Size() > best_size) {
945 best_size =
var->Size();
955 class HighestRegretSelectorOnMin :
public BaseObject {
957 explicit HighestRegretSelectorOnMin(
const std::vector<IntVar*>& vars)
959 for (
int64 i = 0; i < vars.size(); ++i) {
960 iterators_[i] = vars[i]->MakeDomainIterator(
true);
963 ~HighestRegretSelectorOnMin()
override {}
964 int64 Choose(Solver*
const s,
const std::vector<IntVar*>& vars,
966 std::string DebugString()
const override {
return "MaxRegretSelector"; }
969 DCHECK(!
var->Bound());
974 return iterator->Value() - vmin;
981 int64 HighestRegretSelectorOnMin::Choose(Solver*
const s,
982 const std::vector<IntVar*>& vars,
984 int64 last_unbound) {
985 int64 best_regret = 0;
987 for (
int64 i = first_unbound; i <= last_unbound; ++i) {
988 IntVar*
const var = vars[i];
990 const int64 regret = ComputeRegret(
var, i);
991 if (regret > best_regret) {
992 best_regret = regret;
1002 int64 ChooseRandom(Solver* solver,
const std::vector<IntVar*>& vars,
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()) {
1017 class CheapestVarSelector :
public BaseObject {
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,
1024 std::string DebugString()
const override {
return "CheapestVarSelector"; }
1030 int64 CheapestVarSelector::Choose(Solver*
const s,
1031 const std::vector<IntVar*>& vars,
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) {
1050 class PathSelector :
public BaseObject {
1053 ~PathSelector()
override {}
1054 int64 Choose(Solver*
const s,
const std::vector<IntVar*>& vars,
1056 std::string DebugString()
const override {
return "ChooseNextOnPath"; }
1059 bool UpdateIndex(
const std::vector<IntVar*>& vars,
int64*
index)
const;
1060 bool FindPathStart(
const std::vector<IntVar*>& vars,
int64*
index)
const;
1065 int64 PathSelector::Choose(Solver*
const s,
const std::vector<IntVar*>& vars,
1068 if (!UpdateIndex(vars, &
index)) {
1072 while (vars[
index]->Bound()) {
1074 if (!UpdateIndex(vars, &
index)) {
1078 if (count >= vars.size() &&
1079 !FindPathStart(vars, &
index)) {
1083 first_.SetValue(s,
index);
1087 bool PathSelector::UpdateIndex(
const std::vector<IntVar*>& vars,
1089 if (*
index >= vars.size()) {
1090 if (!FindPathStart(vars,
index)) {
1103 bool PathSelector::FindPathStart(
const std::vector<IntVar*>& vars,
1106 for (
int64 i = vars.size() - 1; i >= 0; --i) {
1107 if (vars[i]->Bound()) {
1109 if (
next < vars.size() && !vars[
next]->Bound()) {
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;
1125 if (!has_possible_prev) {
1132 for (
int64 i = 0; i < vars.size(); ++i) {
1133 if (!vars[i]->Bound()) {
1143 int64 SelectMinValue(
const IntVar* v,
int64 id) {
return v->Min(); }
1147 int64 SelectMaxValue(
const IntVar* v,
int64 id) {
return v->Max(); }
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) {
1157 const uint64 size = v->Size();
1158 Solver*
const s = v->solver();
1159 if (size > span / 4) {
1162 const int64 value = v->Min() + s->Rand64(span);
1163 if (v->Contains(
value)) {
1169 if (
index <= size / 2) {
1170 for (
int64 i = v->Min(); i <= v->Max(); ++i) {
1171 if (v->Contains(i)) {
1179 for (
int64 i = v->Max(); i > v->Min(); --i) {
1180 if (v->Contains(i)) {
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) {
1201 const int64 mid = (vmin + vmax) / 2;
1202 if (v->Contains(mid)) {
1205 const int64 diameter = vmax - mid;
1206 for (
int64 i = 1; i <= diameter; ++i) {
1207 if (v->Contains(mid - i)) {
1210 if (v->Contains(mid + i)) {
1219 int64 SelectSplitValue(
const IntVar* v,
int64 id) {
1220 const int64 vmin = v->Min();
1221 const int64 vmax = v->Max();
1229 class CheapestValueSelector :
public BaseObject {
1233 : eval_(std::move(eval)), tie_breaker_(std::move(tie_breaker)) {}
1234 ~CheapestValueSelector()
override {}
1236 std::string DebugString()
const override {
return "CheapestValue"; }
1241 std::vector<int64> cache_;
1244 int64 CheapestValueSelector::Select(
const IntVar* v,
int64 id) {
1247 std::unique_ptr<IntVarIterator> it(v->MakeDomainIterator(
false));
1248 for (
const int64 i : InitAndGetValues(it.get())) {
1249 int64 eval = eval_(
id, i);
1253 cache_.push_back(i);
1254 }
else if (eval == best) {
1255 cache_.push_back(i);
1258 DCHECK_GT(cache_.size(), 0);
1259 if (tie_breaker_ ==
nullptr || cache_.size() == 1) {
1260 return cache_.back();
1262 return cache_[tie_breaker_(cache_.size())];
1274 class BestValueByComparisonSelector :
public BaseObject {
1276 explicit BestValueByComparisonSelector(
1277 Solver::VariableValueComparator comparator)
1278 : comparator_(std::move(comparator)) {}
1279 ~BestValueByComparisonSelector()
override {}
1281 std::string DebugString()
const override {
1282 return "BestValueByComparisonSelector";
1286 Solver::VariableValueComparator comparator_;
1289 int64 BestValueByComparisonSelector::Select(
const IntVar* v,
int64 id) {
1290 std::unique_ptr<IntVarIterator> it(v->MakeDomainIterator(
false));
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;
1305 class VariableAssignmentSelector :
public BaseVariableAssignmentSelector {
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)),
1315 ~VariableAssignmentSelector()
override {}
1317 return value_selector_(
var,
id);
1319 int64 ChooseVariable()
override {
1323 std::string DebugString()
const override;
1326 Solver::VariableIndexSelector var_selector_;
1327 Solver::VariableValueSelector value_selector_;
1328 const std::string name_;
1331 std::string VariableAssignmentSelector::DebugString()
const {
1337 class BaseEvaluatorSelector :
public BaseVariableAssignmentSelector {
1339 BaseEvaluatorSelector(Solver* solver,
const std::vector<IntVar*>& vars,
1341 ~BaseEvaluatorSelector()
override {}
1351 std::string DebugStringInternal(
const std::string&
name)
const {
1358 BaseEvaluatorSelector::BaseEvaluatorSelector(
1359 Solver* solver,
const std::vector<IntVar*>& vars,
1361 : BaseVariableAssignmentSelector(solver, vars),
1366 class DynamicEvaluatorSelector :
public BaseEvaluatorSelector {
1368 DynamicEvaluatorSelector(Solver* solver,
const std::vector<IntVar*>& vars,
1371 ~DynamicEvaluatorSelector()
override {}
1373 int64 ChooseVariable()
override;
1374 std::string DebugString()
const override;
1379 std::vector<Element> cache_;
1382 DynamicEvaluatorSelector::DynamicEvaluatorSelector(
1383 Solver* solver,
const std::vector<IntVar*>& vars,
1386 : BaseEvaluatorSelector(solver, vars, std::move(evaluator)),
1388 tie_breaker_(std::move(tie_breaker)) {}
1390 int64 DynamicEvaluatorSelector::SelectValue(
const IntVar*
var,
int64 id) {
1391 return cache_[first_].value;
1394 int64 DynamicEvaluatorSelector::ChooseVariable() {
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())) {
1403 if (
value < best_evaluation) {
1404 best_evaluation =
value;
1406 cache_.push_back(Element(i, j));
1407 }
else if (
value == best_evaluation && tie_breaker_) {
1408 cache_.push_back(Element(i, j));
1414 if (cache_.empty()) {
1418 if (tie_breaker_ ==
nullptr || cache_.size() == 1) {
1420 return cache_.front().var;
1422 first_ = tie_breaker_(cache_.size());
1423 return cache_[first_].var;
1427 std::string DynamicEvaluatorSelector::DebugString()
const {
1428 return DebugStringInternal(
"AssignVariablesOnDynamicEvaluator");
1433 class StaticEvaluatorSelector :
public BaseEvaluatorSelector {
1435 StaticEvaluatorSelector(Solver* solver,
const std::vector<IntVar*>& vars,
1437 ~StaticEvaluatorSelector()
override {}
1439 int64 ChooseVariable()
override;
1440 std::string DebugString()
const override;
1447 bool operator()(
const Element& lhs,
const Element& rhs)
const {
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)));
1456 return evaluator_(element.var, element.value);
1464 std::vector<Element> elements_;
1468 StaticEvaluatorSelector::StaticEvaluatorSelector(
1469 Solver* solver,
const std::vector<IntVar*>& vars,
1471 : BaseEvaluatorSelector(solver, vars, evaluator),
1475 int64 StaticEvaluatorSelector::SelectValue(
const IntVar*
var,
int64 id) {
1476 return elements_[first_].value;
1479 int64 StaticEvaluatorSelector::ChooseVariable() {
1482 int64 element_size = 0;
1484 if (!
vars_[i]->Bound()) {
1485 element_size +=
vars_[i]->Size();
1488 elements_.resize(element_size);
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);
1500 std::sort(elements_.begin(), elements_.end(), comp_);
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);
1511 solver_->SaveAndSetValue(&first_,
static_cast<int64>(elements_.size()));
1515 std::string StaticEvaluatorSelector::DebugString()
const {
1516 return DebugStringInternal(
"AssignVariablesOnStaticEvaluator");
1521 class AssignOneVariableValue :
public Decision {
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_);
1537 AssignOneVariableValue::AssignOneVariableValue(IntVar*
const v,
int64 val)
1538 : var_(v), value_(val) {}
1540 std::string AssignOneVariableValue::DebugString()
const {
1541 return absl::StrFormat(
"[%s == %d] or [%s != %d]", var_->DebugString(),
1542 value_, var_->DebugString(), value_);
1545 void AssignOneVariableValue::Apply(Solver*
const s) { var_->SetValue(value_); }
1547 void AssignOneVariableValue::Refute(Solver*
const s) {
1548 var_->RemoveValue(value_);
1552 Decision* Solver::MakeAssignVariableValue(IntVar*
const var,
int64 val) {
1553 return RevAlloc(
new AssignOneVariableValue(
var, val));
1559 class AssignOneVariableValueOrFail :
public Decision {
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_);
1575 AssignOneVariableValueOrFail::AssignOneVariableValueOrFail(IntVar*
const v,
1577 : var_(v), value_(
value) {}
1579 std::string AssignOneVariableValueOrFail::DebugString()
const {
1580 return absl::StrFormat(
"[%s == %d] or fail", var_->DebugString(), value_);
1583 void AssignOneVariableValueOrFail::Apply(Solver*
const s) {
1584 var_->SetValue(value_);
1587 void AssignOneVariableValueOrFail::Refute(Solver*
const s) { s->Fail(); }
1590 Decision* Solver::MakeAssignVariableValueOrFail(IntVar*
const var,
1592 return RevAlloc(
new AssignOneVariableValueOrFail(
var,
value));
1598 class AssignOneVariableValueDoNothing :
public Decision {
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_);
1608 void Accept(DecisionVisitor*
const visitor)
const override {
1609 visitor->VisitSetVariableValue(var_, value_);
1619 Decision* Solver::MakeAssignVariableValueOrDoNothing(IntVar*
const var,
1621 return RevAlloc(
new AssignOneVariableValueDoNothing(
var,
value));
1627 class SplitOneVariable :
public Decision {
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_);
1641 const bool start_with_lower_half_;
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) {}
1648 std::string SplitOneVariable::DebugString()
const {
1649 if (start_with_lower_half_) {
1650 return absl::StrFormat(
"[%s <= %d]", var_->DebugString(), value_);
1652 return absl::StrFormat(
"[%s >= %d]", var_->DebugString(), value_);
1656 void SplitOneVariable::Apply(Solver*
const s) {
1657 if (start_with_lower_half_) {
1658 var_->SetMax(value_);
1660 var_->SetMin(value_ + 1);
1664 void SplitOneVariable::Refute(Solver*
const s) {
1665 if (start_with_lower_half_) {
1666 var_->SetMin(value_ + 1);
1668 var_->SetMax(value_);
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));
1678 Decision* Solver::MakeVariableLessOrEqualValue(IntVar*
const var,
int64 value) {
1679 return MakeSplitVariableDomain(
var,
value,
true);
1682 Decision* Solver::MakeVariableGreaterOrEqualValue(IntVar*
const var,
1684 return MakeSplitVariableDomain(
var,
value,
false);
1690 class AssignVariablesValues :
public Decision {
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]);
1704 virtual void Accept(ModelVisitor*
const visitor)
const {
1705 visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
1706 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
1708 visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
1712 const std::vector<IntVar*>
vars_;
1713 const std::vector<int64> values_;
1716 AssignVariablesValues::AssignVariablesValues(
const std::vector<IntVar*>& vars,
1717 const std::vector<int64>& values)
1718 :
vars_(vars), values_(values) {}
1720 std::string AssignVariablesValues::DebugString()
const {
1722 for (
int i = 0; i <
vars_.size(); ++i) {
1723 absl::StrAppendFormat(&out,
"[%s == %d]",
vars_[i]->DebugString(),
1729 void AssignVariablesValues::Apply(Solver*
const s) {
1730 for (
int i = 0; i <
vars_.size(); ++i) {
1731 vars_[i]->SetValue(values_[i]);
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);
1742 s->AddConstraint(s->MakeSumGreaterOrEqual(terms, 1));
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));
1755 class BaseAssignVariables :
public DecisionBuilder {
1763 BaseAssignVariables(BaseVariableAssignmentSelector*
const selector, Mode mode)
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);
1775 static Solver::VariableIndexSelector MakeVariableSelector(
1776 Solver*
const s,
const std::vector<IntVar*>& vars,
1777 Solver::IntVarStrategy 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);
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);
1817 LOG(FATAL) <<
"Unknown int var strategy " << str;
1822 static Solver::VariableValueSelector MakeValueSelector(
1823 Solver*
const s, Solver::IntValueStrategy 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;
1840 LOG(FATAL) <<
"Unknown int value strategy " << val_str;
1845 void Accept(ModelVisitor*
const visitor)
const override {
1854 BaseAssignVariables::~BaseAssignVariables() {}
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];
1864 return s->RevAlloc(
new AssignOneVariableValue(
var,
value));
1866 return s->RevAlloc(
new SplitOneVariable(
var,
value,
true));
1868 return s->RevAlloc(
new SplitOneVariable(
var,
value,
false));
1874 std::string BaseAssignVariables::DebugString()
const {
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));
1890 std::string ChooseVariableName(Solver::IntVarStrategy 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";
1919 LOG(FATAL) <<
"Unknown int var strategy " << var_str;
1924 std::string SelectValueName(Solver::IntValueStrategy 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";
1941 LOG(FATAL) <<
"Unknown int value strategy " << val_str;
1946 std::string BuildHeuristicsName(Solver::IntVarStrategy var_str,
1947 Solver::IntValueStrategy val_str) {
1948 return ChooseVariableName(var_str) +
"_" + SelectValueName(val_str);
1952 DecisionBuilder* Solver::MakePhase(IntVar*
const v0,
1953 Solver::IntVarStrategy var_str,
1954 Solver::IntValueStrategy val_str) {
1955 std::vector<IntVar*> vars(1);
1957 return MakePhase(vars, var_str, val_str);
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);
1966 return MakePhase(vars, var_str, val_str);
1969 DecisionBuilder* Solver::MakePhase(IntVar*
const v0, IntVar*
const v1,
1971 Solver::IntVarStrategy var_str,
1972 Solver::IntValueStrategy val_str) {
1973 std::vector<IntVar*> vars(3);
1977 return MakePhase(vars, var_str, val_str);
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);
1989 return MakePhase(vars, var_str, val_str);
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;
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));
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);
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));
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);
2043 const std::string
name = ChooseVariableName(var_str) +
"_SelectCheapestValue";
2044 return BaseAssignVariables::MakePhase(
this, vars, choose_variable,
2046 BaseAssignVariables::ASSIGN);
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);
2060 return BaseAssignVariables::MakePhase(
this, vars, choose_variable,
2061 select_value,
"CheapestValue",
2062 BaseAssignVariables::ASSIGN);
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);
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);
2081 return BaseAssignVariables::MakePhase(
this, vars, choose_variable,
2082 select_value,
"CheapestValue",
2083 BaseAssignVariables::ASSIGN);
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);
2098 return BaseAssignVariables::MakePhase(
this, vars, choose_variable,
2099 select_value,
"CheapestValue",
2100 BaseAssignVariables::ASSIGN);
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);
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);
2120 return BaseAssignVariables::MakePhase(
this, vars, choose_variable,
2121 select_value,
"CheapestValue",
2122 BaseAssignVariables::ASSIGN);
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);
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;
2137 case Solver::CHOOSE_STATIC_GLOBAL_BEST: {
2139 selector = RevAlloc(
new StaticEvaluatorSelector(
this, vars, eval));
2142 case Solver::CHOOSE_DYNAMIC_GLOBAL_BEST: {
2143 selector = RevAlloc(
new DynamicEvaluatorSelector(
this, vars, eval,
2144 std::move(tie_breaker)));
2149 new BaseAssignVariables(selector, BaseAssignVariables::ASSIGN));
2155 class AssignVariablesFromAssignment :
public DecisionBuilder {
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) {}
2162 ~AssignVariablesFromAssignment()
override {}
2164 Decision* Next(Solver*
const s)
override {
2165 if (iter_ <
vars_.size()) {
2166 IntVar*
const var =
vars_[iter_++];
2168 new AssignOneVariableValue(
var, assignment_->Value(
var)));
2170 return db_->Next(s);
2174 void Accept(ModelVisitor*
const visitor)
const override {
2175 visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
2176 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
2178 visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
2182 const Assignment*
const assignment_;
2183 DecisionBuilder*
const db_;
2184 const std::vector<IntVar*>
vars_;
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));
2199 SolutionCollector::SolutionCollector(Solver*
const solver,
2200 const Assignment*
const assignment)
2201 : SearchMonitor(solver),
2202 prototype_(assignment == nullptr ? nullptr : new Assignment(assignment)) {
2205 SolutionCollector::SolutionCollector(Solver*
const solver)
2206 : SearchMonitor(solver), prototype_(new Assignment(solver)) {}
2208 SolutionCollector::~SolutionCollector() {
2209 for (
auto& data : solution_data_) {
2210 delete data.solution;
2215 void SolutionCollector::Add(IntVar*
const var) {
2216 if (prototype_ !=
nullptr) {
2217 prototype_->Add(
var);
2221 void SolutionCollector::Add(
const std::vector<IntVar*>& vars) {
2222 if (prototype_ !=
nullptr) {
2223 prototype_->Add(vars);
2227 void SolutionCollector::Add(IntervalVar*
const var) {
2228 if (prototype_ !=
nullptr) {
2229 prototype_->Add(
var);
2233 void SolutionCollector::Add(
const std::vector<IntervalVar*>& vars) {
2234 if (prototype_ !=
nullptr) {
2235 prototype_->Add(vars);
2239 void SolutionCollector::Add(SequenceVar*
const var) {
2240 if (prototype_ !=
nullptr) {
2241 prototype_->Add(
var);
2245 void SolutionCollector::Add(
const std::vector<SequenceVar*>& vars) {
2246 if (prototype_ !=
nullptr) {
2247 prototype_->Add(vars);
2251 void SolutionCollector::AddObjective(IntVar*
const objective) {
2252 if (prototype_ !=
nullptr && objective !=
nullptr) {
2253 prototype_->AddObjective(objective);
2257 void SolutionCollector::EnterSearch() {
2258 for (
auto& data : solution_data_) {
2259 delete data.solution;
2262 solution_data_.clear();
2263 recycle_solutions_.clear();
2266 void SolutionCollector::PushSolution() {
2267 Push(BuildSolutionDataForCurrentState());
2270 void SolutionCollector::PopSolution() {
2271 if (!solution_data_.empty()) {
2272 FreeSolution(solution_data_.back().solution);
2273 solution_data_.pop_back();
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();
2286 solution =
new Assignment(prototype_.get());
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();
2298 data.objective_value = 0;
2303 void SolutionCollector::FreeSolution(Assignment* solution) {
2304 if (solution !=
nullptr) {
2305 recycle_solutions_.push_back(solution);
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";
2314 Assignment* SolutionCollector::solution(
int n)
const {
2316 return solution_data_[n].solution;
2319 int SolutionCollector::solution_count()
const {
return solution_data_.size(); }
2321 int64 SolutionCollector::wall_time(
int n)
const {
2323 return solution_data_[n].time;
2326 int64 SolutionCollector::branches(
int n)
const {
2328 return solution_data_[n].branches;
2331 int64 SolutionCollector::failures(
int n)
const {
2333 return solution_data_[n].failures;
2336 int64 SolutionCollector::objective_value(
int n)
const {
2338 return solution_data_[n].objective_value;
2342 return solution(n)->Value(
var);
2345 int64 SolutionCollector::StartValue(
int n, IntervalVar*
const var)
const {
2346 return solution(n)->StartValue(
var);
2349 int64 SolutionCollector::DurationValue(
int n, IntervalVar*
const var)
const {
2350 return solution(n)->DurationValue(
var);
2353 int64 SolutionCollector::EndValue(
int n, IntervalVar*
const var)
const {
2354 return solution(n)->EndValue(
var);
2357 int64 SolutionCollector::PerformedValue(
int n, IntervalVar*
const var)
const {
2358 return solution(n)->PerformedValue(
var);
2361 const std::vector<int>& SolutionCollector::ForwardSequence(
2362 int n, SequenceVar*
const var)
const {
2363 return solution(n)->ForwardSequence(
var);
2366 const std::vector<int>& SolutionCollector::BackwardSequence(
2367 int n, SequenceVar*
const var)
const {
2368 return solution(n)->BackwardSequence(
var);
2371 const std::vector<int>& SolutionCollector::Unperformed(
2372 int n, SequenceVar*
const var)
const {
2373 return solution(n)->Unperformed(
var);
2380 class FirstSolutionCollector :
public SolutionCollector {
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;
2393 FirstSolutionCollector::FirstSolutionCollector(Solver*
const s,
2394 const Assignment*
const a)
2395 : SolutionCollector(s,
a), done_(false) {}
2397 FirstSolutionCollector::FirstSolutionCollector(Solver*
const s)
2398 : SolutionCollector(s), done_(false) {}
2400 FirstSolutionCollector::~FirstSolutionCollector() {}
2402 void FirstSolutionCollector::EnterSearch() {
2403 SolutionCollector::EnterSearch();
2407 bool FirstSolutionCollector::AtSolution() {
2415 std::string FirstSolutionCollector::DebugString()
const {
2416 if (prototype_ ==
nullptr) {
2417 return "FirstSolutionCollector()";
2419 return "FirstSolutionCollector(" + prototype_->DebugString() +
")";
2424 SolutionCollector* Solver::MakeFirstSolutionCollector(
2425 const Assignment*
const assignment) {
2426 return RevAlloc(
new FirstSolutionCollector(
this, assignment));
2429 SolutionCollector* Solver::MakeFirstSolutionCollector() {
2430 return RevAlloc(
new FirstSolutionCollector(
this));
2437 class LastSolutionCollector :
public SolutionCollector {
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;
2446 LastSolutionCollector::LastSolutionCollector(Solver*
const s,
2447 const Assignment*
const a)
2448 : SolutionCollector(s,
a) {}
2450 LastSolutionCollector::LastSolutionCollector(Solver*
const s)
2451 : SolutionCollector(s) {}
2453 LastSolutionCollector::~LastSolutionCollector() {}
2455 bool LastSolutionCollector::AtSolution() {
2461 std::string LastSolutionCollector::DebugString()
const {
2462 if (prototype_ ==
nullptr) {
2463 return "LastSolutionCollector()";
2465 return "LastSolutionCollector(" + prototype_->DebugString() +
")";
2470 SolutionCollector* Solver::MakeLastSolutionCollector(
2471 const Assignment*
const assignment) {
2472 return RevAlloc(
new LastSolutionCollector(
this, assignment));
2475 SolutionCollector* Solver::MakeLastSolutionCollector() {
2476 return RevAlloc(
new LastSolutionCollector(
this));
2482 class BestValueSolutionCollector :
public SolutionCollector {
2484 BestValueSolutionCollector(Solver*
const s,
const Assignment*
const a,
2486 BestValueSolutionCollector(Solver*
const s,
bool maximize);
2487 ~BestValueSolutionCollector()
override {}
2488 void EnterSearch()
override;
2489 bool AtSolution()
override;
2490 std::string DebugString()
const override;
2497 BestValueSolutionCollector::BestValueSolutionCollector(
2498 Solver*
const s,
const Assignment*
const a,
bool maximize)
2499 : SolutionCollector(s,
a),
2503 BestValueSolutionCollector::BestValueSolutionCollector(Solver*
const s,
2505 : SolutionCollector(s),
2509 void BestValueSolutionCollector::EnterSearch() {
2510 SolutionCollector::EnterSearch();
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_)) {
2521 best_ = objective->Max();
2523 (solution_count() == 0 || objective->Min() <
best_)) {
2526 best_ = objective->Min();
2533 std::string BestValueSolutionCollector::DebugString()
const {
2534 if (prototype_ ==
nullptr) {
2535 return "BestValueSolutionCollector()";
2537 return "BestValueSolutionCollector(" + prototype_->DebugString() +
")";
2542 SolutionCollector* Solver::MakeBestValueSolutionCollector(
2543 const Assignment*
const assignment,
bool maximize) {
2544 return RevAlloc(
new BestValueSolutionCollector(
this, assignment, maximize));
2547 SolutionCollector* Solver::MakeBestValueSolutionCollector(
bool maximize) {
2548 return RevAlloc(
new BestValueSolutionCollector(
this, maximize));
2554 class NBestValueSolutionCollector :
public SolutionCollector {
2556 NBestValueSolutionCollector(Solver*
const solver,
2557 const Assignment*
const assignment,
2558 int solution_count,
bool maximize);
2559 NBestValueSolutionCollector(Solver*
const solver,
int solution_count,
2561 ~NBestValueSolutionCollector()
override { Clear(); }
2562 void EnterSearch()
override;
2563 void ExitSearch()
override;
2564 bool AtSolution()
override;
2565 std::string DebugString()
const override;
2575 NBestValueSolutionCollector::NBestValueSolutionCollector(
2576 Solver*
const solver,
const Assignment*
const assignment,
2577 int solution_count,
bool maximize)
2578 : SolutionCollector(solver, assignment),
2582 NBestValueSolutionCollector::NBestValueSolutionCollector(Solver*
const solver,
2585 : SolutionCollector(solver),
2589 void NBestValueSolutionCollector::EnterSearch() {
2590 SolutionCollector::EnterSearch();
2594 solver()->SetUseFastLocalSearch(
false);
2599 void NBestValueSolutionCollector::ExitSearch() {
2606 bool NBestValueSolutionCollector::AtSolution() {
2607 if (prototype_ !=
nullptr) {
2608 const IntVar* objective = prototype_->Objective();
2609 if (objective !=
nullptr) {
2610 const int64 objective_value =
2614 {objective_value, BuildSolutionDataForCurrentState()});
2617 if (top.first > objective_value) {
2621 {objective_value, BuildSolutionDataForCurrentState()});
2629 std::string NBestValueSolutionCollector::DebugString()
const {
2630 if (prototype_ ==
nullptr) {
2631 return "NBestValueSolutionCollector()";
2633 return "NBestValueSolutionCollector(" + prototype_->DebugString() +
")";
2637 void NBestValueSolutionCollector::Clear() {
2646 SolutionCollector* Solver::MakeNBestValueSolutionCollector(
2647 const Assignment*
const assignment,
int solution_count,
bool maximize) {
2648 if (solution_count == 1) {
2649 return MakeBestValueSolutionCollector(assignment, maximize);
2651 return RevAlloc(
new NBestValueSolutionCollector(
this, assignment,
2652 solution_count, maximize));
2655 SolutionCollector* Solver::MakeNBestValueSolutionCollector(
int solution_count,
2657 if (solution_count == 1) {
2658 return MakeBestValueSolutionCollector(maximize);
2661 new NBestValueSolutionCollector(
this, solution_count, maximize));
2668 class AllSolutionCollector :
public SolutionCollector {
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;
2677 AllSolutionCollector::AllSolutionCollector(Solver*
const s,
2678 const Assignment*
const a)
2679 : SolutionCollector(s,
a) {}
2681 AllSolutionCollector::AllSolutionCollector(Solver*
const s)
2682 : SolutionCollector(s) {}
2684 AllSolutionCollector::~AllSolutionCollector() {}
2686 bool AllSolutionCollector::AtSolution() {
2691 std::string AllSolutionCollector::DebugString()
const {
2692 if (prototype_ ==
nullptr) {
2693 return "AllSolutionCollector()";
2695 return "AllSolutionCollector(" + prototype_->DebugString() +
")";
2700 SolutionCollector* Solver::MakeAllSolutionCollector(
2701 const Assignment*
const assignment) {
2702 return RevAlloc(
new AllSolutionCollector(
this, assignment));
2705 SolutionCollector* Solver::MakeAllSolutionCollector() {
2706 return RevAlloc(
new AllSolutionCollector(
this));
2711 OptimizeVar::OptimizeVar(Solver*
const s,
bool maximize, IntVar*
const a,
2718 found_initial_solution_(false) {
2724 s->set_optimization_direction(Solver::MAXIMIZATION);
2726 s->set_optimization_direction(Solver::MINIMIZATION);
2730 OptimizeVar::~OptimizeVar() {}
2732 void OptimizeVar::EnterSearch() {
2733 found_initial_solution_ =
false;
2741 void OptimizeVar::BeginNextDecision(DecisionBuilder*
const db) {
2742 if (solver()->SearchDepth() == 0) {
2747 void OptimizeVar::ApplyBound() {
2748 if (found_initial_solution_) {
2757 void OptimizeVar::RefuteDecision(Decision*
const d) { ApplyBound(); }
2759 bool OptimizeVar::AcceptSolution() {
2760 const int64 val = var_->Value();
2761 if (!found_initial_solution_) {
2771 bool OptimizeVar::AtSolution() {
2772 int64 val = var_->Value();
2774 CHECK(!found_initial_solution_ || val >
best_);
2777 CHECK(!found_initial_solution_ || val <
best_);
2780 found_initial_solution_ =
true;
2785 if (
delta !=
nullptr) {
2786 const bool delta_has_objective =
delta->HasObjective();
2787 if (!delta_has_objective) {
2788 delta->AddObjective(var_);
2790 if (
delta->Objective() == var_) {
2791 const Assignment*
const local_search_state =
2792 solver()->GetOrCreateLocalSearchState();
2794 const int64 delta_min_objective =
2796 const int64 min_objective =
2797 local_search_state->HasObjective()
2798 ?
CapAdd(local_search_state->ObjectiveMin(),
step_)
2800 delta->SetObjectiveMin(
2801 std::max({var_->Min(), min_objective, delta_min_objective}));
2804 const int64 delta_max_objective =
2806 const int64 max_objective =
2807 local_search_state->HasObjective()
2808 ?
CapSub(local_search_state->ObjectiveMax(),
step_)
2810 delta->SetObjectiveMax(
2811 std::min({var_->Max(), max_objective, delta_max_objective}));
2818 std::string OptimizeVar::Print()
const {
2819 return absl::StrFormat(
"objective value = %d, ", var_->Value());
2822 std::string OptimizeVar::DebugString()
const {
2825 out =
"MaximizeVar(";
2827 out =
"MinimizeVar(";
2829 absl::StrAppendFormat(&out,
"%s, step = %d, best = %d)", var_->DebugString(),
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,
2840 visitor->EndVisitExtension(ModelVisitor::kObjectiveExtension);
2843 OptimizeVar* Solver::MakeMinimize(IntVar*
const v,
int64 step) {
2844 return RevAlloc(
new OptimizeVar(
this,
false, v, step));
2847 OptimizeVar* Solver::MakeMaximize(IntVar*
const v,
int64 step) {
2848 return RevAlloc(
new OptimizeVar(
this,
true, v, step));
2851 OptimizeVar* Solver::MakeOptimize(
bool maximize, IntVar*
const v,
int64 step) {
2852 return RevAlloc(
new OptimizeVar(
this, maximize, v, step));
2856 class WeightedOptimizeVar :
public OptimizeVar {
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),
2865 CHECK_EQ(sub_objectives.size(), weights.size());
2868 ~WeightedOptimizeVar()
override {}
2869 std::string Print()
const override;
2872 const std::vector<IntVar*> sub_objectives_;
2873 const std::vector<int64> weights_;
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]);
2890 OptimizeVar* Solver::MakeWeightedOptimize(
2891 bool maximize,
const std::vector<IntVar*>& sub_objectives,
2892 const std::vector<int64>& weights,
int64 step) {
2894 new WeightedOptimizeVar(
this, maximize, sub_objectives, weights, step));
2897 OptimizeVar* Solver::MakeWeightedMinimize(
2898 const std::vector<IntVar*>& sub_objectives,
2899 const std::vector<int64>& weights,
int64 step) {
2901 new WeightedOptimizeVar(
this,
false, sub_objectives, weights, step));
2904 OptimizeVar* Solver::MakeWeightedMaximize(
2905 const std::vector<IntVar*>& sub_objectives,
2906 const std::vector<int64>& weights,
int64 step) {
2908 new WeightedOptimizeVar(
this,
true, sub_objectives, weights, step));
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),
2918 OptimizeVar* Solver::MakeWeightedMinimize(
2919 const std::vector<IntVar*>& sub_objectives,
const std::vector<int>& weights,
2921 return MakeWeightedMinimize(sub_objectives,
ToInt64Vector(weights), step);
2924 OptimizeVar* Solver::MakeWeightedMaximize(
2925 const std::vector<IntVar*>& sub_objectives,
const std::vector<int>& weights,
2927 return MakeWeightedMaximize(sub_objectives,
ToInt64Vector(weights), step);
2933 class Metaheuristic :
public SearchMonitor {
2935 Metaheuristic(Solver*
const solver,
bool maximize, IntVar* objective,
2937 ~Metaheuristic()
override {}
2939 bool AtSolution()
override;
2940 void EnterSearch()
override;
2941 void RefuteDecision(Decision*
const d)
override;
2952 Metaheuristic::Metaheuristic(Solver*
const solver,
bool maximize,
2953 IntVar* objective,
int64 step)
2954 : SearchMonitor(solver),
2961 bool Metaheuristic::AtSolution() {
2971 void Metaheuristic::EnterSearch() {
2974 solver()->SetUseFastLocalSearch(
false);
2984 void Metaheuristic::RefuteDecision(Decision* d) {
2995 if (
delta !=
nullptr) {
2996 if (!
delta->HasObjective()) {
3001 delta->SetObjectiveMin(
3004 delta->SetObjectiveMax(
3014 class TabuSearch :
public Metaheuristic {
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;
3025 std::string DebugString()
const override {
return "Tabu Search"; }
3035 typedef std::list<VarValue> TabuList;
3037 virtual std::vector<IntVar*> CreateTabuVars();
3038 const TabuList& forbid_tabu_list() {
return forbid_tabu_list_; }
3041 void AgeList(
int64 tenure, TabuList* list);
3044 const std::vector<IntVar*>
vars_;
3045 Assignment assignment_;
3047 TabuList keep_tabu_list_;
3049 TabuList forbid_tabu_list_;
3050 int64 forbid_tenure_;
3051 double tabu_factor_;
3053 bool found_initial_solution_;
3058 TabuSearch::TabuSearch(Solver*
const s,
bool maximize, IntVar* objective,
3059 int64 step,
const std::vector<IntVar*>& vars,
3062 : Metaheuristic(s, maximize, objective, step),
3066 keep_tenure_(keep_tenure),
3067 forbid_tenure_(forbid_tenure),
3068 tabu_factor_(tabu_factor),
3070 found_initial_solution_(false) {
3071 assignment_.Add(
vars_);
3074 void TabuSearch::EnterSearch() {
3075 Metaheuristic::EnterSearch();
3076 found_initial_solution_ =
false;
3079 void TabuSearch::ApplyDecision(Decision*
const d) {
3080 Solver*
const s = solver();
3081 if (d == s->balancing_decision()) {
3086 IntVar* aspiration = s->MakeBoolVar();
3088 s->AddConstraint(s->MakeIsGreaterOrEqualCstCt(
3095 IntVar* tabu_var =
nullptr;
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_);
3106 if (tabu_var !=
nullptr) {
3108 s->MakeGreaterOrEqual(s->MakeSum(aspiration, tabu_var),
int64{1}));
3121 if (found_initial_solution_) {
3122 s->AddConstraint(s->MakeNonEquality(
objective_, last_));
3126 std::vector<IntVar*> TabuSearch::CreateTabuVars() {
3127 Solver*
const s = solver();
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_));
3139 for (
const VarValue& vv : forbid_tabu_list_) {
3140 tabu_vars.push_back(s->MakeIsDifferentCstVar(vv.var_, vv.value_));
3145 bool TabuSearch::AtSolution() {
3146 if (!Metaheuristic::AtSolution()) {
3149 found_initial_solution_ =
true;
3155 for (
int i = 0; i <
vars_.size(); ++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);
3164 if (forbid_tenure_ > 0) {
3165 VarValue forbid_value(
var, old_value,
stamp_);
3166 forbid_tabu_list_.push_front(forbid_value);
3171 assignment_.Store();
3176 bool TabuSearch::LocalOptimum() {
3183 return found_initial_solution_;
3192 void TabuSearch::AgeList(
int64 tenure, TabuList* list) {
3193 while (!list->empty() && list->back().stamp_ <
stamp_ - tenure) {
3198 void TabuSearch::AgeLists() {
3199 AgeList(keep_tenure_, &keep_tabu_list_);
3200 AgeList(forbid_tenure_, &forbid_tabu_list_);
3204 class GenericTabuSearch :
public TabuSearch {
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"; }
3213 std::vector<IntVar*> CreateTabuVars()
override;
3216 std::vector<IntVar*> GenericTabuSearch::CreateTabuVars() {
3217 Solver*
const s = solver();
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_));
3225 std::vector<IntVar*> tabu_vars;
3226 if (!forbid_values.empty()) {
3227 tabu_vars.push_back(s->MakeIsGreaterCstVar(s->MakeSum(forbid_values), 0));
3234 SearchMonitor* Solver::MakeTabuSearch(
bool maximize, IntVar*
const v,
3236 const std::vector<IntVar*>& vars,
3238 double tabu_factor) {
3239 return RevAlloc(
new TabuSearch(
this, maximize, v, step, vars, keep_tenure,
3240 forbid_tenure, tabu_factor));
3243 SearchMonitor* Solver::MakeGenericTabuSearch(
3244 bool maximize, IntVar*
const v,
int64 step,
3245 const std::vector<IntVar*>& tabu_vars,
int64 forbid_tenure) {
3247 new GenericTabuSearch(
this, maximize, v, step, tabu_vars, forbid_tenure));
3253 class SimulatedAnnealing :
public Metaheuristic {
3255 SimulatedAnnealing(Solver*
const s,
bool maximize, IntVar* objective,
3257 ~SimulatedAnnealing()
override {}
3258 void EnterSearch()
override;
3259 void ApplyDecision(Decision* d)
override;
3260 bool AtSolution()
override;
3261 bool LocalOptimum()
override;
3263 std::string DebugString()
const override {
return "Simulated Annealing"; }
3266 double Temperature()
const;
3268 const int64 temperature0_;
3271 bool found_initial_solution_;
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),
3282 rand_(CpRandomSeed()),
3283 found_initial_solution_(false) {}
3285 void SimulatedAnnealing::EnterSearch() {
3286 Metaheuristic::EnterSearch();
3287 found_initial_solution_ =
false;
3290 void SimulatedAnnealing::ApplyDecision(Decision*
const d) {
3291 Solver*
const s = solver();
3292 if (d == s->balancing_decision()) {
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);
3299 const double rand_log2_double = log2(rand_double);
3301 const int64 energy_bound = Temperature() * rand_log2_double;
3313 bool SimulatedAnnealing::AtSolution() {
3314 if (!Metaheuristic::AtSolution()) {
3317 found_initial_solution_ =
true;
3321 bool SimulatedAnnealing::LocalOptimum() {
3328 return found_initial_solution_ && Temperature() > 0;
3332 if (iteration_ > 0) {
3337 double SimulatedAnnealing::Temperature()
const {
3338 if (iteration_ > 0) {
3339 return (1.0 * temperature0_) / iteration_;
3346 SearchMonitor* Solver::MakeSimulatedAnnealing(
bool maximize, IntVar*
const v,
3348 int64 initial_temperature) {
3350 new SimulatedAnnealing(
this, maximize, v, step, initial_temperature));
3355 typedef std::pair<int64, int64>
Arc;
3360 class GuidedLocalSearchPenalties {
3362 virtual ~GuidedLocalSearchPenalties() {}
3363 virtual bool HasValues()
const = 0;
3364 virtual void Increment(
const Arc& arc) = 0;
3366 virtual void Reset() = 0;
3370 class GuidedLocalSearchPenaltiesTable :
public GuidedLocalSearchPenalties {
3372 explicit GuidedLocalSearchPenaltiesTable(
int size);
3373 ~GuidedLocalSearchPenaltiesTable()
override {}
3374 bool HasValues()
const override {
return has_values_; }
3375 void Increment(
const Arc& arc)
override;
3377 void Reset()
override;
3380 std::vector<std::vector<int64>> penalties_;
3384 GuidedLocalSearchPenaltiesTable::GuidedLocalSearchPenaltiesTable(
int size)
3385 : penalties_(size), has_values_(
false) {}
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);
3393 ++first_penalties[second];
3397 void GuidedLocalSearchPenaltiesTable::Reset() {
3398 has_values_ =
false;
3399 for (
int i = 0; i < penalties_.size(); ++i) {
3400 penalties_[i].clear();
3405 const std::vector<int64>& first_penalties = penalties_[arc.first];
3406 const int64 second = arc.second;
3407 if (second >= first_penalties.size()) {
3410 return first_penalties[second];
3415 class GuidedLocalSearchPenaltiesMap :
public GuidedLocalSearchPenalties {
3417 explicit GuidedLocalSearchPenaltiesMap(
int size);
3418 ~GuidedLocalSearchPenaltiesMap()
override {}
3419 bool HasValues()
const override {
return (!penalties_.empty()); }
3420 void Increment(
const Arc& arc)
override;
3422 void Reset()
override;
3426 absl::flat_hash_map<Arc, int64> penalties_;
3429 GuidedLocalSearchPenaltiesMap::GuidedLocalSearchPenaltiesMap(
int size)
3430 : penalized_(size,
false) {}
3432 void GuidedLocalSearchPenaltiesMap::Increment(
const Arc& arc) {
3434 penalized_.Set(arc.first,
true);
3437 void GuidedLocalSearchPenaltiesMap::Reset() {
3443 if (penalized_.Get(arc.first)) {
3449 class GuidedLocalSearch :
public Metaheuristic {
3451 GuidedLocalSearch(Solver*
const s, IntVar* objective,
bool maximize,
3452 int64 step,
const std::vector<IntVar*>& vars,
3453 double penalty_factor);
3454 ~GuidedLocalSearch()
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,
3462 virtual int64 AssignmentPenalty(
const Assignment& assignment,
int index,
3464 virtual bool EvaluateElementValue(
const Assignment::IntContainer& container,
3466 int64* penalty) = 0;
3467 virtual IntExpr* MakeElementPenalty(
int index) = 0;
3468 std::string DebugString()
const override {
return "Guided Local Search"; }
3472 bool operator()(
const std::pair<Arc, double>& i,
3473 const std::pair<Arc, double>& j) {
3474 return i.second > j.second;
3479 const int64*
const out_values,
bool cache_delta_values);
3482 Assignment assignment_;
3485 const std::vector<IntVar*>
vars_;
3488 std::unique_ptr<GuidedLocalSearchPenalties> penalties_;
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),
3506 if (!vars.empty()) {
3508 assignment_.Add(
vars_);
3514 for (
int i = 0; i <
vars_.size(); ++i) {
3517 if (FLAGS_cp_use_sparse_gls_penalties) {
3518 penalties_ = absl::make_unique<GuidedLocalSearchPenaltiesMap>(
vars_.size());
3521 absl::make_unique<GuidedLocalSearchPenaltiesTable>(
vars_.size());
3532 void GuidedLocalSearch::ApplyDecision(Decision*
const d) {
3533 if (d == solver()->balancing_decision()) {
3537 if (penalties_->HasValues()) {
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);
3555 IntExpr* min_pen_exp =
3557 IntVar* min_exp = solver()->MakeMin(min_pen_exp,
best_ +
step_)->Var();
3558 solver()->AddConstraint(
3559 solver()->MakeGreaterOrEqual(
objective_, min_exp));
3561 IntExpr* max_pen_exp =
3563 IntVar* max_exp = solver()->MakeMax(max_pen_exp,
best_ -
step_)->Var();
3564 solver()->AddConstraint(solver()->MakeLessOrEqual(
objective_, max_exp));
3578 bool GuidedLocalSearch::AtSolution() {
3579 if (!Metaheuristic::AtSolution()) {
3585 assignment_.Store();
3589 void GuidedLocalSearch::EnterSearch() {
3590 Metaheuristic::EnterSearch();
3596 penalties_->Reset();
3602 if (
delta !=
nullptr || deltadelta !=
nullptr) {
3603 if (!penalties_->HasValues()) {
3607 if (!deltadelta->Empty()) {
3618 for (
int i = 0; i <
vars_.size(); ++i) {
3628 if (!
delta->HasObjective()) {
3633 delta->SetObjectiveMin(
3636 delta->ObjectiveMin()));
3638 delta->SetObjectiveMax(
3641 delta->ObjectiveMax()));
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();
3661 int64 new_penalty = 0;
3662 if (EvaluateElementValue(container,
index, &i, &new_penalty)) {
3663 penalty =
CapAdd(penalty, new_penalty);
3664 if (cache_delta_values) {
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])) {
3682 const int64 var_value = assignment_.Value(
vars_[i]);
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));
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;
3695 penalties_->Increment(utility[i].first);
3705 class BinaryGuidedLocalSearch :
public GuidedLocalSearch {
3707 BinaryGuidedLocalSearch(Solver*
const solver, IntVar*
const objective,
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,
3718 bool EvaluateElementValue(
const Assignment::IntContainer& container,
3720 int64* penalty)
override;
3727 BinaryGuidedLocalSearch::BinaryGuidedLocalSearch(
3728 Solver*
const solver, IntVar*
const objective,
3730 int64 step,
const std::vector<IntVar*>& vars,
double penalty_factor)
3731 : GuidedLocalSearch(solver, objective, maximize, step, vars,
3733 objective_function_(std::move(objective_function)) {}
3735 IntExpr* BinaryGuidedLocalSearch::MakeElementPenalty(
int index) {
3736 return solver()->MakeElement(
3741 int64 BinaryGuidedLocalSearch::AssignmentElementPenalty(
3742 const Assignment& assignment,
int index) {
3746 int64 BinaryGuidedLocalSearch::AssignmentPenalty(
const Assignment& assignment,
3748 return objective_function_(
index,
next);
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());
3764 const Arc arc(i, j);
3765 const int64 penalty = penalties_->Value(arc);
3767 const double penalized_value_fp =
3770 ?
static_cast<int64>(penalized_value_fp)
3773 return -penalized_value;
3775 return penalized_value;
3782 class TernaryGuidedLocalSearch :
public GuidedLocalSearch {
3784 TernaryGuidedLocalSearch(
3785 Solver*
const solver, IntVar*
const objective,
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,
3795 bool EvaluateElementValue(
const Assignment::IntContainer& container,
3797 int64* penalty)
override;
3801 int64 GetAssignmentSecondaryValue(
const Assignment::IntContainer& container,
3802 int index,
int* container_index)
const;
3804 const std::vector<IntVar*> secondary_vars_;
3808 TernaryGuidedLocalSearch::TernaryGuidedLocalSearch(
3809 Solver*
const solver, IntVar*
const objective,
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,
3815 secondary_vars_(secondary_vars),
3816 objective_function_(std::move(objective_function)) {
3817 if (!secondary_vars.empty()) {
3818 assignment_.Add(secondary_vars);
3822 IntExpr* TernaryGuidedLocalSearch::MakeElementPenalty(
int index) {
3823 return solver()->MakeElement(
3828 int64 TernaryGuidedLocalSearch::AssignmentElementPenalty(
3829 const Assignment& assignment,
int index) {
3831 assignment.Value(secondary_vars_[
index]));
3834 int64 TernaryGuidedLocalSearch::AssignmentPenalty(
const Assignment& assignment,
3837 assignment.Value(secondary_vars_[
index]));
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));
3855 const Arc arc(i, j);
3856 const int64 penalty = penalties_->Value(arc);
3858 const double penalized_value_fp =
3861 ?
static_cast<int64>(penalized_value_fp)
3864 return -penalized_value;
3866 return penalized_value;
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();
3883 return container.Element(secondary_var).Value();
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,
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));
3911 SearchLimit::~SearchLimit() {}
3913 void SearchLimit::EnterSearch() {
3918 void SearchLimit::BeginNextDecision(DecisionBuilder*
const b) {
3923 void SearchLimit::RefuteDecision(Decision*
const d) {
3928 void SearchLimit::PeriodicCheck() {
3929 if (crossed_ || Check()) {
3935 void SearchLimit::TopPeriodicCheck() {
3936 if (solver()->TopLevelSearch() != solver()->ActiveSearch()) {
3937 solver()->TopPeriodicCheck();
3943 RegularLimit::RegularLimit(Solver*
const s, absl::Duration
time,
int64 branches,
3945 bool smart_time_check,
bool cumulative)
3947 duration_limit_(
time),
3948 solver_time_at_limit_start_(s->Now()),
3949 last_time_elapsed_(
absl::ZeroDuration()),
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) {}
3961 RegularLimit::~RegularLimit() {}
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_;
3974 SearchLimit* RegularLimit::MakeClone()
const {
return MakeIdenticalClone(); }
3976 RegularLimit* RegularLimit::MakeIdenticalClone()
const {
3977 Solver*
const s = solver();
3978 return s->MakeLimit(wall_time(), branches_, failures_, solutions_,
3982 bool RegularLimit::Check() {
3983 Solver*
const s = solver();
3985 return s->branches() - branches_offset_ >= branches_ ||
3986 s->failures() - failures_offset_ >= failures_ || CheckTime() ||
3987 s->solutions() - solutions_offset_ >= solutions_;
3990 int RegularLimit::ProgressPercent() {
3991 Solver*
const s = solver();
3992 int64 progress = GetPercent(s->branches(), branches_offset_, branches_);
3994 GetPercent(s->failures(), failures_offset_, failures_));
3996 progress, GetPercent(s->solutions(), solutions_offset_, solutions_));
3997 if (duration_limit() != absl::InfiniteDuration()) {
3998 progress =
std::max(progress, (100 * TimeElapsed()) / duration_limit());
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();
4014 void RegularLimit::ExitSearch() {
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_;
4025 void RegularLimit::UpdateLimits(absl::Duration
time,
int64 branches,
4027 duration_limit_ =
time;
4028 branches_ = branches;
4029 failures_ = failures;
4030 solutions_ = solutions;
4033 bool RegularLimit::IsUncheckedSolutionLimitReached() {
4034 Solver*
const s = solver();
4035 return s->solutions() + s->unchecked_solutions() - solutions_offset_ >=
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"));
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,
4052 visitor->VisitIntegerArgument(ModelVisitor::kFailuresLimitArgument,
4054 visitor->VisitIntegerArgument(ModelVisitor::kSolutionLimitArgument,
4056 visitor->VisitIntegerArgument(ModelVisitor::kSmartTimeCheckArgument,
4058 visitor->VisitIntegerArgument(ModelVisitor::kCumulativeArgument, cumulative_);
4059 visitor->EndVisitExtension(ModelVisitor::kObjectiveExtension);
4062 bool RegularLimit::CheckTime() {
return TimeElapsed() >= duration_limit(); }
4064 absl::Duration RegularLimit::TimeElapsed() {
4065 const int64 kMaxSkip = 100;
4066 const int64 kCheckWarmupIterations = 100;
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));
4077 std::min(check_count_ + kMaxSkip, estimated_check_count_at_limit);
4079 last_time_elapsed_ = elapsed;
4081 return last_time_elapsed_;
4084 RegularLimit* Solver::MakeTimeLimit(absl::Duration
time) {
4089 RegularLimit* Solver::MakeBranchesLimit(
int64 branches) {
4094 RegularLimit* Solver::MakeFailuresLimit(
int64 failures) {
4099 RegularLimit* Solver::MakeSolutionsLimit(
int64 solutions) {
4105 int64 solutions,
bool smart_time_check,
4107 return MakeLimit(absl::Milliseconds(
time), branches, failures, solutions,
4108 smart_time_check, cumulative);
4111 RegularLimit* Solver::MakeLimit(absl::Duration
time,
int64 branches,
4113 bool smart_time_check,
bool cumulative) {
4114 return RevAlloc(
new RegularLimit(
this,
time, branches, failures, solutions,
4115 smart_time_check, cumulative));
4118 RegularLimit* Solver::MakeLimit(
const RegularLimitParameters&
proto) {
4119 return MakeLimit(
proto.time() ==
kint64max ? absl::InfiniteDuration()
4120 : absl::Milliseconds(
proto.time()),
4122 proto.smart_time_check(),
proto.cumulative());
4125 RegularLimitParameters Solver::MakeDefaultRegularLimitParameters()
const {
4126 RegularLimitParameters
proto;
4131 proto.set_smart_time_check(
false);
4132 proto.set_cumulative(
false);
4138 class ORLimit :
public SearchLimit {
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.";
4150 bool Check()
override {
4153 const bool check_1 = limit_1_->Check();
4154 const bool check_2 = limit_2_->Check();
4155 return check_1 || check_2;
4158 void Init()
override {
4163 void Copy(
const SearchLimit*
const limit)
override {
4164 LOG(FATAL) <<
"Not implemented.";
4167 SearchLimit* MakeClone()
const override {
4169 return solver()->MakeLimit(limit_1_->MakeClone(), limit_2_->MakeClone());
4172 void EnterSearch()
override {
4173 limit_1_->EnterSearch();
4174 limit_2_->EnterSearch();
4176 void BeginNextDecision(DecisionBuilder*
const b)
override {
4177 limit_1_->BeginNextDecision(
b);
4178 limit_2_->BeginNextDecision(
b);
4180 void PeriodicCheck()
override {
4181 limit_1_->PeriodicCheck();
4182 limit_2_->PeriodicCheck();
4184 void RefuteDecision(Decision*
const d)
override {
4185 limit_1_->RefuteDecision(d);
4186 limit_2_->RefuteDecision(d);
4188 std::string DebugString()
const override {
4189 return absl::StrCat(
"OR limit (", limit_1_->DebugString(),
" OR ",
4190 limit_2_->DebugString(),
")");
4194 SearchLimit*
const limit_1_;
4195 SearchLimit*
const limit_2_;
4199 SearchLimit* Solver::MakeLimit(SearchLimit*
const limit_1,
4200 SearchLimit*
const limit_2) {
4201 return RevAlloc(
new ORLimit(limit_1, limit_2));
4205 class CustomLimit :
public SearchLimit {
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;
4214 std::function<bool()> limiter_;
4217 CustomLimit::CustomLimit(Solver*
const s, std::function<
bool()> limiter)
4218 : SearchLimit(s), limiter_(std::move(limiter)) {}
4220 bool CustomLimit::Check() {
4221 if (limiter_)
return limiter_();
4225 void CustomLimit::Init() {}
4227 void CustomLimit::Copy(
const SearchLimit*
const limit) {
4228 const CustomLimit*
const custom =
4229 reinterpret_cast<const CustomLimit* const
>(limit);
4230 limiter_ = custom->limiter_;
4233 SearchLimit* CustomLimit::MakeClone()
const {
4234 return solver()->RevAlloc(
new CustomLimit(solver(), limiter_));
4238 SearchLimit* Solver::MakeCustomLimit(std::function<
bool()> limiter) {
4239 return RevAlloc(
new CustomLimit(
this, std::move(limiter)));
4245 class SolveOnce :
public DecisionBuilder {
4247 explicit SolveOnce(DecisionBuilder*
const db) : db_(db) {
4248 CHECK(db !=
nullptr);
4251 SolveOnce(DecisionBuilder*
const db,
4252 const std::vector<SearchMonitor*>& monitors)
4253 : db_(db), monitors_(monitors) {
4254 CHECK(db !=
nullptr);
4257 ~SolveOnce()
override {}
4259 Decision* Next(Solver* s)
override {
4260 bool res = s->SolveAndCommit(db_, monitors_);
4267 std::string DebugString()
const override {
4268 return absl::StrFormat(
"SolveOnce(%s)", db_->DebugString());
4271 void Accept(ModelVisitor*
const visitor)
const override {
4272 db_->Accept(visitor);
4276 DecisionBuilder*
const db_;
4277 std::vector<SearchMonitor*> monitors_;
4281 DecisionBuilder* Solver::MakeSolveOnce(DecisionBuilder*
const db) {
4282 return RevAlloc(
new SolveOnce(db));
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));
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));
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));
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));
4325 DecisionBuilder* Solver::MakeSolveOnce(
4326 DecisionBuilder*
const db,
const std::vector<SearchMonitor*>& monitors) {
4327 return RevAlloc(
new SolveOnce(db, monitors));
4333 class NestedOptimize :
public DecisionBuilder {
4335 NestedOptimize(DecisionBuilder*
const db, Assignment*
const solution,
4336 bool maximize,
int64 step)
4338 solution_(solution),
4341 collector_(nullptr) {
4342 CHECK(db !=
nullptr);
4343 CHECK(solution !=
nullptr);
4344 CHECK(solution->HasObjective());
4348 NestedOptimize(DecisionBuilder*
const db, Assignment*
const solution,
4349 bool maximize,
int64 step,
4350 const std::vector<SearchMonitor*>& monitors)
4352 solution_(solution),
4355 monitors_(monitors),
4356 collector_(nullptr) {
4357 CHECK(db !=
nullptr);
4358 CHECK(solution !=
nullptr);
4359 CHECK(solution->HasObjective());
4363 void AddMonitors() {
4364 Solver*
const solver = solution_->solver();
4365 collector_ = solver->MakeLastSolutionCollector(solution_);
4366 monitors_.push_back(collector_);
4367 OptimizeVar*
const optimize =
4369 monitors_.push_back(optimize);
4372 Decision* Next(Solver* solver)
override {
4373 solver->Solve(db_, monitors_);
4374 if (collector_->solution_count() == 0) {
4377 collector_->solution(0)->Restore();
4381 std::string DebugString()
const override {
4382 return absl::StrFormat(
"NestedOptimize(db = %s, maximize = %d, step = %d)",
4386 void Accept(ModelVisitor*
const visitor)
const override {
4387 db_->Accept(visitor);
4391 DecisionBuilder*
const db_;
4392 Assignment*
const solution_;
4395 std::vector<SearchMonitor*> monitors_;
4396 SolutionCollector* collector_;
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));
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));
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));
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));
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));
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));
4461 int64 NextLuby(
int i) {
4469 while (power < (i + 1)) {
4472 if (power == i + 1) {
4475 return NextLuby(i - (power / 2) + 1);
4478 class LubyRestart :
public SearchMonitor {
4480 LubyRestart(Solver*
const s,
int scale_factor)
4482 scale_factor_(scale_factor),
4485 next_step_(scale_factor) {
4486 CHECK_GE(scale_factor, 1);
4489 ~LubyRestart()
override {}
4491 void BeginFail()
override {
4492 if (++current_fails_ >= next_step_) {
4494 next_step_ = NextLuby(++iteration_) * scale_factor_;
4495 solver()->RestartCurrentSearch();
4499 std::string DebugString()
const override {
4500 return absl::StrFormat(
"LubyRestart(%i)", scale_factor_);
4504 const int scale_factor_;
4506 int64 current_fails_;
4511 SearchMonitor* Solver::MakeLubyRestart(
int scale_factor) {
4512 return RevAlloc(
new LubyRestart(
this, scale_factor));
4518 class ConstantRestart :
public SearchMonitor {
4520 ConstantRestart(Solver*
const s,
int frequency)
4521 : SearchMonitor(s), frequency_(frequency), current_fails_(0) {
4522 CHECK_GE(frequency, 1);
4525 ~ConstantRestart()
override {}
4527 void BeginFail()
override {
4528 if (++current_fails_ >= frequency_) {
4530 solver()->RestartCurrentSearch();
4534 std::string DebugString()
const override {
4535 return absl::StrFormat(
"ConstantRestart(%i)", frequency_);
4539 const int frequency_;
4540 int64 current_fails_;
4544 SearchMonitor* Solver::MakeConstantRestart(
int frequency) {
4545 return RevAlloc(
new ConstantRestart(
this, frequency));
4568 const std::vector<SymmetryBreaker*>& visitors)
4570 visitors_(visitors),
4571 clauses_(visitors.size()),
4572 decisions_(visitors.size()),
4573 directions_(visitors.size()) {
4574 for (
int i = 0; i < visitors_.size(); ++i) {
4575 visitors_[i]->set_symmetry_manager_and_index(
this, i);
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()) {
4588 decisions_[i].Push(solver(), d);
4589 directions_[i].Push(solver(),
false);
4596 for (
int i = 0; i < visitors_.size(); ++i) {
4597 if (decisions_[i].Last() !=
nullptr && decisions_[i].LastValue() == d) {
4608 Constraint*
ct =
nullptr;
4610 std::vector<IntVar*> guard;
4615 IntVar*
const term = *tmp;
4617 if (term->Max() == 0) {
4621 if (term->Min() == 0) {
4622 DCHECK_EQ(1, term->Max());
4624 guard.push_back(term);
4630 guard.push_back(clauses_[
index].LastValue());
4631 directions_[
index].SetLastValue(
true);
4636 ct = solver()->MakeEquality(solver()->MakeMin(guard), Zero());
4638 DCHECK(
ct !=
nullptr);
4639 solver()->AddConstraint(
ct);
4643 clauses_[visitor->index_in_symmetry_manager()].Push(solver(), term);
4646 std::string
DebugString()
const override {
return "SymmetryManager"; }
4649 const std::vector<SymmetryBreaker*> visitors_;
4650 std::vector<SimpleRevFIFO<IntVar*>> clauses_;
4651 std::vector<SimpleRevFIFO<Decision*>> decisions_;
4652 std::vector<SimpleRevFIFO<bool>> directions_;
4657 void SymmetryBreaker::AddIntegerVariableEqualValueClause(IntVar*
const var,
4659 CHECK(
var !=
nullptr);
4660 Solver*
const solver =
var->solver();
4661 IntVar*
const term = solver->MakeIsEqualCstVar(
var,
value);
4662 symmetry_manager()->AddTermToClause(
this, term);
4665 void SymmetryBreaker::AddIntegerVariableGreaterOrEqualValueClause(
4667 CHECK(
var !=
nullptr);
4668 Solver*
const solver =
var->solver();
4669 IntVar*
const term = solver->MakeIsGreaterOrEqualCstVar(
var,
value);
4670 symmetry_manager()->AddTermToClause(
this, term);
4673 void SymmetryBreaker::AddIntegerVariableLessOrEqualValueClause(
4675 CHECK(
var !=
nullptr);
4676 Solver*
const solver =
var->solver();
4677 IntVar*
const term = solver->MakeIsLessOrEqualCstVar(
var,
value);
4678 symmetry_manager()->AddTermToClause(
this, term);
4683 SearchMonitor* Solver::MakeSymmetryManager(
4684 const std::vector<SymmetryBreaker*>& visitors) {
4688 SearchMonitor* Solver::MakeSymmetryManager(SymmetryBreaker*
const v1) {
4689 std::vector<SymmetryBreaker*> visitors;
4690 visitors.push_back(v1);
4691 return MakeSymmetryManager(visitors);
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);
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);
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);