Skip to content

Commit 27ebae0

Browse files
committed
fix #5016
1 parent a42049b commit 27ebae0

File tree

3 files changed

+53
-35
lines changed

3 files changed

+53
-35
lines changed

ortools/linear_solver/proto_solver/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ cc_library(
222222
"//ortools/linear_solver:linear_solver_cc_proto",
223223
"//ortools/linear_solver:model_validator",
224224
"//ortools/util:lazy_mutable_copy",
225+
"@abseil-cpp//absl/log",
225226
"@abseil-cpp//absl/status",
226227
"@abseil-cpp//absl/status:statusor",
227228
"@abseil-cpp//absl/strings",

ortools/linear_solver/proto_solver/highs_proto_solver.cc

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <vector>
2222

2323
#include "Highs.h"
24+
#include "absl/log/log.h"
2425
#include "absl/status/status.h"
2526
#include "absl/status/statusor.h"
2627
#include "absl/strings/str_cat.h"
@@ -222,43 +223,51 @@ absl::StatusOr<MPSolutionResponse> HighsSolveProto(
222223
const absl::Time time_before = absl::Now();
223224
UserTimer user_timer;
224225
user_timer.Start();
225-
HighsStatus run_status = highs.run();
226-
switch (run_status) {
227-
case HighsStatus::kError: {
228-
response.set_status(MPSOLVER_NOT_SOLVED);
229-
response.set_status_str("Error running HiGHS run()");
230-
return response;
231-
}
232-
case HighsStatus::kWarning: {
233-
response.set_status_str("Warning HiGHS run()");
226+
const HighsStatus run_status = highs.run();
227+
VLOG(2) << "run_status: " << highsStatusToString(run_status);
228+
if (run_status == HighsStatus::kError) {
229+
response.set_status(MPSOLVER_NOT_SOLVED);
230+
response.set_status_str("Error running HiGHS run()");
231+
return response;
232+
}
233+
const HighsModelStatus model_status = highs.getModelStatus();
234+
VLOG(2) << "model_status: " << highs.modelStatusToString(model_status);
235+
236+
switch (model_status) {
237+
case HighsModelStatus::kOptimal:
238+
response.set_status(MPSOLVER_OPTIMAL);
239+
break;
240+
case HighsModelStatus::kUnboundedOrInfeasible:
241+
response.set_status_str(
242+
"The model may actually be unbounded: HiGHS returned "
243+
"kUnboundedOrInfeasible");
244+
response.set_status(MPSOLVER_INFEASIBLE);
245+
break;
246+
case HighsModelStatus::kInfeasible:
247+
response.set_status(MPSOLVER_INFEASIBLE);
248+
break;
249+
case HighsModelStatus::kUnbounded:
250+
response.set_status(MPSOLVER_UNBOUNDED);
251+
break;
252+
case HighsModelStatus::kTimeLimit: // ABSL_FALLTHROUGH_INTENDED
253+
case HighsModelStatus::kIterationLimit: // ABSL_FALLTHROUGH_INTENDED
254+
case HighsModelStatus::kInterrupt: // ABSL_FALLTHROUGH_INTENDED
255+
case HighsModelStatus::kSolutionLimit: // ABSL_FALLTHROUGH_INTENDED
256+
case HighsModelStatus::kMemoryLimit: {
257+
const HighsInfo& info = highs.getInfo();
258+
if (info.primal_solution_status == kSolutionStatusFeasible) {
259+
response.set_status(MPSOLVER_FEASIBLE);
260+
} else {
261+
response.set_status(MPSOLVER_UNKNOWN_STATUS);
262+
}
234263
break;
235264
}
236-
case HighsStatus::kOk: {
237-
HighsModelStatus model_status = highs.getModelStatus();
238-
switch (model_status) {
239-
case HighsModelStatus::kOptimal:
240-
response.set_status(MPSOLVER_OPTIMAL);
241-
break;
242-
case HighsModelStatus::kUnboundedOrInfeasible:
243-
response.set_status_str(
244-
"The model may actually be unbounded: HiGHS returned "
245-
"kUnboundedOrInfeasible");
246-
response.set_status(MPSOLVER_INFEASIBLE);
247-
break;
248-
case HighsModelStatus::kInfeasible:
249-
response.set_status(MPSOLVER_INFEASIBLE);
250-
break;
251-
case HighsModelStatus::kUnbounded:
252-
response.set_status(MPSOLVER_UNBOUNDED);
253-
break;
254-
default: {
255-
// TODO(user): report feasible status.
256-
const HighsInfo& info = highs.getInfo();
257-
if (info.primal_solution_status == kSolutionStatusFeasible)
258-
response.set_status(MPSOLVER_FEASIBLE);
259-
break;
260-
}
265+
default: {
266+
const HighsInfo& info = highs.getInfo();
267+
if (info.primal_solution_status == kSolutionStatusFeasible) {
268+
response.set_status(MPSOLVER_FEASIBLE);
261269
}
270+
break;
262271
}
263272
}
264273

ortools/linear_solver/python/solve_model.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
_INPUT = flags.DEFINE_string("input", "", "Input file to load and solve.")
2525
_PARAMS = flags.DEFINE_string("params", "", "Solver parameters in string format.")
2626
_SOLVER = flags.DEFINE_string("solver", "sat", "Solver type to solve the model with.")
27+
_TIME_LIMIT = flags.DEFINE_float(
28+
"time_limit", -1, "Time limit in seconds for the solver. -1 means no limit."
29+
)
2730

2831

2932
def main(argv: Sequence[str]) -> None:
@@ -52,6 +55,10 @@ def main(argv: Sequence[str]) -> None:
5255
print(f"Cannot create solver with name '{_SOLVER.value}'")
5356
return
5457

58+
# Set time limit.
59+
if _TIME_LIMIT.value > 0:
60+
solver.set_time_limit_in_seconds(_TIME_LIMIT.value)
61+
5562
# Set parameters.
5663
if _PARAMS.value:
5764
solver.set_solver_specific_parameters(_PARAMS.value)
@@ -60,7 +67,8 @@ def main(argv: Sequence[str]) -> None:
6067
solver.enable_output(True)
6168

6269
# And solve.
63-
solver.solve(model)
70+
status = solver.solve(model)
71+
print(f"Status: {status}")
6472

6573

6674
if __name__ == "__main__":

0 commit comments

Comments
 (0)