21#include "absl/strings/string_view.h"
29std::string MaybeExtendName(absl::string_view base_name,
30 absl::string_view extension) {
31 if (base_name.empty()) {
34 return absl::StrCat(base_name,
"/", extension);
46 for (
const auto& term : right.
terms) {
47 left.
terms[term.first] -= term.second;
54 for (
auto& term : expr.
terms) {
55 term.second = -term.second;
65 GScipLinearRange result;
66 result.lower_bound = -std::numeric_limits<double>::infinity();
67 result.upper_bound = -diff.
offset;
68 for (
const auto& term : diff.
terms) {
69 result.variables.push_back(term.first);
70 result.coefficients.push_back(term.second);
76 absl::string_view
name) {
83 const std::vector<GScipLinearExpr>& terms,
84 absl::string_view
name) {
93 std::vector<SCIP_VAR*> indicators;
94 for (
int i = 0; i < terms.size(); ++i) {
95 auto z = gscip->AddVariable(0.0, 1.0, 0.0, GScipVarType::kInteger,
96 MaybeExtendName(
name, absl::StrCat(
"z_", i)));
98 indicators.push_back(*z);
101 for (
int i = 0; i < terms.size(); ++i) {
105 ->AddLinearConstraint(
106 GScipLe(terms.at(i), resultant),
107 MaybeExtendName(
name, absl::StrCat(
"x_", i,
"_le_y")))
111 GScipLinearRange y_less_x =
GScipLe(resultant, terms.at(i));
112 CHECK_EQ(y_less_x.lower_bound, -std::numeric_limits<double>::infinity());
113 GScipIndicatorConstraint ind;
114 ind.indicator_variable = indicators.at(i);
115 ind.variables = y_less_x.variables;
116 ind.coefficients = y_less_x.coefficients;
117 ind.upper_bound = y_less_x.upper_bound;
120 ->AddIndicatorConstraint(
121 ind, MaybeExtendName(
122 name, absl::StrCat(
"y_le__x_", i,
"_if_z_", i)))
128 GScipLinearRange z_use;
129 z_use.upper_bound = 1.0;
130 z_use.lower_bound = 1.0;
131 z_use.variables = indicators;
132 z_use.coefficients = std::vector<double>(indicators.size(), 1.0);
134 return gscip->AddLinearConstraint(z_use, MaybeExtendName(
name,
"one_z"))
139 const std::vector<GScipLinearExpr>& terms,
140 absl::string_view
name) {
141 std::vector<GScipLinearExpr> negated_terms;
142 negated_terms.reserve(terms.size());
150 GScip* gscip, std::vector<SCIP_Var*> quadratic_variables1,
151 std::vector<SCIP_Var*> quadratic_variables2,
152 std::vector<double> quadratic_coefficients, absl::string_view
name) {
153 constexpr double kInf = std::numeric_limits<double>::infinity();
155 gscip->AddVariable(-kInf, kInf, 1.0, GScipVarType::kContinuous,
156 MaybeExtendName(
name,
"obj"));
158 GScipQuadraticRange
range;
159 range.quadratic_variables1 = quadratic_variables1;
160 range.quadratic_variables2 = quadratic_variables2;
161 range.quadratic_coefficients = quadratic_coefficients;
162 range.linear_coefficients = {-1.0};
163 range.linear_variables = {*obj_term};
164 if (gscip->ObjectiveIsMaximize()) {
168 range.lower_bound = 0.0;
173 range.upper_bound = 0.0;
175 return gscip->AddQuadraticConstraint(
range, MaybeExtendName(
name,
"cons"))
181 absl::string_view
name,
const GScipConstraintOptions& options) {
182 if (std::isfinite(indicator_range.
range.upper_bound)) {
183 GScipIndicatorConstraint ub_constraint;
184 ub_constraint.upper_bound = indicator_range.
range.upper_bound;
185 ub_constraint.variables = indicator_range.
range.variables;
186 ub_constraint.coefficients = indicator_range.
range.coefficients;
190 ->AddIndicatorConstraint(
191 ub_constraint, MaybeExtendName(
name,
"ub"), options)
194 if (std::isfinite(indicator_range.
range.lower_bound)) {
197 GScipIndicatorConstraint lb_constraint;
198 lb_constraint.upper_bound = -indicator_range.
range.lower_bound;
199 lb_constraint.variables = indicator_range.
range.variables;
200 for (
const double c : indicator_range.
range.coefficients) {
201 lb_constraint.coefficients.push_back(-c);
206 ->AddIndicatorConstraint(
207 lb_constraint, MaybeExtendName(
name,
"lb"), options)
210 return absl::OkStatus();
#define RETURN_IF_ERROR(expr)
const std::string name
A name for logging purposes.
In SWIG mode, we don't want anything besides these top-level includes.
GScipLinearExpr GScipDifference(GScipLinearExpr left, const GScipLinearExpr &right)
Returns left - right.
absl::Status GScipCreateMinimum(GScip *gscip, const GScipLinearExpr &resultant, const std::vector< GScipLinearExpr > &terms, absl::string_view name)
GScipLinearExpr GScipNegate(GScipLinearExpr expr)
Returns -expr.
GScipLinearRange GScipLe(const GScipLinearExpr left, const GScipLinearExpr &right)
absl::Status GScipCreateAbs(GScip *gscip, SCIP_Var *x, SCIP_Var *abs_x, absl::string_view name)
absl::Status GScipCreateMaximum(GScip *gscip, const GScipLinearExpr &resultant, const std::vector< GScipLinearExpr > &terms, absl::string_view name)
absl::Status GScipCreateIndicatorRange(GScip *gscip, const GScipIndicatorRangeConstraint &indicator_range, absl::string_view name, const GScipConstraintOptions &options)
Supports unbounded variables in indicator_range.range.variables.
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)
const std::optional< Range > & range
SCIP_VAR * indicator_variable
absl::flat_hash_map< SCIP_VAR *, double > terms
GScipLinearExpr()=default