14#ifndef PDLP_TEST_UTIL_H_
15#define PDLP_TEST_UTIL_H_
24#include "Eigen/SparseCore"
25#include "absl/log/check.h"
26#include "absl/types/span.h"
27#include "gtest/gtest.h"
208 const Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& sparse_mat);
214MATCHER_P(TupleIsNear, tolerance,
"is near") {
215 return std::abs(std::get<0>(arg) - std::get<1>(arg)) <= tolerance;
218MATCHER(TupleFloatEq,
"is almost equal to") {
219 testing::Matcher<float> matcher = testing::FloatEq(std::get<1>(arg));
220 return matcher.Matches(std::get<0>(arg));
230Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic> EigenArray2DFromNestedSpans(
231 absl::Span<
const absl::Span<const T>> rows) {
232 Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic> result(0, rows.size());
234 result.resize(rows.size(), rows[0].size());
236 for (
int i = 0;
i < rows.size(); ++
i) {
237 CHECK_EQ(rows[0].
size(), rows[i].
size());
238 result.row(i) = Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>(
239 &rows[
i][0], rows[
i].size());
254template <
typename ContainerType>
255decltype(testing::Pointwise(internal::TupleIsNear(0.0), ContainerType()))
256FloatArrayNear(
const ContainerType& container,
double tolerance) {
257 return testing::Pointwise(internal::TupleIsNear(tolerance), container);
272template <
typename ContainerType>
273decltype(testing::Pointwise(internal::TupleFloatEq(), ContainerType()))
274FloatArrayEq(
const ContainerType& container) {
275 return testing::Pointwise(internal::TupleFloatEq(), container);
279template <
typename EigenType>
280Eigen::Array<
typename EigenType::Scalar, Eigen::Dynamic, Eigen::Dynamic,
282EvalAsColMajorEigenArray(
const EigenType&
input) {
287template <
typename Scalar>
288absl::Span<const Scalar> EigenArrayAsSpan(
289 const Eigen::Array<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>&
291 return absl::Span<const Scalar>(array.data(), array.size());
302MATCHER_P2(EigenArrayNear, expected_array, tolerance,
303 "array is near " + testing::PrintToString(expected_array) +
304 " within tolerance " + testing::PrintToString(tolerance)) {
305 if (arg.rows() != expected_array.rows() ||
306 arg.cols() != expected_array.cols()) {
307 *result_listener <<
"where shape (" << expected_array.rows() <<
", "
308 << expected_array.cols() <<
") doesn't match ("
309 << arg.rows() <<
", " << arg.cols() <<
")";
316 auto realized_expected_array = EvalAsColMajorEigenArray(expected_array);
317 auto realized_actual_array = EvalAsColMajorEigenArray(arg);
318 return ExplainMatchResult(
319 FloatArrayNear(EigenArrayAsSpan(realized_expected_array), tolerance),
320 EigenArrayAsSpan(realized_actual_array), result_listener);
331 "array is almost equal to " +
332 testing::PrintToString(expected_array)) {
333 if (arg.rows() != expected_array.rows() ||
334 arg.cols() != expected_array.cols()) {
335 *result_listener <<
"where shape (" << expected_array.rows() <<
", "
336 << expected_array.cols() <<
") doesn't match ("
337 << arg.rows() <<
", " << arg.cols() <<
")";
344 auto realized_expected_array = EvalAsColMajorEigenArray(expected_array);
345 auto realized_actual_array = EvalAsColMajorEigenArray(arg);
346 return ExplainMatchResult(
347 FloatArrayEq(EigenArrayAsSpan(realized_expected_array)),
348 EigenArrayAsSpan(realized_actual_array), result_listener);
361EigenArrayNearMatcherP2<Eigen::Array<T, Eigen::Dynamic, 1>,
double>
362EigenArrayNear(absl::Span<const T> data,
double tolerance) {
363 Eigen::Array<T, Eigen::Dynamic, 1> temp_array =
364 Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>(&data[0],
366 return EigenArrayNear(temp_array, tolerance);
370EigenArrayNearMatcherP2<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>,
double>
371EigenArrayNear(absl::Span<
const absl::Span<const T>> rows,
double tolerance) {
372 return EigenArrayNear(internal::EigenArray2DFromNestedSpans(rows), tolerance);
376EigenArrayEqMatcherP<Eigen::Array<T, Eigen::Dynamic, 1>> EigenArrayEq(
377 absl::Span<const T> data) {
378 Eigen::Array<T, Eigen::Dynamic, 1> temp_array =
379 Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>(&data[0],
381 return EigenArrayEq(temp_array);
385EigenArrayEqMatcherP<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>
386EigenArrayEq(absl::Span<
const absl::Span<const T>> rows) {
387 return EigenArrayEq(internal::EigenArray2DFromNestedSpans(rows));
395template <
typename Scalar,
int Rows,
int Cols,
int Options,
int MaxRows,
397void PrintTo(
const Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>& array,
399 IOFormat format(StreamPrecision, 0,
", ",
",\n",
"[",
"]",
"[",
"]");
400 *os <<
"\n" << array.format(format);
void PrintTo(const Array< Scalar, Rows, Cols, Options, MaxRows, MaxCols > &array, std::ostream *os)
MATCHER_P(FirstElementIs, first_element_matcher,(negation ? absl::StrCat("is empty or first element ", MatcherToString(first_element_matcher, true)) :absl::StrCat("has at least one element and first element ", MatcherToString(first_element_matcher, false))))
Validation utilities for solvers.proto.
QuadraticProgram SmallPrimalDualInfeasibleLp()
QuadraticProgram TestDiagonalQp1()
QuadraticProgram CorrelationClusteringStarLp()
QuadraticProgram SmallDualInfeasibleLp()
QuadraticProgram SmallInitializationLp()
QuadraticProgram TestDiagonalQp3()
QuadraticProgram TinyLp()
void VerifyTestLp(const QuadraticProgram &qp, bool maximize)
Verifies that the given QuadraticProgram equals TestLp().
::Eigen::ArrayXXd ToDense(const Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > &sparse_mat)
QuadraticProgram TestLp()
QuadraticProgram SmallInconsistentVariableBoundsLp()
QuadraticProgram LpWithoutConstraints()
QuadraticProgram TestDiagonalQp2()
QuadraticProgram SmallInvalidProblemLp()
void VerifyTestDiagonalQp1(const QuadraticProgram &qp, bool maximize)
QuadraticProgram CorrelationClusteringLp()
| /
QuadraticProgram SmallPrimalInfeasibleLp()
static int input(yyscan_t yyscanner)