public SobolRsg(int dimensionality, ulong seed, DirectionIntegers directionIntegers) { dimensionality_ = dimensionality; sequenceCounter_ = 0; firstDraw_ = true; sequence_ = new Sample <List <double> >(new InitializedList <double>(dimensionality), 1.0); integerSequence_ = new InitializedList <ulong>(dimensionality); directionIntegers_ = new InitializedList <List <ulong> >(dimensionality); for (int i = 0; i < dimensionality; i++) { directionIntegers_[i] = new InitializedList <ulong>(bits_); } if (!(dimensionality > 0)) { throw new Exception("dimensionality must be greater than 0"); } if (!(dimensionality <= PPMT_MAX_DIM)) { throw new Exception("dimensionality " + dimensionality + " exceeds the number of available " + "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")"); } // initializes coefficient array of the k-th primitive polynomial // and degree of the k-th primitive polynomial List <uint> degree = new InitializedList <uint>(dimensionality_); List <long> ppmt = new InitializedList <long>(dimensionality_); bool useAltPolynomials = false; if (directionIntegers == DirectionIntegers.Kuo || directionIntegers == DirectionIntegers.Kuo2 || directionIntegers == DirectionIntegers.Kuo3 || directionIntegers == DirectionIntegers.SobolLevitan || directionIntegers == DirectionIntegers.SobolLevitanLemieux) { useAltPolynomials = true; } // degree 0 is not used ppmt[0] = 0; degree[0] = 0; int k, index; uint currentDegree = 1; k = 1; index = 0; uint altDegree = useAltPolynomials ? maxAltDegree : 0; for ( ; k < Math.Min(dimensionality_, altDegree); k++, index++) { ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } for ( ; k < dimensionality_; k++, index++) { ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } // initializes bits_ direction integers for each dimension // and store them into directionIntegers_[dimensionality_][bits_] // // In each dimension k with its associated primitive polynomial, // the first degree_[k] direction integers can be chosen freely // provided that only the l leftmost bits can be non-zero, and // that the l-th leftmost bit must be set // degenerate (no free direction integers) first dimension int j; for (j = 0; j < bits_; j++) { directionIntegers_[0][j] = (1UL << (bits_ - j - 1)); } int maxTabulated = 0; // dimensions from 2 (k=1) to maxTabulated (k=maxTabulated-1) included // are initialized from tabulated coefficients switch (directionIntegers) { case DirectionIntegers.Unit: maxTabulated = dimensionality_; for (k = 1; k < maxTabulated; k++) { for (int l = 1; l <= degree[k]; l++) { directionIntegers_[k][l - 1] = 1UL; directionIntegers_[k][l - 1] <<= (bits_ - l); } } break; case DirectionIntegers.Jaeckel: // maxTabulated=32 maxTabulated = initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.SobolLevitan: // maxTabulated=40 maxTabulated = SLinitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (SLinitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = SLinitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.SobolLevitanLemieux: // maxTabulated=360 maxTabulated = Linitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Linitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Linitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD5: // maxTabulated=1898 maxTabulated = JoeKuoD5initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD5initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD5initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD6: // maxTabulated=1799 maxTabulated = JoeKuoD6initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD6initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD6initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD7: // maxTabulated=1898 maxTabulated = JoeKuoD7initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD7initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD7initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo: // maxTabulated=4925 maxTabulated = Kuoinitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuoinitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuoinitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo2: // maxTabulated=3946 maxTabulated = Kuo2initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo2initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuo2initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo3: // maxTabulated=4585 maxTabulated = Kuo3initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo3initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuo3initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; default: break; } // random initialization for higher dimensions if (dimensionality_ > maxTabulated) { MersenneTwisterUniformRng uniformRng = new MersenneTwisterUniformRng(seed); for (k = maxTabulated; k < dimensionality_; k++) { for (int l = 1; l <= degree[k]; l++) { do { // u is in (0,1) double u = uniformRng.next().value; // the direction integer has at most the // rightmost l bits non-zero directionIntegers_[k][l - 1] = (ulong)(u * (1UL << l)); } while (!((directionIntegers_[k][l - 1] & 1UL) != 0)); // iterate until the direction integer is odd // that is it has the rightmost bit set // shifting bits_-l bits to the left // we are guaranteed that the l-th leftmost bit // is set, and only the first l leftmost bit // can be non-zero directionIntegers_[k][l - 1] <<= (bits_ - l); } } } // computation of directionIntegers_[k][l] for l>=degree_[k] // by recurrence relation for (k = 1; k < dimensionality_; k++) { uint gk = degree[k]; for (int l = (int)gk; l < bits_; l++) { // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel ulong n = (directionIntegers_[k][(int)(l - gk)] >> (int)gk); // a[k][j] are the coefficients of the monomials in ppmt[k] // The highest order coefficient a[k][0] is not actually // used in the recurrence relation, and the lowest order // coefficient a[k][gk] is always set: this is the reason // why the highest and lowest coefficient of // the polynomial ppmt[k] are not included in its encoding, // provided that its degree is known. // That is: a[k][j] = ppmt[k] >> (gk-j-1) for (uint z = 1; z < gk; z++) { // XORed with a selection of (unshifted) direction // integers controlled by which of the a[k][j] are set if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0) { n ^= directionIntegers_[k][(int)(l - z)]; } } // a[k][gk] is always set, so directionIntegers_[k][l-gk] // will always enter n ^= directionIntegers_[k][(int)(l - gk)]; directionIntegers_[k][l] = n; } } // in case one needs to check the directionIntegers used /* bool printDirectionIntegers = false; * if (printDirectionIntegers) { * std::ofstream outStream("directionIntegers.txt"); * for (k=0; k<std::min(32UL,dimensionality_); k++) { * outStream << std::endl << k+1 << "\t" * << degree[k] << "\t" * << ppmt[k] << "\t"; * for (j=0; j<10; j++) { * outStream << io::power_of_two( * directionIntegers_[k][j]) << "\t"; * } * } * outStream.close(); * } */ // initialize the Sobol integer/double vectors // first draw for (k = 0; k < dimensionality_; k++) { integerSequence_[k] = directionIntegers_[k][0]; } }
public SobolRsg(int dimensionality, ulong seed, DirectionIntegers directionIntegers) { dimensionality_ = dimensionality; sequenceCounter_ = 0; firstDraw_ = true; sequence_ = new Sample<List<double>>(new InitializedList<double>(dimensionality), 1.0); integerSequence_ = new InitializedList<ulong>(dimensionality); directionIntegers_ = new InitializedList<List<ulong>>(dimensionality, new List<ulong>(bits_)); for (int i = 0; i < dimensionality; i++) directionIntegers_[i] = new InitializedList<ulong>(bits_); if (!(dimensionality>0)) throw new ApplicationException("dimensionality must be greater than 0"); if (!(dimensionality<=PPMT_MAX_DIM)) throw new ApplicationException("dimensionality " + dimensionality + " exceeds the number of available " + "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")"); // initializes coefficient array of the k-th primitive polynomial // and degree of the k-th primitive polynomial List<uint> degree = new InitializedList<uint>(dimensionality_); List<long> ppmt = new InitializedList<long>(dimensionality_); bool useAltPolynomials = false; if (directionIntegers == DirectionIntegers.Kuo || directionIntegers == DirectionIntegers.Kuo2 || directionIntegers == DirectionIntegers.Kuo3 || directionIntegers == DirectionIntegers.SobolLevitan || directionIntegers == DirectionIntegers.SobolLevitanLemieux) useAltPolynomials = true; // degree 0 is not used ppmt[0]=0; degree[0]=0; int k, index; uint currentDegree=1; k=1; index=0; uint altDegree = useAltPolynomials ? maxAltDegree : 0; for (; k<Math.Min(dimensionality_,altDegree); k++,index++) { ppmt[k] = AltPrimitivePolynomials[currentDegree-1][index]; if (ppmt[k]==-1) { ++currentDegree; index=0; ppmt[k] = AltPrimitivePolynomials[currentDegree-1][index]; } degree[k] = currentDegree; } for (; k<dimensionality_; k++,index++) { ppmt[k] = PrimitivePolynomials[currentDegree-1][index]; if (ppmt[k]==-1) { ++currentDegree; index=0; ppmt[k] = PrimitivePolynomials[currentDegree-1][index]; } degree[k] = currentDegree; } // initializes bits_ direction integers for each dimension // and store them into directionIntegers_[dimensionality_][bits_] // // In each dimension k with its associated primitive polynomial, // the first degree_[k] direction integers can be chosen freely // provided that only the l leftmost bits can be non-zero, and // that the l-th leftmost bit must be set // degenerate (no free direction integers) first dimension int j; for (j=0; j<bits_; j++) directionIntegers_[0][j] = (1UL<<(bits_-j-1)); int maxTabulated = 0; // dimensions from 2 (k=1) to maxTabulated (k=maxTabulated-1) included // are initialized from tabulated coefficients switch (directionIntegers) { case DirectionIntegers.Unit: maxTabulated=dimensionality_; for (k=1; k<maxTabulated; k++) { for (int l=1; l<=degree[k]; l++) { directionIntegers_[k][l-1] = 1UL; directionIntegers_[k][l-1] <<= (bits_-l); } } break; case DirectionIntegers.Jaeckel: // maxTabulated=32 maxTabulated = initializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.SobolLevitan: // maxTabulated=40 maxTabulated = SLinitializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (SLinitializers[k-1][j] != 0UL) { directionIntegers_[k][j] = SLinitializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.SobolLevitanLemieux: // maxTabulated=360 maxTabulated = Linitializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Linitializers[k-1][j] != 0UL) { directionIntegers_[k][j] = Linitializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.JoeKuoD5: // maxTabulated=1898 maxTabulated = JoeKuoD5initializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD5initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD5initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.JoeKuoD6: // maxTabulated=1799 maxTabulated = JoeKuoD6initializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD6initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD6initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.JoeKuoD7: // maxTabulated=1898 maxTabulated = JoeKuoD7initializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD7initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD7initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.Kuo: // maxTabulated=4925 maxTabulated = Kuoinitializers.Length + 1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuoinitializers[k-1][j] != 0UL) { directionIntegers_[k][j] = Kuoinitializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.Kuo2: // maxTabulated=3946 maxTabulated = Kuo2initializers.Length+1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo2initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = Kuo2initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; case DirectionIntegers.Kuo3: // maxTabulated=4585 maxTabulated = Kuo3initializers.Length+1; for (k=1; k<Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo3initializers[k-1][j] != 0UL) { directionIntegers_[k][j] = Kuo3initializers[k-1][j]; directionIntegers_[k][j] <<= (bits_-j-1); j++; } } break; default: break; } // random initialization for higher dimensions if (dimensionality_>maxTabulated) { MersenneTwisterUniformRng uniformRng = new MersenneTwisterUniformRng(seed); for (k=maxTabulated; k<dimensionality_; k++) { for (int l=1; l<=degree[k]; l++) { do { // u is in (0,1) double u = uniformRng.next().value; // the direction integer has at most the // rightmost l bits non-zero directionIntegers_[k][l-1] = (ulong)(u*(1UL<<l)); } while (!((directionIntegers_[k][l-1] & 1UL) != 0)); // iterate until the direction integer is odd // that is it has the rightmost bit set // shifting bits_-l bits to the left // we are guaranteed that the l-th leftmost bit // is set, and only the first l leftmost bit // can be non-zero directionIntegers_[k][l-1] <<= (bits_-l); } } } // computation of directionIntegers_[k][l] for l>=degree_[k] // by recurrence relation for (k=1; k<dimensionality_; k++) { uint gk = degree[k]; for (int l=(int)gk; l<bits_; l++) { // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel ulong n = (directionIntegers_[k][(int)(l - gk)] >> (int)gk); // a[k][j] are the coefficients of the monomials in ppmt[k] // The highest order coefficient a[k][0] is not actually // used in the recurrence relation, and the lowest order // coefficient a[k][gk] is always set: this is the reason // why the highest and lowest coefficient of // the polynomial ppmt[k] are not included in its encoding, // provided that its degree is known. // That is: a[k][j] = ppmt[k] >> (gk-j-1) for (uint z=1; z<gk; z++) { // XORed with a selection of (unshifted) direction // integers controlled by which of the a[k][j] are set if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0) n ^= directionIntegers_[k][(int)(l-z)]; } // a[k][gk] is always set, so directionIntegers_[k][l-gk] // will always enter n ^= directionIntegers_[k][(int)(l-gk)]; directionIntegers_[k][l]=n; } } // in case one needs to check the directionIntegers used /* bool printDirectionIntegers = false; if (printDirectionIntegers) { std::ofstream outStream("directionIntegers.txt"); for (k=0; k<std::min(32UL,dimensionality_); k++) { outStream << std::endl << k+1 << "\t" << degree[k] << "\t" << ppmt[k] << "\t"; for (j=0; j<10; j++) { outStream << io::power_of_two( directionIntegers_[k][j]) << "\t"; } } outStream.close(); } */ // initialize the Sobol integer/double vectors // first draw for (k=0; k<dimensionality_; k++) { integerSequence_[k]=directionIntegers_[k][0]; } }