minor changes; change the search parameters in the cp_model.proto
This commit is contained in:
69
dependencies/archives/autoconf.patch
vendored
69
dependencies/archives/autoconf.patch
vendored
@@ -1,69 +0,0 @@
|
||||
diff --git i/doc/autoconf.texi w/doc/autoconf.texi
|
||||
--- i/doc/autoconf.texi
|
||||
+++ w/doc/autoconf.texi
|
||||
@@ -15,7 +15,7 @@
|
||||
@c The ARG is an optional argument. To be used for macro arguments in
|
||||
@c their documentation (@defmac).
|
||||
@macro ovar{varname}
|
||||
-@r{[}@var{\varname\}@r{]}@c
|
||||
+@r{[}@var{\varname\}@r{]}
|
||||
@end macro
|
||||
|
||||
@c @dvar(ARG, DEFAULT)
|
||||
@@ -23,7 +23,7 @@
|
||||
@c The ARG is an optional argument, defaulting to DEFAULT. To be used
|
||||
@c for macro arguments in their documentation (@defmac).
|
||||
@macro dvar{varname, default}
|
||||
-@r{[}@var{\varname\} = @samp{\default\}@r{]}@c
|
||||
+@r{[}@var{\varname\} = @samp{\default\}@r{]}
|
||||
@end macro
|
||||
|
||||
@c Handling the indexes with Texinfo yields several different problems.
|
||||
@@ -8013,10 +8013,10 @@
|
||||
@code{ac_cv_f77_libs} or @code{ac_cv_fc_libs}, respectively.
|
||||
@end defmac
|
||||
|
||||
-@defmac AC_F77_DUMMY_MAIN (@ovar{action-if-found}, @dvar{action-if-not-found, @
|
||||
- AC_MSG_FAILURE})
|
||||
-@defmacx AC_FC_DUMMY_MAIN (@ovar{action-if-found}, @dvar{action-if-not-found, @
|
||||
- AC_MSG_FAILURE})
|
||||
+@defmac AC_F77_DUMMY_MAIN (@ovar{action-if-found}, @
|
||||
+ @dvar{action-if-not-found, AC_MSG_FAILURE})
|
||||
+@defmacx AC_FC_DUMMY_MAIN (@ovar{action-if-found}, @
|
||||
+ @dvar{action-if-not-found, AC_MSG_FAILURE})
|
||||
@acindex{F77_DUMMY_MAIN}
|
||||
@cvindex F77_DUMMY_MAIN
|
||||
@acindex{FC_DUMMY_MAIN}
|
||||
@@ -8267,8 +8267,8 @@
|
||||
@code{ac_cv_fc_pp_srcext_@var{ext}} variables, respectively.
|
||||
@end defmac
|
||||
|
||||
-@defmac AC_FC_PP_DEFINE (@ovar{action-if-success}, @dvar{action-if-failure, @
|
||||
- AC_MSG_FAILURE})
|
||||
+@defmac AC_FC_PP_DEFINE (@ovar{action-if-success}, @
|
||||
+ @dvar{action-if-failure, AC_MSG_FAILURE})
|
||||
@acindex{FC_PP_DEFINE}
|
||||
@caindex fc_pp_define
|
||||
|
||||
@@ -8286,8 +8286,8 @@
|
||||
variable.
|
||||
@end defmac
|
||||
|
||||
-@defmac AC_FC_FREEFORM (@ovar{action-if-success}, @dvar{action-if-failure, @
|
||||
- AC_MSG_FAILURE})
|
||||
+@defmac AC_FC_FREEFORM (@ovar{action-if-success}, @
|
||||
+ @dvar{action-if-failure, AC_MSG_FAILURE})
|
||||
@acindex{FC_FREEFORM}
|
||||
@caindex fc_freeform
|
||||
|
||||
@@ -8313,8 +8313,8 @@
|
||||
the @code{ac_cv_fc_freeform} variable.
|
||||
@end defmac
|
||||
|
||||
-@defmac AC_FC_FIXEDFORM (@ovar{action-if-success}, @dvar{action-if-failure, @
|
||||
- AC_MSG_FAILURE})
|
||||
+@defmac AC_FC_FIXEDFORM (@ovar{action-if-success}, @
|
||||
+ @dvar{action-if-failure, AC_MSG_FAILURE})
|
||||
@acindex{FC_FIXEDFORM}
|
||||
@caindex fc_fixedform
|
||||
|
||||
@@ -699,14 +699,14 @@ void InlinedVector<T, N, A>::swap(InlinedVector& other) {
|
||||
template <typename T, int N, typename A>
|
||||
template <typename Iter>
|
||||
inline void InlinedVector<T, N, A>::AppendRange(Iter first, Iter last,
|
||||
std::input_iterator_tag) {
|
||||
std::input_iterator_tag) {
|
||||
std::copy(first, last, std::back_inserter(*this));
|
||||
}
|
||||
|
||||
template <typename T, int N, typename A>
|
||||
template <typename Iter>
|
||||
inline void InlinedVector<T, N, A>::AppendRange(Iter first, Iter last,
|
||||
std::forward_iterator_tag) {
|
||||
std::forward_iterator_tag) {
|
||||
typedef typename std::iterator_traits<Iter>::difference_type Length;
|
||||
Length length = std::distance(first, last);
|
||||
size_t s = size();
|
||||
|
||||
@@ -93,7 +93,8 @@ int string_view::rfind(const string_view& s, size_type pos) const {
|
||||
|
||||
int string_view::rfind(char c, size_type pos) const {
|
||||
if (length_ <= 0) return npos;
|
||||
for (int i = std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
|
||||
for (int i = std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0;
|
||||
--i) {
|
||||
if (ptr_[i] == c) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -835,7 +835,10 @@ void SolveFzWithCpModelProto(const fz::Model& fz_model,
|
||||
// Enumerate all sat solutions.
|
||||
m.parameters.set_enumerate_all_solutions(true);
|
||||
}
|
||||
m.parameters.set_use_fixed_search(!p.free_search);
|
||||
if (!p.free_search) {
|
||||
m.parameters.set_search_branching(SatParameters::FIXED_SEARCH);
|
||||
}
|
||||
|
||||
if (p.time_limit_in_ms > 0) {
|
||||
m.parameters.set_max_time_in_seconds(p.time_limit_in_ms * 1e-3);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/file.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/bop/bop_parameters.pb.h"
|
||||
#include "ortools/bop/integral_solver.h"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/base/strutil.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
|
||||
#include "ortools/base/integral_types.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/port.h"
|
||||
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/glop/lp_solver.h"
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "ortools/base/hash.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
|
||||
@@ -992,5 +993,6 @@ MPSolverInterface* BuildGLPKInterface(bool mip, MPSolver* const solver) {
|
||||
return new GLPKInterface(solver, mip);
|
||||
}
|
||||
|
||||
|
||||
} // namespace operations_research
|
||||
#endif // #if defined(USE_GLPK)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "ortools/base/map_util.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ortools/port/file.h"
|
||||
|
||||
|
||||
#include "ortools/base/join.h"
|
||||
#include "ortools/base/map_util.h"
|
||||
#include "ortools/base/stl_util.h"
|
||||
#include "ortools/base/hash.h"
|
||||
@@ -41,8 +42,7 @@
|
||||
#include "ortools/linear_solver/model_exporter.h"
|
||||
#include "ortools/linear_solver/model_validator.h"
|
||||
#include "ortools/util/fp_utils.h"
|
||||
|
||||
// TODO(user): Clean up includes. E.g., parameters.pb.h seems not used.
|
||||
#include "ortools/base/canonical_errors.h"
|
||||
|
||||
DEFINE_bool(verify_solution, false,
|
||||
"Systematically verify the solution when calling Solve()"
|
||||
@@ -399,7 +399,7 @@ MPSolverInterface* BuildSolverInterface(MPSolver* const solver) {
|
||||
namespace {
|
||||
int NumDigits(int n) {
|
||||
// Number of digits needed to write a non-negative integer in base 10.
|
||||
// Note(user): std::max(1, log(0) + 1) == std::max(1, -inf) == 1.
|
||||
// Note(user): max(1, log(0) + 1) == max(1, -inf) == 1.
|
||||
#if defined(_MSC_VER)
|
||||
return static_cast<int>(std::max(1.0L, log(1.0L * n) / log(10.0L) + 1.0));
|
||||
#else
|
||||
@@ -764,12 +764,12 @@ bool MPSolver::LoadSolutionFromProto(const MPSolutionResponse& response) {
|
||||
}
|
||||
double largest_error = 0;
|
||||
interface_->ExtractModel();
|
||||
|
||||
// Look further: verify that the variable values are within the bounds.
|
||||
int num_vars_out_of_bounds = 0;
|
||||
const double tolerance = MPSolverParameters::kDefaultPrimalTolerance;
|
||||
int last_offending_var = -1;
|
||||
for (int i = 0; i < response.variable_value_size(); ++i) {
|
||||
// Look further: verify the bounds. Since linear solvers yield (small)
|
||||
// numerical errors, though, we just log a warning if the variables look
|
||||
// like they are out of their bounds. The user should inspect the values.
|
||||
const double var_value = response.variable_value(i);
|
||||
MPVariable* var = variables_[i];
|
||||
// TODO(user): Use parameter when they become available in this class.
|
||||
@@ -778,8 +778,8 @@ bool MPSolver::LoadSolutionFromProto(const MPSolutionResponse& response) {
|
||||
if (lb_error > tolerance || ub_error > tolerance) {
|
||||
++num_vars_out_of_bounds;
|
||||
largest_error = std::max(largest_error, std::max(lb_error, ub_error));
|
||||
last_offending_var = i;
|
||||
}
|
||||
var->set_solution_value(var_value);
|
||||
}
|
||||
if (num_vars_out_of_bounds > 0) {
|
||||
LOG(WARNING)
|
||||
@@ -789,6 +789,7 @@ bool MPSolver::LoadSolutionFromProto(const MPSolutionResponse& response) {
|
||||
<< tolerance;
|
||||
}
|
||||
// Set the objective value, if is known.
|
||||
// NOTE(user): We do not verify the objective, even though we could!
|
||||
if (response.has_objective_value()) {
|
||||
interface_->objective_value_ = response.objective_value();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/stringprintf.h"
|
||||
#include "ortools/base/timer.h"
|
||||
#include "ortools/base/port.h"
|
||||
#include "scip/scip.h"
|
||||
#include "scip/scipdefplugins.h"
|
||||
#include "ortools/base/hash.h"
|
||||
|
||||
@@ -377,9 +377,9 @@ message CpModelProto {
|
||||
// The objective to minimize. Can be empty for pure decision problems.
|
||||
CpObjectiveProto objective = 4;
|
||||
|
||||
// Defines the strategy that the solver should follow when the "fixed_search"
|
||||
// parameters is set to true. Note that this strategy is also used as an
|
||||
// heuristic when we are not in fixed search.
|
||||
// Defines the strategy that the solver should follow when the
|
||||
// search_branching parameter is set to FIXED_SEARCH. Note that this strategy
|
||||
// is also used as a heuristic when we are not in fixed search.
|
||||
//
|
||||
// If empty, the solver will try to assign all variables to their min value in
|
||||
// the order of their appearance in the variables field above. Otherwise, it
|
||||
|
||||
@@ -506,7 +506,8 @@ ModelWithMapping::ModelWithMapping(const CpModelProto& model_proto,
|
||||
const SatParameters& parameters = *(model->GetOrCreate<SatParameters>());
|
||||
const bool view_all_booleans_as_integers =
|
||||
(parameters.linearization_level() > 2) ||
|
||||
(parameters.use_fixed_search() && model_proto.search_strategy().empty());
|
||||
(parameters.search_branching() == SatParameters::FIXED_SEARCH &&
|
||||
model_proto.search_strategy().empty());
|
||||
if (view_all_booleans_as_integers) {
|
||||
var_to_instantiate_as_integer.resize(num_proto_variables);
|
||||
for (int i = 0; i < num_proto_variables; ++i) {
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
namespace operations_research {
|
||||
namespace sat {
|
||||
|
||||
// TODO(user): the complexity of this heuristic and the one below is ok when
|
||||
// use_fixed_search() is false because it is not executed often, however, we do
|
||||
// a linear scan for each search decision when use_fixed_search() is true, which
|
||||
// seems bad. Improve.
|
||||
// TODO(user): the complexity caused by the linear scan in this heuristic and
|
||||
// the one below is ok when search_branching is set to SAT_SEARCH because it is
|
||||
// not executed often, but otherwise it is done for each search decision,
|
||||
// which seems expensive. Improve.
|
||||
std::function<LiteralIndex()> FirstUnassignedVarAtItsMinHeuristic(
|
||||
const std::vector<IntegerVariable>& vars, Model* model) {
|
||||
IntegerEncoder* const integer_encoder = model->GetOrCreate<IntegerEncoder>();
|
||||
@@ -99,18 +99,15 @@ std::function<LiteralIndex()> ExploitIntegerLpSolution(
|
||||
auto* trail = model->GetOrCreate<Trail>();
|
||||
auto* integer_trail = model->GetOrCreate<IntegerTrail>();
|
||||
auto* lp_dispatcher = model->GetOrCreate<LinearProgrammingDispatcher>();
|
||||
|
||||
// Note that the order of the constraints in lp_constraints does not matter.
|
||||
// TODO(user): keep this list somewhere instead of re-creating it like this?
|
||||
std::set<LinearProgrammingConstraint*> lp_constraints;
|
||||
for (auto entry : *lp_dispatcher) lp_constraints.insert(entry.second);
|
||||
auto* lp_constraints =
|
||||
model->GetOrCreate<LinearProgrammingConstraintCollection>();
|
||||
|
||||
// Use the normal heuristic if the LP(s) do not seem to cover enough variables
|
||||
// to be relevant.
|
||||
// TODO(user): Instead, try and depending on the result call it again or not?
|
||||
{
|
||||
int num_lp_variables = 0;
|
||||
for (LinearProgrammingConstraint* lp : lp_constraints) {
|
||||
for (LinearProgrammingConstraint* lp : *lp_constraints) {
|
||||
num_lp_variables += lp->NumVariables();
|
||||
}
|
||||
const int num_integer_variables =
|
||||
@@ -134,7 +131,7 @@ std::function<LiteralIndex()> ExploitIntegerLpSolution(
|
||||
|
||||
bool all_lp_integers = true;
|
||||
double obj = 0.0;
|
||||
for (LinearProgrammingConstraint* lp : lp_constraints) {
|
||||
for (LinearProgrammingConstraint* lp : *lp_constraints) {
|
||||
if (!lp->HasSolution() || !lp->SolutionIsInteger()) {
|
||||
all_lp_integers = false;
|
||||
break;
|
||||
@@ -223,28 +220,56 @@ SatSolver::Status SolveIntegerProblemWithLazyEncoding(
|
||||
solver->SetAssumptionLevel(0);
|
||||
|
||||
const SatParameters& parameters = *(model->GetOrCreate<SatParameters>());
|
||||
if (parameters.use_fixed_search()) {
|
||||
CHECK(assumptions.empty()) << "Not supported yet";
|
||||
// Note that it is important to do the level-zero propagation if it wasn't
|
||||
// already done because EnqueueDecisionAndBackjumpOnConflict() assumes that
|
||||
// the solver is in a "propagated" state.
|
||||
if (!solver->Propagate()) return SatSolver::MODEL_UNSAT;
|
||||
}
|
||||
|
||||
if (parameters.use_portfolio_search() && assumptions.empty()) {
|
||||
auto incomplete_portfolio = AddModelHeuristics({next_decision}, model);
|
||||
auto portfolio = CompleteHeuristics(
|
||||
incomplete_portfolio,
|
||||
SequentialSearch({SatSolverHeuristic(model), next_decision}));
|
||||
if (parameters.exploit_integer_lp_solution()) {
|
||||
for (auto& ref : portfolio) {
|
||||
ref = ExploitIntegerLpSolution(ref, model);
|
||||
}
|
||||
switch (parameters.search_branching()) {
|
||||
case SatParameters::AUTOMATIC_SEARCH:
|
||||
break;
|
||||
case SatParameters::FIXED_SEARCH: {
|
||||
CHECK(assumptions.empty()) << "Not supported yet";
|
||||
// Note that it is important to do the level-zero propagation if it wasn't
|
||||
// already done because EnqueueDecisionAndBackjumpOnConflict() assumes
|
||||
// that the solver is in a "propagated" state.
|
||||
if (!solver->Propagate()) return SatSolver::MODEL_UNSAT;
|
||||
break;
|
||||
}
|
||||
case SatParameters::PORTFOLIO_SEARCH: {
|
||||
CHECK(assumptions.empty()) << "Not supported yet";
|
||||
auto incomplete_portfolio = AddModelHeuristics({next_decision}, model);
|
||||
auto portfolio = CompleteHeuristics(
|
||||
incomplete_portfolio,
|
||||
SequentialSearch({SatSolverHeuristic(model), next_decision}));
|
||||
if (parameters.exploit_integer_lp_solution()) {
|
||||
for (auto& ref : portfolio) {
|
||||
ref = ExploitIntegerLpSolution(ref, model);
|
||||
}
|
||||
}
|
||||
auto default_restart_policy = SatSolverRestartPolicy(model);
|
||||
auto restart_policies = std::vector<std::function<bool()>>(
|
||||
portfolio.size(), default_restart_policy);
|
||||
return SolveProblemWithPortfolioSearch(portfolio, restart_policies,
|
||||
model);
|
||||
}
|
||||
case SatParameters::LP_SEARCH: {
|
||||
CHECK(assumptions.empty()) << "Not supported yet";
|
||||
// Fill portfolio with pseudocost heuristics.
|
||||
std::vector<std::function<LiteralIndex()>> lp_heuristics;
|
||||
for (const auto& ct :
|
||||
*(model->GetOrCreate<LinearProgrammingConstraintCollection>())) {
|
||||
lp_heuristics.push_back(ct->HeuristicLPPseudoCostBinary(model));
|
||||
}
|
||||
auto portfolio = CompleteHeuristics(
|
||||
lp_heuristics,
|
||||
SequentialSearch({SatSolverHeuristic(model), next_decision}));
|
||||
if (parameters.exploit_integer_lp_solution()) {
|
||||
for (auto& ref : portfolio) {
|
||||
ref = ExploitIntegerLpSolution(ref, model);
|
||||
}
|
||||
}
|
||||
auto default_restart_policy = SatSolverRestartPolicy(model);
|
||||
auto restart_policies = std::vector<std::function<bool()>>(
|
||||
portfolio.size(), default_restart_policy);
|
||||
return SolveProblemWithPortfolioSearch(portfolio, restart_policies,
|
||||
model);
|
||||
}
|
||||
auto default_restart_policy = SatSolverRestartPolicy(model);
|
||||
auto restart_policies = std::vector<std::function<bool()>>(
|
||||
portfolio.size(), default_restart_policy);
|
||||
return SolveProblemWithPortfolioSearch(portfolio, restart_policies, model);
|
||||
}
|
||||
|
||||
if (parameters.exploit_integer_lp_solution() && assumptions.empty()) {
|
||||
@@ -259,7 +284,7 @@ SatSolver::Status SolveIntegerProblemWithLazyEncoding(
|
||||
while (!time_limit->LimitReached()) {
|
||||
// If we are not in fixed search, let the SAT solver do a full search to
|
||||
// instantiate all the already created Booleans.
|
||||
if (!parameters.use_fixed_search()) {
|
||||
if (parameters.search_branching() == SatParameters::AUTOMATIC_SEARCH) {
|
||||
if (assumptions.empty()) {
|
||||
const SatSolver::Status status = solver->Solve();
|
||||
if (status != SatSolver::MODEL_SAT) return status;
|
||||
|
||||
@@ -93,6 +93,7 @@ void LinearProgrammingConstraint::SetObjectiveCoefficient(IntegerVariable ivar,
|
||||
void LinearProgrammingConstraint::RegisterWith(Model* model) {
|
||||
DCHECK(!lp_constraint_is_registered_);
|
||||
lp_constraint_is_registered_ = true;
|
||||
model->GetOrCreate<LinearProgrammingConstraintCollection>()->push_back(this);
|
||||
|
||||
// Note that the order is important so that the lp objective is exactly the
|
||||
// same as the cp objective after scaling by the factor stored in lp_data_.
|
||||
|
||||
@@ -222,29 +222,6 @@ class LinearProgrammingConstraint : public PropagatorInterface,
|
||||
int NumVariables() const { return integer_variables_.size(); }
|
||||
std::string DimensionString() const { return lp_data_.GetDimensionString(); }
|
||||
|
||||
private:
|
||||
// Generates a set of IntegerLiterals explaining why the best solution can not
|
||||
// be improved using reduced costs. This is used to generate explanations for
|
||||
// both infeasibility and bounds deductions.
|
||||
void FillReducedCostsReason();
|
||||
|
||||
// Same as FillReducedCostReason() but for the case of a DUAL_UNBOUNDED
|
||||
// problem. This exploit the dual ray as a reason for the primal infeasiblity.
|
||||
void FillDualRayReason();
|
||||
|
||||
// Fills the deductions vector with reduced cost deductions that can be made
|
||||
// from the current state of the LP solver. The given delta should be the
|
||||
// difference between the cp objective upper bound and lower bound given by
|
||||
// the lp.
|
||||
void ReducedCostStrengtheningDeductions(double cp_objective_delta);
|
||||
|
||||
// Gets or creates an LP variable that mirrors a CP variable.
|
||||
// The variable should be a positive reference.
|
||||
glop::ColIndex GetOrCreateMirrorVariable(IntegerVariable positive_variable);
|
||||
|
||||
// Returns the variable value on the same scale as the CP variable value.
|
||||
glop::Fractional GetVariableValueAtCpScale(glop::ColIndex var);
|
||||
|
||||
// Returns a LiteralIndex guided by the underlying LP constraints.
|
||||
// This looks at all unassigned 0-1 variables, takes the one with
|
||||
// a support value closest to 0.5, and tries to assign it to 1.
|
||||
@@ -273,6 +250,29 @@ class LinearProgrammingConstraint : public PropagatorInterface,
|
||||
// pseudo = a * pseudo + (1-a) reduced.
|
||||
std::function<LiteralIndex()> HeuristicLPPseudoCostBinary(Model* model);
|
||||
|
||||
private:
|
||||
// Generates a set of IntegerLiterals explaining why the best solution can not
|
||||
// be improved using reduced costs. This is used to generate explanations for
|
||||
// both infeasibility and bounds deductions.
|
||||
void FillReducedCostsReason();
|
||||
|
||||
// Same as FillReducedCostReason() but for the case of a DUAL_UNBOUNDED
|
||||
// problem. This exploit the dual ray as a reason for the primal infeasiblity.
|
||||
void FillDualRayReason();
|
||||
|
||||
// Fills the deductions vector with reduced cost deductions that can be made
|
||||
// from the current state of the LP solver. The given delta should be the
|
||||
// difference between the cp objective upper bound and lower bound given by
|
||||
// the lp.
|
||||
void ReducedCostStrengtheningDeductions(double cp_objective_delta);
|
||||
|
||||
// Gets or creates an LP variable that mirrors a CP variable.
|
||||
// The variable should be a positive reference.
|
||||
glop::ColIndex GetOrCreateMirrorVariable(IntegerVariable positive_variable);
|
||||
|
||||
// Returns the variable value on the same scale as the CP variable value.
|
||||
glop::Fractional GetVariableValueAtCpScale(glop::ColIndex var);
|
||||
|
||||
// TODO(user): use solver's precision epsilon.
|
||||
static const double kEpsilon;
|
||||
|
||||
@@ -338,6 +338,13 @@ class LinearProgrammingDispatcher
|
||||
explicit LinearProgrammingDispatcher(Model* model) {}
|
||||
};
|
||||
|
||||
// A class that stores the collection of all LP constraints in a model.
|
||||
class LinearProgrammingConstraintCollection
|
||||
: public std::vector<LinearProgrammingConstraint*> {
|
||||
public:
|
||||
LinearProgrammingConstraintCollection() {}
|
||||
};
|
||||
|
||||
// Cut generator for the circuit constraint, where in any feasible solution, the
|
||||
// arcs that are present (variable at 1) must form a circuit through all the
|
||||
// nodes of the graph. Self arc are forbidden in this case.
|
||||
|
||||
@@ -18,7 +18,7 @@ package operations_research.sat;
|
||||
// Contains the definitions for all the sat algorithm parameters and their
|
||||
// default values.
|
||||
//
|
||||
// NEXT TAG: 96
|
||||
// NEXT TAG: 95
|
||||
message SatParameters {
|
||||
// ==========================================================================
|
||||
// Branching and polarity
|
||||
@@ -472,23 +472,34 @@ message SatParameters {
|
||||
optional int32 max_num_cuts = 91 [default = 1000];
|
||||
optional bool only_add_cuts_at_level_zero = 92 [default = false];
|
||||
|
||||
// If true then all decisions taken by the solver are made using a fixed order
|
||||
// as specified in the API or in the cp_model.proto search_order field.
|
||||
//
|
||||
// TODO(user): This is not working in all situation yet. The time limit is not
|
||||
// really enforced properly, we don't support assumptions, and all the
|
||||
// decisions variables must be integers.
|
||||
optional bool use_fixed_search = 82 [default = false];
|
||||
// The search branching will be used to decide how to branch on unfixed nodes.
|
||||
enum SearchBranching {
|
||||
// Try to fix all literals using the underlying SAT solver's heuristics,
|
||||
// then generate and fix literals until integer variables are fixed.
|
||||
AUTOMATIC_SEARCH = 0;
|
||||
|
||||
// If true, the solver will use generic heuristics to find solutions and
|
||||
// prove optimality. Incompatible with use_fixed_search.
|
||||
optional bool use_portfolio_search = 94 [default = false];
|
||||
// If used then all decisions taken by the solver are made using a fixed
|
||||
// order as specified in the API or in the cp_model.proto search_order
|
||||
// field.
|
||||
//
|
||||
// TODO(user): This is not working in all situation yet. The time limit is
|
||||
// not really enforced properly, we don't support assumptions, and all the
|
||||
// decisions variables must be integers.
|
||||
FIXED_SEARCH = 1;
|
||||
|
||||
// If used, the solver will use various generic heuristics in turn.
|
||||
PORTFOLIO_SEARCH = 2;
|
||||
|
||||
// If used, the solver will use heuristics from the LP relaxation.
|
||||
LP_SEARCH = 3;
|
||||
}
|
||||
optional SearchBranching search_branching = 82 [default = AUTOMATIC_SEARCH];
|
||||
|
||||
// If true and the Lp relaxation of the problem has an integer optimal
|
||||
// solution, try to exploit it. Note that since the LP relaxation may not
|
||||
// contain all the constraints, such a solution is not necessarily a solution
|
||||
// of the full problem.
|
||||
optional bool exploit_integer_lp_solution = 95 [default = true];
|
||||
optional bool exploit_integer_lp_solution = 94 [default = true];
|
||||
|
||||
// The default optimization method is a simple "linear scan", each time trying
|
||||
// to find a better solution than the previous one. If this is true, then we
|
||||
|
||||
@@ -335,6 +335,10 @@ void SatPresolver::PresolveWithBva() {
|
||||
|
||||
// We use the same notation as in the article mentionned in the .h
|
||||
void SatPresolver::SimpleBva(LiteralIndex l) {
|
||||
literal_to_p_size_.resize(literal_to_clauses_.size(), 0);
|
||||
DCHECK(std::all_of(literal_to_p_size_.begin(), literal_to_p_size_.end(),
|
||||
[](int v) { return v == 0; }));
|
||||
|
||||
// We will try to add a literal to m_lit_ and take a subset of m_cls_ such
|
||||
// that |m_lit_| * |m_cls_| - |m_lit_| - |m_cls_| is maximized.
|
||||
m_lit_ = {l};
|
||||
@@ -342,7 +346,10 @@ void SatPresolver::SimpleBva(LiteralIndex l) {
|
||||
|
||||
int reduction = 0;
|
||||
while (true) {
|
||||
p_.clear();
|
||||
LiteralIndex lmax = kNoLiteralIndex;
|
||||
int max_size = 0;
|
||||
|
||||
flattened_p_.clear();
|
||||
for (const ClauseIndex c : m_cls_) {
|
||||
const std::vector<Literal>& clause = clauses_[c];
|
||||
if (clause.empty()) continue; // It has been deleted.
|
||||
@@ -368,24 +375,21 @@ void SatPresolver::SimpleBva(LiteralIndex l) {
|
||||
VLOG(1) << "self-subsumbtion";
|
||||
}
|
||||
|
||||
DCHECK(p_[l_diff].empty() || p_[l_diff].back() != c);
|
||||
p_[l_diff].push_back(c);
|
||||
flattened_p_.push_back({l_diff, c});
|
||||
const int new_size = ++literal_to_p_size_[l_diff];
|
||||
if (new_size > max_size) {
|
||||
lmax = l_diff;
|
||||
max_size = new_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LiteralIndex lmax = kNoLiteralIndex;
|
||||
int max_size = 0;
|
||||
for (const auto& entry : p_) {
|
||||
if (entry.second.size() > max_size) {
|
||||
lmax = entry.first;
|
||||
max_size = entry.second.size();
|
||||
}
|
||||
}
|
||||
if (lmax == kNoLiteralIndex) break;
|
||||
const int new_m_lit_size = m_lit_.size() + 1;
|
||||
const int new_m_cls_size = p_[lmax].size();
|
||||
const int new_m_cls_size = max_size;
|
||||
const int new_reduction =
|
||||
new_m_lit_size * new_m_cls_size - new_m_cls_size - new_m_lit_size;
|
||||
|
||||
if (new_reduction <= reduction) break;
|
||||
CHECK_NE(1, new_m_lit_size);
|
||||
CHECK_NE(1, new_m_cls_size);
|
||||
@@ -396,9 +400,20 @@ void SatPresolver::SimpleBva(LiteralIndex l) {
|
||||
// not that often compared to the initial computation of p.
|
||||
reduction = new_reduction;
|
||||
m_lit_.insert(lmax);
|
||||
m_cls_ = p_[lmax];
|
||||
|
||||
// Set m_cls_ to p_[lmax].
|
||||
m_cls_.clear();
|
||||
for (const auto entry : flattened_p_) {
|
||||
literal_to_p_size_[entry.first] = 0;
|
||||
if (entry.first == lmax) m_cls_.push_back(entry.second);
|
||||
}
|
||||
flattened_p_.clear();
|
||||
}
|
||||
|
||||
// Make sure literal_to_p_size_ is all zero.
|
||||
for (const auto entry : flattened_p_) literal_to_p_size_[entry.first] = 0;
|
||||
flattened_p_.clear();
|
||||
|
||||
// A strictly positive reduction means that applying the BVA transform will
|
||||
// reduce the overall number of clauses by that much. Here we can control
|
||||
// what kind of reduction we want to apply.
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define OR_TOOLS_SAT_SIMPLIFICATION_H_
|
||||
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@@ -302,7 +301,8 @@ class SatPresolver {
|
||||
// Temporary data for SimpleBva().
|
||||
std::set<LiteralIndex> m_lit_;
|
||||
std::vector<ClauseIndex> m_cls_;
|
||||
std::unordered_map<LiteralIndex, std::vector<ClauseIndex>> p_;
|
||||
ITIVector<LiteralIndex, int> literal_to_p_size_;
|
||||
std::vector<std::pair<LiteralIndex, ClauseIndex>> flattened_p_;
|
||||
std::vector<Literal> tmp_new_clause_;
|
||||
|
||||
// List of clauses on which we need to call ProcessClauseToSimplifyOthers().
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// to find (whereas the class methods are easy to find).
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include "ortools/base/integral_types.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
const char inst_retired_event[] = "inst_retired:any_p:u";
|
||||
const char cycles_event[] = "cycles:u";
|
||||
|
||||
std::string MemoryUsage() {
|
||||
const int64 mem = operations_research::sysinfo::MemoryUsageProcess();
|
||||
static const int64 kDisplayThreshold = 2;
|
||||
|
||||
@@ -341,6 +341,11 @@ class DisabledScopedTimeDistributionUpdater {
|
||||
#ifdef HAS_PERF_SUBSYSTEM
|
||||
// Helper classes to count instructions during execution of a block of code and
|
||||
// add print the results to logs.
|
||||
//
|
||||
// Note: To enable instruction counting on machines running Debian, execute the
|
||||
// following commands to modify the permissions.
|
||||
// sudo echo "1" > /proc/sys/kernel/perf_event_paranoid
|
||||
// sudo echo "0" > /proc/sys/kernel/kptr_restrict
|
||||
class EnabledScopedInstructionCounter {
|
||||
public:
|
||||
explicit EnabledScopedInstructionCounter(const std::string& name,
|
||||
@@ -402,8 +407,8 @@ inline std::string RemoveOperationsResearchAndGlop(const std::string& pretty_fun
|
||||
pretty_function, {{"operations_research::", ""}, {"glop::", ""}});
|
||||
}
|
||||
|
||||
#define SCOPED_INSTRUCTION_COUNT(time_limit) \
|
||||
operations_research::ScopedInstructionCounterTemp scoped_instruction_count( \
|
||||
#define SCOPED_INSTRUCTION_COUNT(time_limit) \
|
||||
operations_research::ScopedInstructionCounter scoped_instruction_count( \
|
||||
RemoveOperationsResearchAndGlop(__PRETTY_FUNCTION__), time_limit)
|
||||
|
||||
#endif // HAS_PERF_SUBSYSTEM
|
||||
|
||||
Reference in New Issue
Block a user