Skip to content

Commit a05b6ab

Browse files
authored
Faster skipTo() implementation in Burley's scrambled Sobol RNG (lballabio#2431)
2 parents 71e800b + 1bc9e98 commit a05b6ab

2 files changed

Lines changed: 48 additions & 5 deletions

File tree

ql/math/randomnumbers/burley2020sobolrsg.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,9 @@ namespace QuantLib {
4343
}
4444

4545
const std::vector<std::uint32_t>& Burley2020SobolRsg::skipTo(std::uint32_t n) const {
46-
reset();
47-
for (Size k = 0; k < n + 1; ++k) {
48-
nextInt32Sequence();
49-
}
46+
nextSequenceCounter_ = n;
47+
nextInt32Sequence();
48+
--nextSequenceCounter_;
5049
return integerSequence_;
5150
}
5251

@@ -138,7 +137,7 @@ namespace QuantLib {
138137
}
139138
} while (i < dimensionality_);
140139
QL_REQUIRE(++nextSequenceCounter_ != 0,
141-
"Burley2020SobolRsg::nextIn32Sequence(): period exceeded");
140+
"Burley2020SobolRsg::nextInt32Sequence(): period exceeded");
142141
return integerSequence_;
143142
}
144143

test-suite/lowdiscrepancysequences.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,50 @@ BOOST_AUTO_TEST_CASE(testSobolSkipping) {
10681068
}
10691069
}
10701070

1071+
BOOST_AUTO_TEST_CASE(testSobolBurleySkipping) {
1072+
1073+
BOOST_TEST_MESSAGE("Testing Sobol Burley sequence skipping...");
1074+
1075+
unsigned long seed = 42;
1076+
unsigned long scramblingSeed = 43;
1077+
Size dimensionality[] = { 1, 10, 100, 1000 };
1078+
unsigned long skip[] = { 0, 1, 42, 512, 10000 };
1079+
SobolRsg::DirectionIntegers integers[] = {
1080+
SobolRsg::Jaeckel,
1081+
SobolRsg::SobolLevitan,
1082+
SobolRsg::SobolLevitanLemieux };
1083+
1084+
for (auto& integer : integers) {
1085+
for (Size& j : dimensionality) {
1086+
for (unsigned long& k : skip) {
1087+
1088+
// extract n samples
1089+
Burley2020SobolRsg rsg1(j, seed, integer, scramblingSeed);
1090+
for (Size l = 0; l < k; l++)
1091+
rsg1.nextInt32Sequence();
1092+
1093+
// skip n samples at once
1094+
Burley2020SobolRsg rsg2(j, seed, integer, scramblingSeed);
1095+
rsg2.skipTo(k);
1096+
1097+
// compare next 100 samples
1098+
for (Size m = 0; m < 100; m++) {
1099+
const std::vector<std::uint_least32_t>& s1 = rsg1.nextInt32Sequence();
1100+
const std::vector<std::uint_least32_t>& s2 = rsg2.nextInt32Sequence();
1101+
for (Size n = 0; n < s1.size(); n++) {
1102+
if (s1[n] != s2[n]) {
1103+
BOOST_ERROR("Mismatch after skipping:"
1104+
<< "\n size: " << j << "\n integers: " << integer
1105+
<< "\n skipped: " << k << "\n at index: " << n
1106+
<< "\n expected: " << s1[n] << "\n found: " << s2[n]);
1107+
}
1108+
}
1109+
}
1110+
}
1111+
}
1112+
}
1113+
}
1114+
10711115
BOOST_AUTO_TEST_CASE(testHighDimensionalIntegrals, *precondition(if_speed(Slow))) {
10721116
BOOST_TEST_MESSAGE("Testing high-dimensional integrals...");
10731117

0 commit comments

Comments
 (0)