OR-Tools  9.1
rins.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "ortools/sat/rins.h"
15 
16 #include <cstdint>
17 #include <limits>
18 
20 #include "ortools/sat/integer.h"
22 
23 namespace operations_research {
24 namespace sat {
25 
27  auto* lp_solutions = model->Mutable<SharedLPSolutionRepository>();
28  if (lp_solutions == nullptr) return;
29 
30  const LPVariables& lp_vars = *model->GetOrCreate<LPVariables>();
31  std::vector<double> relaxation_values(
32  lp_vars.model_vars_size, std::numeric_limits<double>::infinity());
33 
34  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
35  for (const LPVariable& lp_var : lp_vars.vars) {
36  const IntegerVariable positive_var = lp_var.positive_var;
37  if (integer_trail->IsCurrentlyIgnored(positive_var)) continue;
38 
39  LinearProgrammingConstraint* lp = lp_var.lp;
40  if (lp == nullptr || !lp->HasSolution()) continue;
41 
42  relaxation_values[lp_var.model_var] = lp->GetSolutionValue(positive_var);
43  }
44  lp_solutions->NewLPSolution(std::move(relaxation_values));
45 }
46 
47 namespace {
48 
49 std::vector<double> GetLPRelaxationValues(
50  const SharedLPSolutionRepository* lp_solutions, absl::BitGenRef random) {
51  std::vector<double> relaxation_values;
52 
53  if (lp_solutions == nullptr || lp_solutions->NumSolutions() == 0) {
54  return relaxation_values;
55  }
56 
57  // TODO(user): Experiment with random biased solutions.
58  const SharedSolutionRepository<double>::Solution lp_solution =
60 
61  for (int model_var = 0; model_var < lp_solution.variable_values.size();
62  ++model_var) {
63  relaxation_values.push_back(lp_solution.variable_values[model_var]);
64  }
65  return relaxation_values;
66 }
67 
68 std::vector<double> GetGeneralRelaxationValues(
69  const SharedRelaxationSolutionRepository* relaxation_solutions,
70  absl::BitGenRef random) {
71  std::vector<double> relaxation_values;
72 
73  if (relaxation_solutions == nullptr ||
75  return relaxation_values;
76  }
77  const SharedSolutionRepository<int64_t>::Solution relaxation_solution =
79 
80  for (int model_var = 0;
81  model_var < relaxation_solution.variable_values.size(); ++model_var) {
82  relaxation_values.push_back(relaxation_solution.variable_values[model_var]);
83  }
84  return relaxation_values;
85 }
86 
87 std::vector<double> GetIncompleteSolutionValues(
88  SharedIncompleteSolutionManager* incomplete_solutions) {
89  std::vector<double> empty_solution_values;
90 
91  if (incomplete_solutions == nullptr ||
93  return empty_solution_values;
94  }
95 
97 }
98 } // namespace
99 
101  const SharedResponseManager* response_manager,
105  absl::BitGenRef random) {
106  RINSNeighborhood rins_neighborhood;
107 
108  const bool use_only_relaxation_values =
109  (response_manager == nullptr ||
110  response_manager->SolutionsRepository().NumSolutions() == 0);
111 
112  if (use_only_relaxation_values && lp_solutions == nullptr &&
113  incomplete_solutions == nullptr) {
114  // As of now RENS doesn't generate good neighborhoods from integer
115  // relaxation solutions.
116  return rins_neighborhood;
117  }
118 
119  std::vector<double> relaxation_values;
120  if (incomplete_solutions != nullptr) {
121  relaxation_values = GetIncompleteSolutionValues(incomplete_solutions);
122  } else if (lp_solutions != nullptr) {
123  relaxation_values = GetLPRelaxationValues(lp_solutions, random);
124  } else {
125  CHECK(relaxation_solutions != nullptr)
126  << "No relaxation solutions repository or lp solutions repository "
127  "provided.";
128  relaxation_values =
129  GetGeneralRelaxationValues(relaxation_solutions, random);
130  }
131  if (relaxation_values.empty()) return rins_neighborhood;
132 
133  const double tolerance = 1e-6;
135  use_only_relaxation_values
137  : response_manager->SolutionsRepository().GetRandomBiasedSolution(
138  random);
139  for (int model_var = 0; model_var < relaxation_values.size(); ++model_var) {
140  const double relaxation_value = relaxation_values[model_var];
141 
142  if (relaxation_value == std::numeric_limits<double>::infinity()) {
143  continue;
144  }
145 
146  if (use_only_relaxation_values) {
147  // The tolerance make sure that if the relaxation_value is close to an
148  // integer, then we fix the variable to this integer value.
149  //
150  // Important: the LP relaxation doesn't know about holes in the variable
151  // domains, so the intersection of [domain_lb, domain_ub] with the
152  // initial variable domain might be empty.
153  const int64_t domain_lb =
154  static_cast<int64_t>(std::floor(relaxation_value + tolerance));
155  const int64_t domain_ub =
156  static_cast<int64_t>(std::ceil(relaxation_value - tolerance));
157  if (domain_lb == domain_ub) {
158  rins_neighborhood.fixed_vars.push_back({model_var, domain_lb});
159  } else {
160  rins_neighborhood.reduced_domain_vars.push_back(
161  {model_var, {domain_lb, domain_ub}});
162  }
163 
164  } else {
165  const IntegerValue best_solution_value =
166  IntegerValue(solution.variable_values[model_var]);
167  if (std::abs(best_solution_value.value() - relaxation_value) < 1e-4) {
168  rins_neighborhood.fixed_vars.push_back(
169  {model_var, best_solution_value.value()});
170  }
171  }
172  }
173 
174  return rins_neighborhood;
175 }
176 
177 } // namespace sat
178 } // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:491
RINSNeighborhood GetRINSNeighborhood(const SharedResponseManager *response_manager, const SharedRelaxationSolutionRepository *relaxation_solutions, const SharedLPSolutionRepository *lp_solutions, SharedIncompleteSolutionManager *incomplete_solutions, absl::BitGenRef random)
Definition: rins.cc:100
SharedLPSolutionRepository * lp_solutions
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
std::vector< LPVariable > vars
Definition: rins.h:46
GRBmodel * model
void NewLPSolution(std::vector< double > lp_solution)
IntegerVariable positive_var
Definition: rins.h:34
SharedIncompleteSolutionManager * incomplete_solutions
LinearProgrammingConstraint * lp
Definition: rins.h:35
std::vector< std::pair< int, int64_t > > fixed_vars
Definition: rins.h:59
SharedRelaxationSolutionRepository * relaxation_solutions
Collection of objects used to extend the Constraint Solver library.
void RecordLPRelaxationValues(Model *model)
Definition: rins.cc:26
Solution GetRandomBiasedSolution(absl::BitGenRef random) const
std::vector< std::pair< int, std::pair< int64_t, int64_t > > > reduced_domain_vars
Definition: rins.h:62
const SharedSolutionRepository< int64_t > & SolutionsRepository() const