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 * Create an instance.
44 *
45 * @param rng RNG.
46 */
47 public ComputePi(UniformRandomProvider rng) {
48 super(rng, DIMENSION);
49 }
50
51 /**
52 * Program entry point.
53 *
54 * @param args Arguments.
55 * The order is as follows:
56 * <ol>
57 * <li>
58 * Number of random 2-dimensional points to generate.
59 * </li>
60 * <li>
61 * {@link RandomSource Random source identifier}.
62 * </li>
63 * </ol>
64 */
65 public static void main(String[] args) {
66 if (args.length != EXPECTED_ARGUMENTS) {
67 throw new IllegalStateException("Require arguments: [points] [RNG name]");
68 }
69
70 final long numPoints = Long.parseLong(args[0]);
71 final RandomSource randomSource = RandomSource.valueOf(args[1]);
72
73 final ComputePi piApp = new ComputePi(randomSource.create());
74 final double piMC = piApp.compute(numPoints);
75
76 //CHECKSTYLE: stop all
77 System.out.printf("After generating %d random numbers, the error on |𝛑 - %s| is %s%n",
78 DIMENSION * numPoints, piMC, Math.abs(piMC - Math.PI));
79 //CHECKSTYLE: resume all
80 }
81
82 /**
83 * Compute the value of pi.
84 *
85 * @param numPoints Number of random points to generate.
86 * @return the approximate value of pi.
87 */
88 public double compute(long numPoints) {
89 return 4 * integrate(numPoints);
90 }
91
92 /** {@inheritDoc} */
93 @Override
94 protected boolean isInside(double... rand) {
95 final double r2 = rand[0] * rand[0] + rand[1] * rand[1];
96 return r2 <= 1;
97 }
98 }