Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#ifndef SOBOLSEQUENCETEST_H_
#define SOBOLSEQUENCETEST_H_
#include "MantidKernel/SobolSequence.h"
#include <boost/algorithm/string/predicate.hpp>
using Mantid::Kernel::SobolSequence;
class SobolSequenceTest : public CxxTest::TestSuite {
public:
void test_That_Object_Construction_Does_Not_Throw() {
TS_ASSERT_THROWS_NOTHING(SobolSequence(1));
}
void test_That_Next_For_Two_Generators_Returns_Same_Value() {
SobolSequence gen_1(3), gen_2(3);
const std::vector<double> seq1 = gen_1.nextPoint();
const std::vector<double> seq2 = gen_2.nextPoint();
TS_ASSERT(boost::algorithm::equals(seq1, seq2));
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void test_That_A_Given_Number_Of_Dimensions_Produces_Expected_Sequence() {
SobolSequence randGen(5);
assert_Sequence_Is_As_Expected_For_Five_Dimensions(randGen);
}
void test_That_Restart_Produces_The_Sequence_From_The_Beginning() {
SobolSequence randGen(5);
doNextValueCalls(20, randGen);
randGen.restart();
assert_Sequence_Is_As_Expected_For_Five_Dimensions(randGen);
}
void test_Save_Call_Restore_Gives_Sequence_From_Saved_Point() {
SobolSequence randGen(5);
doNextValueCalls(25, randGen); // Move from start to test it doesn't just go
// back to beginning
randGen.save();
const size_t ncheck(20);
auto firstValues = doNextValueCalls(ncheck, randGen);
randGen.restore();
auto secondValues = doNextValueCalls(ncheck, randGen);
for (size_t i = 0; i < ncheck; ++i) {
TS_ASSERT(boost::algorithm::equals(firstValues[i], secondValues[i]));
}
}
void
test_Save_Call_Restore_Call_Then_Restore_Gives_Sequence_From_Saved_Point() {
SobolSequence randGen(5);
doNextValueCalls(25, randGen); // Move from start to test it doesn't just go
// back to beginning
randGen.save();
const size_t ncheck(20);
auto firstValues = doNextValueCalls(ncheck, randGen);
randGen.restore();
doNextValueCalls(ncheck, randGen);
randGen.restore();
auto thirdValues = doNextValueCalls(ncheck, randGen);
for (size_t i = 0; i < ncheck; ++i) {
TS_ASSERT(boost::algorithm::equals(firstValues[i], thirdValues[i]));
}
}
private:
std::vector<std::vector<double>> doNextValueCalls(const unsigned int ncalls,
SobolSequence &randGen) {
std::vector<std::vector<double>> values(ncalls);
for (unsigned int i = 0; i < ncalls; ++i) {
values[i] = randGen.nextPoint();
}
return values;
}
void
assert_Sequence_Is_As_Expected_For_Five_Dimensions(SobolSequence &randGen) {
double expectedValues[3][5] = {
{0.5, 0.5, 0.5, 0.5, 0.5},
{0.75, 0.25, 0.75, 0.25, 0.75},
{0.25, 0.75, 0.25, 0.75, 0.25},
for (auto &expectedValue : expectedValues) {
const std::vector<double> randPoint = randGen.nextPoint();
for (std::size_t j = 0; j < 5; ++j) {
TS_ASSERT_DELTA(randPoint[j], expectedValue[j], 1e-12);
}
}
}
};
class SobolSequenceTestPerformance : public CxxTest::TestSuite {
public:
void test_Large_Number_Of_Next_Point_Calls() {
const unsigned int ndimensions(14);
SobolSequence generator(ndimensions);
const size_t ncalls = 10000000;
size_t sumSizes(0); // Make sure the optimizer actuall does the loop
for (size_t i = 0; i < ncalls; ++i) {
const std::vector<double> &point = generator.nextPoint();
sumSizes += point.size();
}
TS_ASSERT(sumSizes > 0);
}
};