diff --git a/ortools/linear_solver/python/BUILD.bazel b/ortools/linear_solver/python/BUILD.bazel index d72d568e8e..d8493e9634 100644 --- a/ortools/linear_solver/python/BUILD.bazel +++ b/ortools/linear_solver/python/BUILD.bazel @@ -83,3 +83,13 @@ py_test( "//ortools/linear_solver:linear_solver_py_pb2", ], ) + +py_binary( + name = "solve_model", + srcs = ["solve_model.py"], + deps = [ + ":model_builder", + requirement("absl-py"), + "//ortools/linear_solver:linear_solver_py_pb2", + ], +) diff --git a/ortools/linear_solver/python/model_builder.py b/ortools/linear_solver/python/model_builder.py index 60167b803b..66df10dc68 100644 --- a/ortools/linear_solver/python/model_builder.py +++ b/ortools/linear_solver/python/model_builder.py @@ -1537,17 +1537,29 @@ class Model: return mbh.to_mpmodel_proto(self.__helper) def import_from_mps_string(self, mps_string: str) -> bool: + """Loads the a model from an MPS string.""" return self.__helper.import_from_mps_string(mps_string) def import_from_mps_file(self, mps_file: str) -> bool: + """Loads the a model from an MPS file.""" return self.__helper.import_from_mps_file(mps_file) def import_from_lp_string(self, lp_string: str) -> bool: + """Loads the a model from an LP string.""" return self.__helper.import_from_lp_string(lp_string) def import_from_lp_file(self, lp_file: str) -> bool: + """Loads the a model from an LP file.""" return self.__helper.import_from_lp_file(lp_file) + def import_from_proto_file(self, proto_file: str) -> bool: + """Loads the a model from an proto file.""" + return self.__helper.load_model_from_file(proto_file) + + def export_to_proto_file(self, proto_file: str) -> bool: + """Write a model to a proto file.""" + return self.__helper.write_model_to_file(proto_file) + # Model getters and Setters @property diff --git a/ortools/linear_solver/python/model_builder_helper.cc b/ortools/linear_solver/python/model_builder_helper.cc index eb58b900a3..5b6cdacbcf 100644 --- a/ortools/linear_solver/python/model_builder_helper.cc +++ b/ortools/linear_solver/python/model_builder_helper.cc @@ -177,6 +177,8 @@ PYBIND11_MODULE(model_builder_helper, m) { arg("options") = MPModelExportOptions()) .def("write_model_to_file", &ModelBuilderHelper::WriteModelToFile, arg("filename")) + .def("load_model_from_file", &ModelBuilderHelper::LoadModelFromFile, + arg("filename")) .def("import_from_mps_string", &ModelBuilderHelper::ImportFromMpsString, arg("mps_string")) .def("import_from_mps_file", &ModelBuilderHelper::ImportFromMpsFile, diff --git a/ortools/linear_solver/python/solve_model.py b/ortools/linear_solver/python/solve_model.py index 0dd55c072f..59d5385114 100644 --- a/ortools/linear_solver/python/solve_model.py +++ b/ortools/linear_solver/python/solve_model.py @@ -26,16 +26,22 @@ _SOLVER = flags.DEFINE_string("solver", "sat", "Solver type to solve the model w def main(argv: Sequence[str]) -> None: + """Load a model and solves it.""" if len(argv) > 1: raise app.UsageError("Too many command-line arguments.") model = model_builder.ModelBuilder() # Load MPS file. - if not model.import_from_mps_file(_INPUT.value): - print(f"Cannot import MPS file: '{_INPUT.value}'") + if _INPUT.value.endswith(".mps"): + if not model.import_from_mps_file(_INPUT.value): + print(f"Cannot import MPS file: '{_INPUT.value}'") + return + elif not model.import_from_proto_file(_INPUT.value): + print(f"Cannot import Proto file: '{_INPUT.value}'") return + # Create solver. solver = model_builder.ModelSolver(_SOLVER.value) if not solver.solver_is_supported(): diff --git a/ortools/linear_solver/wrappers/model_builder_helper.cc b/ortools/linear_solver/wrappers/model_builder_helper.cc index 206b93f520..a0fe7f8acc 100644 --- a/ortools/linear_solver/wrappers/model_builder_helper.cc +++ b/ortools/linear_solver/wrappers/model_builder_helper.cc @@ -61,13 +61,23 @@ std::string ModelBuilderHelper::ExportToLpString( } bool ModelBuilderHelper::WriteModelToFile(const std::string& filename) { - if (absl::EndsWith(filename, "txt")) { + if (absl::EndsWith(filename, "txt") || + absl::EndsWith(filename, ".textproto")) { return file::SetTextProto(filename, model_, file::Defaults()).ok(); } else { return file::SetBinaryProto(filename, model_, file::Defaults()).ok(); } } +bool ModelBuilderHelper::LoadModelFromFile(const std::string& filename) { + if (absl::EndsWith(filename, "txt") || + absl::EndsWith(filename, ".textproto")) { + return file::GetTextProto(filename, &model_, file::Defaults()).ok(); + } else { + return file::GetBinaryProto(filename, &model_, file::Defaults()).ok(); + } +} + // See comment in the header file why we need to wrap absl::Status code with // code having simpler APIs. bool ModelBuilderHelper::ImportFromMpsString(const std::string& mps_string) { diff --git a/ortools/linear_solver/wrappers/model_builder_helper.h b/ortools/linear_solver/wrappers/model_builder_helper.h index 7c1d713547..1d1f09501b 100644 --- a/ortools/linear_solver/wrappers/model_builder_helper.h +++ b/ortools/linear_solver/wrappers/model_builder_helper.h @@ -51,6 +51,7 @@ class ModelBuilderHelper { std::string ExportToLpString(const operations_research::MPModelExportOptions& options = MPModelExportOptions()); bool WriteModelToFile(const std::string& filename); + bool LoadModelFromFile(const std::string& filename); bool ImportFromMpsString(const std::string& mps_string); bool ImportFromMpsFile(const std::string& mps_file);