OR-Tools  9.6
test_util_test.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 <cmath>
17 #include <deque>
18 #include <limits>
19 #include <list>
20 #include <vector>
21 
22 #include "Eigen/Core"
23 #include "absl/log/check.h"
24 #include "absl/types/span.h"
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 
28 namespace operations_research::pdlp {
29 namespace {
30 
31 using ::absl::Span;
32 using ::Eigen::ColMajor;
33 using ::Eigen::Dynamic;
34 using ::Eigen::RowMajor;
35 using ::testing::Matcher;
37 
38 TEST(FloatArrayNearTest, TypicalUse) {
39  std::vector<double> test_vector({0.998, -1.414, 3.142});
40  std::vector<double> reference_vector({1.0, -M_SQRT2, M_PI});
41  EXPECT_THAT(test_vector, FloatArrayNear(reference_vector, 1.0e-2));
42  EXPECT_THAT(test_vector, Not(FloatArrayNear(reference_vector, 1.0e-4)));
43 }
44 
45 template <typename ContainerType>
46 class FloatArrayNearContainerTypeTest : public testing::Test {};
47 
48 using TestContainerTypes = testing::Types<std::vector<float>, std::deque<float>,
49  std::list<float>, Span<const float>>;
50 TYPED_TEST_SUITE(FloatArrayNearContainerTypeTest, TestContainerTypes);
51 
52 TYPED_TEST(FloatArrayNearContainerTypeTest, MatchesApproximately) {
53  using ContainerType = TypeParam;
54  auto test_values = {0.505f, 1.0f, -0.992f, 1.995f};
55  ContainerType test_container(test_values);
56  auto reference_values = {0.5f, 1.0f, -1.0f, 2.0f};
57  ContainerType reference_container(reference_values);
58 
59  const Matcher<ContainerType> m1 = FloatArrayNear(reference_container, 1.0e-2);
60  EXPECT_TRUE(m1.Matches(test_container));
61  const Matcher<ContainerType> m2 = FloatArrayNear(reference_container, 1.0e-3);
62  EXPECT_FALSE(m2.Matches(test_container));
63 }
64 
65 TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchWrongSize) {
66  using ContainerType = TypeParam;
67  EXPECT_THAT(ContainerType({1.0f, 2.0f}),
68  Not(FloatArrayNear(ContainerType({1.0f, 2.0f, 3.0f}), 1.0e-2)));
69 }
70 
71 TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchWrongOrder) {
72  using ContainerType = TypeParam;
73  EXPECT_THAT(ContainerType({1.0f, 3.0f, 2.0f}),
74  Not(FloatArrayNear(ContainerType({1.0f, 2.0f, 3.0f}), 1.0e-2)));
75 }
76 
77 TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchNaNs) {
78  using ContainerType = TypeParam;
79  auto test_values = {1.0f, std::numeric_limits<float>::quiet_NaN()};
80  ContainerType test_container(test_values);
81 
82  EXPECT_THAT(test_container,
83  Not(FloatArrayNear(ContainerType({1.0f, 2.0f}), 1.0e0)));
84  EXPECT_THAT(test_container, Not(FloatArrayNear(test_container, 1.0e0)));
85 }
86 
87 TEST(FloatArrayNearTest, WithIntegerElements) {
88  std::vector<int> test_vector({505, 1000, -992, 1990});
89  std::vector<int> reference_vector({500, 1000, -1000, 2000});
90 
91  const Matcher<std::vector<int>> m1 = FloatArrayNear(reference_vector, 10);
92  EXPECT_TRUE(m1.Matches(test_vector));
93  const Matcher<std::vector<int>> m2 = FloatArrayNear(reference_vector, 1);
94  EXPECT_FALSE(m2.Matches(test_vector));
95 }
96 
97 TEST(FloatArrayEqTest, TypicalUse) {
98  std::vector<float> reference_vector({1.0e6, -M_SQRT2, M_PI});
99  // Values are within 4 ULPs.
100  std::vector<float> test_vector({1.0e6 + 0.25, -1.41421323, 3.14159262});
101  EXPECT_THAT(test_vector, FloatArrayEq(reference_vector));
102  // Create a difference of 5 ULPs in the first element.
103  test_vector[0] = 1.0e6 + 0.3125;
104  EXPECT_THAT(test_vector, Not(FloatArrayEq(reference_vector)));
105 }
106 
107 template <typename ContainerType>
108 class FloatArrayEqContainerTypeTest : public testing::Test {};
109 
110 TYPED_TEST_SUITE(FloatArrayEqContainerTypeTest, TestContainerTypes);
111 
112 TYPED_TEST(FloatArrayEqContainerTypeTest, MatchesApproximately) {
113  using ContainerType = TypeParam;
114  auto reference_values = {-1.0e6f, 0.0f, 1.0f};
115  ContainerType reference_container(reference_values);
116  const Matcher<ContainerType> m = FloatArrayEq(reference_container);
117  EXPECT_TRUE(m.Matches(reference_container));
118  EXPECT_TRUE(m.Matches(ContainerType({-1.0e6 + 0.25, 5.0e-45, 1.0000002})));
119  EXPECT_TRUE(m.Matches(ContainerType({-1.0e6 - 0.25, -5.0e-45, 0.9999998})));
120  EXPECT_FALSE(m.Matches(ContainerType({-1.0e6 + 0.3125, 0.0, 1.0})));
121  EXPECT_FALSE(m.Matches(ContainerType({-1.0e6, 1.0e-44, 1.0})));
122  EXPECT_FALSE(m.Matches(ContainerType({-1.0e6, 0.0, 1.0000006})));
123 }
124 
125 TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchWrongSize) {
126  using ContainerType = TypeParam;
127  EXPECT_THAT(ContainerType({1.0f, 2.0f}),
128  Not(FloatArrayEq(ContainerType({1.0f, 2.0f, 3.0f}))));
129 }
130 
131 TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchWrongOrder) {
132  using ContainerType = TypeParam;
133  EXPECT_THAT(ContainerType({1.0f, 3.0f, 2.0f}),
134  Not(FloatArrayEq(ContainerType({1.0f, 2.0f, 3.0f}))));
135 }
136 
137 TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchNaNs) {
138  using ContainerType = TypeParam;
139  auto reference_values = {1.0f, std::numeric_limits<float>::quiet_NaN()};
140  ContainerType reference_container(reference_values);
141  const Matcher<ContainerType> m = FloatArrayEq(reference_container);
142  EXPECT_FALSE(m.Matches(reference_container));
143  EXPECT_FALSE(m.Matches(ContainerType({1.0f, 2.0f})));
144 }
145 
146 TYPED_TEST(FloatArrayEqContainerTypeTest, HandlesInfinities) {
147  using ContainerType = TypeParam;
148  auto reference_values = {1.0f, std::numeric_limits<float>::infinity(),
149  -std::numeric_limits<float>::infinity()};
150  ContainerType reference_container(reference_values);
151  const Matcher<ContainerType> m = FloatArrayEq(reference_container);
152  EXPECT_TRUE(m.Matches(reference_container));
153  EXPECT_FALSE(m.Matches(ContainerType({1.0f, 2.0f, 3.0f})));
154 }
155 
156 static const double kEps = 1.0e-6;
157 
158 TEST(EigenArrayNearTest, ArrayXd) {
159  const Eigen::ArrayXd expected = Eigen::ArrayXd::Random(4);
160  Eigen::ArrayXd actual = expected;
161  EXPECT_THAT(actual, EigenArrayNear(expected, kEps));
162  EXPECT_THAT(actual, EigenArrayNear(expected, 1.0e-100));
163 
164  actual += 100;
165  EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
166  // Wrong shape.
167  actual.resize(2);
168  EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
169 }
170 
171 TEST(EigenArrayNearTest, ArrayXdInlinedValues) {
172  Eigen::ArrayXd actual(3);
173  actual << 1.0, 2.0, 3.0;
174  EXPECT_THAT(actual, EigenArrayNear<double>({1.0, 2.0, 3.0}, kEps));
175  EXPECT_THAT(actual,
176  EigenArrayNear<double>({1.0, 2.0 + 0.5 * kEps, 3.0}, kEps));
177 
178  EXPECT_THAT(actual, Not(EigenArrayNear<double>({1.0, 2.0, 5.0}, kEps)));
179  // Wrong shape.
180  EXPECT_THAT(actual, Not(EigenArrayNear<double>({1.0, 2.0}, kEps)));
181 }
182 
183 TEST(EigenArrayNearTest, EmptyArrayX) {
184  const Eigen::ArrayXi empty;
185  EXPECT_THAT(empty, EigenArrayNear(empty, kEps));
186  // Can pass in an Eigen expression type.
187  EXPECT_THAT(empty, EigenArrayNear(Eigen::ArrayXi(), kEps));
188 
189  EXPECT_THAT(empty, Not(EigenArrayNear<int>({1, 2}, kEps)));
190  EXPECT_THAT(empty, Not(EigenArrayNear(Eigen::ArrayXi::Zero(3), kEps)));
191 }
192 
193 TEST(EigenArrayNearTest, ArrayXXf) {
194  const Eigen::ArrayXXf expected = Eigen::ArrayXXf::Random(4, 5);
195  Eigen::ArrayXXf actual = expected;
196  EXPECT_THAT(actual, EigenArrayNear(expected, kEps));
197  EXPECT_THAT(actual, EigenArrayNear(expected, 1.0e-100));
198 
199  actual.row(2) += 100;
200  EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
201  // Wrong shape.
202  EXPECT_THAT(expected, Not(EigenArrayNear(expected.transpose(), kEps)));
203  actual.resize(4, 3);
204  EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
205 
206  // Expression type.
207  actual.resize(3, 2);
208  actual.col(0) << 1.0, 2.0, 3.0;
209  actual.col(1) << 4.0, 5.0, 6.0;
210  std::vector<float> expected_vector({1.0, 2.0, 3.0, 4.0, 5.0, 6.0});
211  EXPECT_THAT(actual, EigenArrayNear(Eigen::Map<Eigen::ArrayXXf>(
212  &expected_vector[0], /*rows=*/3,
213  /*cols=*/2),
214  kEps));
215  // Wrong shape.
216  EXPECT_THAT(actual, Not(EigenArrayNear(Eigen::Map<Eigen::ArrayXXf>(
217  &expected_vector[0], /*rows=*/3,
218  /*cols=*/1),
219  kEps)));
220 }
221 
222 TEST(EigenArrayNearTest, DifferentMajor) {
223  Eigen::Array<float, Dynamic, Dynamic, ColMajor> col_major(2, 3);
224  col_major << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
225  Eigen::Array<float, Dynamic, Dynamic, RowMajor> row_major(2, 3);
226  row_major << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
227  CHECK_EQ(col_major(1, 0), row_major(1, 0));
228 
229  EXPECT_THAT(row_major, EigenArrayNear(col_major, 0.0));
230  EXPECT_THAT(row_major, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
231  {4.0, 5.0, 6.0}},
232  0.0));
233  EXPECT_THAT(col_major, EigenArrayNear(row_major, 0.0));
234  EXPECT_THAT(col_major, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
235  {4.0, 5.0, 6.0}},
236  0.0));
237 }
238 
239 TEST(EigenArrayNearTest, ArrayXXfInlinedValues) {
240  Eigen::ArrayXXf actual(2, 3);
241  actual.row(0) << 1.0, 2.0, 3.0;
242  actual.row(1) << 4.0, -5.0, -6.0;
243 
244  EXPECT_THAT(actual, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
245  {4.0, -5.0, -6.0}},
246  kEps));
247  EXPECT_THAT(actual, EigenArrayNear<float>(
248  {{1.0, 2.0, 3.0},
249  {4.0, -5.0, static_cast<float>(-6.0 - 0.9 * kEps)}},
250  kEps));
251  EXPECT_THAT(actual, Not(EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
252  {4.0, -5.0, -8.0}},
253  kEps)));
254  // Wrong shape.
255  EXPECT_THAT(actual, Not(EigenArrayNear<float>({{1.0, 2.0, 3.0}}, kEps)));
256 }
257 
258 TEST(EigenArrayEqTest, ArrayXd) {
259  const Eigen::ArrayXd expected = Eigen::ArrayXd::Random(4);
260  Eigen::ArrayXd actual = expected;
261  EXPECT_THAT(actual, EigenArrayEq(expected));
262 
263  actual += 100;
264  EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
265  // Wrong shape.
266  actual.resize(2);
267  EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
268 }
269 
270 TEST(EigenArrayEqTest, ArrayXdInlinedValues) {
271  Eigen::ArrayXd actual(3);
272  actual << 1.0, 2.0, 3.0;
273  EXPECT_THAT(actual, EigenArrayEq<double>({1.0, 2.0, 3.0}));
274  EXPECT_THAT(actual, EigenArrayEq<double>({1.0, 2.0 + 5.0e-7, 3.0}));
275 
276  EXPECT_THAT(actual, Not(EigenArrayEq<double>({1.0, 2.0, 5.0})));
277  // Wrong shape.
278  EXPECT_THAT(actual, Not(EigenArrayEq<double>({1.0, 2.0})));
279 }
280 
281 TEST(EigenArrayEqTest, EmptyArrayX) {
282  const Eigen::ArrayXi empty;
283  EXPECT_THAT(empty, EigenArrayEq(empty));
284  // Can pass in an Eigen expression type.
285  EXPECT_THAT(empty, EigenArrayEq(Eigen::ArrayXi()));
286 
287  EXPECT_THAT(empty, Not(EigenArrayEq<int>({1, 2})));
288  EXPECT_THAT(empty, Not(EigenArrayEq(Eigen::ArrayXi::Zero(3))));
289 }
290 
291 TEST(EigenArrayEqTest, ArrayXXf) {
292  const Eigen::ArrayXXf expected = Eigen::ArrayXXf::Random(4, 5);
293  Eigen::ArrayXXf actual = expected;
294  EXPECT_THAT(actual, EigenArrayEq(expected));
295 
296  actual.row(2) += 100;
297  EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
298  // Wrong shape.
299  EXPECT_THAT(expected, Not(EigenArrayEq(expected.transpose())));
300  actual.resize(4, 3);
301  EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
302 
303  // Expression type.
304  actual.resize(3, 2);
305  actual.col(0) << 1.0, 2.0, 3.0;
306  actual.col(1) << 4.0, 5.0, 6.0;
307  std::vector<float> expected_vector({1.0, 2.0, 3.0, 4.0, 5.0, 6.0});
308  EXPECT_THAT(actual, EigenArrayEq(Eigen::Map<Eigen::ArrayXXf>(
309  &expected_vector[0], /*rows=*/3, /*cols=*/2)));
310  // Wrong shape.
311  EXPECT_THAT(actual, Not(EigenArrayEq(Eigen::Map<Eigen::ArrayXXf>(
312  &expected_vector[0], /*rows=*/3, /*cols=*/1))));
313 }
314 
315 TEST(EigenArrayEqTest, ArrayXXfInlinedValues) {
316  Eigen::ArrayXXf actual(2, 3);
317  actual.row(0) << 1.0, 2.0, 3.0;
318  actual.row(1) << 4.0, -5.0, -6.0;
319 
320  EXPECT_THAT(actual, EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
321  {4.0, -5.0, -6.0}}));
322  EXPECT_THAT(actual, EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
323  {4.0, -5.0, -6.0 - 1.0e-6}}));
324  EXPECT_THAT(actual, Not(EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
325  {4.0, -5.0, -8.0}})));
326  // Wrong shape.
327  EXPECT_THAT(actual, Not(EigenArrayEq<float>({{1.0, 2.0, 3.0}})));
328 }
329 
330 } // namespace
331 } // namespace operations_research::pdlp
decltype(testing::Pointwise(internal::TupleFloatEq(), ContainerType())) FloatArrayEq(const ContainerType &container)
Definition: test_util.h:273
EigenArrayNearMatcherP2< Eigen::Array< T, Eigen::Dynamic, 1 >, double > EigenArrayNear(absl::Span< const T > data, double tolerance)
Definition: test_util.h:361
EigenArrayEqMatcherP< Eigen::Array< T, Eigen::Dynamic, 1 > > EigenArrayEq(absl::Span< const T > data)
Definition: test_util.h:375
decltype(testing::Pointwise(internal::TupleIsNear(0.0), ContainerType())) FloatArrayNear(const ContainerType &container, double tolerance)
Definition: test_util.h:255
BoolVar Not(BoolVar x)
A convenient wrapper so we can write Not(x) instead of x.Not() which is sometimes clearer.
Definition: cp_model.cc:86
int64_t Zero()
NOLINT.
TEST(LinearAssignmentTest, NullMatrix)