|
30 | 30 | #include <ql/math/randomnumbers/randomizedlds.hpp> |
31 | 31 | #include <ql/math/randomnumbers/randomsequencegenerator.hpp> |
32 | 32 | #include <ql/math/randomnumbers/sobolrsg.hpp> |
| 33 | +#include <ql/math/randomnumbers/burley2020scrambledsobolrsg.hpp> |
33 | 34 | #include <ql/utilities/dataformatters.hpp> |
34 | 35 | #include <ql/math/randomnumbers/latticerules.hpp> |
35 | 36 | #include <ql/math/randomnumbers/latticersg.hpp> |
@@ -1070,6 +1071,62 @@ void LowDiscrepancyTest::testSobolSkipping() { |
1070 | 1071 | } |
1071 | 1072 | } |
1072 | 1073 |
|
| 1074 | +void LowDiscrepancyTest::testHighDimensionalIntegrals() { |
| 1075 | + |
| 1076 | + BOOST_TEST_MESSAGE("Testing High Dimensional Integrals"); |
| 1077 | + |
| 1078 | + /* We are running "Integration test 1, results for high dimensions" (Figure 9) from: |
| 1079 | +
|
| 1080 | + Sobol, Asotsky, Kreinin, Kucherenko: Construction and Comparison of High-Dimensional Sobol’ |
| 1081 | + Generators, available at https://www.broda.co.uk/doc/HD_SobolGenerator.pdf |
| 1082 | +
|
| 1083 | + We check the error of Kuo1 (using Gray code and sequential numbers) roughly against what |
| 1084 | + their graph suggests. In addition we check the error of the Burley2020-scrambled version of |
| 1085 | + Kuo1 against what we experimentally find - the error turns out to be more than one order |
| 1086 | + better than the unscrambled version. */ |
| 1087 | + |
| 1088 | + auto integrand = [](const std::vector<Real>& c, const std::vector<Real>& x) { |
| 1089 | + Real p = 1.0; |
| 1090 | + for (Size i = 0; i < c.size(); ++i) { |
| 1091 | + p *= 1.0 + c[i] * (x[i] - 0.5); |
| 1092 | + } |
| 1093 | + return p; |
| 1094 | + }; |
| 1095 | + |
| 1096 | + Size N = 30031; |
| 1097 | + |
| 1098 | + BOOST_TEST_MESSAGE("dimension,Sobol(Gray),Sobol(Seq),Burley2020"); |
| 1099 | + |
| 1100 | + std::vector<Size> dimension = {1000,2000,5000}; |
| 1101 | + std::vector<std::vector<Real>> expectedOrderOfError = { |
| 1102 | + {-3.0, -3.0, -4.5}, {-2.5, -2.5, -4.0}, {-2.0, -2.0, -4.0}}; |
| 1103 | + |
| 1104 | + for (Size d = 0; d < dimension.size(); ++d) { |
| 1105 | + |
| 1106 | + std::vector<Real> c1(dimension[d], 0.01); |
| 1107 | + |
| 1108 | + SobolRsg s1(dimension[d], 42, SobolRsg::DirectionIntegers::Kuo, true); |
| 1109 | + SobolRsg s2(dimension[d], 42, SobolRsg::DirectionIntegers::Kuo, false); |
| 1110 | + Burley2020SobolRsg s3(dimension[d], 42, SobolRsg::DirectionIntegers::Kuo, 43); |
| 1111 | + |
| 1112 | + Real I1 = 0.0, I2 = 0.0, I3 = 0.0; |
| 1113 | + for (Size i = 0; i < N; ++i) { |
| 1114 | + I1 += integrand(c1, s1.nextSequence().value) / static_cast<double>(N); |
| 1115 | + I2 += integrand(c1, s2.nextSequence().value) / static_cast<double>(N); |
| 1116 | + I3 += integrand(c1, s3.nextSequence().value) / static_cast<double>(N); |
| 1117 | + } |
| 1118 | + |
| 1119 | + Real errOrder1 = std::log10(std::abs(I1-1.0)); |
| 1120 | + Real errOrder2 = std::log10(std::abs(I2-1.0)); |
| 1121 | + Real errOrder3 = std::log10(std::abs(I3-1.0)); |
| 1122 | + |
| 1123 | + BOOST_TEST_MESSAGE(dimension[d] << "," << errOrder1 << "," << errOrder2 << "," << errOrder3); |
| 1124 | + |
| 1125 | + BOOST_CHECK(errOrder1 < expectedOrderOfError[d][0]); |
| 1126 | + BOOST_CHECK(errOrder2 < expectedOrderOfError[d][1]); |
| 1127 | + BOOST_CHECK(errOrder3 < expectedOrderOfError[d][2]); |
| 1128 | + } |
| 1129 | +} |
1073 | 1130 |
|
1074 | 1131 | test_suite* LowDiscrepancyTest::suite() { |
1075 | 1132 | auto* suite = BOOST_TEST_SUITE("Low-discrepancy sequence tests"); |
@@ -1112,5 +1169,7 @@ test_suite* LowDiscrepancyTest::suite() { |
1112 | 1169 | suite->add(QUANTLIB_TEST_CASE( |
1113 | 1170 | &LowDiscrepancyTest::testRandomizedLowDiscrepancySequence)); |
1114 | 1171 |
|
| 1172 | + suite->add(QUANTLIB_TEST_CASE(&LowDiscrepancyTest::testHighDimensionalIntegrals)); |
| 1173 | + |
1115 | 1174 | return suite; |
1116 | 1175 | } |
0 commit comments