25#include "absl/log/check.h"
26#include "absl/random/bit_gen_ref.h"
27#include "absl/random/distributions.h"
28#include "absl/types/span.h"
40 if (lp_solutions ==
nullptr)
return;
50 std::vector<double> relaxation_values(
51 mapping->NumProtoVariables(), std::numeric_limits<double>::infinity());
54 const int size = lp_values->size();
56 const int proto_var = mapping->GetProtoVariableFromIntegerVariable(
var);
57 if (proto_var != -1) {
58 relaxation_values[proto_var] = (*lp_values)[
var];
62 lp_solutions->NewLPSolution(std::move(relaxation_values));
67std::vector<double> GetLPRelaxationValues(
68 const SharedLPSolutionRepository* lp_solutions, absl::BitGenRef random) {
69 std::vector<double> relaxation_values;
71 if (lp_solutions ==
nullptr || lp_solutions->NumSolutions() == 0) {
72 return relaxation_values;
75 const SharedSolutionRepository<double>::Solution lp_solution =
76 lp_solutions->GetRandomBiasedSolution(random);
80 relaxation_values.push_back(lp_solution.variable_values[
model_var]);
82 return relaxation_values;
85std::vector<double> GetIncompleteSolutionValues(
86 SharedIncompleteSolutionManager* incomplete_solutions) {
87 std::vector<double> empty_solution_values;
89 if (incomplete_solutions ==
nullptr || !incomplete_solutions->HasSolution()) {
90 return empty_solution_values;
93 return incomplete_solutions->PopLast();
104 bool operator<(
const VarWeight& o)
const {
return weight < o.weight; }
107void FillRinsNeighborhood(absl::Span<const int64_t>
solution,
108 absl::Span<const double> relaxation_values,
109 double difficulty, absl::BitGenRef random,
110 ReducedDomainNeighborhood& reduced_domains) {
111 std::vector<VarWeight> var_lp_gap_pairs;
113 const double relaxation_value = relaxation_values[
model_var];
114 if (relaxation_value == std::numeric_limits<double>::infinity())
continue;
117 const double pertubation = absl::Uniform(random, -kEpsilon, kEpsilon);
118 var_lp_gap_pairs.push_back({
120 std::abs(relaxation_value -
static_cast<double>(best_solution_value)) +
124 std::sort(var_lp_gap_pairs.begin(), var_lp_gap_pairs.end());
126 const int target_size = std::min(
127 static_cast<int>(std::round(
128 static_cast<double>(relaxation_values.size()) * (1.0 - difficulty))),
129 static_cast<int>(var_lp_gap_pairs.size()));
130 for (
int i = 0;
i < target_size; ++
i) {
131 const int model_var = var_lp_gap_pairs[
i].model_var;
136void FillRensNeighborhood(absl::Span<const double> relaxation_values,
137 double difficulty, absl::BitGenRef random,
138 ReducedDomainNeighborhood& reduced_domains) {
139 std::vector<VarWeight> var_fractionality_pairs;
141 const double relaxation_value = relaxation_values[
model_var];
142 if (relaxation_value == std::numeric_limits<double>::infinity())
continue;
144 const double pertubation = absl::Uniform(random, -kEpsilon, kEpsilon);
145 var_fractionality_pairs.push_back(
146 {
model_var, std::abs(std::round(relaxation_value) - relaxation_value) +
149 std::sort(var_fractionality_pairs.begin(), var_fractionality_pairs.end());
150 const int target_size =
static_cast<int>(std::round(
151 static_cast<double>(relaxation_values.size()) * (1.0 - difficulty)));
152 for (
int i = 0;
i < var_fractionality_pairs.size(); ++
i) {
153 const int model_var = var_fractionality_pairs[
i].model_var;
154 const double relaxation_value = relaxation_values[
model_var];
155 if (
i < target_size) {
157 reduced_domains.fixed_vars.push_back(
158 {
model_var,
static_cast<int64_t
>(std::round(relaxation_value))});
163 const int64_t domain_lb =
164 static_cast<int64_t
>(std::floor(relaxation_value));
166 reduced_domains.reduced_domain_vars.push_back(
167 {
model_var, {domain_lb, domain_lb + 1}});
178 absl::BitGenRef random) {
180 CHECK(lp_solutions !=
nullptr);
181 CHECK(incomplete_solutions !=
nullptr);
182 const bool lp_solution_available = lp_solutions->
NumSolutions() > 0;
183 const bool incomplete_solution_available =
186 if (!lp_solution_available && !incomplete_solution_available) {
187 return reduced_domains;
192 std::bernoulli_distribution random_bool(0.5);
194 const bool use_lp_relaxation =
195 lp_solution_available && incomplete_solution_available
196 ? random_bool(random)
197 : lp_solution_available;
199 const std::vector<double> relaxation_values =
200 use_lp_relaxation ? GetLPRelaxationValues(lp_solutions, random)
201 : GetIncompleteSolutionValues(incomplete_solutions);
202 if (relaxation_values.empty())
return reduced_domains;
204 std::bernoulli_distribution three_out_of_four(0.75);
206 if (response_manager !=
nullptr &&
208 three_out_of_four(random)) {
209 const std::vector<int64_t>
solution =
213 FillRinsNeighborhood(
solution, relaxation_values, difficulty, random,
217 FillRensNeighborhood(relaxation_values, difficulty, random,
223 use_lp_relaxation ?
"lp" :
"pump",
"_lns");
224 return reduced_domains;
const SharedSolutionRepository< int64_t > & SolutionsRepository() const
Solution GetRandomBiasedSolution(absl::BitGenRef random) const
Returns a random solution biased towards good solutions.
constexpr double kEpsilon
Epsilon for type Fractional, i.e. the smallest e such that 1.0 + e != 1.0 .
ReducedDomainNeighborhood GetRinsRensNeighborhood(const SharedResponseManager *response_manager, const SharedLPSolutionRepository *lp_solutions, SharedIncompleteSolutionManager *incomplete_solutions, double difficulty, absl::BitGenRef random)
void RecordLPRelaxationValues(Model *model)
Adds the current LP solution to the pool.
In SWIG mode, we don't want anything besides these top-level includes.