Example #1
0
 public SobolVectorGenerator(int d) : base(d)
 {
     sequences = new SobolSequence[d];
     for (int i = 0; i < sequences.Length; i++)
     {
         SobolSequenceParameters p = SobolSequenceParameters.sobolParameters[i];
         sequences[i] = new SobolSequence(p.Dimension, p.Coefficients, p.Seeds);
     }
 }
Example #2
0
        /// <summary>
        /// Integrates the given function over the given volume.
        /// </summary>
        /// <param name="integrand">The function to integrate, which maps R<sup>d</sup> to R.</param>
        /// <param name="volume">The box defining the volume over with to integrate.</param>
        /// <param name="settings">The evaluation settings to use.</param>
        /// <returns>The value of the integral.</returns>
        public static double Integrate(Func <IList <double>, double> integrand, IList <Interval> volume, EvaluationSettings settings)
        {
            if (integrand == null)
            {
                throw new ArgumentNullException("integrand");
            }
            if (volume == null)
            {
                throw new ArgumentNullException("volume");
            }

            // get the dimension of the problem from the volume
            int d = volume.Count;

            if ((d < 1) || (d > sobolParameters.Length))
            {
                throw new InvalidOperationException();
            }

            // if no settings were provided, use defaults
            if (settings == null)
            {
                settings = new EvaluationSettings()
                {
                    RelativePrecision = 1.0 / (1 << (14 - 3 * d / 2)),
                    AbsolutePrecision = RelativePrecision / 128.0,
                    EvaluationBudget  = 1 << (18 + 3 * d / 2)
                };
            }

            // compute the volume of the box
            double V = 1.0;

            for (int j = 0; j < volume.Count; j++)
            {
                V *= volume[j].Width;
            }

            // generate the appropriate number of Sobol sequences
            SobolSequence[] s = new SobolSequence[d];
            for (int j = 0; j < d; j++)
            {
                SobolSequenceParameters p = sobolParameters[j];
                s[j] = new SobolSequence(p.Dimension, p.Coefficients, p.Seeds);
            }

            // create one vector to store the argument
            // we don't want to recreate the vector in the
            // heap on each iteration
            double[] x = new double[d];

            // keep track of the average sampled value
            double M = 0.0; double M_old = Double.NaN;

            // set the first convergence checkpoint to ~4000 points for d=2, increasing
            // for higher d
            int i_next = 1 << (10 + d);

            for (int i = 1; i <= settings.EvaluationBudget; i++)
            {
                // move to the next value in each dimension's Sobol sequence
                // and construct the argument vector
                for (int j = 0; j < d; j++)
                {
                    s[j].MoveNext();
                    x[j] = volume[j].LeftEndpoint + s[j].Current * volume[j].Width;
                }

                // evaluate the function
                double y = integrand(x);

                // update the mean
                M += (y - M) / i;

                // check for convergence at regular intervals
                if (i == i_next)
                {
                    // estimate error as change since last check
                    double dM = 2.0 * Math.Abs(M - M_old);

                    if (dM < settings.RelativePrecision * Math.Abs(M) || Math.Abs(V) * dM < settings.AbsolutePrecision)
                    {
                        return(V * M);
                    }

                    // no convergence, so remember current value and set next checkpoint
                    M_old  = M;
                    i_next = 2 * i_next;

                    // Consider how to do this better:
                    // 1. Is there any way we can do better than doubling? Say increasing by 4/3 and then 3/2, for an average increase of
                    // 40% instead of 100%? If so, how do we estimate error at each step?
                    // 2. Can we use Romberg extrapolation? I tried using both M and M_old, assuming an error term of 1/N. This gives
                    // the extrapolated value 2 M - M_old, but experimentally this is usually a worse value than M. I should try out
                    // 3-value extrapolation.
                }
            }

            throw new NonconvergenceException();
        }