OR-Tools  8.1
gscip_ext.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 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 
15 
16 #include "ortools/base/logging.h"
18 
19 namespace operations_research {
20 
21 namespace {
22 
23 std::string MaybeExtendName(const std::string& base_name,
24  const std::string& extension) {
25  if (base_name.empty()) {
26  return "";
27  }
28  return absl::StrCat(base_name, "/", extension);
29 }
30 
31 } // namespace
32 
33 GScipLinearExpr::GScipLinearExpr(SCIP_VAR* variable) { terms[variable] = 1.0; }
34 
35 GScipLinearExpr::GScipLinearExpr(double offset) : offset(offset) {}
36 
38  left.offset -= right.offset;
39  for (const auto& term : right.terms) {
40  left.terms[term.first] -= term.second;
41  }
42  return left;
43 }
44 
46  expr.offset = -expr.offset;
47  for (auto& term : expr.terms) {
48  term.second = -term.second;
49  }
50  return expr;
51 }
52 
53 // Returns the range -inf <= left.terms - right.terms <= right.offset -
54 // left.offset
56  GScipLinearExpr diff = Difference(left, right);
57  GScipLinearRange result;
58  result.lower_bound = -std::numeric_limits<double>::infinity();
59  result.upper_bound = -diff.offset;
60  for (const auto& term : diff.terms) {
61  result.variables.push_back(term.first);
62  result.coefficients.push_back(term.second);
63  }
64  return result;
65 }
66 
67 absl::Status CreateAbs(GScip* gscip, SCIP_Var* x, SCIP_Var* abs_x,
68  const std::string& name) {
69  return CreateMaximum(gscip, GScipLinearExpr(abs_x),
71 }
72 
73 absl::Status CreateMaximum(GScip* gscip, const GScipLinearExpr& resultant,
74  const std::vector<GScipLinearExpr>& terms,
75  const std::string& name) {
76  // TODO(user): it may be better to write this in terms of the disjuntive
77  // constraint, we need to support disjunctions in gscip.h to do this.
78  //
79  // z_i in {0,1}, indicates if y = x_i
80  //
81  // x_i <= y
82  // z_i => y <= x_i
83  // \sum_i z_i == 1
84  std::vector<SCIP_VAR*> indicators;
85  for (int i = 0; i < terms.size(); ++i) {
86  auto z = gscip->AddVariable(0.0, 1.0, 0.0, GScipVarType::kInteger,
87  MaybeExtendName(name, absl::StrCat("z_", i)));
88  RETURN_IF_ERROR(z.status());
89  indicators.push_back(*z);
90  }
91 
92  for (int i = 0; i < terms.size(); ++i) {
93  // x_i <= y
95  gscip
96  ->AddLinearConstraint(
97  Le(terms.at(i), resultant),
98  MaybeExtendName(name, absl::StrCat("x_", i, "_le_y")))
99  .status());
100  // z_i => y <= x_i
101  {
102  GScipLinearRange y_less_x = Le(resultant, terms.at(i));
103  CHECK_EQ(y_less_x.lower_bound, -std::numeric_limits<double>::infinity());
105  ind.indicator_variable = indicators.at(i);
106  ind.variables = y_less_x.variables;
107  ind.coefficients = y_less_x.coefficients;
108  ind.upper_bound = y_less_x.upper_bound;
110  gscip
111  ->AddIndicatorConstraint(
112  ind, MaybeExtendName(
113  name, absl::StrCat("y_le__x_", i, "_if_z_", i)))
114  .status());
115  }
116  }
117 
118  // sum_i z_i = 1.
119  GScipLinearRange z_use;
120  z_use.upper_bound = 1.0;
121  z_use.lower_bound = 1.0;
122  z_use.variables = indicators;
123  z_use.coefficients = std::vector<double>(indicators.size(), 1.0);
124 
125  return gscip->AddLinearConstraint(z_use, MaybeExtendName(name, "one_z"))
126  .status();
127 }
128 
129 absl::Status CreateMinimum(GScip* gscip, const GScipLinearExpr& resultant,
130  const std::vector<GScipLinearExpr>& terms,
131  const std::string& name) {
132  std::vector<GScipLinearExpr> negated_terms;
133  negated_terms.reserve(terms.size());
134  for (const GScipLinearExpr& e : terms) {
135  negated_terms.push_back(Negate(e));
136  }
137  return CreateMaximum(gscip, Negate(resultant), negated_terms, name);
138 }
139 
141  GScip* gscip, std::vector<SCIP_Var*> quadratic_variables1,
142  std::vector<SCIP_Var*> quadratic_variables2,
143  std::vector<double> quadratic_coefficients, const std::string& name) {
144  constexpr double kInf = std::numeric_limits<double>::infinity();
145  auto obj_term =
146  gscip->AddVariable(-kInf, kInf, 1.0, GScipVarType::kContinuous,
147  MaybeExtendName(name, "obj"));
148  RETURN_IF_ERROR(obj_term.status());
149  GScipQuadraticRange range;
150  range.quadratic_variables1 = quadratic_variables1;
151  range.quadratic_variables2 = quadratic_variables2;
152  range.quadratic_coefficients = quadratic_coefficients;
153  range.linear_coefficients = {-1.0};
154  range.linear_variables = {*obj_term};
155  if (gscip->ObjectiveIsMaximize()) {
156  // maximize z
157  // z <= Q(x, y)
158  // => 0 <= Q(x, y) - z <= inf
159  range.lower_bound = 0.0;
160  } else {
161  // minimize z
162  // z >= Q(x, y)
163  // => 0 >= Q(x, y) - z >= -inf
164  range.upper_bound = 0.0;
165  }
166  return gscip->AddQuadraticConstraint(range, MaybeExtendName(name, "cons"))
167  .status();
168 }
169 
170 absl::Status CreateIndicatorRange(
171  GScip* gscip, const GScipIndicatorRangeConstraint& indicator_range,
172  const std::string& name, const GScipConstraintOptions& options) {
173  if (std::isfinite(indicator_range.range.upper_bound)) {
174  GScipIndicatorConstraint ub_constraint;
175  ub_constraint.upper_bound = indicator_range.range.upper_bound;
176  ub_constraint.variables = indicator_range.range.variables;
177  ub_constraint.coefficients = indicator_range.range.coefficients;
178  ub_constraint.indicator_variable = indicator_range.indicator_variable;
179  ub_constraint.negate_indicator = indicator_range.negate_indicator;
180  RETURN_IF_ERROR(gscip
181  ->AddIndicatorConstraint(
182  ub_constraint, MaybeExtendName(name, "ub"), options)
183  .status());
184  }
185  if (std::isfinite(indicator_range.range.lower_bound)) {
186  // want z -> lb <= a * x
187  // <=> z -> -lb >= -a * x
188  GScipIndicatorConstraint lb_constraint;
189  lb_constraint.upper_bound = -indicator_range.range.lower_bound;
190  lb_constraint.variables = indicator_range.range.variables;
191  for (const double c : indicator_range.range.coefficients) {
192  lb_constraint.coefficients.push_back(-c);
193  }
194  lb_constraint.indicator_variable = indicator_range.indicator_variable;
195  lb_constraint.negate_indicator = indicator_range.negate_indicator;
196  RETURN_IF_ERROR(gscip
197  ->AddIndicatorConstraint(
198  lb_constraint, MaybeExtendName(name, "lb"), options)
199  .status());
200  }
201  return absl::OkStatus();
202 }
203 
204 } // namespace operations_research
operations_research::GScipIndicatorConstraint
Definition: gscip.h:422
operations_research::GScipQuadraticRange::linear_variables
std::vector< SCIP_Var * > linear_variables
Definition: gscip.h:374
gscip_ext.h
operations_research::GScipIndicatorRangeConstraint
Definition: gscip_ext.h:79
operations_research::GScipConstraintOptions
Definition: gscip.h:483
operations_research::GScipLinearRange
Definition: gscip.h:93
operations_research::GScipIndicatorRangeConstraint::negate_indicator
bool negate_indicator
Definition: gscip_ext.h:81
logging.h
operations_research::GScipLinearRange::upper_bound
double upper_bound
Definition: gscip.h:97
operations_research::GScipIndicatorRangeConstraint::indicator_variable
SCIP_VAR * indicator_variable
Definition: gscip_ext.h:80
operations_research::GScipLinearExpr
Definition: gscip_ext.h:46
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::GScip::ObjectiveIsMaximize
bool ObjectiveIsMaximize()
Definition: gscip.cc:535
operations_research::CreateMinimum
absl::Status CreateMinimum(GScip *gscip, const GScipLinearExpr &resultant, const std::vector< GScipLinearExpr > &terms, const std::string &name)
Definition: gscip_ext.cc:129
operations_research::Le
GScipLinearRange Le(const GScipLinearExpr left, const GScipLinearExpr &right)
Definition: gscip_ext.cc:55
operations_research::GScipIndicatorConstraint::negate_indicator
bool negate_indicator
Definition: gscip.h:425
operations_research::GScipIndicatorConstraint::coefficients
std::vector< double > coefficients
Definition: gscip.h:429
operations_research::AddQuadraticObjectiveTerm
absl::Status AddQuadraticObjectiveTerm(GScip *gscip, std::vector< SCIP_Var * > quadratic_variables1, std::vector< SCIP_Var * > quadratic_variables2, std::vector< double > quadratic_coefficients, const std::string &name)
Definition: gscip_ext.cc:140
operations_research::GScipQuadraticRange::lower_bound
double lower_bound
Definition: gscip.h:370
operations_research::GScipQuadraticRange::quadratic_variables2
std::vector< SCIP_Var * > quadratic_variables2
Definition: gscip.h:388
operations_research::GScipLinearRange::variables
std::vector< SCIP_VAR * > variables
Definition: gscip.h:95
operations_research::GScipQuadraticRange
Definition: gscip.h:368
operations_research::GScipLinearRange::coefficients
std::vector< double > coefficients
Definition: gscip.h:96
operations_research::CreateAbs
absl::Status CreateAbs(GScip *gscip, SCIP_Var *x, SCIP_Var *abs_x, const std::string &name)
Definition: gscip_ext.cc:67
operations_research::CreateMaximum
absl::Status CreateMaximum(GScip *gscip, const GScipLinearExpr &resultant, const std::vector< GScipLinearExpr > &terms, const std::string &name)
Definition: gscip_ext.cc:73
operations_research::GScip::AddQuadraticConstraint
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:329
operations_research::GScipLinearExpr::GScipLinearExpr
GScipLinearExpr()=default
operations_research::GScip
Definition: gscip.h:120
operations_research::GScipQuadraticRange::linear_coefficients
std::vector< double > linear_coefficients
Definition: gscip.h:375
operations_research::GScipQuadraticRange::upper_bound
double upper_bound
Definition: gscip.h:392
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
status_macros.h
operations_research::GScipLinearExpr::offset
double offset
Definition: gscip_ext.h:48
operations_research::GScipQuadraticRange::quadratic_variables1
std::vector< SCIP_Var * > quadratic_variables1
Definition: gscip.h:387
operations_research::CreateIndicatorRange
absl::Status CreateIndicatorRange(GScip *gscip, const GScipIndicatorRangeConstraint &indicator_range, const std::string &name, const GScipConstraintOptions &options)
Definition: gscip_ext.cc:170
operations_research::Negate
GScipLinearExpr Negate(GScipLinearExpr expr)
Definition: gscip_ext.cc:45
operations_research::GScipIndicatorConstraint::indicator_variable
SCIP_VAR * indicator_variable
Definition: gscip.h:424
operations_research::GScipLinearExpr::terms
absl::flat_hash_map< SCIP_VAR *, double > terms
Definition: gscip_ext.h:47
operations_research::GScipQuadraticRange::quadratic_coefficients
std::vector< double > quadratic_coefficients
Definition: gscip.h:389
operations_research::GScip::AddLinearConstraint
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:303
operations_research::GScipIndicatorRangeConstraint::range
GScipLinearRange range
Definition: gscip_ext.h:82
operations_research::Difference
GScipLinearExpr Difference(GScipLinearExpr left, const GScipLinearExpr &right)
Definition: gscip_ext.cc:37
RETURN_IF_ERROR
#define RETURN_IF_ERROR(expr)
Definition: status_macros.h:27
operations_research::GScip::AddVariable
absl::StatusOr< SCIP_VAR * > AddVariable(double lb, double ub, double obj_coef, GScipVarType var_type, const std::string &var_name="", const GScipVariableOptions &options=DefaultGScipVariableOptions())
Definition: gscip.cc:271
operations_research::GScipIndicatorConstraint::upper_bound
double upper_bound
Definition: gscip.h:431
operations_research::GScipLinearRange::lower_bound
double lower_bound
Definition: gscip.h:94
name
const std::string name
Definition: default_search.cc:808
operations_research::GScipIndicatorConstraint::variables
std::vector< SCIP_Var * > variables
Definition: gscip.h:427