add WriteToMpsFile in model_builder, model_exporter
This commit is contained in:
@@ -338,6 +338,10 @@ public final class ModelBuilder {
|
||||
return helper.exportToLpString(obfuscate);
|
||||
}
|
||||
|
||||
public boolean writeToMpsFile(String filename, boolean obfuscate) {
|
||||
return helper.writeToMpsFile(filename, obfuscate);
|
||||
}
|
||||
|
||||
public boolean importFromMpsString(String mpsString) {
|
||||
return helper.importFromMpsString(mpsString);
|
||||
}
|
||||
|
||||
@@ -376,6 +376,7 @@ cc_library(
|
||||
deps = [
|
||||
":linear_solver_cc_proto",
|
||||
"//ortools/base",
|
||||
"//ortools/base:file",
|
||||
"//ortools/base:hash",
|
||||
"//ortools/base:map_util",
|
||||
"//ortools/util:fp_utils",
|
||||
@@ -395,6 +396,7 @@ cc_binary(
|
||||
":linear_solver",
|
||||
":linear_solver_cc_proto",
|
||||
"//ortools/base",
|
||||
"//ortools/base:file",
|
||||
"//ortools/lp_data:lp_parser",
|
||||
"//ortools/lp_data:model_reader",
|
||||
"//ortools/lp_data:mps_reader",
|
||||
|
||||
@@ -399,6 +399,11 @@ public class Model
|
||||
return helper_.ExportToLpString(obfuscate);
|
||||
}
|
||||
|
||||
public bool WriteToMpsFile(String filename, bool obfuscate)
|
||||
{
|
||||
return helper_.WriteToMpsFile(filename, obfuscate);
|
||||
}
|
||||
|
||||
public bool ImportFromMpsString(String mpsString)
|
||||
{
|
||||
return helper_.ImportFromMpsString(mpsString);
|
||||
|
||||
@@ -39,6 +39,12 @@ VECTOR_AS_CSHARP_ARRAY(double, double, double, DoubleVector);
|
||||
options.obfuscate = obfuscate;
|
||||
return $self->ExportToLpString(options);
|
||||
}
|
||||
|
||||
bool WriteToMpsFile(const std::string& filename, bool obfuscate) {
|
||||
operations_research::MPModelExportOptions options;
|
||||
options.obfuscate = obfuscate;
|
||||
return $self->WriteToMpsFile(filename, options);
|
||||
}
|
||||
} // Extend operations_research::ModelBuilderHelper
|
||||
|
||||
%ignoreall
|
||||
@@ -120,6 +126,7 @@ VECTOR_AS_CSHARP_ARRAY(double, double, double, DoubleVector);
|
||||
%unignore operations_research::ModelBuilderHelper::ImportFromMpsFile;
|
||||
%unignore operations_research::ModelBuilderHelper::ImportFromLpString;
|
||||
%unignore operations_research::ModelBuilderHelper::ImportFromLpFile;
|
||||
%unignore operations_research::ModelBuilderHelper::WriteToMpsFile(std::string, bool);
|
||||
%unignore operations_research::ModelBuilderHelper::ExportToMpsString(bool);
|
||||
%unignore operations_research::ModelBuilderHelper::ExportToLpString(bool);
|
||||
%unignore operations_research::ModelBuilderHelper::OverwriteModel;
|
||||
|
||||
@@ -99,6 +99,12 @@ class GlobalRefGuard {
|
||||
options.obfuscate = obfuscate;
|
||||
return $self->ExportToLpString(options);
|
||||
}
|
||||
|
||||
bool writeToMpsFile(const std::string& filename, bool obfuscate) {
|
||||
operations_research::MPModelExportOptions options;
|
||||
options.obfuscate = obfuscate;
|
||||
return $self->WriteToMpsFile(filename, options);
|
||||
}
|
||||
} // Extend operations_research::ModelBuilderHelper
|
||||
|
||||
%ignoreall
|
||||
@@ -182,6 +188,7 @@ class GlobalRefGuard {
|
||||
%rename (importFromLpFile) operations_research::ModelBuilderHelper::ImportFromLpFile;
|
||||
%unignore operations_research::ModelBuilderHelper::exportToMpsString;
|
||||
%unignore operations_research::ModelBuilderHelper::exportToLpString;
|
||||
%unignore operations_research::ModelBuilderHelper::writeToMpsFile;
|
||||
%rename (overwriteModel) operations_research::ModelBuilderHelper::OverwriteModel;
|
||||
|
||||
%unignore operations_research::ModelSolverHelper;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/ascii.h"
|
||||
@@ -29,11 +30,12 @@
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/file.h"
|
||||
#include "ortools/base/helpers.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/map_util.h"
|
||||
#include "ortools/base/options.h"
|
||||
#include "ortools/base/status_macros.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
#include "ortools/util/fp_utils.h"
|
||||
|
||||
ABSL_FLAG(bool, lp_log_invalid_name, false, "DEPRECATED.");
|
||||
|
||||
@@ -91,7 +93,8 @@ class MPModelProtoExporter {
|
||||
bool ExportModelAsLpFormat(const MPModelExportOptions& options,
|
||||
std::string* output);
|
||||
bool ExportModelAsMpsFormat(const MPModelExportOptions& options,
|
||||
std::string* output);
|
||||
std::string* output, File* output_file);
|
||||
void FlushAndResetString(std::string* output, File* file);
|
||||
|
||||
private:
|
||||
// Computes the number of continuous, integer and binary variables.
|
||||
@@ -241,12 +244,32 @@ absl::StatusOr<std::string> ExportModelAsMpsFormat(
|
||||
}
|
||||
MPModelProtoExporter exporter(model);
|
||||
std::string output;
|
||||
if (!exporter.ExportModelAsMpsFormat(options, &output)) {
|
||||
if (!exporter.ExportModelAsMpsFormat(options, &output, nullptr)) {
|
||||
return absl::InvalidArgumentError("Unable to export model.");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
absl::Status WriteModelToMpsFile(absl::string_view filename,
|
||||
const MPModelProto& model,
|
||||
const MPModelExportOptions& options) {
|
||||
if (model.general_constraint_size() > 0) {
|
||||
return absl::InvalidArgumentError("General constraints are not supported.");
|
||||
}
|
||||
File* file;
|
||||
RETURN_IF_ERROR(file::Open(filename, "w", &file, file::Defaults()));
|
||||
|
||||
absl::Status status = absl::OkStatus();
|
||||
MPModelProtoExporter exporter(model);
|
||||
std::string output;
|
||||
if (!exporter.ExportModelAsMpsFormat(options, &output, file)) {
|
||||
status.Update(file->Close(file::Defaults())); // Even if Write() fails!
|
||||
return absl::InvalidArgumentError("Unable to export model.");
|
||||
}
|
||||
status.Update(file->Close(file::Defaults()));
|
||||
return status;
|
||||
}
|
||||
|
||||
namespace {
|
||||
MPModelProtoExporter::MPModelProtoExporter(const MPModelProto& model)
|
||||
: proto_(model),
|
||||
@@ -740,8 +763,17 @@ void MPModelProtoExporter::AppendMpsColumns(
|
||||
}
|
||||
}
|
||||
|
||||
void MPModelProtoExporter::FlushAndResetString(std::string* output,
|
||||
File* output_file) {
|
||||
if (output_file == nullptr) return;
|
||||
if (output->empty()) return;
|
||||
CHECK_OK(file::WriteString(output_file, *output, file::Defaults()));
|
||||
output->clear();
|
||||
}
|
||||
|
||||
bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
const MPModelExportOptions& options, std::string* output) {
|
||||
const MPModelExportOptions& options, std::string* output,
|
||||
File* output_file) {
|
||||
output->clear();
|
||||
Setup();
|
||||
ComputeMpsSmartColumnWidths(options.obfuscate);
|
||||
@@ -787,6 +819,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
if (!rows_section.empty()) {
|
||||
absl::StrAppend(output, "ROWS\n", rows_section);
|
||||
}
|
||||
FlushAndResetString(output, output_file);
|
||||
|
||||
// As the information regarding a column needs to be contiguous, we create
|
||||
// a vector associating a variable index to a vector containing the indices
|
||||
@@ -825,6 +858,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
if (!columns_section.empty()) {
|
||||
absl::StrAppend(output, "COLUMNS\n", columns_section);
|
||||
}
|
||||
FlushAndResetString(output, output_file);
|
||||
|
||||
// RHS (right-hand-side) section.
|
||||
current_mps_column_ = 0;
|
||||
@@ -850,6 +884,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
if (!rhs_section.empty()) {
|
||||
absl::StrAppend(output, "RHS\n", rhs_section);
|
||||
}
|
||||
FlushAndResetString(output, output_file);
|
||||
|
||||
// RANGES section.
|
||||
current_mps_column_ = 0;
|
||||
@@ -866,6 +901,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
if (!ranges_section.empty()) {
|
||||
absl::StrAppend(output, "RANGES\n", ranges_section);
|
||||
}
|
||||
FlushAndResetString(output, output_file);
|
||||
|
||||
// BOUNDS section.
|
||||
current_mps_column_ = 0;
|
||||
@@ -926,8 +962,10 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(
|
||||
if (!bounds_section.empty()) {
|
||||
absl::StrAppend(output, "BOUNDS\n", bounds_section);
|
||||
}
|
||||
FlushAndResetString(output, output_file);
|
||||
|
||||
absl::StrAppend(output, "ENDATA\n");
|
||||
FlushAndResetString(output, output_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
|
||||
namespace operations_research {
|
||||
@@ -95,6 +97,35 @@ absl::StatusOr<std::string> ExportModelAsMpsFormat(
|
||||
const MPModelProto& model,
|
||||
const MPModelExportOptions& options = MPModelExportOptions());
|
||||
|
||||
/**
|
||||
* Write the current model (variables, constraints, objective) to a file in MPS
|
||||
* file format, using the "free" MPS format.
|
||||
*
|
||||
* Returns false if some error has occurred during execution. Models with
|
||||
* maximization objectives trigger an error, because MPS can encode only
|
||||
* minimization problems.
|
||||
*
|
||||
* The validity of names is automatically checked. If a variable name or a
|
||||
* constraint name is invalid or non-existent, a new valid name is
|
||||
* automatically generated.
|
||||
*
|
||||
* Name validity and obfuscation works exactly as in ExportModelAsLpFormat().
|
||||
*
|
||||
* For more information about the MPS format:
|
||||
* http://en.wikipedia.org/wiki/MPS_(format)
|
||||
* A close-to-original description coming from OSL:
|
||||
* http://tinyurl.com/mps-format-by-osl
|
||||
* A recent description from CPLEX:
|
||||
* http://tinyurl.com/mps-format-by-cplex
|
||||
* CPLEX extensions:
|
||||
* http://tinyurl.com/mps-extensions-by-cplex
|
||||
* Gurobi's description:
|
||||
* http://www.gurobi.com/documentation/5.1/reference-manual/node869
|
||||
*/
|
||||
absl::Status WriteModelToMpsFile(
|
||||
absl::string_view filename, const MPModelProto& model,
|
||||
const MPModelExportOptions& options = MPModelExportOptions());
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // OR_TOOLS_LINEAR_SOLVER_MODEL_EXPORTER_H_
|
||||
|
||||
@@ -1581,6 +1581,11 @@ class Model:
|
||||
options.obfuscate = obfuscate
|
||||
return self.__helper.export_to_mps_string(options)
|
||||
|
||||
def write_to_mps_file(self, filename: str, obfuscate: bool = False) -> bool:
|
||||
options: mbh.MPModelExportOptions = mbh.MPModelExportOptions()
|
||||
options.obfuscate = obfuscate
|
||||
return self.__helper.write_to_mps_file(filename, options)
|
||||
|
||||
def export_to_proto(self) -> linear_solver_pb2.MPModelProto:
|
||||
"""Exports the optimization model to a ProtoBuf format."""
|
||||
return mbh.to_mpmodel_proto(self.__helper)
|
||||
|
||||
@@ -175,6 +175,8 @@ PYBIND11_MODULE(model_builder_helper, m) {
|
||||
arg("options") = MPModelExportOptions())
|
||||
.def("export_to_lp_string", &ModelBuilderHelper::ExportToLpString,
|
||||
arg("options") = MPModelExportOptions())
|
||||
.def("write_to_mps_file", &ModelBuilderHelper::WriteToMpsFile,
|
||||
arg("filename"), arg("options") = MPModelExportOptions())
|
||||
.def("read_model_from_proto_file",
|
||||
&ModelBuilderHelper::ReadModelFromProtoFile, arg("filename"))
|
||||
.def("write_model_to_proto_file",
|
||||
|
||||
@@ -55,10 +55,12 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/flags/declare.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "ortools/base/file.h"
|
||||
@@ -68,6 +70,7 @@
|
||||
#include "ortools/base/options.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
#include "ortools/linear_solver/model_exporter.h"
|
||||
#include "ortools/lp_data/lp_parser.h"
|
||||
#include "ortools/lp_data/mps_reader.h"
|
||||
#include "ortools/lp_data/sol_reader.h"
|
||||
@@ -114,6 +117,8 @@ ABSL_FLAG(std::string, dump_response, "",
|
||||
"If non-empty, dumps MPSolutionResponse there.");
|
||||
ABSL_FLAG(std::string, sol_file, "",
|
||||
"If non-empty, output the best solution in Miplib .sol format.");
|
||||
ABSL_FLAG(std::string, dump_mps, "",
|
||||
"If non-empty, dumps the model in mps format there.");
|
||||
|
||||
ABSL_DECLARE_FLAG(bool, verify_solution); // Defined in ./linear_solver.cc
|
||||
ABSL_DECLARE_FLAG(bool,
|
||||
@@ -310,6 +315,11 @@ void Run() {
|
||||
<< absl::GetFlag(FLAGS_dump_format);
|
||||
}
|
||||
|
||||
if (!absl::GetFlag(FLAGS_dump_mps).empty()) {
|
||||
CHECK_OK(WriteModelToMpsFile(absl::GetFlag(FLAGS_dump_mps),
|
||||
request_proto.model()));
|
||||
}
|
||||
|
||||
// Set or override request proto options from the command line flags.
|
||||
if (type.has_value() || !request_proto.has_solver_type()) {
|
||||
request_proto.set_solver_type(static_cast<MPModelRequest::SolverType>(
|
||||
|
||||
@@ -69,6 +69,11 @@ std::string ModelBuilderHelper::ExportToLpString(
|
||||
.value_or("");
|
||||
}
|
||||
|
||||
bool ModelBuilderHelper::WriteToMpsFile(const std::string& filename,
|
||||
const MPModelExportOptions& options) {
|
||||
return WriteModelToMpsFile(filename, model_, options).ok();
|
||||
}
|
||||
|
||||
bool ModelBuilderHelper::ReadModelFromProtoFile(const std::string& filename) {
|
||||
if (file::GetTextProto(filename, &model_, file::Defaults()).ok() ||
|
||||
file::GetBinaryProto(filename, &model_, file::Defaults()).ok()) {
|
||||
|
||||
@@ -51,6 +51,9 @@ class ModelBuilderHelper {
|
||||
options = MPModelExportOptions());
|
||||
std::string ExportToLpString(const operations_research::MPModelExportOptions&
|
||||
options = MPModelExportOptions());
|
||||
bool WriteToMpsFile(const std::string& filename,
|
||||
const operations_research::MPModelExportOptions& options =
|
||||
MPModelExportOptions());
|
||||
bool ReadModelFromProtoFile(const std::string& filename);
|
||||
bool WriteModelToProtoFile(const std::string& filename);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user