Add quadratic objective terms to LP export

This commit is contained in:
Peter Mitri
2025-04-08 17:36:29 +02:00
parent a5bbbcbcff
commit a6cb85a641

View File

@@ -147,6 +147,8 @@ class MPModelProtoExporter {
// error (for example, var_index is out of range).
bool WriteLpTerm(int var_index, double coefficient,
std::string* output) const;
bool WriteLpQuadraticTerm(int var1_index, int var2_index, double coefficient,
std::string* output) const;
// Appends a pair name, value to "output", formatted to comply with the MPS
// standard.
@@ -456,6 +458,30 @@ bool MPModelProtoExporter::WriteLpTerm(int var_index, double coefficient,
return true;
}
bool MPModelProtoExporter::WriteLpQuadraticTerm(int var1_index, int var2_index,
double coefficient,
std::string* output) const {
output->clear();
if (var1_index < 0 || var1_index >= proto_.variable_size()) {
LOG(DFATAL) << "Reference to out-of-bounds variable index # " << var1_index;
return false;
}
if (var2_index < 0 || var2_index >= proto_.variable_size()) {
LOG(DFATAL) << "Reference to out-of-bounds variable index # " << var2_index;
return false;
}
auto variable_product =
var1_index == var2_index
? absl::StrCat(exported_variable_names_[var1_index], "^2")
: absl::StrCat(exported_variable_names_[var1_index], " * ",
exported_variable_names_[var2_index]);
if (coefficient != 0.0) {
*output = absl::StrCat(DoubleToStringWithForcedSign(coefficient), " ",
variable_product, " ");
}
return true;
}
namespace {
bool IsBoolean(const MPVariableProto& var) {
return var.is_integer() && ceil(var.lower_bound()) == 0.0 &&
@@ -572,6 +598,24 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(
obj_line_breaker.Append(term);
show_variable[var_index] = coeff != 0.0 || show_variable[var_index];
}
if (proto_.has_quadratic_objective()) {
obj_line_breaker.Append(" + [ ");
for (int i_term = 0;
i_term < proto_.quadratic_objective().qvar1_index_size(); ++i_term) {
const int qvar1 = proto_.quadratic_objective().qvar1_index(i_term);
const int qvar2 = proto_.quadratic_objective().qvar2_index(i_term);
const double coeff = proto_.quadratic_objective().coefficient(i_term);
std::string term;
if (!WriteLpQuadraticTerm(qvar1, qvar2, 2 * coeff, &term)) {
return false;
}
obj_line_breaker.Append(term);
show_variable[qvar1] = coeff != 0.0 || show_variable[qvar1];
show_variable[qvar2] = coeff != 0.0 || show_variable[qvar2];
}
obj_line_breaker.Append(" ] / 2");
}
// Linear Constraints
absl::StrAppend(output, obj_line_breaker.GetOutput(), "\nSubject to\n");
for (int cst_index = 0; cst_index < proto_.constraint_size(); ++cst_index) {