21#include "absl/types/optional.h"
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
27#include "ortools/pdlp/solve_log.pb.h"
35using ::testing::AllOf;
37using ::testing::ElementsAre;
42using ::testing::SizeIs;
44TEST(CorrectedDualTest, SimpleLpWithSuboptimalDual) {
45 const int num_threads = 2;
46 const int num_shards = 10;
47 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
49 Eigen::VectorXd primal_solution(4), dual_solution(4);
52 primal_solution << 0, 0, 6, 2.5;
53 dual_solution << -2, 0, 2.375, 1;
55 sharded_qp, primal_solution, dual_solution, POINT_TYPE_CURRENT_ITERATE);
57 EXPECT_DOUBLE_EQ(stats.dual_objective(), -36.5);
58 EXPECT_DOUBLE_EQ(stats.corrected_dual_objective(), -36.5);
66TEST(CorrectedDualTest, SimpleLpWithVariableFarFromBound) {
67 const int num_threads = 2;
68 const int num_shards = 10;
69 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
71 Eigen::VectorXd primal_solution(4), dual_solution(4);
72 primal_solution << 0, 0, 2, 2.5;
73 dual_solution << -2, 0, 2.375, 1;
75 sharded_qp, primal_solution, dual_solution, POINT_TYPE_CURRENT_ITERATE);
77 EXPECT_DOUBLE_EQ(stats.dual_objective(), -33.5);
78 EXPECT_DOUBLE_EQ(stats.corrected_dual_objective(), -36.5);
79 EXPECT_DOUBLE_EQ(stats.l_inf_dual_residual(), 0.5);
80 EXPECT_DOUBLE_EQ(stats.l2_dual_residual(), 0.5);
83TEST(CorrectedDualObjective, QpSuboptimal) {
84 const int num_threads = 2;
85 const int num_shards = 10;
89 Eigen::VectorXd primal_solution(2), dual_solution(1);
91 primal_solution << -2.0, 2.0;
93 sharded_qp, primal_solution, dual_solution, POINT_TYPE_CURRENT_ITERATE);
100 EXPECT_DOUBLE_EQ(stats.corrected_dual_objective(), -28.0);
103TEST(RandomProjectionsTest, OneRandomProjectionsOfZeroVector) {
104 const int num_threads = 2;
105 const int num_shards = 10;
106 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
108 PointMetadata metadata;
112 EXPECT_THAT(metadata.random_primal_projections(), ElementsAre(0.0));
113 EXPECT_THAT(metadata.random_dual_projections(), ElementsAre(0.0));
116TEST(RandomProjectionsTest, TwoRandomProjectionsOfVector) {
117 const int num_threads = 2;
118 const int num_shards = 10;
119 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
121 PointMetadata metadata;
125 EXPECT_THAT(metadata.random_primal_projections(), SizeIs(2));
126 EXPECT_THAT(metadata.random_dual_projections(), SizeIs(2));
129 EXPECT_THAT(metadata.random_primal_projections(),
130 Each(AllOf(Ge(-2.0), Le(2.0), Ne(0.0))));
131 EXPECT_THAT(metadata.random_dual_projections(), Each(Eq(0.0)));
134TEST(ReducedCostsTest, SimpleLp) {
135 const int num_threads = 2;
136 const int num_shards = 10;
137 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
139 Eigen::VectorXd primal_solution(4), dual_solution(4);
142 primal_solution << 0.0, -2.0, 6.0, 3.5;
143 dual_solution << 1.0, 0.0, 0.0, -2.0;
147 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution),
148 ElementsAre(0.0, 0.0, 0.0, -3.0));
149 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution,
151 ElementsAre(0.0, 0.0, 0.0, -4.0));
154TEST(ReducedCostsTest, SimpleLpWithGapResiduals) {
155 const int num_threads = 2;
156 const int num_shards = 10;
157 ShardedQuadraticProgram sharded_qp(
TestLp(), num_threads, num_shards);
159 Eigen::VectorXd primal_solution(4), dual_solution(4);
161 dual_solution << 1.0, 0.0, 0.0, -1.0;
167 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution),
168 ElementsAre(0.0, 0.0, 0.0, 0.0));
171 primal_solution << 0.0, 0.0, 4.0, 3.0;
172 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution),
173 ElementsAre(0.0, 0.0, -0.5, -2.0));
176TEST(ReducedCostsTest, SimpleQp) {
177 const int num_threads = 2;
178 const int num_shards = 10;
182 Eigen::VectorXd primal_solution(2), dual_solution(1);
183 primal_solution << 1.0, 2.0;
184 dual_solution << 0.0;
190 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution),
191 ElementsAre(3.0, 0.0));
192 EXPECT_THAT(
ReducedCosts(sharded_qp, primal_solution, dual_solution,
194 ElementsAre(0.0, 0.0));
198 const auto test_stats = ParseTextOrDie<IterationStats>(R
"pb(
199 convergence_information {
200 candidate_type: POINT_TYPE_CURRENT_ITERATE
201 primal_objective: 1.0
203 convergence_information {
204 candidate_type: POINT_TYPE_AVERAGE_ITERATE
205 primal_objective: 2.0
208 const auto average_info =
210 ASSERT_TRUE(average_info.has_value());
211 EXPECT_EQ(average_info->candidate_type(), POINT_TYPE_AVERAGE_ITERATE);
212 EXPECT_EQ(average_info->primal_objective(), 2.0);
214 const auto current_info =
216 ASSERT_TRUE(current_info.has_value());
217 EXPECT_EQ(current_info->candidate_type(), POINT_TYPE_CURRENT_ITERATE);
218 EXPECT_EQ(current_info->primal_objective(), 1.0);
226 const auto test_stats = ParseTextOrDie<IterationStats>(R
"pb(
227 infeasibility_information {
228 candidate_type: POINT_TYPE_CURRENT_ITERATE
229 primal_ray_linear_objective: 1.0
231 infeasibility_information {
232 candidate_type: POINT_TYPE_AVERAGE_ITERATE
233 primal_ray_linear_objective: 2.0
236 const auto average_info =
238 ASSERT_TRUE(average_info.has_value());
239 EXPECT_EQ(average_info->candidate_type(), POINT_TYPE_AVERAGE_ITERATE);
240 EXPECT_EQ(average_info->primal_ray_linear_objective(), 2.0);
242 const auto current_info =
244 ASSERT_TRUE(current_info.has_value());
245 EXPECT_EQ(current_info->candidate_type(), POINT_TYPE_CURRENT_ITERATE);
246 EXPECT_EQ(current_info->primal_ray_linear_objective(), 1.0);
254 const auto test_stats = ParseTextOrDie<IterationStats>(R
"pb(
256 point_type: POINT_TYPE_CURRENT_ITERATE
257 active_primal_variable_count: 1
260 point_type: POINT_TYPE_AVERAGE_ITERATE
261 active_primal_variable_count: 2
264 const auto average_info =
266 ASSERT_TRUE(average_info.has_value());
267 EXPECT_EQ(average_info->point_type(), POINT_TYPE_AVERAGE_ITERATE);
268 EXPECT_EQ(average_info->active_primal_variable_count(), 2);
270 const auto current_info =
272 ASSERT_TRUE(current_info.has_value());
273 EXPECT_EQ(current_info->point_type(), POINT_TYPE_CURRENT_ITERATE);
274 EXPECT_EQ(current_info->active_primal_variable_count(), 1);
T ParseTextOrDie(const std::string &input)
ConvergenceInformation ComputeScaledConvergenceInformation(const ShardedQuadraticProgram &sharded_qp, const VectorXd &primal_solution, const VectorXd &dual_solution, PointType candidate_type)
VectorXd ReducedCosts(const ShardedQuadraticProgram &sharded_qp, const VectorXd &primal_solution, const VectorXd &dual_solution, bool use_zero_primal_objective)
absl::optional< PointMetadata > GetPointMetadata(const IterationStats &stats, const PointType point_type)
absl::optional< ConvergenceInformation > GetConvergenceInformation(const IterationStats &stats, PointType candidate_type)
void SetRandomProjections(const ShardedQuadraticProgram &sharded_qp, const Eigen::VectorXd &primal_solution, const Eigen::VectorXd &dual_solution, const std::vector< int > &random_projection_seeds, PointMetadata &metadata)
absl::optional< InfeasibilityInformation > GetInfeasibilityInformation(const IterationStats &stats, PointType candidate_type)
QuadraticProgram TestLp()
QuadraticProgram TestDiagonalQp1()
TEST(LinearAssignmentTest, NullMatrix)