OR-Tools  9.6
test_util.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "ortools/pdlp/test_util.h"
15 
16 #include <cstdint>
17 #include <limits>
18 #include <string>
19 #include <vector>
20 
21 #include "Eigen/Core"
22 #include "Eigen/SparseCore"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
26 
27 namespace operations_research::pdlp {
28 
29 using ::testing::ElementsAre;
30 
31 constexpr double kInfinity = std::numeric_limits<double>::infinity();
32 
34  QuadraticProgram lp(4, 4);
35  lp.constraint_lower_bounds << 12, -kInfinity, -4, -1;
36  lp.constraint_upper_bounds << 12, 7, kInfinity, 1;
37  lp.variable_lower_bounds << -kInfinity, -2, -kInfinity, 2.5;
39  std::vector<Eigen::Triplet<double, int64_t>> triplets = {
40  {0, 0, 2}, {0, 1, 1}, {0, 2, 1}, {0, 3, 2}, {1, 0, 1},
41  {1, 2, 1}, {2, 0, 4}, {3, 2, 1.5}, {3, 3, -1}};
42  lp.constraint_matrix.setFromTriplets(triplets.begin(), triplets.end());
43 
44  lp.objective_vector << 5.5, -2, -1, 1;
45  lp.objective_offset = -14;
46  return lp;
47 }
48 
49 void VerifyTestLp(const QuadraticProgram& qp, bool maximize) {
50  const double objective_sign = maximize ? -1 : 1;
51  EXPECT_THAT(objective_sign * qp.objective_offset, testing::DoubleEq(-14));
52  EXPECT_THAT(objective_sign * qp.objective_vector,
53  ElementsAre(5.5, -2, -1, 1));
54  EXPECT_EQ(qp.objective_scaling_factor, objective_sign);
55  EXPECT_FALSE(qp.objective_matrix.has_value());
56  EXPECT_THAT(qp.variable_lower_bounds,
57  ElementsAre(-kInfinity, -2, -kInfinity, 2.5));
58  EXPECT_THAT(qp.variable_upper_bounds,
59  ElementsAre(kInfinity, kInfinity, 6, 3.5));
60  EXPECT_THAT(qp.constraint_lower_bounds, ElementsAre(12, -kInfinity, -4, -1));
61  EXPECT_THAT(qp.constraint_upper_bounds, ElementsAre(12, 7, kInfinity, 1));
62  EXPECT_THAT(ToDense(qp.constraint_matrix),
63  EigenArrayEq<double>(
64  {{2, 1, 1, 2}, {1, 0, 1, 0}, {4, 0, 0, 0}, {0, 0, 1.5, -1}}));
65 }
66 
68  QuadraticProgram lp(4, 3);
69  lp.objective_offset = -14;
70  lp.objective_vector << 5, 2, 1, 1;
71  lp.constraint_lower_bounds << 12, 7, 1;
73  lp.variable_lower_bounds << 0, 0, 0, 0;
74  lp.variable_upper_bounds << 2, 4, 6, 3;
75  lp.constraint_matrix.coeffRef(0, 0) = 2.0;
76  lp.constraint_matrix.coeffRef(0, 1) = 1.0;
77  lp.constraint_matrix.coeffRef(0, 2) = 1.0;
78  lp.constraint_matrix.coeffRef(0, 3) = 2.0;
79  lp.constraint_matrix.coeffRef(1, 0) = 1.0;
80  lp.constraint_matrix.coeffRef(1, 2) = 1.0;
81  lp.constraint_matrix.coeffRef(2, 2) = 1.0;
82  lp.constraint_matrix.coeffRef(2, 3) = -1.0;
83  lp.constraint_matrix.makeCompressed();
84  return lp;
85 }
86 
88  QuadraticProgram lp(6, 3);
89  lp.objective_offset = 4;
90  lp.objective_vector << -1.0, -1.0, 1.0, -1.0, 1.0, -1.0;
91  lp.constraint_lower_bounds << -1.0, -1.0, -1.0;
93  lp.variable_lower_bounds << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
94  lp.variable_upper_bounds << 1.0, 1.0, 1.0, 1.0, 1.0, 1.0;
95  lp.constraint_matrix.coeffRef(0, 1) = -1.0;
96  lp.constraint_matrix.coeffRef(0, 2) = 1.0;
97  lp.constraint_matrix.coeffRef(0, 5) = -1.0;
98  lp.constraint_matrix.coeffRef(1, 3) = -1.0;
99  lp.constraint_matrix.coeffRef(1, 4) = 1.0;
100  lp.constraint_matrix.coeffRef(1, 5) = -1.0;
101  lp.constraint_matrix.coeffRef(2, 0) = -1.0;
102  lp.constraint_matrix.coeffRef(2, 1) = -1.0;
103  lp.constraint_matrix.coeffRef(2, 3) = 1.0;
104  lp.constraint_matrix.makeCompressed();
105  return lp;
106 }
107 
109  QuadraticProgram lp(6, 3);
110  lp.objective_offset = 3;
111  lp.objective_vector << -1.0, -1.0, -1.0, 1.0, 1.0, 1.0;
112  lp.constraint_lower_bounds << -1.0, -1.0, -1.0;
114  lp.variable_lower_bounds << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
115  lp.variable_upper_bounds << 1.0, 1.0, 1.0, 1.0, 1.0, 1.0;
116  lp.constraint_matrix.coeffRef(0, 0) = -1.0;
117  lp.constraint_matrix.coeffRef(0, 1) = -1.0;
118  lp.constraint_matrix.coeffRef(0, 3) = 1.0;
119  lp.constraint_matrix.coeffRef(1, 0) = -1.0;
120  lp.constraint_matrix.coeffRef(1, 2) = -1.0;
121  lp.constraint_matrix.coeffRef(1, 4) = 1.0;
122  lp.constraint_matrix.coeffRef(2, 1) = -1.0;
123  lp.constraint_matrix.coeffRef(2, 2) = -1.0;
124  lp.constraint_matrix.coeffRef(2, 5) = 1.0;
125  lp.constraint_matrix.makeCompressed();
126  return lp;
127 }
128 
129 namespace {
130 
131 Eigen::DiagonalMatrix<double, Eigen::Dynamic> ConstructDiagonal(
132  const std::vector<double>& vec) {
133  Eigen::DiagonalMatrix<double, Eigen::Dynamic> diag;
134  diag.resize(vec.size());
135  for (int i = 0; i < vec.size(); ++i) {
136  diag.diagonal()[i] = vec[i];
137  }
138  return diag;
139 }
140 
141 } // namespace
142 
144  QuadraticProgram qp(2, 1);
146  qp.constraint_upper_bounds << 1;
147  qp.variable_lower_bounds << 1, -2;
148  qp.variable_upper_bounds << 2, 4;
149  qp.objective_vector << -1, -1;
150  qp.objective_offset = 5;
151  std::vector<Eigen::Triplet<double, int64_t>> constraint_triplets = {
152  {0, 0, 1}, {0, 1, 1}};
153  qp.constraint_matrix.setFromTriplets(constraint_triplets.begin(),
154  constraint_triplets.end());
155  qp.objective_matrix = ConstructDiagonal({4.0, 1.0});
156  return qp;
157 }
158 
160  QuadraticProgram qp(2, 1);
161  qp.constraint_lower_bounds << 2;
162  qp.constraint_upper_bounds << 2;
163  qp.variable_lower_bounds << 0, 0;
165  qp.objective_vector << -3, -1;
166  qp.objective_offset = 0;
167  std::vector<Eigen::Triplet<double, int64_t>> constraint_triplets = {
168  {0, 0, 1}, {0, 1, -1}};
169  qp.constraint_matrix.setFromTriplets(constraint_triplets.begin(),
170  constraint_triplets.end());
171  qp.objective_matrix = ConstructDiagonal({1.0, 1.0});
172  return qp;
173 }
174 
176  QuadraticProgram qp(3, 2);
177  qp.constraint_lower_bounds << 1, 4;
178  qp.constraint_upper_bounds << 1, 4;
179  qp.variable_lower_bounds << 0, 0, 0;
181  qp.objective_vector << 1, 0, -1;
182  qp.objective_offset = 0;
183  std::vector<Eigen::Triplet<double, int64_t>> constraint_triplets = {
184  {0, 0, 1}, {0, 2, -1}, {1, 0, 2}};
185  qp.constraint_matrix.setFromTriplets(constraint_triplets.begin(),
186  constraint_triplets.end());
187  qp.objective_matrix = ConstructDiagonal({0.0, 1.0, 2.0});
188  return qp;
189 }
190 
192  QuadraticProgram lp(2, 1);
193  lp.constraint_matrix.coeffRef(0, 0) = 1.0;
194  lp.constraint_matrix.coeffRef(0, 1) = -1.0;
195  lp.constraint_lower_bounds << 2.0;
196  lp.constraint_upper_bounds << 1.0;
197  lp.variable_lower_bounds << 0.0, 0.0;
199  lp.constraint_matrix.makeCompressed();
200  lp.objective_vector << 1.0, 1.0;
201  return lp;
202 }
203 
205  QuadraticProgram lp(2, 1);
206  lp.constraint_matrix.coeffRef(0, 0) = 1.0;
207  lp.constraint_matrix.coeffRef(0, 1) = -1.0;
208  lp.constraint_matrix.makeCompressed();
210  lp.constraint_upper_bounds << 1.0;
211  lp.variable_lower_bounds << 2.0, 0.0;
212  lp.variable_upper_bounds << 1.0, kInfinity;
213  lp.objective_vector << 1.0, 1.0;
214  return lp;
215 }
216 
218  QuadraticProgram lp(2, 2);
219  lp.constraint_matrix.coeffRef(0, 0) = 1.0;
220  lp.constraint_matrix.coeffRef(0, 1) = -1.0;
221  lp.constraint_matrix.coeffRef(1, 0) = -1.0;
222  lp.constraint_matrix.coeffRef(1, 1) = 1.0;
224  lp.variable_lower_bounds << 0.0, 0.0;
226  lp.constraint_matrix.makeCompressed();
227 
228  lp.constraint_upper_bounds << 1.0, -2.0;
229  lp.objective_vector << 1.0, 1.0;
230  return lp;
231 }
232 
235  lp.constraint_upper_bounds(1) = 2.0;
236  lp.objective_vector *= -1.0;
237  return lp;
238 }
239 
242  lp.objective_vector *= -1.0;
243  return lp;
244 }
245 
247  QuadraticProgram lp(2, 2);
248  lp.constraint_matrix.coeffRef(0, 0) = 1.0;
249  lp.constraint_matrix.coeffRef(0, 1) = 1.0;
250  lp.constraint_matrix.coeffRef(1, 0) = 1.0;
251  lp.constraint_matrix.coeffRef(1, 1) = 2.0;
253  lp.constraint_upper_bounds << 2.0, 2.0;
254  lp.variable_lower_bounds << 0.5, 0.5;
255  lp.variable_upper_bounds << 2.0, 2.0;
256  lp.constraint_matrix.makeCompressed();
257 
258  lp.objective_vector << -4.0, 0.0;
259  return lp;
260 }
261 
263  QuadraticProgram lp(2, 0);
264  lp.variable_lower_bounds << 0.0, -kInfinity;
265  lp.variable_upper_bounds << kInfinity, 0.0;
266  lp.objective_vector << 4.0, 0.0;
267  return lp;
268 }
269 
270 void VerifyTestDiagonalQp1(const QuadraticProgram& qp, bool maximize) {
271  const double objective_sign = maximize ? -1 : 1;
272  EXPECT_EQ(qp.objective_scaling_factor, objective_sign);
273  EXPECT_THAT(objective_sign * qp.objective_offset, testing::DoubleEq(5));
274  EXPECT_THAT(objective_sign * qp.objective_vector, ElementsAre(-1, -1));
275  ASSERT_TRUE(qp.objective_matrix.has_value());
276  EXPECT_THAT(objective_sign * qp.objective_matrix->diagonal(),
277  EigenArrayEq<double>({4, 1}));
278  EXPECT_THAT(qp.variable_lower_bounds, ElementsAre(1, -2));
279  EXPECT_THAT(qp.variable_upper_bounds, ElementsAre(2, 4));
280  EXPECT_THAT(qp.constraint_lower_bounds, ElementsAre(-kInfinity));
281  EXPECT_THAT(qp.constraint_upper_bounds, ElementsAre(1));
282  EXPECT_THAT(ToDense(qp.constraint_matrix), EigenArrayEq<double>({{1, 1}}));
283 }
284 
285 ::Eigen::ArrayXXd ToDense(
286  const Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& sparse_mat) {
287  return ::Eigen::ArrayXXd(::Eigen::MatrixXd(sparse_mat));
288 }
289 
290 } // namespace operations_research::pdlp
QuadraticProgram SmallDualInfeasibleLp()
Definition: test_util.cc:233
QuadraticProgram TestDiagonalQp2()
Definition: test_util.cc:159
::Eigen::ArrayXXd ToDense(const Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > &sparse_mat)
Definition: test_util.cc:285
QuadraticProgram CorrelationClusteringStarLp()
Definition: test_util.cc:108
QuadraticProgram TestDiagonalQp3()
Definition: test_util.cc:175
QuadraticProgram TinyLp()
Definition: test_util.cc:67
void VerifyTestLp(const QuadraticProgram &qp, bool maximize)
Definition: test_util.cc:49
QuadraticProgram LpWithoutConstraints()
Definition: test_util.cc:262
QuadraticProgram SmallInvalidProblemLp()
Definition: test_util.cc:191
void VerifyTestDiagonalQp1(const QuadraticProgram &qp, bool maximize)
Definition: test_util.cc:270
QuadraticProgram SmallPrimalDualInfeasibleLp()
Definition: test_util.cc:240
QuadraticProgram TestLp()
Definition: test_util.cc:33
QuadraticProgram SmallInitializationLp()
Definition: test_util.cc:246
QuadraticProgram SmallPrimalInfeasibleLp()
Definition: test_util.cc:217
QuadraticProgram SmallInconsistentVariableBoundsLp()
Definition: test_util.cc:204
QuadraticProgram TestDiagonalQp1()
Definition: test_util.cc:143
QuadraticProgram CorrelationClusteringLp()
Definition: test_util.cc:87
constexpr double kInfinity
Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > constraint_matrix
std::optional< Eigen::DiagonalMatrix< double, Eigen::Dynamic > > objective_matrix