Google OR-Tools: ortools/constraint_solver/default_search.cc Source File
24#include "absl/container/flat_hash_set.h"
25#include "absl/strings/str_format.h"
35ABSL_FLAG(int, cp_impact_divider, 10, "Divider for continuous update.");
41const int kDefaultNumberOfSplits = 100;
42const int kDefaultHeuristicPeriod = 100;
43const int kDefaultHeuristicNumFailuresLimit = 30;
44const bool kDefaultUseLastConflict = true;
67 DomainWatcher(const std::vector<IntVar*>& vars, int cache_size)
69 cached_log_.Init(cache_size);
73 DomainWatcher(const DomainWatcher&) = delete;
74 DomainWatcher& operator=(const DomainWatcher&) = delete;
76 double LogSearchSpaceSize() {
78 for (int index = 0; index < vars_.size(); ++index) {
79 result += cached_log_.Log2(vars_[index]->Size());
84 double Log2(int64_t size) const { return cached_log_.Log2(size); }
87 std::vector<IntVar*> vars_;
95 enum Operation { NONE, ASSIGN, SPLIT_LOW, SPLIT_HIGH };
97 FindVar() : var_(nullptr), value_(0), operation_(NONE) {}
101 void VisitSetVariableValue(IntVar* var, int64_t value) override {
107 void VisitSplitVariableDomain(IntVar* var, int64_t value,
108 bool start_with_lower_half) override {
111 operation_ = start_with_lower_half ? SPLIT_LOW : SPLIT_HIGH;
114 void VisitScheduleOrPostpone(IntervalVar* const var, int64_t est) override {
118 virtual void VisitTryRankFirst(SequenceVar* const sequence, int index) {
122 virtual void VisitTryRankLast(SequenceVar* const sequence, int index) {
126 void VisitUnknownDecision() override { operation_ = NONE; }
130 CHECK_NE(operation_, NONE);
136 CHECK_NE(operation_, NONE);
140 Operation operation() const { return operation_; }
142 std::string DebugString() const override {
143 return "FindVar decision visitor";
161 update_impact_callback_(nullptr),
162 new_start_(false),
165 update_impact_closure_([this]() { UpdateImpacts(); }),
166 updater_(update_impact_closure_) {
167 CHECK(update_impact_closure_ != nullptr);
170 ~InitVarImpacts() override {}
174 update_impact_callback_(var_index_, var_->Min());
177 void Init(IntVar* const var, IntVarIterator* const iterator, int var_index) {
185 Decision* Next(Solver* const solver) override {
187 CHECK(iterator_ != nullptr);
190 for (const int64_t value : InitAndGetValues(iterator_)) {
191 active_values_.push_back(value);
195 if (value_index_ == active_values_.size()) {
199 updater_.value_ = active_values_[value_index_];
204 void set_update_impact_callback(std::function<void(int, int64_t)> callback) {
205 update_impact_callback_ = std::move(callback);
210 class AssignCallFail : public Decision {
212 explicit AssignCallFail(const std::function<void()>& update_impact_closure)
215 update_impact_closure_(update_impact_closure) {
216 CHECK(update_impact_closure_ != nullptr);
220 AssignCallFail(const AssignCallFail&) = delete;
221 AssignCallFail& operator=(const AssignCallFail&) = delete;
222 ~AssignCallFail() override {}
223 void Apply(Solver* const solver) override {
230 void Refute(Solver* const solver) override {}
236 const std::function<void()>& update_impact_closure_;
240 std::function<void(int, int64_t)> update_impact_callback_;
242 IntVarIterator* iterator_;
244 std::vector<int64_t> active_values_;
246 std::function<void()> update_impact_closure_;
256 class AssignIntervalCallFail : public Decision {
258 explicit AssignIntervalCallFail(
259 const std::function<void()>& update_impact_closure)
263 update_impact_closure_(update_impact_closure) {
264 CHECK(update_impact_closure_ != nullptr);
268 AssignIntervalCallFail(const AssignIntervalCallFail&) = delete;
269 AssignIntervalCallFail& operator=(const AssignIntervalCallFail&) = delete;
270 ~AssignIntervalCallFail() override {}
271 void Apply(Solver* const solver) override {
273 var_->SetRange(value_min_, value_max_);
278 void Refute(Solver* const solver) override {}
286 const std::function<void()>& update_impact_closure_;
291 explicit InitVarImpactsWithSplits(int split_size)
293 update_impact_callback_(nullptr),
294 new_start_(false),
300 update_impact_closure_([this]() { UpdateImpacts(); }),
301 updater_(update_impact_closure_) {
302 CHECK(update_impact_closure_ != nullptr);
305 ~InitVarImpactsWithSplits() override {}
308 for (const int64_t value : InitAndGetValues(iterator_)) {
309 update_impact_callback_(var_index_, value);
313 void Init(IntVar* const var, IntVarIterator* const iterator, int var_index) {
321 int64_t IntervalStart(int index) const {
322 const int64_t length = max_value_ - min_value_ + 1;
323 return (min_value_ + length * index / split_size_);
326 Decision* Next(Solver* const solver) override {
332 if (split_index_ == split_size_) {
336 updater_.value_min_ = IntervalStart(split_index_);
338 if (split_index_ == split_size_) {
339 updater_.value_max_ = max_value_;
341 updater_.value_max_ = IntervalStart(split_index_) - 1;
346 void set_update_impact_callback(std::function<void(int, int64_t)> callback) {
347 update_impact_callback_ = std::move(callback);
352 std::function<void(int, int64_t)> update_impact_callback_;
354 IntVarIterator* iterator_;
360 std::function<void()> update_impact_closure_;
361 AssignIntervalCallFail updater_;
371 static const int kLogCacheSize;
372 static const double kPerfectImpact;
373 static const double kFailureImpact;
374 static const double kInitFailureImpact;
375 static const int kUninitializedVarIndex;
377 ImpactRecorder(Solver* const solver, DomainWatcher* const domain_watcher,
378 const std::vector<IntVar*>& vars,
381 domain_watcher_(domain_watcher),
386 original_min_(size_, 0LL),
387 domain_iterators_(new IntVarIterator*[size_]),
388 display_level_(display_level),
389 current_var_(kUninitializedVarIndex),
391 init_done_(false) {
392 for (int i = 0; i < size_; ++i) {
393 domain_iterators_[i] = vars_[i]->MakeDomainIterator(true);
399 ImpactRecorder(const ImpactRecorder&) = delete;
400 ImpactRecorder& operator=(const ImpactRecorder&) = delete;
402 void ApplyDecision(Decision* const d) override {
407 if (find_var_.operation() == FindVar::ASSIGN &&
408 var_map_.contains(find_var_.var())) {
409 current_var_ = var_map_[find_var_.var()];
410 current_value_ = find_var_.value();
411 current_log_space_ = domain_watcher_->LogSearchSpaceSize();
413 current_var_ = kUninitializedVarIndex;
418 void AfterDecision(Decision* const d, bool apply) override {
419 if (init_done_ && current_var_ != kUninitializedVarIndex) {
420 if (current_log_space_ > 0.0) {
421 const double log_space = domain_watcher_->LogSearchSpaceSize();
423 const double impact = kPerfectImpact - log_space / current_log_space_;
424 UpdateImpact(current_var_, current_value_, impact);
425 current_var_ = kUninitializedVarIndex;
428 current_log_space_ = log_space;
433 void BeginFail() override {
434 if (init_done_ && current_var_ != kUninitializedVarIndex) {
435 UpdateImpact(current_var_, current_value_, kFailureImpact);
436 current_var_ = kUninitializedVarIndex;
442 for (int i = 0; i < size_; ++i) {
443 original_min_[i] = vars_[i]->Min();
447 impacts_[i].resize(vars_[i]->Max() - vars_[i]->Min() + 1,
451 for (int i = 0; i < size_; ++i) {
452 for (int j = 0; j < impacts_[i].size(); ++j) {
453 impacts_[i][j] = kInitFailureImpact;
458 void UpdateImpact(int var_index, int64_t value, double impact) {
459 const int64_t value_index = value - original_min_[var_index];
460 const double current_impact = impacts_[var_index][value_index];
462 (current_impact * (absl::GetFlag(FLAGS_cp_impact_divider) - 1) +
464 absl::GetFlag(FLAGS_cp_impact_divider);
465 impacts_[var_index][value_index] = new_impact;
468 void InitImpact(int var_index, int64_t value) {
469 const double log_space = domain_watcher_->LogSearchSpaceSize();
470 const double impact = kPerfectImpact - log_space / current_log_space_;
471 const int64_t value_index = value - original_min_[var_index];
472 DCHECK_LT(var_index, size_);
473 DCHECK_LT(value_index, impacts_[var_index].size());
474 impacts_[var_index][value_index] = impact;
478 void FirstRun(int64_t splits) {
479 Solver* const s = solver();
480 current_log_space_ = domain_watcher_->LogSearchSpaceSize();
482 LOG(INFO) << " - initial log2(SearchSpace) = " << current_log_space_;
484 const int64_t init_time = s->wall_time();
486 int64_t removed_counter = 0;
487 FirstRunVariableContainers* container =
488 s->RevAlloc(new FirstRunVariableContainers(this, splits));
490 for (int var_index = 0; var_index < size_; ++var_index) {
491 IntVar* const var = vars_[var_index];
495 IntVarIterator* const iterator = domain_iterators_[var_index];
496 DecisionBuilder* init_decision_builder = nullptr;
497 const bool no_split = var->Size() < splits;
500 container->without_split()->set_update_impact_callback(
501 container->update_impact_callback());
502 container->without_split()->Init(var, iterator, var_index);
503 init_decision_builder = container->without_split();
507 container->with_splits()->set_update_impact_callback(
508 container->update_impact_callback());
509 container->with_splits()->Init(var, iterator, var_index);
510 init_decision_builder = container->with_splits();
515 s->Solve(init_decision_builder);
520 if (init_count_ != var->Size() && no_split) {
521 container->ClearRemovedValues();
522 for (const int64_t value : InitAndGetValues(iterator)) {
523 const int64_t value_index = value - original_min_[var_index];
524 if (impacts_[var_index][value_index] == kInitFailureImpact) {
525 container->PushBackRemovedValue(value);
528 CHECK(container->HasRemovedValues()) << var->DebugString();
529 removed_counter += container->NumRemovedValues();
530 const double old_log = domain_watcher_->Log2(var->Size());
531 var->RemoveValues(container->removed_values());
532 current_log_space_ += domain_watcher_->Log2(var->Size()) - old_log;
537 LOG(INFO) << " - init done, time = " << s->wall_time() - init_time
538 << " ms, " << removed_counter
539 << " values removed, log2(SearchSpace) = "
542 LOG(INFO) << " - init done, time = " << s->wall_time() - init_time
546 s->SaveAndSetValue(&init_done_, true);
552 void ScanVarImpacts(int var_index, int64_t* const best_impact_value,
553 double* const var_impacts,
556 CHECK(best_impact_value != nullptr);
557 CHECK(var_impacts != nullptr);
558 double max_impact = -std::numeric_limits<double>::max();
559 double min_impact = std::numeric_limits<double>::max();
560 double sum_var_impact = 0.0;
561 int64_t min_impact_value = -1;
562 int64_t max_impact_value = -1;
563 for (const int64_t value : InitAndGetValues(domain_iterators_[var_index])) {
564 const int64_t value_index = value - original_min_[var_index];
565 DCHECK_LT(var_index, size_);
566 DCHECK_LT(value_index, impacts_[var_index].size());
567 const double current_impact = impacts_[var_index][value_index];
568 sum_var_impact += current_impact;
569 if (current_impact > max_impact) {
570 max_impact = current_impact;
573 if (current_impact < min_impact) {
574 min_impact = current_impact;
581 *var_impacts = sum_var_impact / vars_[var_index]->Size();
585 *var_impacts = max_impact;
589 *var_impacts = sum_var_impact;
596 *best_impact_value = min_impact_value;
600 *best_impact_value = max_impact_value;
606 std::string DebugString() const override { return "ImpactRecorder"; }
611 class FirstRunVariableContainers : public BaseObject {
613 FirstRunVariableContainers(ImpactRecorder* impact_recorder, int64_t splits)
614 : update_impact_callback_(
615 [impact_recorder](int var_index, int64_t value) {
616 impact_recorder->InitImpact(var_index, value);
621 std::function<void(int, int64_t)> update_impact_callback() const {
622 return update_impact_callback_;
624 void PushBackRemovedValue(int64_t value) {
625 removed_values_.push_back(value);
627 bool HasRemovedValues() const { return !removed_values_.empty(); }
628 void ClearRemovedValues() { removed_values_.clear(); }
629 size_t NumRemovedValues() const { return removed_values_.size(); }
630 const std::vector<int64_t>& removed_values() const {
633 InitVarImpacts* without_split() { return &without_splits_; }
634 InitVarImpactsWithSplits* with_splits() { return &with_splits_; }
636 std::string DebugString() const override {
637 return "FirstRunVariableContainers";
641 const std::function<void(int, int64_t)> update_impact_callback_;
642 std::vector<int64_t> removed_values_;
643 InitVarImpacts without_splits_;
644 InitVarImpactsWithSplits with_splits_;
647 DomainWatcher* const domain_watcher_;
648 std::vector<IntVar*> vars_;
650 double current_log_space_;
653 std::vector<std::vector<double> > impacts_;
654 std::vector<int64_t> original_min_;
655 std::unique_ptr<IntVarIterator*[]> domain_iterators_;
661 absl::flat_hash_map<const IntVar*, int> var_map_;
665const int ImpactRecorder::kLogCacheSize = 1000;
666const double ImpactRecorder::kPerfectImpact = 1.0;
667const double ImpactRecorder::kFailureImpact = 1.0;
668const double ImpactRecorder::kInitFailureImpact = 2.0;
669const int ImpactRecorder::kUninitializedVarIndex = -1;
674 ChoiceInfo() : value_(0), var_(nullptr), left_(false) {}
676 ChoiceInfo(IntVar* const var, int64_t value, bool left)
677 : value_(value), var_(var), left_(left) {}
679 std::string DebugString() const {
680 return absl::StrFormat("%s %s %d", var_->name(), (left_ ? "==" : "!="),
684 IntVar* var() const { return var_; }
686 bool left() const { return left_; }
688 int64_t value() const { return value_; }
690 void set_left(bool left) { left_ = left; }
700class RunHeuristicsAsDives : public Decision {
702 RunHeuristicsAsDives(Solver* const solver, const std::vector<IntVar*>& vars,
704 bool run_all_heuristics, int random_seed,
705 int heuristic_period, int heuristic_num_failures_limit)
706 : heuristic_limit_(nullptr),
708 run_all_heuristics_(run_all_heuristics),
710 heuristic_period_(heuristic_period),
711 heuristic_branch_count_(0),
713 Init(solver, vars, heuristic_num_failures_limit);
718 void Apply(Solver* const solver) override {
719 if (!RunAllHeuristics(solver)) {
724 void Refute(Solver* const solver) override {}
727 if (heuristic_period_ <= 0) {
730 ++heuristic_branch_count_;
731 return heuristic_branch_count_ % heuristic_period_ == 0;
734 bool RunOneHeuristic(Solver* const solver, int index) {
735 HeuristicWrapper* const wrapper = heuristics_[index];
739 solver->SolveAndCommit(wrapper->phase, heuristic_limit_);
741 LOG(INFO) << " --- solution found by heuristic " << wrapper->name
747 bool RunAllHeuristics(Solver* const solver) {
748 if (run_all_heuristics_) {
749 for (int index = 0; index < heuristics_.size(); ++index) {
750 for (int run = 0; run < heuristics_[index]->runs; ++run) {
751 if (RunOneHeuristic(solver, index)) {
758 DCHECK_GT(heuristics_.size(), 0);
759 const int index = absl::Uniform<int>(random_, 0, heuristics_.size());
760 return RunOneHeuristic(solver, index);
766 return absl::Uniform<int>(random_, 0, size);
769 void Init(Solver* const solver, const std::vector<IntVar*>& vars,
770 int heuristic_num_failures_limit) {
775 heuristics_.push_back(new HeuristicWrapper(
779 heuristics_.push_back(new HeuristicWrapper(
786 "AssignCenterValueToMinDomainSize", kRunOnce));
788 heuristics_.push_back(new HeuristicWrapper(
790 "AssignRandomValueToFirstUnbound", kRunALot));
792 heuristics_.push_back(new HeuristicWrapper(
794 "AssignMinValueToRandomVariable", kRunMore));
796 heuristics_.push_back(new HeuristicWrapper(
798 "AssignMaxValueToRandomVariable", kRunMore));
800 heuristics_.push_back(new HeuristicWrapper(
802 "AssignRandomValueToRandomVariable", kRunMore));
804 heuristic_limit_ = solver->MakeFailuresLimit(heuristic_num_failures_limit);
807 int heuristic_runs() const { return heuristic_runs_; }
813 HeuristicWrapper(Solver* const solver, const std::vector<IntVar*>& vars,
816 const std::string& heuristic_name, int heuristic_runs)
817 : phase(solver->MakePhase(vars, var_strategy, value_strategy)),
822 DecisionBuilder* const phase;
831 std::vector<HeuristicWrapper*> heuristics_;
832 SearchMonitor* heuristic_limit_;
836 const int heuristic_period_;
837 int heuristic_branch_count_;
846 static const double kSmallSearchSpaceLimit;
848 DefaultIntegerSearch(Solver* const solver, const std::vector<IntVar*>& vars,
849 const DefaultPhaseParameters& parameters)
852 domain_watcher_(vars, ImpactRecorder::kLogCacheSize),
853 impact_recorder_(solver, &domain_watcher_, vars,
854 parameters.display_level),
855 heuristics_(solver, vars_, parameters_.display_level,
856 parameters_.run_all_heuristics, parameters_.random_seed,
857 parameters_.heuristic_period,
858 parameters_.heuristic_num_failures_limit),
862 last_operation_(FindVar::NONE),
864 init_done_(false) {}
866 ~DefaultIntegerSearch() override {}
868 Decision* Next(Solver* const solver) override {
871 if (heuristics_.ShouldRun()) {
875 Decision* const decision = parameters_.decision_builder != nullptr
876 ? parameters_.decision_builder->Next(solver)
880 if (decision == nullptr) {
888 decision->Accept(&find_var_);
889 IntVar* const decision_var =
890 find_var_.operation() != FindVar::NONE ? find_var_.var() : nullptr;
900 if (parameters_.use_last_conflict && last_int_var_ != nullptr &&
901 !last_int_var_->Bound() &&
902 (decision_var == nullptr || decision_var != last_int_var_)) {
903 switch (last_operation_) {
905 if (last_int_var_->Contains(last_int_value_)) {
906 Decision* const assign =
907 solver->MakeAssignVariableValue(last_int_var_, last_int_value_);
914 case FindVar::SPLIT_LOW: {
915 if (last_int_var_->Max() > last_int_value_ &&
916 last_int_var_->Min() <= last_int_value_) {
917 Decision* const split = solver->MakeVariableLessOrEqualValue(
918 last_int_var_, last_int_value_);
925 case FindVar::SPLIT_HIGH: {
926 if (last_int_var_->Min() < last_int_value_ &&
927 last_int_var_->Max() >= last_int_value_) {
928 Decision* const split = solver->MakeVariableGreaterOrEqualValue(
929 last_int_var_, last_int_value_);
942 if (parameters_.use_last_conflict) {
944 decision->Accept(&find_var_);
945 if (find_var_.operation() != FindVar::NONE) {
946 last_int_var_ = find_var_.var();
947 last_int_value_ = find_var_.value();
948 last_operation_ = find_var_.operation();
955 void ClearLastDecision() {
958 last_operation_ = FindVar::NONE;
961 void AppendMonitors(Solver* const solver,
962 std::vector<SearchMonitor*>* const extras) override {
965 if (parameters_.decision_builder == nullptr) {
966 extras->push_back(&impact_recorder_);
970 void Accept(ModelVisitor* const visitor) const override {
977 std::string DebugString() const override {
978 std::string out = "DefaultIntegerSearch(";
980 if (parameters_.decision_builder == nullptr) {
981 out.append("Impact Based Search, ");
983 out.append(parameters_.decision_builder->DebugString());
991 std::string StatString() const {
992 const int runs = heuristics_.heuristic_runs();
999 result.append("1 heuristic run");
1001 absl::StrAppendFormat(&result, "%d heuristic runs", runs);
1004 if (last_conflict_count_ > 0) {
1008 if (last_conflict_count_ == 1) {
1009 result.append("1 last conflict hint");
1011 absl::StrAppendFormat(&result, "%d last conflict hints",
1019 void CheckInit(Solver* const solver) {
1023 if (parameters_.decision_builder == nullptr) {
1025 for (int i = 0; i < vars_.size(); ++i) {
1026 if (vars_[i]->Max() - vars_[i]->Min() > 0xFFFFFF) {
1028 LOG(INFO) << "Domains are too large, switching to simple "
1032 reinterpret_cast<void**>(¶meters_.decision_builder));
1033 parameters_.decision_builder =
1036 solver->SaveAndSetValue(&init_done_, true);
1041 if (domain_watcher_.LogSearchSpaceSize() < kSmallSearchSpaceLimit) {
1043 LOG(INFO) << "Search space is too small, switching to simple "
1047 reinterpret_cast<void**>(¶meters_.decision_builder));
1048 parameters_.decision_builder = solver->MakePhase(
1050 solver->SaveAndSetValue(&init_done_, true);
1055 LOG(INFO) << "Init impact based search phase on " << vars_.size()
1056 << " variables, initialization splits = "
1057 << parameters_.initialization_splits
1058 << ", heuristic_period = " << parameters_.heuristic_period
1059 << ", run_all_heuristics = "
1060 << parameters_.run_all_heuristics;
1063 impact_recorder_.FirstRun(parameters_.initialization_splits);
1065 if (parameters_.persistent_impact) {
1068 solver->SaveAndSetValue(&init_done_, true);
1076 Decision* ImpactNext(Solver* const solver) {
1079 double best_var_impact = -std::numeric_limits<double>::max();
1080 for (int i = 0; i < vars_.size(); ++i) {
1081 if (!vars_[i]->Bound()) {
1082 int64_t current_value = 0;
1083 double current_var_impact = 0.0;
1084 impact_recorder_.ScanVarImpacts(i, ¤t_value, ¤t_var_impact,
1085 parameters_.var_selection_schema,
1086 parameters_.value_selection_schema);
1087 if (current_var_impact > best_var_impact) {
1088 var = vars_[i];
1090 best_var_impact = current_var_impact;
1097 return solver->MakeAssignVariableValue(var, value);
1103 std::vector<IntVar*> vars_;
1104 DefaultPhaseParameters parameters_;
1105 DomainWatcher domain_watcher_;
1106 ImpactRecorder impact_recorder_;
1107 RunHeuristicsAsDives heuristics_;
1111 FindVar::Operation last_operation_;
1112 int last_conflict_count_;
1116const double DefaultIntegerSearch::kSmallSearchSpaceLimit = 10.0;
1122 DefaultIntegerSearch* const dis = dynamic_cast<DefaultIntegerSearch*>(db);
static const char kVariableGroupExtension[]
static const char kVarsArgument[]
A search monitor is a simple set of callbacks to monitor all search events.
@ CHOOSE_MIN_SIZE_LOWEST_MIN
@ CHOOSE_RANDOM
Randomly select one of the remaining unbound variables.
@ CHOOSE_MIN_SIZE_HIGHEST_MAX
DecisionBuilder * MakeDefaultPhase(const std::vector< IntVar * > &vars)
Definition default_search.cc:1126
ConstraintSolverParameters parameters() const
Stored Parameters.
@ ASSIGN_MAX_VALUE
Selects the max value of the selected variable.
@ ASSIGN_MIN_VALUE
Selects the min value of the selected variable.
@ ASSIGN_RANDOM_VALUE
Selects randomly one of the possible values of the selected variable.
ABSL_FLAG(int, cp_impact_divider, 10, "Divider for continuous update.")
void STLDeleteElements(T *container)
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
std::string DefaultPhaseStatString(DecisionBuilder *db)
Definition default_search.cc:1121
Select next search node to expand Select next item_i to assign(using primary propagator) - Generate a new search node where item_i is in the knapsack - Check validity of this new partial solution(using propagators) - If valid
This struct holds all parameters for the default search.
bool use_last_conflict
Should we use last conflict method. The default is false.
DecisionBuilder * decision_builder
When defined, this overrides the default impact based decision builder.
int initialization_splits
int heuristic_num_failures_limit
The failure limit for each heuristic that we run.
DefaultPhaseParameters()
Definition default_search.cc:47
DisplayLevel display_level
@ CHOOSE_MAX_VALUE_IMPACT
@ CHOOSE_MAX_AVERAGE_IMPACT
ValueSelection value_selection_schema
This parameter describes which value to select for a given var.
int random_seed
Seed used to initialize the random part in some heuristics.
VariableSelection var_selection_schema