-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Open
Labels
BugSolver: MathOptMathOpt related issueMathOpt related issueSolver: XpressFICO Xpress Solver related issueFICO Xpress Solver related issue
Milestone
Description
For SCIP and GLPK the following test pass since integer round leading to empty bound is correctly managed
We should try to improve xpress_solver to have the same behaviour...
or-tools/ortools/math_opt/solver_tests/mip_tests.cc
Lines 141 to 157 in 4336f9f
| TEST_P(SimpleMipTest, FractionalBoundsContainNoInteger) { | |
| if (GetParam().solver_type == SolverType::kGurobi) { | |
| // TODO(b/272298816): Gurobi bindings are broken here. | |
| GTEST_SKIP() << "TODO(b/272298816): Gurobi bindings are broken here."; | |
| } | |
| if (GetParam().solver_type == SolverType::kXpress) { | |
| // Xpress rounds bounds of integer variables on input, so the bounds | |
| // specified here result in [1,0]. Xpress also checks that bounds are | |
| // not contradicting, so it rejects creation of such a variable. | |
| GTEST_SKIP() << "Xpress does not support contradictory bounds."; | |
| } | |
| Model model; | |
| const Variable x = model.AddIntegerVariable(0.5, 0.6, "x"); | |
| model.Maximize(x); | |
| EXPECT_THAT(Solve(model, GetParam().solver_type), | |
| IsOkAndHolds(TerminatesWith(TerminationReason::kInfeasible))); | |
| } |
ref: GLPK implem...
or-tools/ortools/math_opt/solvers/glpk_solver.cc
Lines 1782 to 1809 in 4336f9f
| std::optional<SolveResultProto> GlpkSolver::EmptyIntegerBoundsResult() { | |
| const int num_cols = glp_get_num_cols(problem_); | |
| for (int c = 1; c <= num_cols; ++c) { | |
| if (!variables_.IsInteger(problem_, c)) { | |
| continue; | |
| } | |
| const double lb = variables_.unrounded_lower_bounds[c - 1]; | |
| const double ub = variables_.unrounded_upper_bounds[c - 1]; | |
| if (lb > ub) { | |
| // Unrounded bounds are inverted; this case is covered by | |
| // ListInvertedBounds(). We don't want to depend on the order of calls of | |
| // the two functions here so we exclude this case. | |
| continue; | |
| } | |
| if (std::ceil(lb) <= std::floor(ub)) { | |
| continue; | |
| } | |
| // We found a variable with empty integer bounds (that is lb <= ub but | |
| // ceil(lb) > floor(ub)). | |
| return ResultForIntegerInfeasible( | |
| /*is_maximize=*/glp_get_obj_dir(problem_) == GLP_MAX, | |
| /*bad_variable_id=*/variables_.ids[c - 1], | |
| /*lb=*/lb, /*ub=*/ub); | |
| } | |
| return std::nullopt; | |
| } |
or-tools/ortools/math_opt/solvers/glpk_solver.cc
Lines 1090 to 1098 in 4336f9f
| // Deal with empty integer bounds that result in inverted bounds due to bounds | |
| // rounding. | |
| { // Limit scope of `result`. | |
| std::optional<SolveResultProto> result = EmptyIntegerBoundsResult(); | |
| if (result.has_value()) { | |
| RETURN_IF_ERROR(set_solve_time(result.value())); | |
| return std::move(result).value(); | |
| } | |
| } |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
BugSolver: MathOptMathOpt related issueMathOpt related issueSolver: XpressFICO Xpress Solver related issueFICO Xpress Solver related issue