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 }