24 #include "Eigen/SparseCore"
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
30 #include "ortools/pdlp/solve_log.pb.h"
36 using ::Eigen::VectorXd;
37 using ::testing::ElementsAre;
38 using ::testing::ElementsAreArray;
39 using ::testing::IsNan;
41 TEST(ShardedWeightedAverageTest, SimpleAverage) {
44 Eigen::VectorXd vec1(2), vec2(2);
48 ShardedWeightedAverage
average(&sharder);
52 ASSERT_TRUE(
average.HasNonzeroWeight());
53 EXPECT_EQ(
average.NumTerms(), 2);
55 EXPECT_THAT(
average.ComputeAverage(), ElementsAre(2.0, 5.0));
58 EXPECT_FALSE(
average.HasNonzeroWeight());
59 EXPECT_EQ(
average.NumTerms(), 0);
62 TEST(ShardedWeightedAverageTest, MoveConstruction) {
65 Eigen::VectorXd vec(2);
68 ShardedWeightedAverage
average(&sharder);
71 ShardedWeightedAverage average2(std::move(
average));
72 EXPECT_THAT(average2.ComputeAverage(), ElementsAre(4.0, 1.0));
75 TEST(ShardedWeightedAverageTest, MoveAssignment) {
76 Sharder sharder1(2, 2,
78 Sharder sharder2(3, 2,
80 Eigen::VectorXd vec1(2), vec2(2);
84 ShardedWeightedAverage average1(&sharder1);
85 average1.Add(vec1, 2.0);
87 ShardedWeightedAverage average2(&sharder2);
89 average2 = std::move(average1);
90 average2.Add(vec2, 2.0);
91 EXPECT_THAT(average2.ComputeAverage(), ElementsAre(2.0, 2.0));
94 TEST(ShardedWeightedAverageTest, ZeroAverage) {
98 ShardedWeightedAverage
average(&sharder);
99 ASSERT_FALSE(
average.HasNonzeroWeight());
101 EXPECT_THAT(
average.ComputeAverage(), ElementsAre(0.0));
106 TEST(ShardedWeightedAverageTest, AveragesEqualWithoutRoundoff) {
107 Sharder sharder(4, 1,
109 ShardedWeightedAverage
average(&sharder);
110 EXPECT_THAT(
average.ComputeAverage(), ElementsAre(0, 0, 0, 0));
112 data << 1.0, 1.0 / 3, 3.0 / 7, 3.14159;
114 EXPECT_THAT(
average.ComputeAverage(), ElementsAreArray(data));
116 EXPECT_THAT(
average.ComputeAverage(), ElementsAreArray(data));
118 EXPECT_THAT(
average.ComputeAverage(), ElementsAreArray(data));
121 TEST(ShardedWeightedAverageTest, AddsZeroWeight) {
122 Sharder sharder(1, 1,
125 ShardedWeightedAverage
average(&sharder);
126 ASSERT_FALSE(
average.HasNonzeroWeight());
130 EXPECT_FALSE(
average.HasNonzeroWeight());
131 EXPECT_THAT(
average.ComputeAverage(), ElementsAre(0.0));
139 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
142 EXPECT_EQ(stats.num_variables(), 4);
143 EXPECT_EQ(stats.num_constraints(), 4);
144 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 1.0);
145 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 1.0);
146 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 9);
147 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 4.0);
148 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 1.0);
149 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_avg(), 14.5 / 9.0);
150 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), std::sqrt(31.25));
151 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_max(), 5.5);
152 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_min(), 1.0);
153 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_avg(), 2.375);
154 EXPECT_DOUBLE_EQ(stats.objective_vector_l2_norm(), std::sqrt(36.25));
155 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 0);
156 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 0.0);
157 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 0.0);
158 EXPECT_THAT(stats.objective_matrix_abs_avg(), IsNan());
159 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), 0.0);
160 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 1);
161 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 1.0);
162 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 1.0);
163 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_avg(), 1.0);
164 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), 1.0);
165 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 12.0);
166 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 1.0);
167 EXPECT_DOUBLE_EQ(stats.combined_bounds_avg(), 6.0);
168 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), std::sqrt(210.0));
172 ShardedQuadraticProgram lp(
TinyLp(), 2, 2);
175 EXPECT_EQ(stats.num_variables(), 4);
176 EXPECT_EQ(stats.num_constraints(), 3);
177 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 1.0);
178 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 1.0);
179 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 8);
180 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 2.0);
181 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 1.0);
182 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_avg(), 1.25);
183 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), std::sqrt(14.0));
184 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_max(), 5.0);
185 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_min(), 1.0);
186 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_avg(), 2.25);
187 EXPECT_DOUBLE_EQ(stats.objective_vector_l2_norm(), std::sqrt(31.0));
188 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 0);
189 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 0.0);
190 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 0.0);
191 EXPECT_THAT(stats.objective_matrix_abs_avg(), IsNan());
192 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), 0.0);
193 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 4);
194 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 6.0);
195 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 2.0);
196 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_avg(), 3.75);
197 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), std::sqrt(65.0));
198 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 12.0);
199 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 1.0);
200 EXPECT_DOUBLE_EQ(stats.combined_bounds_avg(), 20.0 / 3.0);
201 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), std::sqrt(194.0));
208 EXPECT_EQ(stats.num_variables(), 2);
209 EXPECT_EQ(stats.num_constraints(), 1);
210 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 1.0);
211 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 1.0);
212 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 2);
213 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 1.0);
214 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 1.0);
215 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_avg(), 1.0);
216 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), std::sqrt(2.0));
217 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_max(), 1.0);
218 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_min(), 1.0);
219 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_avg(), 1.0);
220 EXPECT_DOUBLE_EQ(stats.objective_vector_l2_norm(), std::sqrt(2.0));
221 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 2);
222 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 4.0);
223 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 1.0);
224 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_avg(), 2.5);
225 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), std::sqrt(17.0));
226 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 2);
227 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 6.0);
228 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 1.0);
229 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_avg(), 3.5);
230 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), std::sqrt(37.0));
231 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 1.0);
232 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 1.0);
233 EXPECT_DOUBLE_EQ(stats.combined_bounds_avg(), 1.0);
234 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), 1.0);
237 TEST(ProblemStatsTest, ModifiedTestDiagonalQp1) {
240 orig_qp.objective_matrix->diagonal() << 2.0, 0.0;
241 ShardedQuadraticProgram qp(orig_qp, 2, 2);
244 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 1);
245 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 2.0);
246 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 2.0);
247 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_avg(), 1.0);
248 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), 2.0);
254 TEST(ProblemStatsTest, TestLpWithInfiniteConstraintBoundThreshold) {
255 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
256 const QuadraticProgramStats stats =
259 EXPECT_EQ(stats.num_variables(), 4);
260 EXPECT_EQ(stats.num_constraints(), 4);
261 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 1.0);
262 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 1.0);
263 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 9);
264 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 4.0);
265 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 1.0);
266 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_avg(), 14.5 / 9.0);
267 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), std::sqrt(31.25));
268 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_max(), 5.5);
269 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_min(), 1.0);
270 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_avg(), 2.375);
271 EXPECT_DOUBLE_EQ(stats.objective_vector_l2_norm(), std::sqrt(36.25));
272 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 0);
273 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 0.0);
274 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 0.0);
275 EXPECT_THAT(stats.objective_matrix_abs_avg(), IsNan());
276 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), 0.0);
277 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 1);
278 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 1.0);
279 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 1.0);
280 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_avg(), 1.0);
281 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), 1.0);
282 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 7.0);
283 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 1.0);
284 EXPECT_DOUBLE_EQ(stats.combined_bounds_avg(), 3.0);
285 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), std::sqrt(66.0));
288 TEST(ProblemStatsTest, NoFiniteGaps) {
292 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 0);
293 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 0.0);
294 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 0.0);
295 EXPECT_THAT(stats.variable_bound_gaps_avg(), IsNan());
296 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), 0.0);
304 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 0);
305 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 0.0);
306 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 0.0);
307 EXPECT_THAT(stats.constraint_matrix_abs_avg(), IsNan());
308 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), 0.0);
309 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 0.0);
310 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 0.0);
311 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 0.0);
312 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 0.0);
313 EXPECT_THAT(stats.combined_bounds_avg(), IsNan());
314 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), 0.0);
317 TEST(ProblemStatsTest, EmptyLp) {
318 ShardedQuadraticProgram lp(QuadraticProgram(0, 0), 2, 2);
322 EXPECT_EQ(stats.num_variables(), 0);
323 EXPECT_EQ(stats.num_constraints(), 0);
324 EXPECT_DOUBLE_EQ(stats.constraint_matrix_col_min_l_inf_norm(), 0.0);
325 EXPECT_DOUBLE_EQ(stats.constraint_matrix_row_min_l_inf_norm(), 0.0);
326 EXPECT_EQ(stats.constraint_matrix_num_nonzeros(), 0);
327 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_max(), 0.0);
328 EXPECT_DOUBLE_EQ(stats.constraint_matrix_abs_min(), 0.0);
329 EXPECT_THAT(stats.constraint_matrix_abs_avg(), IsNan());
330 EXPECT_DOUBLE_EQ(stats.constraint_matrix_l2_norm(), 0.0);
331 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_max(), 0.0);
332 EXPECT_DOUBLE_EQ(stats.objective_vector_abs_min(), 0.0);
333 EXPECT_THAT(stats.objective_vector_abs_avg(), IsNan());
334 EXPECT_DOUBLE_EQ(stats.objective_vector_l2_norm(), 0.0);
335 EXPECT_EQ(stats.objective_matrix_num_nonzeros(), 0);
336 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_max(), 0.0);
337 EXPECT_DOUBLE_EQ(stats.objective_matrix_abs_min(), 0.0);
338 EXPECT_THAT(stats.objective_matrix_abs_avg(), IsNan());
339 EXPECT_DOUBLE_EQ(stats.objective_matrix_l2_norm(), 0.0);
340 EXPECT_EQ(stats.variable_bound_gaps_num_finite(), 0);
341 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_max(), 0.0);
342 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_min(), 0.0);
343 EXPECT_THAT(stats.variable_bound_gaps_avg(), IsNan());
344 EXPECT_DOUBLE_EQ(stats.variable_bound_gaps_l2_norm(), 0.0);
345 EXPECT_DOUBLE_EQ(stats.combined_bounds_max(), 0.0);
346 EXPECT_DOUBLE_EQ(stats.combined_bounds_min(), 0.0);
347 EXPECT_THAT(stats.combined_bounds_avg(), IsNan());
348 EXPECT_DOUBLE_EQ(stats.combined_bounds_l2_norm(), 0.0);
356 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
357 VectorXd row_scaling_vec(4), col_scaling_vec(4);
358 row_scaling_vec << 1, 2, 1, 3;
359 col_scaling_vec << 0, 1, 2, -1;
361 EXPECT_THAT(row_scaling_vec, ElementsAre(1 / std::sqrt(2), 1.0, 1.0, 1.0));
362 EXPECT_THAT(col_scaling_vec,
363 ElementsAre(0.0, 1.0, 2.0 / 3.0, -1.0 / std::sqrt(3.0)));
370 TEST(L2RuizRescaling, OneIteration) {
371 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
372 VectorXd row_scaling_vec(4), col_scaling_vec(4);
373 row_scaling_vec << 1, 2, 1, 3;
374 col_scaling_vec << 0, 1, 2, -1;
376 EXPECT_THAT(row_scaling_vec, ElementsAre(1.0 / std::pow(3.0, 0.5), 1.0, 1.0,
377 3.0 / std::pow(90.0, 0.25)));
378 EXPECT_THAT(col_scaling_vec, ElementsAre(0.0, 1.0, 2.0 / std::pow(101, 0.25),
379 -1.0 / std::pow(13.0, 0.25)));
385 TEST(L2RuizRescaling, OneIterationNonSquare) {
386 QuadraticProgram test_lp(2, 1);
387 std::vector<Eigen::Triplet<double, int64_t>> triplets = {{0, 0, 2.0},
389 test_lp.constraint_matrix.setFromTriplets(triplets.begin(), triplets.end());
390 ShardedQuadraticProgram lp(std::move(test_lp), 2,
392 VectorXd row_scaling_vec = VectorXd::Ones(1);
393 VectorXd col_scaling_vec = VectorXd::Ones(2);
395 EXPECT_THAT(row_scaling_vec, ElementsAre(1.0 / std::pow(13.0, 0.25)));
396 EXPECT_THAT(col_scaling_vec,
397 ElementsAre(1.0 / std::sqrt(2.0), 1.0 / std::sqrt(3.0)));
403 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
404 VectorXd row_scaling_vec(4), col_scaling_vec(4);
405 VectorXd col_norm(4), row_norm(4);
406 row_scaling_vec << 1, 1, 1, 1;
407 col_scaling_vec << 1, 1, 1, 1;
411 col_scaling_vec, lp.ConstraintMatrixSharder());
414 lp.TransposedConstraintMatrixSharder());
415 EXPECT_THAT(row_norm, EigenArrayNear<double>({1.0, 1.0, 1.0, 1.0}, 1.0e-4));
416 EXPECT_THAT(col_norm, EigenArrayNear<double>({1.0, 1.0, 1.0, 1.0}, 1.0e-4));
428 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
430 RescalingOptions{.l_inf_ruiz_iterations = 1, .l2_norm_rescaling =
true},
432 EXPECT_THAT(scaling.row_scaling_vec,
433 EigenArrayNear<double>(
434 {1.0 / sqrt(2.0 * 1.5275), 1.0 / sqrt(1.0 * 0.9574),
435 1.0 / sqrt(4.0 * 1.0), 1.0 / sqrt(1.5 * 1.1547)},
437 EXPECT_THAT(scaling.col_scaling_vec,
438 EigenArrayNear<double>(
439 {1.0 / sqrt(4.0 * 1.3229), 1.0 / sqrt(1.0 * 0.7071),
440 1.0 / sqrt(1.5 * 1.4142), 1.0 / sqrt(2.0 * 1.1547)},
444 TEST(ComputePrimalGradientTest, CorrectForLp) {
447 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
449 VectorXd primal_solution(4), dual_solution(4);
450 primal_solution << 0.0, 0.0, 0.0, 3.0;
451 dual_solution << -1.0, 0.0, 1.0, 1.0;
454 lp, primal_solution, lp.TransposedConstraintMatrix() * dual_solution);
458 EXPECT_THAT(primal_part.gradient,
459 ElementsAre(5.5 - 2.0, -2.0 + 1.0, -1.0 - 0.5, 1.0 + 3.0));
461 EXPECT_DOUBLE_EQ(primal_part.value, 3.0 + 9.0);
464 TEST(ComputeDualGradientTest, CorrectForLp) {
467 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
469 VectorXd primal_solution(4), dual_solution(4);
470 primal_solution << 0.0, 0.0, 0.0, 3.0;
471 dual_solution << -1.0, 0.0, 1.0, 1.0;
474 lp, dual_solution, lp.Qp().constraint_matrix * primal_solution);
478 EXPECT_THAT(dual_part.gradient,
479 ElementsAre(12.0 - 6.0, 7.0, -4.0, -1.0 + 3.0));
481 EXPECT_DOUBLE_EQ(dual_part.value, 12.0 * -1.0 + -4.0 * 1.0 + -1.0 * 1.0);
484 TEST(ComputeDualGradientTest, CorrectOnTwoSidedConstraints) {
485 QuadraticProgram qp =
TestLp();
489 qp.constraint_lower_bounds[0] = 4;
490 qp.constraint_lower_bounds[1] = 5;
491 qp.constraint_upper_bounds[2] = -1;
492 ShardedQuadraticProgram sharded_qp(std::move(qp), 2,
495 VectorXd primal_solution(4), dual_solution(4);
496 primal_solution << 0.0, 0.0, 0.0, 3.0;
497 dual_solution << 0.0, 0.0, 0.0, -1.0;
499 const LagrangianPart dual_part =
501 sharded_qp.Qp().constraint_matrix * primal_solution);
505 EXPECT_THAT(dual_part.gradient,
506 ElementsAre(0.0, 5.0 - 0.0, -1.0 - 0.0, 1.0 + 3.0));
508 EXPECT_DOUBLE_EQ(dual_part.value, 1.0 * -1.0);
511 TEST(HasValidBoundsTest, SmallInvalidLp) {
516 EXPECT_FALSE(is_valid);
519 TEST(HasValidBoundsTest, SmallValidLp) {
524 EXPECT_TRUE(is_valid);
527 TEST(ComputePrimalGradientTest, CorrectForQp) {
531 VectorXd primal_solution(2), dual_solution(1);
532 primal_solution << 1.0, 2.0;
533 dual_solution << -2.0;
536 qp, primal_solution, qp.TransposedConstraintMatrix() * dual_solution);
541 EXPECT_THAT(primal_part.gradient,
542 ElementsAre(-1.0 + 2.0 + 4.0, -1.0 + 2.0 + 2.0));
544 EXPECT_DOUBLE_EQ(primal_part.value, 4.0 - 3.0 + 2.0 * 3.0);
547 TEST(ComputeDualGradientTest, CorrectForQp) {
551 VectorXd primal_solution(2), dual_solution(1);
552 primal_solution << 1.0, 2.0;
553 dual_solution << -2.0;
556 qp, dual_solution, qp.Qp().constraint_matrix * primal_solution);
561 EXPECT_THAT(dual_part.gradient, ElementsAre(1.0 - (1.0 + 2.0)));
563 EXPECT_DOUBLE_EQ(dual_part.value, -2.0);
566 TEST(EstimateSingularValuesTest, CorrectForTestLp) {
567 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
570 std::mt19937 random(1);
572 lp, std::nullopt, std::nullopt,
575 EXPECT_NEAR(result.singular_value, 4.76945, 0.01);
576 EXPECT_LT(result.num_iterations, 300);
579 TEST(EstimateSingularValuesTest, CorrectForTestLpWithActivePrimalSubspace) {
580 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
582 VectorXd primal_solution(4);
584 primal_solution << 0.0, -2.0, 0.0, 3.0;
587 std::mt19937 random(1);
589 lp, primal_solution, std::nullopt, 0.01,
591 EXPECT_NEAR(result.singular_value, 4.73818, 0.01);
592 EXPECT_LT(result.num_iterations, 300);
595 TEST(EstimateSingularValuesTest, CorrectForTestLpWithActiveDualSubspace) {
596 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
598 VectorXd dual_solution(4);
601 dual_solution << 1.0, 0.0, 1.0, 3.0;
604 std::mt19937 random(1);
606 lp, std::nullopt, dual_solution, 0.01,
608 EXPECT_NEAR(result.singular_value, 4.64203, 0.01);
609 EXPECT_LT(result.num_iterations, 300);
612 TEST(EstimateSingularValuesTest, CorrectForTestLpWithBothActiveSubspaces) {
613 ShardedQuadraticProgram lp(
TestLp(), 2, 2);
615 VectorXd primal_solution(4), dual_solution(4);
617 primal_solution << 0.0, -2.0, 0.0, 3.0;
620 dual_solution << 1.0, 0.0, 1.0, 3.0;
623 std::mt19937 random(1);
625 lp, primal_solution, dual_solution, 0.01,
627 EXPECT_NEAR(result.singular_value, 4.60829, 0.01);
628 EXPECT_LT(result.num_iterations, 300);
631 TEST(EstimateSingularValuesTest, CorrectForDiagonalLp) {
632 QuadraticProgram diagonal_lp =
TestLp();
633 std::vector<Eigen::Triplet<double, int64_t>> triplets = {
634 {0, 0, 2}, {1, 1, 1}, {2, 2, -3}, {3, 3, -1}};
635 diagonal_lp.constraint_matrix.setFromTriplets(triplets.begin(),
637 ShardedQuadraticProgram lp(diagonal_lp, 2, 2);
640 std::mt19937 random(1);
642 lp, std::nullopt, std::nullopt,
645 EXPECT_NEAR(result.singular_value, 3, 0.0001);
646 EXPECT_LT(result.num_iterations, 300);
649 TEST(ProjectToPrimalVariableBoundsTest,
TestLp) {
650 ShardedQuadraticProgram qp(
TestLp(), 2,
653 primal << -3, -3, 5, 5;
655 EXPECT_THAT(primal, ElementsAre(-3, -2, 5, 3.5));
658 TEST(ProjectToDualVariableBoundsTest,
TestLp) {
659 ShardedQuadraticProgram qp(
TestLp(), 2,
662 dual << 1, 1, -1, -1;
664 EXPECT_THAT(dual, ElementsAre(1, 0, 0, -1));
LagrangianPart ComputeDualGradient(const ShardedQuadraticProgram &sharded_qp, const VectorXd &dual_solution, const VectorXd &primal_product)
LagrangianPart ComputePrimalGradient(const ShardedQuadraticProgram &sharded_qp, const VectorXd &primal_solution, const VectorXd &dual_product)
void LInfRuizRescaling(const ShardedQuadraticProgram &sharded_qp, const int num_iterations, VectorXd &row_scaling_vec, VectorXd &col_scaling_vec)
SingularValueAndIterations EstimateMaximumSingularValueOfConstraintMatrix(const ShardedQuadraticProgram &sharded_qp, const std::optional< VectorXd > &primal_solution, const std::optional< VectorXd > &dual_solution, const double desired_relative_error, const double failure_probability, std::mt19937 &mt_generator)
VectorXd ScaledColLInfNorm(const Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > &matrix, const VectorXd &row_scaling_vec, const VectorXd &col_scaling_vec, const Sharder &sharder)
bool HasValidBounds(const QuadraticProgram &qp)
QuadraticProgram TinyLp()
void ProjectToDualVariableBounds(const ShardedQuadraticProgram &sharded_qp, VectorXd &dual)
QuadraticProgram LpWithoutConstraints()
QuadraticProgram SmallInvalidProblemLp()
void L2NormRescaling(const ShardedQuadraticProgram &sharded_qp, VectorXd &row_scaling_vec, VectorXd &col_scaling_vec)
ScalingVectors ApplyRescaling(const RescalingOptions &rescaling_options, ShardedQuadraticProgram &sharded_qp)
QuadraticProgramStats ComputeStats(const ShardedQuadraticProgram &qp, const double infinite_constraint_bound_threshold)
void ProjectToPrimalVariableBounds(const ShardedQuadraticProgram &sharded_qp, VectorXd &primal)
QuadraticProgram TestLp()
QuadraticProgram SmallPrimalInfeasibleLp()
QuadraticProgram TestDiagonalQp1()
TEST(LinearAssignmentTest, NullMatrix)