27#include "absl/log/check.h"
28#include "absl/status/statusor.h"
29#include "gtest/gtest.h"
34#include "ortools/math_opt/solution.pb.h"
40using ::testing::AnyOf;
43constexpr double kInf = std::numeric_limits<double>::infinity();
59 <<
" disallows_infeasible_or_unbounded: "
72 : model_(
"incremental_solve_test"),
73 zero_(model_.AddContinuousVariable(0, 0,
"zero")),
74 x_1_(model_.AddContinuousVariable(0, 1,
"x_1")),
75 y_1_(model_.AddContinuousVariable(0, 1,
"y_1")),
76 c_1_(model_.AddLinearConstraint(x_1_ + y_1_ <= 1.5,
"c_1")),
77 x_2_(model_.AddContinuousVariable(0, 1,
"x_2")),
78 y_2_(model_.AddContinuousVariable(0, 1,
"y_2")),
79 c_2_(model_.AddLinearConstraint(x_2_ + y_2_ <= 1.5,
"c_2")),
80 x_3_(model_.AddContinuousVariable(0, 1,
"x_3")),
81 y_3_(model_.AddContinuousVariable(0, 1,
"y_3")),
82 c_3_(model_.AddLinearConstraint(x_3_ + y_3_ <= 1.5,
"c_3")) {
83 model_.Maximize(0.1 + 3 * (x_1_ + x_2_ + x_3_) + 2 * (y_1_ + y_2_ + y_3_));
85 const SolveResult first_solve = solver_->Solve().value();
86 CHECK_OK(first_solve.termination.EnsureIsOptimal());
87 CHECK_LE(std::abs(first_solve.objective_value() - 12.1),
kTolerance);
92TEST_P(SimpleLpTest, ProtoNonIncrementalSolve) {
94 const Variable x = model.AddContinuousVariable(0, 1,
"x");
96 const ModelProto proto = model.ExportModel();
98 const SolveResultProto result,
102 {.parameters = GetParam().parameters.Proto()}));
103 ASSERT_EQ(result.termination().reason(), TERMINATION_REASON_OPTIMAL)
105 ASSERT_GE(result.solutions_size(), 1);
106 ASSERT_TRUE(result.solutions(0).has_primal_solution());
107 EXPECT_NEAR(result.solutions(0).primal_solution().objective_value(), 2.0,
109 EXPECT_EQ(result.solutions(0).primal_solution().feasibility_status(),
110 SOLUTION_STATUS_FEASIBLE);
111 if (GetParam().supports_duals) {
112 ASSERT_TRUE(result.solutions(0).has_dual_solution());
113 ASSERT_TRUE(result.solutions(0).dual_solution().has_objective_value());
114 EXPECT_NEAR(result.solutions(0).dual_solution().objective_value(), 2.0,
116 EXPECT_EQ(result.solutions(0).dual_solution().feasibility_status(),
117 SOLUTION_STATUS_FEASIBLE);
142 const Variable x = model.AddContinuousVariable(0.0, 4.0,
"x");
147 if (GetParam().supports_duals) {
171 const Variable x = model.AddContinuousVariable(-2.4, 4.0,
"x");
175 if (GetParam().supports_duals) {
202 auto model = std::make_unique<Model>();
207 model->AddLinearConstraint(p <= x_1 + x_2 <= 1.5,
"y");
208 SolveResult result{Termination::Optimal(2.5)};
209 result.solutions.push_back(
Solution{
212 .objective_value = 2.5,
216 .reduced_costs = {{x_1, 1.0}, {x_2, 0.0}},
217 .objective_value = 2.5,
219 return {.model = std::move(model), .expected_result = result};
223 const SolvedModel solved_model = SimpleLinearConstraint(0.0);
227 {.check_dual = GetParam().supports_duals})));
235 {.check_dual = GetParam().supports_duals})));
260SolvedModel SimpleLinearConstraintDualMin(
double p) {
261 auto model = std::make_unique<Model>();
266 model->AddLinearConstraint(0.5 <= x_1 + x_2 <= p,
"y");
267 SolveResult result{Termination::Optimal(0.5)};
268 result.solutions.push_back(
Solution{
271 .objective_value = 0.5,
275 .reduced_costs = {{x_1, 1.0}, {x_2, 0.0}},
276 .objective_value = 0.5,
278 return {std::move(model), result};
282 const SolvedModel solved_model = SimpleLinearConstraintDualMin(1.5);
286 {.check_dual = GetParam().supports_duals})));
294 {.check_dual = GetParam().supports_duals})));
319SolvedModel SimpleLinearConstraintDualLowerBounds(
double p) {
320 auto model = std::make_unique<Model>();
325 model->AddLinearConstraint(0.5 <= x_1 + x_2 <= p,
"y");
326 SolveResult result{Termination::Optimal(-0.5)};
327 result.solutions.push_back(
Solution{
330 .objective_value = -0.5,
334 .reduced_costs = {{x_1, -1.0}, {x_2, 0.0}},
335 .objective_value = -0.5,
337 return {std::move(model), result};
341 const SolvedModel solved_model = SimpleLinearConstraintDualLowerBounds(1.5);
345 {.check_dual = GetParam().supports_duals})));
349 const SolvedModel solved_model = SimpleLinearConstraintDualLowerBounds(
kInf);
353 {.check_dual = GetParam().supports_duals})));
365 auto model = std::make_unique<Model>();
366 const Variable x_1 = model->AddContinuousVariable(0.0,
kInf,
"x_1");
367 const Variable x_2 = model->AddContinuousVariable(0.0,
kInf,
"x_2");
370 model->AddLinearConstraint(-1 <= x_1 - x_2 <= 1,
"y");
372 model->AddLinearConstraint(-1 <= x_1 - x_2,
"y_1");
373 model->AddLinearConstraint(x_1 - x_2 <= 1,
"y_2");
375 SolveResult result{Termination::Unbounded(
true)};
376 result.primal_rays.emplace_back().variable_values = {{x_1, 1.0}, {x_2, 1.0}};
377 return {std::move(model), result};
383 matcher_options.inf_or_unb_soft_match =
384 !test_params.disallows_infeasible_or_unbounded;
386 test_params.ensures_primal_ray || actual.has_ray();
387 return matcher_options;
391 const SolvedModel solved_model = SimpleUnboundedLP(
true);
393 SimpleSolve(*solved_model.model));
396 PrimalRayMatchOptions(GetParam(), actual)));
400 const SolvedModel solved_model = SimpleUnboundedLP(
false);
402 SimpleSolve(*solved_model.model));
405 PrimalRayMatchOptions(GetParam(), actual)));
434 auto model = std::make_unique<Model>();
435 const Variable x_1 = model->AddContinuousVariable(0, 3,
"x_1");
436 const Variable x_2 = model->AddContinuousVariable(0, 3,
"x_2");
439 model->AddLinearConstraint(p <= x_1 + x_2 <= -1,
"y");
440 SolveResult result{Termination::Infeasible(
443 result.dual_rays.push_back(
444 {.dual_values = {{y, -1.0}}, .reduced_costs = {{x_1, 1.0}, {x_2, 1.0}}});
445 return {std::move(model), result};
453 matcher_options.inf_or_unb_soft_match =
false;
457 matcher_options.inf_or_unb_soft_match =
true;
460 test_params.ensures_dual_ray || actual.has_dual_ray();
461 return matcher_options;
465 const SolvedModel solved_model = SimpleInfeasibleLPMin(-2.0);
467 SimpleSolve(*solved_model.model));
470 DualUnboundedMatchOptions(GetParam(), actual)));
476 SimpleSolve(*solved_model.model));
479 DualUnboundedMatchOptions(GetParam(), actual)));
507 auto model = std::make_unique<Model>();
508 const Variable x_1 = model->AddContinuousVariable(0, 3,
"x_1");
509 const Variable x_2 = model->AddContinuousVariable(0, 3,
"x_2");
512 model->AddLinearConstraint(p <= x_1 + x_2 <= -1,
"y");
513 SolveResult result{Termination::Infeasible(
516 result.dual_rays.push_back(
517 {.dual_values = {{y, 1.0}}, .reduced_costs = {{x_1, -1.0}, {x_2, -1.0}}});
518 return {std::move(model), result};
522 const SolvedModel solved_model = SimpleInfeasibleLPMax(-2.0);
524 SimpleSolve(*solved_model.model));
527 DualUnboundedMatchOptions(GetParam(), actual)));
533 SimpleSolve(*solved_model.model));
536 DualUnboundedMatchOptions(GetParam(), actual)));
578SolvedModel ConstraintDefinedBasisLP(
const double p) {
579 auto model = std::make_unique<Model>();
580 const Variable x_1 = model->AddContinuousVariable(-1, 1,
"x_1");
581 const Variable x_2 = model->AddContinuousVariable(0,
kInf,
"x_2");
584 model->AddLinearConstraint(-p <= x_1 + x_2 <= 2,
"y_1");
586 model->AddLinearConstraint(-2 <= x_1 - x_2 <= p,
"y_2");
587 SolveResult result{Termination::Optimal(2.0)};
588 result.solutions.push_back(
Solution{
591 .objective_value = 2.0,
595 .reduced_costs = {{x_1, 0.0}, {x_2, 0.0}},
596 .objective_value = 2.0,
603 return {std::move(model), result};
607 if (!GetParam().supports_basis) {
609 <<
"Getting the basis is not supported for this config, skipping test.";
611 const SolvedModel solved_model = ConstraintDefinedBasisLP(2.0);
614 {.check_basis = true})));
618 if (!GetParam().supports_basis) {
620 <<
"Getting the basis is not supported for this config, skipping test.";
625 {.check_basis = true})));
666SolvedModel ConstraintVariableDefinedBasisLP(
const double p) {
667 auto model = std::make_unique<Model>();
668 model->set_is_maximize(
true);
669 const Variable x_1 = model->AddContinuousVariable(-1.0, 1.0,
"x_1");
670 const Variable x_2 = model->AddContinuousVariable(0.0,
kInf,
"x_2");
673 model->AddLinearConstraint(-p <= x_1 + x_2 <= 2.0,
"y_1");
675 model->AddLinearConstraint(-2.0 <= x_1 - x_2 <= p,
"y_2");
677 SolveResult result{Termination::Optimal(3.0)};
678 result.solutions.push_back(
Solution{
681 .objective_value = 3,
685 .reduced_costs = {{x_1, 1.0}, {x_2, 0.0}},
686 .objective_value = 3.0,
694 return {std::move(model), result};
698 if (!GetParam().supports_basis) {
700 <<
"Getting the basis is not supported for this config, skipping test.";
702 const SolvedModel solved_model = ConstraintVariableDefinedBasisLP(2.0);
705 {.check_basis = true})));
709 if (!GetParam().supports_basis) {
711 <<
"Getting the basis is not supported for this config, skipping test.";
713 const SolvedModel solved_model = ConstraintVariableDefinedBasisLP(
kInf);
716 {.check_basis = true})));
755SolvedModel VariableDefinedBasisLP(
const double p) {
756 auto model = std::make_unique<Model>();
757 const Variable x_1 = model->AddContinuousVariable(-1.0, 1.0,
"x_1");
758 const Variable x_2 = model->AddContinuousVariable(0.0,
kInf,
"x_2");
761 model->AddLinearConstraint(-p <= x_1 + x_2 <= 2.0,
"y_1");
763 model->AddLinearConstraint(-2.0 <= x_1 - x_2 <= p,
"y_2");
765 SolveResult result{Termination::Optimal(-1.0)};
766 result.solutions.push_back(
Solution{
769 .objective_value = -1,
773 .reduced_costs = {{x_1, 1.0}, {x_2, 1.0}},
774 .objective_value = -1,
781 return {std::move(model), result};
785 if (!GetParam().supports_basis) {
787 <<
"Getting the basis is not supported for this config, skipping test.";
789 const SolvedModel solved_model = VariableDefinedBasisLP(2.0);
792 {.check_basis = true})));
796 if (!GetParam().supports_basis) {
798 <<
"Getting the basis is not supported for this config, skipping test.";
803 {.check_basis = true})));
835 if (!GetParam().supports_basis) {
837 <<
"Getting the basis is not supported for this config, skipping test.";
841 const Variable x_1 = model.AddContinuousVariable(0.0, 1.0,
"x_1");
845 model.AddLinearConstraint(-x_1 + x_2 == 0.0,
"y_1");
849 {{x_1, 2.0}, {x_2, 0.0}}));
850 const Basis expected_basis_alternative_one = {
855 const Basis expected_basis_alternative_two = {
861 ASSERT_TRUE(result.has_basis());
863 AnyOf(
BasisIs(expected_basis_alternative_one),
864 BasisIs(expected_basis_alternative_two)));
906 if (!GetParam().supports_basis) {
908 <<
"Getting the basis is not supported for this config, skipping test.";
916 model.AddLinearConstraint(-
kInf <= 2 * x_2 <=
kInf,
"y_1");
920 {{x_1, 0.0}, {x_2, 0.0}}));
922 const Basis expected_basis_alternative_one = {
927 const Basis expected_basis_alternative_two = {
932 ASSERT_TRUE(result.has_basis());
934 AnyOf(
BasisIs(expected_basis_alternative_one),
935 BasisIs(expected_basis_alternative_two)));
946 GTEST_SKIP() <<
"Glpk returns [GLP_EFAIL] for the first solve.";
949 const Variable x = model.AddContinuousVariable(0, 1,
"x");
951 model.AddLinearConstraint(
x >= 2);
953 const SolveArguments arguments{.parameters = GetParam().parameters};
961 model.set_upper_bound(
x, 3);
969 GTEST_SKIP() <<
"Glpk returns [GLP_EFAIL] for the first solve.";
972 const Variable x = model.AddContinuousVariable(-
kInf, 1,
"x");
975 const SolveArguments arguments{.parameters = GetParam().parameters};
983 model.set_lower_bound(
x, 0);
993 model_.set_minimize();
999 model_.set_objective_offset(1.1);
1005 model_.set_objective_coefficient(x_1_, 5.0);
1006 model_.set_objective_coefficient(x_2_, 5.0);
1007 model_.set_objective_coefficient(x_3_, 5.0);
1014 model_.DeleteVariable(zero_);
1015 model_.set_objective_coefficient(x_1_, 5.0);
1016 model_.set_objective_coefficient(x_2_, 5.0);
1017 model_.set_objective_coefficient(x_3_, 5.0);
1024 model_.DeleteVariable(zero_);
1027 model_.set_objective_coefficient(x_1_, 5.0);
1028 model_.set_objective_coefficient(x_2_, 5.0);
1029 model_.set_objective_coefficient(x_3_, 5.0);
1044 model_.set_lower_bound(y_1_, 0.75);
1045 model_.set_lower_bound(y_2_, 0.75);
1046 model_.set_lower_bound(y_3_, 0.75);
1053 model_.DeleteVariable(zero_);
1054 model_.set_lower_bound(y_1_, 0.75);
1055 model_.set_lower_bound(y_2_, 0.75);
1056 model_.set_lower_bound(y_3_, 0.75);
1063 model_.DeleteVariable(zero_);
1066 model_.set_lower_bound(y_1_, 0.75);
1067 model_.set_lower_bound(y_2_, 0.75);
1068 model_.set_lower_bound(y_3_, 0.75);
1075 model_.set_upper_bound(x_1_, 0.5);
1076 model_.set_upper_bound(x_2_, 0.5);
1077 model_.set_upper_bound(x_3_, 0.5);
1084 model_.set_lower_bound(c_1_, 1.0);
1085 model_.set_lower_bound(c_2_, 1.0);
1086 model_.set_lower_bound(c_3_, 1.0);
1092 EXPECT_EQ(result.solve_stats.simplex_iterations, 0);
1093 EXPECT_EQ(result.solve_stats.barrier_iterations, 0);
1094 EXPECT_EQ(result.solve_stats.first_order_iterations, 0);
1104 model_.set_lower_bound(c_1_, 1.0);
1107 solver_->SolveWithoutUpdate());
1111 EXPECT_EQ(first_result.solve_stats.simplex_iterations, 0);
1112 EXPECT_EQ(first_result.solve_stats.barrier_iterations, 0);
1113 EXPECT_EQ(first_result.solve_stats.first_order_iterations, 0);
1118 model_.set_lower_bound(c_1_, -
kInf);
1119 model_.set_lower_bound(c_2_, 1.0);
1122 solver_->SolveWithoutUpdate());
1126 EXPECT_EQ(second_result.solve_stats.simplex_iterations, 0);
1127 EXPECT_EQ(second_result.solve_stats.barrier_iterations, 0);
1128 EXPECT_EQ(second_result.solve_stats.first_order_iterations, 0);
1131 model_.set_lower_bound(c_2_, -
kInf);
1134 solver_->SolveWithoutUpdate());
1138 EXPECT_EQ(third_result.solve_stats.simplex_iterations, 0);
1139 EXPECT_EQ(third_result.solve_stats.barrier_iterations, 0);
1140 EXPECT_EQ(third_result.solve_stats.first_order_iterations, 0);
1144 model_.set_upper_bound(c_1_, 2.0);
1145 model_.set_upper_bound(c_2_, 2.0);
1146 model_.set_upper_bound(c_3_, 2.0);
1153 model_.set_coefficient(c_1_, y_1_, 0.5);
1154 model_.set_coefficient(c_2_, y_2_, 0.5);
1155 model_.set_coefficient(c_3_, y_3_, 0.5);
1162 const Variable z_1 = model_.AddContinuousVariable(0.0, 1.0,
"z_1");
1163 model_.set_objective_coefficient(z_1, 10.0);
1164 model_.set_coefficient(c_1_, z_1, 1.0);
1165 const Variable z_2 = model_.AddContinuousVariable(0.0, 1.0,
"z_2");
1166 model_.set_objective_coefficient(z_2, 10.0);
1167 model_.set_coefficient(c_2_, z_2, 1.0);
1168 const Variable z_3 = model_.AddContinuousVariable(0.0, 1.0,
"z_3");
1169 model_.set_objective_coefficient(z_3, 10.0);
1170 model_.set_coefficient(c_3_, z_3, 1.0);
1178 model_.set_coefficient(d_1, x_1_, 1.0);
1179 model_.set_coefficient(d_1, y_1_, 2.0);
1181 model_.set_coefficient(d_2, x_2_, 1.0);
1182 model_.set_coefficient(d_2, y_2_, 2.0);
1184 model_.set_coefficient(d_3, x_3_, 1.0);
1185 model_.set_coefficient(d_3, y_3_, 2.0);
1192 model_.DeleteVariable(x_1_);
1193 model_.DeleteVariable(x_2_);
1194 model_.DeleteVariable(x_3_);
1201 model_.DeleteLinearConstraint(c_1_);
1202 model_.DeleteLinearConstraint(c_2_);
1203 model_.DeleteLinearConstraint(c_3_);
1210 model_.set_lower_bound(x_1_, 3.0);
1214 model_.set_upper_bound(x_1_, 5.0);
1222 model_.set_lower_bound(c_1_, 4.0);
1227 model_.set_upper_bound(c_1_, 5.5);
1231 solver_->SolveWithoutUpdate(),
void Maximize(Variable *obj, std::vector< Annotation > search_annotations)
Variable * AddVariable(absl::string_view name, const Domain &domain, bool defined)
--— Builder methods --—
void Minimize(Variable *obj, std::vector< Annotation > search_annotations)
static absl::StatusOr< SolveResultProto > NonIncrementalSolve(const ModelProto &model, SolverTypeProto solver_type, const InitArgs &init_args, const SolveArgs &solve_args)
A shortcut for calling Solver::New() and then Solver::Solve().
An object oriented wrapper for quadratic constraints in ModelStorage.
Matcher< SolveResult > IsOptimalWithSolution(const double expected_objective, const VariableMap< double > expected_variable_values, const double tolerance)
EXPECT_THAT(ComputeInfeasibleSubsystem(model, GetParam().solver_type), IsOkAndHolds(IsInfeasible(true, ModelSubset{ .variable_bounds={{x, ModelSubset::Bounds{.lower=false,.upper=true}}},.linear_constraints={ {c, ModelSubset::Bounds{.lower=true,.upper=false}}}})))
TEST_P(InfeasibleSubsystemTest, CanComputeInfeasibleSubsystem)
@ kInfeasible
The primal problem has no feasible solutions.
<=x<=1 IncrementalMipTest::IncrementalMipTest() :model_("incremental_solve_test"), x_(model_.AddContinuousVariable(0.0, 1.0, "x")), y_(model_.AddIntegerVariable(0.0, 2.0, "y")), c_(model_.AddLinearConstraint(0<=x_+y_<=1.5, "c")) { model_.Maximize(3.0 *x_+2.0 *y_+0.1);solver_=NewIncrementalSolver(&model_, TestedSolver()).value();const SolveResult first_solve=solver_->Solve().value();CHECK(first_solve.has_primal_feasible_solution());CHECK_LE(std::abs(first_solve.objective_value() - 3.6), kTolerance)<< first_solve.objective_value();} namespace { TEST_P(SimpleMipTest, OneVarMax) { Model model;const Variable x=model.AddVariable(0.0, 4.0, false, "x");model.Maximize(2.0 *x);ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));ASSERT_THAT(result, IsOptimal(8.0));EXPECT_THAT(result.variable_values(), IsNear({{x, 4.0}}));} TEST_P(SimpleMipTest, OneVarMin) { Model model;const Variable x=model.AddVariable(-2.4, 4.0, false, "x");model.Minimize(2.0 *x);ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));ASSERT_THAT(result, IsOptimal(-4.8));EXPECT_THAT(result.variable_values(), IsNear({{x, -2.4}}));} TEST_P(SimpleMipTest, OneIntegerVar) { Model model;const Variable x=model.AddVariable(0.0, 4.5, true, "x");model.Maximize(2.0 *x);ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));ASSERT_THAT(result, IsOptimal(8.0));EXPECT_THAT(result.variable_values(), IsNear({{x, 4.0}}));} TEST_P(SimpleMipTest, SimpleLinearConstraint) { Model model;const Variable x=model.AddBinaryVariable("x");const Variable y=model.AddBinaryVariable("y");model.Maximize(2.0 *x+y);model.AddLinearConstraint(0.0<=x+y<=1.5, "c");ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));ASSERT_THAT(result, IsOptimal(2.0));EXPECT_THAT(result.variable_values(), IsNear({{x, 1}, {y, 0}}));} TEST_P(SimpleMipTest, Unbounded) { Model model;const Variable x=model.AddVariable(0.0, kInf, true, "x");model.Maximize(2.0 *x);ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));if(GetParam().report_unboundness_correctly) { ASSERT_THAT(result, TerminatesWithOneOf({TerminationReason::kUnbounded, TerminationReason::kInfeasibleOrUnbounded}));} else { ASSERT_THAT(result, TerminatesWith(TerminationReason::kOtherError));} } TEST_P(SimpleMipTest, Infeasible) { Model model;const Variable x=model.AddVariable(0.0, 3.0, true, "x");model.Maximize(2.0 *x);model.AddLinearConstraint(x >=4.0);ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(model, GetParam().solver_type));ASSERT_THAT(result, TerminatesWith(TerminationReason::kInfeasible));} TEST_P(SimpleMipTest, FractionalBoundsContainNoInteger) { if(GetParam().solver_type==SolverType::kGurobi) { GTEST_SKIP()<< "TODO(b/272298816): Gurobi bindings are broken here.";} 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)));} TEST_P(IncrementalMipTest, EmptyUpdate) { ASSERT_THAT(solver_->Update(), IsOkAndHolds(DidUpdate()));ASSERT_OK_AND_ASSIGN(const SolveResult result, solver_->SolveWithoutUpdate());ASSERT_THAT(result, IsOptimal(3.6));EXPECT_THAT(result.variable_values(), IsNear({{x_, 0.5}, {y_, 1.0}}));} TEST_P(IncrementalMipTest, MakeContinuous) { model_.set_continuous(y_);ASSERT_THAT(solver_->Update(), IsOkAndHolds(DidUpdate()));ASSERT_OK_AND_ASSIGN(const SolveResult result, solver_->SolveWithoutUpdate());ASSERT_THAT(result, IsOptimal(4.1));EXPECT_THAT(result.variable_values(), IsNear({{x_, 1.0}, {y_, 0.5}}));} TEST_P(IncrementalMipTest, DISABLED_MakeContinuousWithNonIntegralBounds) { solver_.reset();Model model("bounds");const Variable x=model.AddIntegerVariable(0.5, 1.5, "x");model.Maximize(x);ASSERT_OK_AND_ASSIGN(const auto solver, NewIncrementalSolver(&model, TestedSolver()));ASSERT_THAT(solver->Solve(), IsOkAndHolds(IsOptimal(1.0)));model.set_continuous(x);ASSERT_THAT(solver->Update(), IsOkAndHolds(DidUpdate()));ASSERT_THAT(solver-> IsOkAndHolds(IsOptimal(1.5)))
ASSERT_THAT(solver->Update(), IsOkAndHolds(DidUpdate()))
Matcher< SolveResult > TerminatesWithOneOf(const std::vector< TerminationReason > &allowed)
Checks that the result has one of the allowed termination reasons.
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
Matcher< SolveResult > IsConsistentWith(const SolveResult &expected, const SolveResultMatcherOptions &options)
absl::StatusOr< std::unique_ptr< IncrementalSolver > > NewIncrementalSolver(Model *model, SolverType solver_type, SolverInitArguments arguments)
@ kFeasible
Solver claims the solution is feasible.
@ kFixedValue
The variable/constraint has identical finite lower and upper bounds.
@ kBasic
The variable/constraint is basic.
@ kFree
The variable/constraint is free (it has no finite bounds).
@ kAtLowerBound
The variable/constraint is at its lower bound (which must be finite).
@ kAtUpperBound
The variable/constraint is at its upper bound (which must be finite).
Enum< E >::Proto EnumToProto(std::optional< E > value)
Matcher< UpdateResult > DidUpdate()
Actual UpdateResult.did_update is true.
constexpr double kTolerance
Matcher< SolveResult > IsOptimalWithDualSolution(const double expected_objective, const LinearConstraintMap< double > expected_dual_values, const VariableMap< double > expected_reduced_costs, const double tolerance)
Matcher< Basis > BasisIs(const Basis &expected)
Matcher< SolveResult > IsOptimal(const std::optional< double > expected_primal_objective, const double tolerance)
@ kFeasible
Solver claims the problem is feasible.
In SWIG mode, we don't want anything besides these top-level includes.
std::string ProtobufShortDebugString(const P &message)
std::string ProtobufDebugString(const P &message)
internal::IsOkAndHoldsMatcher< typename std::decay< InnerMatcher >::type > IsOkAndHolds(InnerMatcher &&inner_matcher)
#define ASSERT_OK_AND_ASSIGN(lhs, rexpr)
bool supports_basis
True if the solver produces a basis.
SolverType solver_type
The tested solver.
bool supports_duals
True if a dual solution is returned.
bool disallows_infeasible_or_unbounded
SimpleLpTestParameters(const SolverType solver_type, SolveParameters parameters, const bool supports_duals, const bool supports_basis, const bool ensures_primal_ray, const bool ensures_dual_ray, const bool disallows_infeasible_or_unbounded)
SolveParameters parameters
SolveParametersProto Proto() const
Configures SolveResult matcher IsConsistentWith() below.
std::unique_ptr< Model > model
SolveResult expected_result