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.simple.RandomSource;
20  
21  /**
22   * Computation of \( \pi \) using Monte-Carlo integration.
23   *
24   * The computation estimates the value by computing the probability that
25   * a point \( p = (x, y) \) will lie in the circle of radius \( r = 1 \)
26   * inscribed in the square of side \( r = 1 \).
27   * The probability could be computed by \[ area_{circle} / area_{square} \],
28   * where \( area_{circle} = \pi * r^2 \) and \( area_{square} = 4 r^2 \).
29   * Hence, the probability is \( \frac{\pi}{4} \).
30   *
31   * The Monte Carlo simulation will produce \( N \) points.
32   * Defining \( N_c \) as the number of point that satisfy \( x^2 + y^2 \le 1 \),
33   * we will have \( \frac{N_c}{N} \approx \frac{\pi}{4} \).
34   */
35  public class ComputePi extends MonteCarloIntegration {
36      /** Expected number of arguments. */
37      private static final int EXPECTED_ARGUMENTS = 2;
38      /** Domain dimension. */
39      private static final int DIMENSION = 2;
40  
41      /**
42       * @param source RNG algorithm.
43       */
44      public ComputePi(RandomSource source) {
45          super(source, DIMENSION);
46      }
47  
48      /**
49       * Program entry point.
50       *
51       * @param args Arguments.
52       * The order is as follows:
53       * <ol>
54       *  <li>
55       *   Number of random 2-dimensional points to generate.
56       *  </li>
57       *  <li>
58       *   {@link RandomSource Random source identifier}.
59       *  </li>
60       * </ol>
61       */
62      public static void main(String[] args) {
63          if (args.length != EXPECTED_ARGUMENTS) {
64              throw new IllegalStateException("Missing arguments");
65          }
66  
67          final long numPoints = Long.parseLong(args[0]);
68          final RandomSource randomSource = RandomSource.valueOf(args[1]);
69  
70          final ComputePi piApp = new ComputePi(randomSource);
71          final double piMC = piApp.compute(numPoints);
72  
73          //CHECKSTYLE: stop all
74          System.out.println("After generating " + (DIMENSION * numPoints) +
75                             " random numbers, the error on 𝛑 is " + Math.abs(piMC - Math.PI));
76          //CHECKSTYLE: resume all
77      }
78  
79      /**
80       * @param numPoints Number of random points to generate.
81       * @return the approximate value of pi.
82       */
83      public double compute(long numPoints) {
84          return 4 * integrate(numPoints);
85      }
86  
87      /** {@inheritDoc} */
88      @Override
89      protected boolean isInside(double... rand) {
90          final double r2 = rand[0] * rand[0] + rand[1] * rand[1];
91          return r2 <= 1;
92      }
93  }