21#include "absl/log/check.h"
22#include "absl/status/statusor.h"
23#include "gtest/gtest.h"
25#include "ortools/math_opt/solution.pb.h"
30constexpr double kInf = std::numeric_limits<double>::infinity();
39 const bool is_maximize,
const bool starting_basis_max_opt) {
44 .model_parameters = {.initial_basis = starting_basis_max_opt
48 CHECK_OK(result.termination.EnsureIsOptimal());
49 return result.solve_stats;
54 const std::unique_ptr<IncrementalSolver> solver =
56 const SolveResult max_result = solver->Solve({.parameters =
params_}).
value();
57 CHECK_OK(max_result.termination.EnsureIsOptimal());
59 max_model_parameters.
initial_basis = max_result.solutions[0].basis;
60 const SolveResult min_result = solver->Solve({.parameters =
params_}).
value();
61 CHECK_OK(min_result.termination.EnsureIsOptimal());
64 const SolveResult max_result_second =
67 {.parameters =
params_, .model_parameters = max_model_parameters})
69 CHECK_OK(max_result_second.termination.EnsureIsOptimal());
70 return max_result_second.solve_stats;
181 LinearConstraint c1 =
183 LinearConstraint c2 =
185 LinearConstraint c3 =
187 LinearConstraint c4 =
248 LinearConstraint c1 =
250 LinearConstraint c2 =
302 LinearConstraint c1 =
344 LinearConstraint c1 =
346 LinearConstraint c2 =
433 LinearConstraint c4 =
456TEST_P(LpBasisStartTest, EmptyModelAndBasis) {
457 model_.Maximize(objective_expression_);
458 const SolveStats stats = SolveWithWarmStart(
460 EXPECT_EQ(stats.simplex_iterations, 0);
463TEST_P(LpBasisStartTest, ModelWithoutVariables) {
464 LinearConstraint
c = model_.AddLinearConstraint(
"trivial equality");
466 const SolveStats stats = SolveWithWarmStart(
468 EXPECT_EQ(stats.simplex_iterations, 0);
479TEST_P(LpBasisStartTest, VariableBoundBoxModel) {
480 const int basis_distance = SetUpVariableBoundBoxModel();
481 const SolveStats stats = SolveWithWarmStart(
483 EXPECT_EQ(stats.simplex_iterations, basis_distance);
486TEST_P(LpBasisStartTest, ConstraintBoxModel) {
487 const int basis_distance = SetUpConstraintBoxModel();
488 const SolveStats stats = SolveWithWarmStart(
490 EXPECT_EQ(stats.simplex_iterations, basis_distance);
493TEST_P(LpBasisStartTest, RangedConstraintBoxModel) {
494 const int basis_distance = SetUpRangedConstraintBoxModel();
495 const SolveStats stats = SolveWithWarmStart(
497 EXPECT_EQ(stats.simplex_iterations, basis_distance);
500TEST_P(LpBasisStartTest, BasicRangedConstraintModel) {
501 const int basis_distance = SetUpBasicRangedConstraintModel();
502 const SolveStats stats = SolveWithWarmStart(
504 EXPECT_EQ(stats.simplex_iterations, basis_distance);
507TEST_P(LpBasisStartTest, UnboundedVariablesAndConstraintsModel) {
510 int basis_distance = SetUpVariableBoundBoxModel();
511 basis_distance += SetUpUnboundedVariablesAndConstraintsModel();
512 const SolveStats stats = SolveWithWarmStart(
514 EXPECT_EQ(stats.simplex_iterations, basis_distance);
517TEST_P(LpBasisStartTest, FixedVariablesModel) {
520 int basis_distance = SetUpVariableBoundBoxModel();
521 basis_distance += SetUpFixedVariablesModel();
522 const SolveStats stats = SolveWithWarmStart(
524 EXPECT_EQ(stats.simplex_iterations, basis_distance);
527TEST_P(LpBasisStartTest, EqualitiesModel) {
530 int basis_distance = SetUpVariableBoundBoxModel();
531 basis_distance += SetUpEqualitiesModel();
532 const SolveStats stats = SolveWithWarmStart(
534 EXPECT_EQ(stats.simplex_iterations, basis_distance);
537TEST_P(LpBasisStartTest, CombinedModels) {
540 int basis_distance = SetUpVariableBoundBoxModel();
541 basis_distance += SetUpConstraintBoxModel();
542 basis_distance += SetUpRangedConstraintBoxModel();
543 basis_distance += SetUpBasicRangedConstraintModel();
544 basis_distance += SetUpUnboundedVariablesAndConstraintsModel();
545 basis_distance += SetUpFixedVariablesModel();
546 basis_distance += SetUpEqualitiesModel();
547 const SolveStats stats = SolveWithWarmStart(
549 EXPECT_EQ(stats.simplex_iterations, basis_distance);
570TEST_P(LpBasisStartTest, VariableBoundBoxModelOptimalRoundtrip) {
571 SetUpVariableBoundBoxModel();
572 const SolveStats stats = RoundTripSolve();
573 EXPECT_EQ(stats.simplex_iterations, 0);
576TEST_P(LpBasisStartTest, ConstraintBoxModelOptimalRoundtrip) {
577 SetUpConstraintBoxModel();
578 const SolveStats stats = RoundTripSolve();
579 EXPECT_EQ(stats.simplex_iterations, 0);
582TEST_P(LpBasisStartTest, RangedConstraintBoxModelOptimalRoundtrip) {
583 SetUpRangedConstraintBoxModel();
584 const SolveStats stats = RoundTripSolve();
585 EXPECT_EQ(stats.simplex_iterations, 0);
588TEST_P(LpBasisStartTest, BasicRangedConstraintModelOptimalRoundtrip) {
589 SetUpBasicRangedConstraintModel();
590 const SolveStats stats = RoundTripSolve();
591 EXPECT_EQ(stats.simplex_iterations, 0);
595 UnboundedVariablesAndConstraintsModelOptimalRoundtrip) {
598 SetUpVariableBoundBoxModel();
599 SetUpUnboundedVariablesAndConstraintsModel();
600 const SolveStats stats = RoundTripSolve();
601 EXPECT_EQ(stats.simplex_iterations, 0);
604TEST_P(LpBasisStartTest, FixedVariablesModelOptimalRoundtrip) {
607 SetUpVariableBoundBoxModel();
608 SetUpFixedVariablesModel();
609 const SolveStats stats = RoundTripSolve();
610 EXPECT_EQ(stats.simplex_iterations, 0);
613TEST_P(LpBasisStartTest, EqualitiesModelOptimalRoundtrip) {
616 SetUpVariableBoundBoxModel();
617 SetUpEqualitiesModel();
618 const SolveStats stats = RoundTripSolve();
619 EXPECT_EQ(stats.simplex_iterations, 0);
622TEST_P(LpBasisStartTest, CombinedModelsOptimalRoundtrip) {
625 SetUpVariableBoundBoxModel();
626 SetUpConstraintBoxModel();
627 SetUpRangedConstraintBoxModel();
628 SetUpBasicRangedConstraintModel();
629 SetUpUnboundedVariablesAndConstraintsModel();
630 SetUpFixedVariablesModel();
631 SetUpEqualitiesModel();
632 const SolveStats stats = RoundTripSolve();
633 EXPECT_EQ(stats.simplex_iterations, 0);
SolverType TestedSolver() const
SolveStats SolveWithWarmStart(bool is_maximize, bool starting_basis_max_opt)
int SetUpConstraintBoxModel()
SolveStats RoundTripSolve()
int SetUpFixedVariablesModel()
LinearExpression objective_expression_
int SetUpEqualitiesModel()
int SetUpVariableBoundBoxModel()
const SolveParameters params_
int SetUpBasicRangedConstraintModel()
int SetUpRangedConstraintBoxModel()
int SetUpUnboundedVariablesAndConstraintsModel()
void Maximize(double objective)
Sets the objective to maximize the provided expression.
void set_is_maximize(bool is_maximize)
Prefer set_maximize() and set_minimize() above for more readable code.
void AddToObjective(double objective)
Adds the provided expression terms to the objective.
Variable AddContinuousVariable(double lower_bound, double upper_bound, absl::string_view name="")
Adds a variable to the model with domain [lower_bound, upper_bound].
LinearConstraint AddLinearConstraint(absl::string_view name="")
Adds a linear constraint to the model with bounds [-inf, +inf].
TEST_P(InfeasibleSubsystemTest, CanComputeInfeasibleSubsystem)
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
absl::StatusOr< std::unique_ptr< IncrementalSolver > > NewIncrementalSolver(Model *model, SolverType solver_type, SolverInitArguments arguments)
@ 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).
In SWIG mode, we don't want anything besides these top-level includes.
LinearConstraintMap< BasisStatus > constraint_status
VariableMap< BasisStatus > variable_status
std::optional< Basis > initial_basis