implement last conflict in default search, hook it to the flatzinc interpreter
This commit is contained in:
@@ -232,27 +232,6 @@ struct DefaultPhaseParameters {
|
||||
|
||||
enum DisplayLevel { NONE = 0, NORMAL = 1, VERBOSE = 2 };
|
||||
|
||||
static const int kDefaultNumberOfSplits;
|
||||
static const int kDefaultHeuristicPeriod;
|
||||
static const int kDefaultHeuristicNumFailuresLimit;
|
||||
static const int kDefaultSeed;
|
||||
static const double kDefaultRestartLogSize;
|
||||
static const bool kDefaultUseNoGoods;
|
||||
|
||||
DefaultPhaseParameters()
|
||||
: var_selection_schema(CHOOSE_MAX_SUM_IMPACT),
|
||||
value_selection_schema(SELECT_MIN_IMPACT),
|
||||
initialization_splits(kDefaultNumberOfSplits),
|
||||
run_all_heuristics(true),
|
||||
heuristic_period(kDefaultHeuristicPeriod),
|
||||
heuristic_num_failures_limit(kDefaultHeuristicNumFailuresLimit),
|
||||
persistent_impact(true),
|
||||
random_seed(kDefaultSeed),
|
||||
restart_log_size(kDefaultRestartLogSize),
|
||||
display_level(NORMAL),
|
||||
use_no_goods(kDefaultUseNoGoods),
|
||||
decision_builder(nullptr) {}
|
||||
|
||||
// This parameter describes how the next variable to instantiate
|
||||
// will be chosen.
|
||||
VariableSelection var_selection_schema;
|
||||
@@ -302,8 +281,13 @@ struct DefaultPhaseParameters {
|
||||
// Should we use Nogoods when restarting. The default is false.
|
||||
bool use_no_goods;
|
||||
|
||||
// Should we use last conflict method. The default is false.
|
||||
bool use_last_conflict;
|
||||
|
||||
// When defined, this override the default impact based decision builder.
|
||||
DecisionBuilder* decision_builder;
|
||||
|
||||
DefaultPhaseParameters();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -36,16 +36,34 @@ DEFINE_int32(cp_impact_divider, 10, "Divider for continuous update.");
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
// Default constants for search phase parameters.
|
||||
const int DefaultPhaseParameters::kDefaultNumberOfSplits = 100;
|
||||
const int DefaultPhaseParameters::kDefaultHeuristicPeriod = 100;
|
||||
const int DefaultPhaseParameters::kDefaultHeuristicNumFailuresLimit = 30;
|
||||
const int DefaultPhaseParameters::kDefaultSeed = 0;
|
||||
const double DefaultPhaseParameters::kDefaultRestartLogSize = -1.0;
|
||||
const bool DefaultPhaseParameters::kDefaultUseNoGoods = true;
|
||||
|
||||
class NoGoodManager;
|
||||
|
||||
namespace {
|
||||
// Default constants for search phase parameters.
|
||||
const int kDefaultNumberOfSplits = 100;
|
||||
const int kDefaultHeuristicPeriod = 100;
|
||||
const int kDefaultHeuristicNumFailuresLimit = 30;
|
||||
const int kDefaultSeed = 0;
|
||||
const double kDefaultRestartLogSize = -1.0;
|
||||
const bool kDefaultUseNoGoods = true;
|
||||
const bool kDefaultUseLastConflict = true;
|
||||
} // namespace
|
||||
|
||||
DefaultPhaseParameters::DefaultPhaseParameters()
|
||||
: var_selection_schema(DefaultPhaseParameters::CHOOSE_MAX_SUM_IMPACT),
|
||||
value_selection_schema(DefaultPhaseParameters::SELECT_MIN_IMPACT),
|
||||
initialization_splits(kDefaultNumberOfSplits),
|
||||
run_all_heuristics(true),
|
||||
heuristic_period(kDefaultHeuristicPeriod),
|
||||
heuristic_num_failures_limit(kDefaultHeuristicNumFailuresLimit),
|
||||
persistent_impact(true),
|
||||
random_seed(kDefaultSeed),
|
||||
restart_log_size(kDefaultRestartLogSize),
|
||||
display_level(DefaultPhaseParameters::NORMAL),
|
||||
use_no_goods(kDefaultUseNoGoods),
|
||||
use_last_conflict(kDefaultUseLastConflict),
|
||||
decision_builder(nullptr) {}
|
||||
|
||||
namespace {
|
||||
// ----- DomainWatcher -----
|
||||
|
||||
@@ -1072,6 +1090,9 @@ class DefaultIntegerSearch : public DecisionBuilder {
|
||||
parameters_.heuristic_period,
|
||||
parameters_.heuristic_num_failures_limit),
|
||||
restart_monitor_(solver, parameters_, &domain_watcher_),
|
||||
find_var_(),
|
||||
last_int_var_(nullptr),
|
||||
last_int_value_(0),
|
||||
init_done_(false) {}
|
||||
|
||||
~DefaultIntegerSearch() override {}
|
||||
@@ -1083,9 +1104,31 @@ class DefaultIntegerSearch : public DecisionBuilder {
|
||||
return &heuristics_;
|
||||
}
|
||||
|
||||
return parameters_.decision_builder != nullptr
|
||||
? parameters_.decision_builder->Next(solver)
|
||||
: ImpactNext(solver);
|
||||
if (parameters_.use_last_conflict &&
|
||||
last_int_var_ != nullptr &&
|
||||
!last_int_var_->Bound() &&
|
||||
last_int_var_->Contains(last_int_value_)) {
|
||||
Decision* const assign_last =
|
||||
solver->MakeAssignVariableValue(last_int_var_, last_int_value_);
|
||||
last_int_var_ = nullptr;
|
||||
last_int_value_ = 0;
|
||||
return assign_last;
|
||||
}
|
||||
|
||||
Decision* const decision = parameters_.decision_builder != nullptr
|
||||
? parameters_.decision_builder->Next(solver)
|
||||
: ImpactNext(solver);
|
||||
|
||||
if (parameters_.use_last_conflict && decision != nullptr) {
|
||||
// Store the last decision to replay it upon failure.
|
||||
decision->Accept(&find_var_);
|
||||
if (find_var_.valid()) {
|
||||
last_int_var_ = find_var_.var();
|
||||
last_int_value_ = find_var_.value();
|
||||
}
|
||||
}
|
||||
|
||||
return decision;
|
||||
}
|
||||
|
||||
void AppendMonitors(Solver* const solver,
|
||||
@@ -1212,6 +1255,9 @@ class DefaultIntegerSearch : public DecisionBuilder {
|
||||
ImpactRecorder impact_recorder_;
|
||||
RunHeuristicsAsDives heuristics_;
|
||||
RestartMonitor restart_monitor_;
|
||||
FindVar find_var_;
|
||||
IntVar* last_int_var_;
|
||||
int64 last_int_value_;
|
||||
bool init_done_;
|
||||
};
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
DEFINE_int32(log_period, 10000000, "Search log period");
|
||||
DEFINE_bool(all, false, "Search for all solutions");
|
||||
DEFINE_bool(free, false, "Ignore search annotations");
|
||||
DEFINE_bool(last_conflict, false, "Use last conflict search hints");
|
||||
DEFINE_int32(num_solutions, 0, "Number of solution to search for");
|
||||
DEFINE_int32(time_limit, 0, "time limit in ms");
|
||||
DEFINE_int32(workers, 0, "Number of workers");
|
||||
@@ -67,6 +68,7 @@ void SequentialRun(const FzModel* model) {
|
||||
FzSolverParameters parameters;
|
||||
parameters.all_solutions = FLAGS_all;
|
||||
parameters.free_search = FLAGS_free;
|
||||
parameters.last_conflict = FLAGS_last_conflict;
|
||||
parameters.heuristic_period = FLAGS_heuristic_period;
|
||||
parameters.ignore_unknown = false;
|
||||
parameters.log_period = FLAGS_log_period;
|
||||
@@ -104,12 +106,14 @@ void ParallelRun(const FzModel* const model, int worker_id,
|
||||
switch (worker_id) {
|
||||
case 0: {
|
||||
parameters.free_search = false;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type = operations_research::FzSolverParameters::DEFAULT;
|
||||
parameters.restart_log_size = -1.0;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
parameters.free_search = true;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type =
|
||||
operations_research::FzSolverParameters::MIN_SIZE;
|
||||
parameters.restart_log_size = -1.0;
|
||||
@@ -117,12 +121,14 @@ void ParallelRun(const FzModel* const model, int worker_id,
|
||||
}
|
||||
case 2: {
|
||||
parameters.free_search = true;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type = operations_research::FzSolverParameters::IBS;
|
||||
parameters.restart_log_size = FLAGS_restart_log_size;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
parameters.free_search = true;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type =
|
||||
operations_research::FzSolverParameters::FIRST_UNBOUND;
|
||||
parameters.restart_log_size = -1.0;
|
||||
@@ -131,6 +137,7 @@ void ParallelRun(const FzModel* const model, int worker_id,
|
||||
}
|
||||
case 4: {
|
||||
parameters.free_search = true;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type = operations_research::FzSolverParameters::DEFAULT;
|
||||
parameters.restart_log_size = -1.0;
|
||||
parameters.heuristic_period = 30;
|
||||
@@ -139,6 +146,7 @@ void ParallelRun(const FzModel* const model, int worker_id,
|
||||
}
|
||||
default: {
|
||||
parameters.free_search = true;
|
||||
parameters.last_conflict = false;
|
||||
parameters.search_type =
|
||||
worker_id % 2 == 0
|
||||
? operations_research::FzSolverParameters::RANDOM_MIN
|
||||
|
||||
@@ -145,6 +145,7 @@ std::string FzMemoryUsage() {
|
||||
FzSolverParameters::FzSolverParameters()
|
||||
: all_solutions(false),
|
||||
free_search(false),
|
||||
last_conflict(false),
|
||||
ignore_annotations(false),
|
||||
ignore_unknown(true),
|
||||
use_log(false),
|
||||
@@ -269,7 +270,7 @@ void FzSolver::ParseSearchAnnotations(bool ignore_unknown,
|
||||
FlattenAnnotations(ann, &flat_annotations);
|
||||
}
|
||||
|
||||
FZLOG << " - using search annotations" << std::endl;
|
||||
FZLOG << " - parsing search annotations" << std::endl;
|
||||
hash_set<IntVar*> added;
|
||||
for (const FzAnnotation& ann : flat_annotations) {
|
||||
FZLOG << " - parse " << ann.DebugString() << FZENDL;
|
||||
@@ -445,7 +446,8 @@ void FzSolver::AddCompletionDecisionBuilders(
|
||||
|
||||
DecisionBuilder* FzSolver::CreateDecisionBuilders(const FzSolverParameters& p,
|
||||
SearchLimit* limit) {
|
||||
FZLOG << "Defining search" << std::endl;
|
||||
FZLOG << "Defining search" << (p.free_search ? " (free)" : " (fixed)")
|
||||
<< std::endl;
|
||||
// Fill builders_ with predefined search.
|
||||
std::vector<DecisionBuilder*> defined;
|
||||
std::vector<IntVar*> defined_variables;
|
||||
@@ -507,6 +509,7 @@ DecisionBuilder* FzSolver::CreateDecisionBuilders(const FzSolverParameters& p,
|
||||
defined_variables, Solver::CHOOSE_RANDOM, Solver::ASSIGN_MAX_VALUE);
|
||||
}
|
||||
}
|
||||
parameters.use_last_conflict = p.last_conflict;
|
||||
parameters.run_all_heuristics = p.run_all_heuristics;
|
||||
parameters.heuristic_period =
|
||||
model_.objective() != nullptr ||
|
||||
@@ -627,8 +630,13 @@ void FzSolver::Solve(FzSolverParameters p,
|
||||
}
|
||||
|
||||
if (p.luby_restart > 0) {
|
||||
FZLOG << " - using luby restart with a factor of " << p.luby_restart
|
||||
<< std::endl;
|
||||
monitors.push_back(solver()->MakeLubyRestart(p.luby_restart));
|
||||
}
|
||||
if (p.last_conflict && p.free_search) {
|
||||
FZLOG << " - using last conflict search hints" << std::endl;
|
||||
}
|
||||
|
||||
bool breaked = false;
|
||||
std::string solution_string;
|
||||
|
||||
@@ -31,6 +31,7 @@ struct FzSolverParameters {
|
||||
|
||||
bool all_solutions;
|
||||
bool free_search;
|
||||
bool last_conflict;
|
||||
bool ignore_annotations;
|
||||
bool ignore_unknown;
|
||||
bool use_log;
|
||||
|
||||
Reference in New Issue
Block a user