1010
1111using namespace Grid ::Batch;
1212
13-
1413class BatchTest : public ::testing::Test
1514{
1615protected:
@@ -19,17 +18,28 @@ class BatchTest: public ::testing::Test
1918 std::vector<double > grid_;
2019 std::vector<int > idx_;
2120
21+ // parameters for cluster generation
2222 int n_each_ = 10 ;
23- double offset_ = 10.0 ;
2423 double width_ = 1.0 ;
24+
25+ // These offsets should be different from each other as maxmin might
26+ // fail for highly symmetric, well-separated clusters.
27+ // Consider the case where the 8 clusters as a whole have octahedral
28+ // symmetry. In this case, R*R^T must be proprotional to the identity,
29+ // and eigenvalues are three-fold degenerate, because xy, yz and zx
30+ // plane are equivalent in terms of the maxmin optimization problem.
31+ // This means eigenvectors are arbitrary in this case.
32+ double offset_x_ = 7.0 ;
33+ double offset_y_ = 8.0 ;
34+ double offset_z_ = 9.0 ;
2535};
2636
27- std::vector<double > gen_octant_cluster (int n_each, double offset , double width) {
37+ std::vector<double > gen_octant_cluster (int n_each, double offset_x, double offset_y, double offset_z , double width) {
2838
2939 // Generates a set of points consisting of 8 well-separated, equal-sized
3040 // clusters located in individual octants.
3141
32- std::vector<double > grid (n_each * 8 );
42+ std::vector<double > grid (n_each * 8 * 3 );
3343 int I = 0 ;
3444
3545 std::random_device rd;
@@ -40,15 +50,14 @@ std::vector<double> gen_octant_cluster(int n_each, double offset, double width)
4050 for (int sign_y : {-1 , 1 }) {
4151 for (int sign_z : {-1 , 1 }) {
4252 for (int i = 0 ; i < n_each; ++i) {
43- grid[3 *I ] = sign_x * offset + dis (gen);
44- grid[3 *I + 1 ] = sign_y * offset + dis (gen);
45- grid[3 *I + 2 ] = sign_z * offset + dis (gen);
53+ grid[3 *I ] = sign_x * offset_x + dis (gen);
54+ grid[3 *I + 1 ] = sign_y * offset_y + dis (gen);
55+ grid[3 *I + 2 ] = sign_z * offset_z + dis (gen);
4656 ++I;
4757 }
4858 }
4959 }
5060 }
51-
5261 return grid;
5362}
5463
@@ -73,9 +82,9 @@ bool is_same_octant(int ngrid, const double* grid) {
7382
7483void BatchTest::SetUp ()
7584{
76- grid_ = gen_octant_cluster (n_each_, offset_ , width_);
85+ grid_ = gen_octant_cluster (n_each_, offset_x_, offset_y_, offset_z_ , width_);
7786
78- idx_.resize (grid_.size ());
87+ idx_.resize (grid_.size () / 3 );
7988 std::iota (idx_.begin (), idx_.end (), 0 );
8089
8190 std::random_device rd;
@@ -91,21 +100,25 @@ TEST_F(BatchTest, MaxMinOctantCluster)
91100 // The resulting batches should be able to recover this structure.
92101
93102 std::vector<int > delim =
94- maxmin (n_each_, grid_.size (), grid_.data (), idx_.data ());
103+ maxmin (grid_.data (), idx_.data (), grid_.size () / 3 , n_each_);
104+
105+ EXPECT_EQ (delim.size (), 8 );
95106
96- EXPECT_EQ (delim.size (), 7 );
97- for (int i = 0 ; i < 7 ; ++i) {
98- // check number of points in each batch via index delimiters
99- EXPECT_EQ (delim[i], (i+1 ) * n_each_);
107+ std::vector<double > grid_batch (3 * n_each_);
108+ for (int i = 0 ; i < 8 ; ++i) {
100109
101- // verify that points in each batch is in the same octant
102- std::vector<double > batch (3 * n_each_);
110+ EXPECT_EQ (delim[i], i * n_each_);
111+
112+ // collect points within the present batch
103113 for (int j = 0 ; j < n_each_; ++j) {
104- for (int k = 0 ; k < 3 ; ++k) {
105- batch[3 *j + k] = grid_[3 *(i*n_each_ + j) + k];
106- }
114+ int ig = idx_[delim[i] + j];
115+ grid_batch[3 *j ] = grid_[3 *ig ];
116+ grid_batch[3 *j + 1 ] = grid_[3 *ig + 1 ];
117+ grid_batch[3 *j + 2 ] = grid_[3 *ig + 2 ];
107118 }
108- EXPECT_TRUE (is_same_octant (n_each_, batch.data ()));
119+
120+ // verify that points in a batch reside in the same octant
121+ EXPECT_TRUE (is_same_octant (n_each_, grid_batch.data ()));
109122 }
110123}
111124
0 commit comments