View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng.examples.quadrature;
18  
19  import org.apache.commons.rng.UniformRandomProvider;
20  import org.apache.commons.rng.simple.RandomSource;
21  
22  /**
23   * Computation of \( \pi \) using Monte-Carlo integration.
24   *
25   * The computation estimates the value by computing the probability that
26   * a point \( p = (x, y) \) will lie in the circle of radius \( r = 1 \)
27   * inscribed in the square of side \( r = 1 \).
28   * The probability could be computed by \[ area_{circle} / area_{square} \],
29   * where \( area_{circle} = \pi * r^2 \) and \( area_{square} = 4 r^2 \).
30   * Hence, the probability is \( \frac{\pi}{4} \).
31   *
32   * The Monte Carlo simulation will produce \( N \) points.
33   * Defining \( N_c \) as the number of point that satisfy \( x^2 + y^2 \le 1 \),
34   * we will have \( \frac{N_c}{N} \approx \frac{\pi}{4} \).
35   */
36  public class ComputePi extends MonteCarloIntegration {
37      /** Expected number of arguments. */
38      private static final int EXPECTED_ARGUMENTS = 2;
39      /** Domain dimension. */
40      private static final int DIMENSION = 2;
41  
42      /**
43       * @param rng RNG.
44       */
45      public ComputePi(UniformRandomProvider rng) {
46          super(rng, DIMENSION);
47      }
48  
49      /**
50       * Program entry point.
51       *
52       * @param args Arguments.
53       * The order is as follows:
54       * <ol>
55       *  <li>
56       *   Number of random 2-dimensional points to generate.
57       *  </li>
58       *  <li>
59       *   {@link RandomSource Random source identifier}.
60       *  </li>
61       * </ol>
62       */
63      public static void main(String[] args) {
64          if (args.length != EXPECTED_ARGUMENTS) {
65              throw new IllegalStateException("Require arguments: [points] [RNG name]");
66          }
67  
68          final long numPoints = Long.parseLong(args[0]);
69          final RandomSource randomSource = RandomSource.valueOf(args[1]);
70  
71          final ComputePi piApp = new ComputePi(randomSource.create());
72          final double piMC = piApp.compute(numPoints);
73  
74          //CHECKSTYLE: stop all
75          System.out.printf("After generating %d random numbers, the error on |𝛑 - %s| is %s%n",
76                            DIMENSION * numPoints, piMC, Math.abs(piMC - Math.PI));
77          //CHECKSTYLE: resume all
78      }
79  
80      /**
81       * @param numPoints Number of random points to generate.
82       * @return the approximate value of pi.
83       */
84      public double compute(long numPoints) {
85          return 4 * integrate(numPoints);
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      protected boolean isInside(double... rand) {
91          final double r2 = rand[0] * rand[0] + rand[1] * rand[1];
92          return r2 <= 1;
93      }
94  }