/// <summary> /// Sobol sequence. /// </summary> public static IEnumerable <Rational> SobolR(PolyGF2 primitivePolynomial, params int[] initialValues) { var v = SobolDirectionVectors(64, primitivePolynomial, initialValues); ulong s = 0; var d = ((System.Numerics.BigInteger) 1) << 64; foreach (var r in Sequences.Ruler()) { s ^= v[r]; yield return(new Rational(s, d)); } }
/// <summary> /// Sobol sequence. /// </summary> public static IEnumerable <Decimal> SobolM(PolyGF2 primitivePolynomial, params int[] initialValues) { var v = SobolDirectionVectors(64, primitivePolynomial, initialValues); ulong s = 0; var d = ((System.Numerics.BigInteger) 1) << 64; foreach (var r in Sequences.Ruler()) { s ^= v[r]; yield return(s / 18446744073709551616M); } }
public void SobolInitialValues(int max) { int d = 2; var g = new Generator("SobolInitialValue"); var v = new bool[max + 1][]; v[0] = new bool[max]; v[0][0] = true; foreach (var p in PolyGF2.GetAllPrimitive().Take(max - 1)) { v[d - 1] = new bool[max]; int s = p.Degree; var m = new int[s]; var V = new SquareMatrixGF2(d); while (true) { for (int i = 0; i < s; i++) { m[i] = g.Int32(2 << i) | 1; } var dv = Subrandom.SobolDirectionVectors(max, p, m); for (int i = 0; i < max; i++) { v[d - 1][i] = dv[i] > (ulong)long.MaxValue; } for (int row = 0; row < d; row++) { for (int col = 0; col < d; col++) { V[row, col] = v[row][col]; } } bool det = V.GetDeterminant(); if (det) { break; } } Trace.Write($"{d}\t{s}\t{p.GetCode() / 2 ^ (1UL << (s-1))}\t"); for (int i = 0; i < s; i++) { Trace.Write($"{m[i]} "); } Trace.WriteLine(""); d++; } }
public void SobolRationalTest() { var p = new PolyGF2(3, 1, 0); var m = new[] { 1, 3, 7 }; foreach (var item in Subrandom.SobolR(p, m).Take(1000)) { System.Diagnostics.Trace.WriteLine(item); } var g = new Generator("SobolRationalTest"); Test(g, () => Subrandom.SobolR(p, m)); }
internal static ulong[] SobolDirectionVectors(int d, PolyGF2 primitivePolynomial, int[] initialValues) { if (initialValues == null) { throw new ArgumentNullException(nameof(initialValues)); } int n = initialValues.Length; if (n != primitivePolynomial.Degree) { throw new ArgumentException("The number of initial values must be the same as the degree of the primitive polynomial."); } PolyGF2 factor; long order; if (!primitivePolynomial.IsPrimitive(out factor, out order)) { ulong q = (1UL << primitivePolynomial.Degree) - 1UL; var o = new PolyGF2((int)order, 0); if (factor != PolyGF2.Zero) { throw new ArgumentException($"Polynomial is not primitive because it is divisible by {factor} = ({primitivePolynomial}) / ({primitivePolynomial / factor})."); } else { throw new ArgumentException($"Polynomial is not primitive because it only has order {order} and not {q}. ({o}) / ({primitivePolynomial}) = ({o / primitivePolynomial})"); } } // Validate initial values. var v = new ulong[d]; long max = 1; var m = initialValues; for (int i = 0; i < n; i++) { max <<= 1; if (m[i] < 0) { throw new ArgumentException($"Initial values cannot be negative. {m[i]} is definitely negative."); } if (m[i] >= max) { throw new ArgumentException($"The i-th initial value (starting with i=0) must be less than 2^i. ${m[i]} should be less than {max}."); } if ((m[i] & 1) == 0) { throw new ArgumentException($"Initial values must be odd. {m[i]} is even."); } v[i] = (ulong)m[i] << (63 - i); } // Compute remaining direction vectors. var exponents = new HashSet <int>(primitivePolynomial.Exponents); for (int i = n; i < d; i++) { ulong sum = v[i - n] >> n; for (int j = 1; j <= n; j++) { if (exponents.Contains(n - j)) { sum ^= v[i - j]; } } v[i] = sum; } return(v); }
/// <summary> /// Sobol sequence. /// </summary> public static IEnumerable <Rational> SobolR(int polynomialCode, params int[] initialValues) { var primitivePolynomial = PolyGF2.FromCode(2UL * (ulong)polynomialCode ^ 1UL ^ (1UL << initialValues.Length)); return(SobolR(primitivePolynomial, initialValues)); }
/// <summary> /// Creates a <see cref="Sobol"/> with specified initial /// values and primitive polynomial coefficients packed into /// bits, with leading and trailing coefficient omitted. /// </summary> /// <param name="polynomialCode">Bit 0 corresponds to x^1.</param> /// <param name="initialValues">Initial values.</param> public Sobol(int polynomialCode, params int[] initialValues) : this(PolyGF2.FromCode(2UL * (ulong)polynomialCode ^ 1UL ^ (1UL << initialValues.Length)) .Exponents.ToArray(), initialValues) { }