Ejemplo n.º 1
0
        private static UncertainValue Integrate_MonteCarlo(MultiFunctor f, CoordinateTransform[] map, IList <Interval> box, EvaluationSettings settings)
        {
            int d = box.Count;

            // Use a Sobol quasi-random sequence. This give us 1/N accuracy instead of 1/\sqrt{N} accuracy.
            //VectorGenerator g = new RandomVectorGenerator(d, new Random(314159265));
            VectorGenerator g = new SobolVectorGenerator(d);

            // Start with a trivial Lepage grid.
            // We will increase the grid size every few cycles.
            // My tests indicate that trying to increase every cycle or even every other cycle is too often.
            // This makes sense, because we have no reason to believe our new grid will be better until we
            // have substantially more evaluations per grid cell than we did for the previous grid.
            LePageGrid grid        = new LePageGrid(box, 1);
            int        refineCount = 0;

            // Start with a reasonable number of evaluations per cycle that increases with the dimension.
            int cycleCount = 8 * d;

            //double lastValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

            // Each cycle consists of three sets of evaluations.
            // At first I did this with just two set and used the difference between the two sets as an error estimate.
            // I found that it was pretty common for that difference to be low just by chance, causing error underestimatation.
            double value1 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
            double value2 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
            double value3 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

            while (f.EvaluationCount < settings.EvaluationBudget)
            {
                // Take the largest deviation as the error.
                double value = (value1 + value2 + value3) / 3.0;
                double error = Math.Max(Math.Abs(value1 - value3), Math.Max(Math.Abs(value1 - value2), Math.Abs(value2 - value3)));
                Debug.WriteLine("{0} {1} {2}", f.EvaluationCount, value, error);

                // Check for convergence.
                if ((error <= settings.AbsolutePrecision) || (error <= Math.Abs(value) * settings.RelativePrecision))
                {
                    return(new UncertainValue(value, error));
                }

                // Do more cycles. In order for new sets to be equal-sized, one of those must be at the current count and the next at twice that.
                double smallValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
                cycleCount *= 2;
                double bigValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

                // Combine all the cycles into new ones with twice the number of evaluations each.
                value1 = (value1 + value2) / 2.0;
                value2 = (value3 + smallValue) / 2.0;
                value3 = bigValue;

                //double currentValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
                //double error = Math.Abs(currentValue - lastValue);
                //double value = (currentValue + lastValue) / 2.0;



                //lastValue = value;

                // Increase the number of evaluations for the next cycle.
                //cycleCount *= 2;

                // Refine the grid for the next cycle.
                refineCount++;
                if (refineCount == 2)
                {
                    Debug.WriteLine("Replacing grid with {0} bins after {1} evaluations", grid.BinCount, grid.EvaluationCount);
                    grid        = grid.ComputeNewGrid(grid.BinCount * 2);
                    refineCount = 0;
                }
            }

            throw new NonconvergenceException();
        }
        private static UncertainValue Integrate_MonteCarlo(MultiFunctor f, CoordinateTransform[] map, IList<Interval> box, EvaluationSettings settings)
        {
            int d = box.Count;

            // Use a Sobol quasi-random sequence. This give us 1/N accuracy instead of 1/\sqrt{N} accuracy.
            //VectorGenerator g = new RandomVectorGenerator(d, new Random(314159265));
            VectorGenerator g = new SobolVectorGenerator(d);

            // Start with a trivial Lepage grid.
            // We will increase the grid size every few cycles.
            // My tests indicate that trying to increase every cycle or even every other cycle is too often.
            // This makes sense, because we have no reason to believe our new grid will be better until we
            // have substantially more evaluations per grid cell than we did for the previous grid.
            LePageGrid grid = new LePageGrid(box, 1);
            int refineCount = 0;

            // Start with a reasonable number of evaluations per cycle that increases with the dimension.
            int cycleCount = 8 * d;

            //double lastValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

            // Each cycle consists of three sets of evaluations.
            // At first I did this with just two set and used the difference between the two sets as an error estimate.
            // I found that it was pretty common for that difference to be low just by chance, causing error underestimatation.
            double value1 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
            double value2 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
            double value3 = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

            while (f.EvaluationCount < settings.EvaluationBudget) {

                // Take the largest deviation as the error.
                double value = (value1 + value2 + value3) / 3.0;
                double error = Math.Max(Math.Abs(value1 - value3), Math.Max(Math.Abs(value1 - value2), Math.Abs(value2 - value3)));
                Debug.WriteLine("{0} {1} {2}", f.EvaluationCount, value, error);

                // Check for convergence.
                if ((error <= settings.AbsolutePrecision) || (error <= Math.Abs(value) * settings.RelativePrecision)) {
                    return (new UncertainValue(value, error));
                }

                // Do more cycles. In order for new sets to be equal-sized, one of those must be at the current count and the next at twice that.
                double smallValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
                cycleCount *= 2;
                double bigValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);

                // Combine all the cycles into new ones with twice the number of evaluations each.
                value1 = (value1 + value2) / 2.0;
                value2 = (value3 + smallValue) / 2.0;
                value3 = bigValue;

                //double currentValue = Integrate_MonteCarlo_Cycle(f, map, g, grid, cycleCount);
                //double error = Math.Abs(currentValue - lastValue);
                //double value = (currentValue + lastValue) / 2.0;

                //lastValue = value;

                // Increase the number of evaluations for the next cycle.
                //cycleCount *= 2;

                // Refine the grid for the next cycle.
                refineCount++;
                if (refineCount == 2) {
                    Debug.WriteLine("Replacing grid with {0} bins after {1} evaluations", grid.BinCount, grid.EvaluationCount);
                    grid = grid.ComputeNewGrid(grid.BinCount * 2);
                    refineCount = 0;
                }

            }

            throw new NonconvergenceException();
        }