Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
gscip_from_mp_model_proto.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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 <cstdint>
17#include <string>
18#include <vector>
19
20#include "absl/memory/memory.h"
21#include "absl/status/status.h"
22#include "absl/strings/str_format.h"
23#include "absl/strings/string_view.h"
29
30namespace operations_research {
31
32absl::StatusOr<GScipAndVariables> GScipAndVariables::FromMPModelProto(
33 const MPModelProto& model) {
34 GScipAndVariables result;
35 ASSIGN_OR_RETURN(result.gscip, GScip::Create(model.name()));
36 RETURN_IF_ERROR(result.gscip->SetMaximize(model.maximize()));
37 RETURN_IF_ERROR(result.gscip->SetObjectiveOffset(model.objective_offset()));
38 for (const MPVariableProto& variable : model.variable()) {
39 ASSIGN_OR_RETURN(SCIP_VAR * v,
40 result.gscip->AddVariable(
41 variable.lower_bound(), variable.upper_bound(),
42 variable.objective_coefficient(),
43 variable.is_integer() ? GScipVarType::kInteger
45 variable.name()));
46 result.variables.push_back(v);
47 }
48 for (const MPConstraintProto& linear_constraint : model.constraint()) {
49 RETURN_IF_ERROR(result.AddLinearConstraint(linear_constraint));
50 }
51 for (const MPGeneralConstraintProto& gen_constraint :
52 model.general_constraint()) {
53 RETURN_IF_ERROR(result.AddGeneralConstraint(gen_constraint));
54 }
55 if (model.has_quadratic_objective()) {
56 RETURN_IF_ERROR(result.AddQuadraticObjective(model.quadratic_objective()));
57 }
58 return result;
59}
60
61std::vector<SCIP_VAR*> GScipAndVariables::TranslateMPVars(
62 absl::Span<const int32_t> mp_vars) {
63 std::vector<SCIP_VAR*> result;
64 result.reserve(mp_vars.size());
65 for (const int32_t var : mp_vars) {
66 result.push_back(variables[var]);
67 }
68 return result;
69}
70
71absl::Status GScipAndVariables::AddLinearConstraint(
72 const MPConstraintProto& lin_constraint) {
73 GScipLinearRange range;
74 range.lower_bound = lin_constraint.lower_bound();
75 range.upper_bound = lin_constraint.upper_bound();
76 range.coefficients = {lin_constraint.coefficient().begin(),
77 lin_constraint.coefficient().end()};
78 range.variables = TranslateMPVars(lin_constraint.var_index());
79 return gscip->AddLinearConstraint(range, lin_constraint.name()).status();
80}
81
82absl::Status GScipAndVariables::AddGeneralConstraint(
83 const MPGeneralConstraintProto& mp_gen) {
84 const std::string& name = mp_gen.name();
85 switch (mp_gen.general_constraint_case()) {
87 return AddIndicatorConstraint(name, mp_gen.indicator_constraint());
89 return AddSosConstraint(name, mp_gen.sos_constraint());
91 return AddQuadraticConstraint(name, mp_gen.quadratic_constraint());
93 return AddAbsConstraint(name, mp_gen.abs_constraint());
95 return AddAndConstraint(name, mp_gen.and_constraint());
97 return AddOrConstraint(name, mp_gen.or_constraint());
99 return AddMaxConstraint(name, mp_gen.max_constraint());
101 return AddMinConstraint(name, mp_gen.min_constraint());
102 default:
103 break;
104 }
105 return absl::UnimplementedError(
106 absl::StrFormat("General constraints of type %i not supported.",
107 mp_gen.general_constraint_case()));
108}
109
110absl::Status GScipAndVariables::AddIndicatorConstraint(
111 absl::string_view name, const MPIndicatorConstraint& mp_ind) {
112 GScipIndicatorRangeConstraint ind_range;
113 ind_range.indicator_variable = variables[mp_ind.var_index()];
114 ind_range.negate_indicator = mp_ind.var_value() == 0;
115 ind_range.range.lower_bound = mp_ind.constraint().lower_bound();
116 ind_range.range.upper_bound = mp_ind.constraint().upper_bound();
117 ind_range.range.coefficients = {mp_ind.constraint().coefficient().begin(),
118 mp_ind.constraint().coefficient().end()};
119 ind_range.range.variables = TranslateMPVars(mp_ind.constraint().var_index());
120 return GScipCreateIndicatorRange(gscip.get(), ind_range, name);
121}
122
123absl::Status GScipAndVariables::AddSosConstraint(
124 const std::string& name, const MPSosConstraint& mp_sos) {
125 GScipSOSData sos;
126 sos.weights = {mp_sos.weight().begin(), mp_sos.weight().end()};
127 sos.variables = TranslateMPVars(mp_sos.var_index());
128 // SOS constraints of type N indicate at most N variables are non-zero.
129 // Constraints with N variables or less are valid, but useless. They also
130 // crash SCIP, so we skip them.
131 switch (mp_sos.type()) {
133 if (sos.variables.size() <= 2) {
134 return absl::OkStatus(); // Skip trivial constraint
135 }
136 return gscip->AddSOS2Constraint(sos, name).status();
138 if (sos.variables.size() <= 1) {
139 return absl::OkStatus(); // Skip trivial constraint
140 }
141 return gscip->AddSOS1Constraint(sos, name).status();
142 }
143 return absl::UnimplementedError(
144 absl::StrCat("Unknown SOS constraint type: ", mp_sos.type(), " (",
145 ProtoEnumToString(mp_sos.type()), ")"));
146}
147
148absl::Status GScipAndVariables::AddQuadraticConstraint(
149 const std::string& name, const MPQuadraticConstraint& mp_quad) {
150 GScipQuadraticRange range;
151 range.lower_bound = mp_quad.lower_bound();
152 range.upper_bound = mp_quad.upper_bound();
153 range.linear_coefficients = {mp_quad.coefficient().begin(),
154 mp_quad.coefficient().end()};
155 range.linear_variables = TranslateMPVars(mp_quad.var_index());
156 range.quadratic_coefficients = {mp_quad.qcoefficient().begin(),
157 mp_quad.qcoefficient().end()};
158 range.quadratic_variables1 = TranslateMPVars(mp_quad.qvar1_index());
159 range.quadratic_variables2 = TranslateMPVars(mp_quad.qvar2_index());
160 return gscip->AddQuadraticConstraint(range, name).status();
161}
162
163absl::Status GScipAndVariables::AddAbsConstraint(
164 absl::string_view name, const MPAbsConstraint& mp_abs) {
165 return GScipCreateAbs(gscip.get(), variables[mp_abs.var_index()],
166 variables[mp_abs.resultant_var_index()], name);
167}
168
169absl::Status GScipAndVariables::AddAndConstraint(
170 const std::string& name, const MPArrayConstraint& mp_and) {
171 GScipLogicalConstraintData and_args;
172 and_args.resultant = variables[mp_and.resultant_var_index()];
173 and_args.operators = TranslateMPVars(mp_and.var_index());
174 return gscip->AddAndConstraint(and_args, name).status();
175}
176
177absl::Status GScipAndVariables::AddOrConstraint(
178 const std::string& name, const MPArrayConstraint& mp_or) {
179 GScipLogicalConstraintData or_args;
180 or_args.resultant = variables[mp_or.resultant_var_index()];
181 or_args.operators = TranslateMPVars(mp_or.var_index());
182 return gscip->AddOrConstraint(or_args, name).status();
183}
184
185std::vector<GScipLinearExpr>
186GScipAndVariables::MpArrayWithConstantToGScipLinearExprs(
187 const MPArrayWithConstantConstraint& mp_array_with_constant) {
188 std::vector<int32_t> unique_vars(mp_array_with_constant.var_index().begin(),
189 mp_array_with_constant.var_index().end());
191 std::vector<GScipLinearExpr> result;
192 for (SCIP_VAR* input_var : TranslateMPVars(unique_vars)) {
193 result.push_back(GScipLinearExpr(input_var));
194 }
195 if (mp_array_with_constant.has_constant()) {
196 result.push_back(GScipLinearExpr(mp_array_with_constant.constant()));
197 }
198 return result;
199}
200absl::Status GScipAndVariables::AddMinConstraint(
201 absl::string_view name, const MPArrayWithConstantConstraint& mp_min) {
202 return GScipCreateMinimum(
203 gscip.get(), GScipLinearExpr(variables[mp_min.resultant_var_index()]),
204 MpArrayWithConstantToGScipLinearExprs(mp_min), name);
205}
206absl::Status GScipAndVariables::AddMaxConstraint(
207 absl::string_view name, const MPArrayWithConstantConstraint& mp_max) {
208 return GScipCreateMaximum(
209 gscip.get(), GScipLinearExpr(variables[mp_max.resultant_var_index()]),
210 MpArrayWithConstantToGScipLinearExprs(mp_max), name);
211}
212
213absl::Status GScipAndVariables::AddQuadraticObjective(
214 const MPQuadraticObjective& quad_obj) {
216 gscip.get(), TranslateMPVars(quad_obj.qvar1_index()),
217 TranslateMPVars(quad_obj.qvar2_index()),
218 {quad_obj.coefficient().begin(), quad_obj.coefficient().end()});
219}
220
222 const PartialVariableAssignment& mp_hint) {
223 GScipSolution hint;
224 for (int i = 0; i < mp_hint.var_index_size(); ++i) {
225 hint[variables[mp_hint.var_index(i)]] = mp_hint.var_value(i);
226 }
227 return gscip->SuggestHint(hint).status();
228}
229
230} // namespace operations_research
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
Definition gscip.cc:362
const ::operations_research::MPVariableProto & variable(int index) const
const ::operations_research::MPGeneralConstraintProto & general_constraint(int index) const
const ::operations_research::MPQuadraticObjective & quadratic_objective() const
const ::operations_research::MPConstraintProto & constraint(int index) const
const ::std::string & name() const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
Definition stl_util.h:55
OR-Tools root namespace.
absl::Status GScipCreateMaximum(GScip *gscip, const GScipLinearExpr &resultant, absl::Span< const GScipLinearExpr > terms, absl::string_view name)
Definition gscip_ext.cc:83
absl::Status GScipCreateAbs(GScip *gscip, SCIP_Var *x, SCIP_Var *abs_x, absl::string_view name)
Definition gscip_ext.cc:76
std::string ProtoEnumToString(ProtoEnumType enum_value)
Definition proto_utils.h:63
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
Definition gscip.h:89
absl::Status GScipCreateMinimum(GScip *gscip, const GScipLinearExpr &resultant, absl::Span< const GScipLinearExpr > terms, absl::string_view name)
Definition gscip_ext.cc:139
absl::Status GScipCreateIndicatorRange(GScip *gscip, const GScipIndicatorRangeConstraint &indicator_range, absl::string_view name, const GScipConstraintOptions &options)
Definition gscip_ext.cc:180
absl::Status GScipAddQuadraticObjectiveTerm(GScip *gscip, std::vector< SCIP_Var * > quadratic_variables1, std::vector< SCIP_Var * > quadratic_variables2, std::vector< double > quadratic_coefficients, absl::string_view name)
Definition gscip_ext.cc:150
absl::Status AddHint(const PartialVariableAssignment &mp_hint)
static absl::StatusOr< GScipAndVariables > FromMPModelProto(const MPModelProto &model)