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"
40 result.
gscip->AddVariable(
41 variable.lower_bound(), variable.upper_bound(),
42 variable.objective_coefficient(),
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) {
71absl::Status GScipAndVariables::AddLinearConstraint(
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();
82absl::Status GScipAndVariables::AddGeneralConstraint(
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());
105 return absl::UnimplementedError(
106 absl::StrFormat(
"General constraints of type %i not supported.",
107 mp_gen.general_constraint_case()));
110absl::Status GScipAndVariables::AddIndicatorConstraint(
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());
123absl::Status GScipAndVariables::AddSosConstraint(
126 sos.weights = {mp_sos.weight().begin(), mp_sos.weight().end()};
127 sos.variables = TranslateMPVars(mp_sos.var_index());
131 switch (mp_sos.type()) {
133 if (sos.variables.size() <= 2) {
134 return absl::OkStatus();
136 return gscip->AddSOS2Constraint(sos, name).status();
138 if (sos.variables.size() <= 1) {
139 return absl::OkStatus();
141 return gscip->AddSOS1Constraint(sos, name).status();
143 return absl::UnimplementedError(
144 absl::StrCat(
"Unknown SOS constraint type: ", mp_sos.type(),
" (",
148absl::Status GScipAndVariables::AddQuadraticConstraint(
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();
163absl::Status GScipAndVariables::AddAbsConstraint(
166 variables[mp_abs.resultant_var_index()], name);
169absl::Status GScipAndVariables::AddAndConstraint(
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();
177absl::Status GScipAndVariables::AddOrConstraint(
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();
185std::vector<GScipLinearExpr>
186GScipAndVariables::MpArrayWithConstantToGScipLinearExprs(
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));
195 if (mp_array_with_constant.has_constant()) {
196 result.push_back(GScipLinearExpr(mp_array_with_constant.constant()));
200absl::Status GScipAndVariables::AddMinConstraint(
203 gscip.get(), GScipLinearExpr(
variables[mp_min.resultant_var_index()]),
204 MpArrayWithConstantToGScipLinearExprs(mp_min), name);
206absl::Status GScipAndVariables::AddMaxConstraint(
209 gscip.get(), GScipLinearExpr(
variables[mp_max.resultant_var_index()]),
210 MpArrayWithConstantToGScipLinearExprs(mp_max), name);
213absl::Status GScipAndVariables::AddQuadraticObjective(
216 gscip.get(), TranslateMPVars(quad_obj.qvar1_index()),
217 TranslateMPVars(quad_obj.qvar2_index()),
218 {quad_obj.coefficient().begin(), quad_obj.coefficient().end()});
227 return gscip->SuggestHint(hint).status();
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
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
bool has_quadratic_objective() const
const ::std::string & name() const
double objective_offset() const
static constexpr Type SOS1_DEFAULT
static constexpr Type SOS2
::int32_t var_index(int index) const
double var_value(int index) const
int var_index_size() const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
absl::Status GScipCreateMaximum(GScip *gscip, const GScipLinearExpr &resultant, absl::Span< const GScipLinearExpr > terms, absl::string_view name)
absl::Status GScipCreateAbs(GScip *gscip, SCIP_Var *x, SCIP_Var *abs_x, absl::string_view name)
std::string ProtoEnumToString(ProtoEnumType enum_value)
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
absl::Status GScipCreateMinimum(GScip *gscip, const GScipLinearExpr &resultant, absl::Span< const GScipLinearExpr > terms, absl::string_view name)
absl::Status GScipCreateIndicatorRange(GScip *gscip, const GScipIndicatorRangeConstraint &indicator_range, absl::string_view name, const GScipConstraintOptions &options)
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)
std::unique_ptr< GScip > gscip
std::vector< SCIP_VAR * > variables
absl::Status AddHint(const PartialVariableAssignment &mp_hint)
static absl::StatusOr< GScipAndVariables > FromMPModelProto(const MPModelProto &model)