This commit is contained in:
Laurent Perron
2023-06-19 15:36:29 +02:00
parent 65fe5554a7
commit c26ac93f00
3 changed files with 13 additions and 33 deletions

View File

@@ -228,7 +228,7 @@ class NeighborhoodGeneratorHelper : public SubSolver {
}
// TODO(user): Refactor the class to be thread-safe instead, it should be
// safer and more easily maintenable. Some complication with accessing the
// safer and more easily maintainable. Some complication with accessing the
// variable<->constraint graph efficiently though.
// Note: This mutex needs to be public for thread annotations.
@@ -664,7 +664,8 @@ class RelaxationInducedNeighborhoodGenerator : public NeighborhoodGenerator {
response_manager_(response_manager),
lp_solutions_(lp_solutions),
incomplete_solutions_(incomplete_solutions) {
CHECK(lp_solutions_ != nullptr || incomplete_solutions != nullptr);
CHECK(lp_solutions_ != nullptr);
CHECK(incomplete_solutions != nullptr);
}
// Both initial solution and difficulty values are ignored.

View File

@@ -3273,7 +3273,7 @@ void SolveCpModelParallel(const CpModelProto& model_proto,
const bool use_feasibility_pump = params.use_feasibility_pump() &&
params.linearization_level() > 0 &&
!testing && !params.interleave_search();
if (use_feasibility_pump) {
if (use_feasibility_pump || params.use_rins_lns()) {
shared.incomplete_solutions =
std::make_unique<SharedIncompleteSolutionManager>();
global_model->Register<SharedIncompleteSolutionManager>(
@@ -3375,20 +3375,12 @@ void SolveCpModelParallel(const CpModelProto& model_proto,
// the requirement of having a SharedLPSolutionRepository to
// create RINS/RENS lns generators.
// TODO(user):
// - Do we keep rens working after the first solution has been found
// - Do we create a variable number of these workers.
// TODO(user): Do we create a variable number of these workers.
incomplete_subsolvers.push_back(std::make_unique<LnsSolver>(
std::make_unique<RelaxationInducedNeighborhoodGenerator>(
helper, shared.response, shared.lp_solutions.get(),
shared.incomplete_solutions.get(), "rins/rens"),
params, helper, &shared));
// incomplete_subsolvers.push_back(std::make_unique<LnsSolver>(
// std::make_unique<RelaxationInducedNeighborhoodGenerator>(
// helper, /*shared_response=*/nullptr, shared.lp_solutions.get(),
// shared.incomplete_solutions.get(), "rens_lns"),
// params, helper, &shared));
}
const bool feasibility_jump_possible =

View File

@@ -88,20 +88,20 @@ std::vector<double> GetIncompleteSolutionValues(
static double kEpsilon = 1e-7;
struct VarWeightTieBreak {
struct VarWeight {
int model_var;
// Variables with minimum weight will be fixed in the neighborhood.
double weight;
// Comparator with tolerance and random tie breaking.
bool operator<(const VarWeightTieBreak& o) const { return weight < o.weight; }
bool operator<(const VarWeight& o) const { return weight < o.weight; }
};
void FillRinsNeighborhood(const std::vector<int64_t>& solution,
const std::vector<double>& relaxation_values,
double difficulty, absl::BitGenRef random,
ReducedDomainNeighborhood& reduced_domains) {
std::vector<VarWeightTieBreak> var_lp_gap_pairs;
std::vector<VarWeight> var_lp_gap_pairs;
for (int model_var = 0; model_var < relaxation_values.size(); ++model_var) {
const double relaxation_value = relaxation_values[model_var];
if (relaxation_value == std::numeric_limits<double>::infinity()) continue;
@@ -129,8 +129,7 @@ void FillRinsNeighborhood(const std::vector<int64_t>& solution,
void FillRensNeighborhood(const std::vector<double>& relaxation_values,
double difficulty, absl::BitGenRef random,
ReducedDomainNeighborhood& reduced_domains) {
const double kTolerance = 1e-6;
std::vector<VarWeightTieBreak> var_fractionality_pairs;
std::vector<VarWeight> var_fractionality_pairs;
for (int model_var = 0; model_var < relaxation_values.size(); ++model_var) {
const double relaxation_value = relaxation_values[model_var];
if (relaxation_value == std::numeric_limits<double>::infinity()) continue;
@@ -155,22 +154,10 @@ void FillRensNeighborhood(const std::vector<double>& relaxation_values,
// domains, so the intersection of [domain_lb, domain_ub] with the
// initial variable domain might be empty.
const int64_t domain_lb =
static_cast<int64_t>(std::floor(relaxation_value - kTolerance));
const int64_t domain_ub =
static_cast<int64_t>(std::ceil(relaxation_value + kTolerance));
if (domain_ub - domain_lb == 1) {
reduced_domains.reduced_domain_vars.push_back(
{model_var, {domain_lb, domain_ub}});
} else if (std::floor(relaxation_value - kTolerance) !=
std::floor(relaxation_value)) {
// The tolerance crosses the integer value of the lb.
reduced_domains.reduced_domain_vars.push_back(
{model_var, {domain_lb + 1, domain_ub}});
} else {
// The tolerance crosses the integer value of the ub.
reduced_domains.reduced_domain_vars.push_back(
{model_var, {domain_lb, domain_ub - 1}});
}
static_cast<int64_t>(std::floor(relaxation_value));
// TODO(user): Use the domain here.
reduced_domains.reduced_domain_vars.push_back(
{model_var, {domain_lb, domain_lb + 1}});
}
}
}