Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SubspaceTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SubspaceTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
13 
14 #include <algorithm>
15 #include <array>
16 #include <cstddef>
17 #include <numeric>
18 #include <ostream>
19 #include <tuple>
20 #include <utility>
21 #include <vector>
22 
23 namespace {
24 
25 using namespace Acts;
26 
27 // meta-programming type list of scalar type + subspace type combinations
28 // clang-format off
29 using ScalarsAndFixedSizeSubspaces = std::tuple<
30  std::tuple<float, detail::FixedSizeSubspace<2u, 1u>>,
31  std::tuple<float, detail::FixedSizeSubspace<2u, 2u>>,
32  std::tuple<float, detail::FixedSizeSubspace<3u, 1u>>,
33  std::tuple<float, detail::FixedSizeSubspace<3u, 2u>>,
34  std::tuple<float, detail::FixedSizeSubspace<3u, 3u>>,
35  std::tuple<float, detail::FixedSizeSubspace<6u, 1u>>,
36  std::tuple<float, detail::FixedSizeSubspace<6u, 2u>>,
37  std::tuple<float, detail::FixedSizeSubspace<6u, 4u>>,
38  std::tuple<float, detail::FixedSizeSubspace<8u, 1u>>,
39  std::tuple<float, detail::FixedSizeSubspace<8u, 2u>>,
40  std::tuple<float, detail::FixedSizeSubspace<8u, 4u>>,
41  std::tuple<double, detail::FixedSizeSubspace<2u, 1u>>,
42  std::tuple<double, detail::FixedSizeSubspace<2u, 2u>>,
43  std::tuple<double, detail::FixedSizeSubspace<3u, 1u>>,
44  std::tuple<double, detail::FixedSizeSubspace<3u, 2u>>,
45  std::tuple<double, detail::FixedSizeSubspace<3u, 3u>>,
46  std::tuple<double, detail::FixedSizeSubspace<6u, 1u>>,
47  std::tuple<double, detail::FixedSizeSubspace<6u, 2u>>,
48  std::tuple<double, detail::FixedSizeSubspace<6u, 4u>>,
49  std::tuple<double, detail::FixedSizeSubspace<8u, 1u>>,
50  std::tuple<double, detail::FixedSizeSubspace<8u, 2u>>,
51  std::tuple<double, detail::FixedSizeSubspace<8u, 4u>>
52 >;
53 // clang-format on
54 
56 template <typename scalar_t, std::size_t kSize>
57 Eigen::Matrix<scalar_t, kSize, 1> makeRandomVector() {
58  Eigen::Matrix<scalar_t, kSize, 1> vec;
59  vec.setRandom();
60  return vec;
61 }
62 
64 std::vector<std::size_t> makeMonotonicIndices(std::size_t n) {
65  std::vector<std::size_t> indices(n);
66  std::iota(indices.begin(), indices.end(), 0u);
67  return indices;
68 }
69 
71 template <std::size_t kSize>
72 std::array<std::size_t, kSize> selectFixedIndices(
73  const std::vector<std::size_t>& fullIndices) {
74  std::array<std::size_t, kSize> indices{};
75  for (auto i = 0u; i < kSize; ++i) {
76  indices[i] = fullIndices[i];
77  }
78  std::sort(indices.begin(), indices.end());
79  return indices;
80 }
81 
82 } // namespace
83 
84 BOOST_AUTO_TEST_SUITE(UtilitiesSubspace)
85 
86 // all these cases should lead to compile-time errors
87 // BOOST_AUTO_TEST_CASE(ConstructFixedInvalid) {
88 // {
89 // using Subspace = detail::FixedSizeSubspace<6u, 7u>;
90 // Subspace subspace(0u, 1u, 2u, 3u, 4u, 5u, 6u);
91 // }
92 // {
93 // using Subspace = detail::FixedSizeSubspace<8u, 9u>;
94 // Subspace subspace(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u);
95 // }
96 // }
97 
98 BOOST_AUTO_TEST_CASE_TEMPLATE(FixedSizeSubspaceFloat, ScalarAndSubspace,
99  ScalarsAndFixedSizeSubspaces) {
100  // extract the test types
101  using Scalar = std::tuple_element_t<0, ScalarAndSubspace>;
102  using Subspace = std::tuple_element_t<1, ScalarAndSubspace>;
103 
104  auto x = makeRandomVector<Scalar, Subspace::fullSize()>();
105  auto fullIndices = makeMonotonicIndices(Subspace::fullSize());
106 
107  // in principle, we would like to iterate over all possible ordered subsets
108  // from the full space indices with a size identical to the subspace. since i
109  // do not know how to do that in a simple manner, we are iterating over all
110  // permutations of the full indices and pick the first n elements. this should
111  // give a reasonable set of different subspace configurations.
112  do {
113  auto indices = selectFixedIndices<Subspace::size()>(fullIndices);
114  Subspace subspace(indices);
115 
116  // verify projector/expander consistency
117  BOOST_CHECK_EQUAL(subspace.template projector<Scalar>().transpose(),
118  subspace.template expander<Scalar>());
119  BOOST_CHECK_EQUAL(subspace.template expander<Scalar>().transpose(),
120  subspace.template projector<Scalar>());
121  // project into the subspace
122  auto s0 = subspace.projectVector(x);
123  auto s1 = (subspace.template projector<Scalar>() * x).eval();
124  for (auto i = 0u; i < subspace.size(); ++i) {
125  BOOST_TEST_INFO("Checking projected subspace component " << i);
126  BOOST_CHECK_EQUAL(s0[i], x[indices[i]]);
127  BOOST_CHECK_EQUAL(s1[i], x[indices[i]]);
128  }
129  // expand from the subspace back into the full space
130  auto y0 = subspace.expandVector(s1);
131  auto y1 = (subspace.template expander<Scalar>() * s0).eval();
132  for (auto i = 0u; i < subspace.fullSize(); ++i) {
133  BOOST_TEST_INFO("Checking expanded fullspace component " << i);
134  BOOST_CHECK_EQUAL(y0[i], subspace.contains(i) ? x[i] : 0);
135  BOOST_CHECK_EQUAL(y1[i], subspace.contains(i) ? x[i] : 0);
136  }
137  } while (std::next_permutation(fullIndices.begin(), fullIndices.end()));
138 }
139 
140 BOOST_AUTO_TEST_SUITE_END()