31#include "absl/flags/flag.h"
32#include "absl/status/status.h"
33#include "absl/status/statusor.h"
34#include "absl/strings/match.h"
35#include "absl/strings/str_cat.h"
36#include "absl/strings/str_join.h"
37#include "absl/strings/string_view.h"
38#include "absl/time/time.h"
46#include "ortools/math_opt/parameters.pb.h"
54inline constexpr absl::string_view
kPbExt =
".pb";
55inline constexpr absl::string_view
kProtoExt =
".proto";
56inline constexpr absl::string_view
kPbTxtExt =
".pb.txt";
58inline constexpr absl::string_view
kMPSExt =
".mps";
63struct SolverTypeProtoFormatter {
65 std::string*
const out,
66 const operations_research::math_opt::SolverTypeProto solver_type) {
74 "the file containing the model to solve; use --format to specify the "
78 "the format of the --input_file; possible values:\n",
"* ",
81 kMPSFormat,
": for MPS file (which can be GZiped)\n",
"* ",
82 kAutoFormat,
": to guess the format from the file extension:\n",
88 std::vector<std::string>, update_files, {},
90 "the file containing ModelUpdateProto to apply to the --input_file; "
91 "when this flag is used, the --format must be either ",
96 "the solver to use, possible values: ",
99 ->RegisteredSolvers(),
100 ", ", SolverTypeProtoFormatter())));
102 "use a message callback to print the solver convergence logs");
104 "the time limit to use for the solve");
112std::optional<absl::string_view> FormatFromFilePath(
113 const absl::string_view file_path) {
114 const std::vector<std::pair<absl::string_view, absl::string_view>>
115 extension_to_format = {
121 for (
const auto& [ext, format] : extension_to_format) {
122 if (absl::EndsWith(file_path, ext)) {
133absl::StatusOr<ModelProto> ReadModel(
const absl::string_view file_path,
134 const absl::string_view format) {
136 return file::GetBinaryProto<ModelProto>(file_path,
file::Defaults());
139 return file::GetTextProto<ModelProto>(file_path,
file::Defaults());
144 LOG(QFATAL) <<
"Unsupported value of --format: " << format;
150absl::StatusOr<ModelUpdateProto> ReadModelUpdate(
151 const absl::string_view file_path,
const absl::string_view format) {
153 return file::GetBinaryProto<ModelUpdateProto>(file_path,
file::Defaults());
156 return file::GetTextProto<ModelUpdateProto>(file_path,
file::Defaults());
158 return absl::InternalError(
159 absl::StrCat(
"invalid format in ReadModelUpdate(): ", format));
163absl::Status PrintSummary(
const SolveResult& result) {
164 std::cout <<
"Solve finished:\n"
165 <<
" termination: " << result.termination <<
"\n"
166 <<
" solve time: " << result.solve_stats.solve_time
167 <<
"\n best primal bound: " << result.solve_stats.best_primal_bound
168 <<
"\n best dual bound: " << result.solve_stats.best_dual_bound
170 if (result.solutions.empty()) {
171 std::cout <<
" no solution" << std::endl;
173 for (
int i = 0; i < result.solutions.size(); ++i) {
174 const Solution& solution = result.solutions[i];
175 std::cout <<
" solution #" << (i + 1) <<
" objective: ";
176 if (solution.primal_solution.has_value()) {
177 std::cout << solution.primal_solution->objective_value;
181 std::cout << std::endl;
184 return absl::OkStatus();
187absl::Status RunSolver() {
188 const std::string input_file_path = absl::GetFlag(FLAGS_input_file);
189 if (input_file_path.empty()) {
190 LOG(QFATAL) <<
"The flag --input_file is mandatory.";
194 std::string format = absl::GetFlag(FLAGS_format);
196 const std::optional<absl::string_view> guessed_format =
197 FormatFromFilePath(input_file_path);
198 if (!guessed_format) {
199 LOG(QFATAL) <<
"Can't guess the format from the file extension, please "
200 "use --format to specify the file format explicitly.";
202 format = *guessed_format;
207 const std::vector<std::string> update_file_paths =
208 absl::GetFlag(FLAGS_update_files);
211 LOG(QFATAL) <<
"Can't use --update_files with a input of format " << format
216 ReadModel(input_file_path, format),
217 _ <<
"failed to read " << input_file_path);
219 std::vector<ModelUpdateProto> model_updates;
220 for (
const std::string& update_file_path : update_file_paths) {
222 ReadModelUpdate(update_file_path, format));
223 model_updates.emplace_back(std::move(update));
229 for (
int u = 0; u < model_updates.size(); ++u) {
230 const ModelUpdateProto& update = model_updates[u];
232 <<
"failed to apply the update file: " << update_file_paths[u];
235 SolveArguments solve_args = {
236 .parameters = {.time_limit = absl::GetFlag(FLAGS_time_limit)},
238 if (absl::GetFlag(FLAGS_solver_logs)) {
242 const SolveResult result,
243 Solve(*
model, absl::GetFlag(FLAGS_solver_type), solve_args),
244 _ <<
"the solver failed");
248 return absl::OkStatus();
255int main(
int argc,
char* argv[]) {
258 const absl::Status
status = operations_research::math_opt::RunSolver();
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static AllSolversRegistry * Instance()
static absl::StatusOr< std::unique_ptr< Model > > FromModelProto(const ModelProto &model_proto)
CpModelProto const * model_proto
ModelSharedTimeLimit * time_limit
void InitGoogle(const char *usage, int *argc, char ***argv, bool deprecated)
constexpr absl::string_view kMathOptTextFormat
int main(int argc, char *argv[])
constexpr absl::string_view kPbExt
constexpr absl::string_view kMathOptBinaryFormat
constexpr absl::string_view kMPSGzipExt
constexpr absl::string_view kMPSExt
constexpr absl::string_view kAutoFormat
constexpr absl::string_view kMPSFormat
constexpr absl::string_view kTextProtoExt
ABSL_FLAG(std::string, input_file, "", "the file containing the model to solve; use --format to specify the " "file format")
constexpr absl::string_view kProtoExt
constexpr absl::string_view kPbTxtExt
absl::string_view EnumToString(const E value)
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
MessageCallback PrinterMessageCallback(std::ostream &output_stream, const absl::string_view prefix)
absl::StatusOr< ModelProto > ReadMpsFile(const absl::string_view filename)
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(const P proto_value)
Collection of objects used to extend the Constraint Solver library.
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)