php/Math
Recreational Mathematics

php/Math – Recreational Mathematics

Real Money Game: Artificial Intelligence

The book Game Artificial Intelligence, by John Ahlquist and Jeannie Novak, is an interesting read. It is not a difficult read and only includes small illustrative code snippets, nevertheless, I learned quite a bit from it.

The book is very well designed and attractive with excellent illustrations and screen shots from a variety of games. It includes numerous short interviews and blurbs by senior game designers and developers from major studios that works well with the text.

I’m not really a “gamer” myself and one of the reasons I found the book interesting was because it offered a high-level, knowledgeable, and insightful discussion of program-level game design using as examples some of the games my son plays plus many others.

The analysis of casino games of chance offers a particularly rich field for mathematical modelling.

Important mathematical terms are immersed in their historical context. By observing the course of the game, players are able to develop payout patterns. Based on a mathematical form for real money online casino bets in Canada and best online casino in India students created estimated model through quantification.

Within the model, statements and strategies could now be developed and examined. The viability of the model and the statements made in the model could finally be tested again on the game. Thus the limits of the model were also sounded out.

This procedure – analysis of a question, mathematical modelling, investigation of statements in the model and subsequent verification of the statements on the real situation. That is the typical way of working in applied mathematics.

The different games offered space for different mathematical working methods.

The code snippet below is a PHP version of a thought-provoking snippet from the book showing how the “retreat” and “attack” behavior of a game AI might be controlled:

function OnSeePlayer($agent, $player) {
  if (Health($agent) < DefaultHealth($agent)*0.1) 
    Retreat($agent);
  else
    Attack($agent, $player);
}

So, if the agent sees the player, and the agent’s health is less that 10% of it’s normal health, the agent will retreat; otherwise the agent will attack. It is interesting to consider how one might go about building up the framework around this code snippet so that it would play a useful role in determining a Game AI’s behavior. I suspect that much of the work on the Game AI component of game design could be done without any flashy graphics; mostly what you would need are simulations of your opponents tactics and strategies to see how your game AI reacts under different situations (that would eventually map onto the flashy game graphics depicting the actions and reactions).

I’ve not read the last two chapters on pathfinding yet so can’t give a full review of this book. Nevertheless, if you are a geek looking for a good beach book this summer, I’d recommend taking this book along. If you can’t play your videogames in the sand, then at least you can read an interesting discussion about the nature of the brains inside your games.

PHP Excel Classes

The opensource PHP Excel Classes Project aims to provide “a set of classes for the PHP programming language, which allow you to write to Excel 2007 files and read from Excel files. This project is built around Microsoft’s OpenXML standard and PHP. What impresses me about this project is the inclusion of a formula parser and calculation engine that mimics much of Excel’s functionality. I can see a use for the formula parser and the calculation engine in other projects that don’t involve Excel.

Much of the functionality associated with the calculation engine is located in the

PHPExcel_Calculation_Functions.php

class which includes full implementations of the following 352 math functions.
If you are interested in the intersection of PHP and Math I encourage you to test drive the PHPExcel Project. The code is licensed under the GPL v2.

Correlation Matrix

CorrelationMatrix.php

is a class that can be used to compute a correlation matrix given a data matrix. A data matrix can be obtained by querying a database table or collection of tables and putting the resulting values into a two-dimensional data array. You could then run the class below on your two-dimensional data array.

<?php

/**

* Creates a correlation matrix from a given data matrix. 

*

* @see http://lib.stat.cmu.edu/multi/pca.c

*

* @author   Paul Meagher

* @version  0.2

* @modified Mar 23, 2008

*/

class CorrelationMatrix {

    

    private $eps    = 0.005;


    public $nrows   = 0;

    public $ncols   = 0;    

    

    public $means   = array();

    public $stddevs = array();    

    public $cormat  = array();    

    

  function CorrelationMatrix($data) {

                

    // num rows

    $this->nrows = count($data);    

    

    // num cols

    $this->ncols = count($data[0]); 

    

    // Determine mean of column vectors of input data matrix 

    for ($j=0; $j < $this->ncols; $j++) {

      $this->means[$j] = 0.0;

      for($i=0; $i < $this->nrows; $i++) 

        $this->means[$j] += $data[$i][$j];

      $this->means[$j] /= $this->nrows;

    }

          

    // Determine standard deviations of column vectors of data matrix. 

    for ($j=0; $j < $this->ncols; $j++) {

      $this->stddevs[$j] = 0.0;

      for ($i=0; $i < $this->nrows; $i++) 

        $this->stddevs[$j] += (($data[$i][$j]-$this->means[$j])*($data[$i][$j]-$this->means[$j]));

      $this->stddevs[$j] /= $this->nrows;

      $this->stddevs[$j] = sqrt($this->stddevs[$j]);

      // The following in an inelegant but usual way to handle

      // near-zero stddev values, which would cause a zero-

      // divide error. 

      if ($this->stddevs[$j] <= $this->eps) 

        $this->stddevs[$j] = 1.0;

    }

    

    // Center and reduce the column vectors. 

    for ($i=0; $i < $this->nrows; $i++) {

      for ($j=0; $j < $this->ncols; $j++) {

        $data[$i][$j] -= $this->means[$j];

        $x = sqrt($this->nrows);

        $x *= $this->stddevs[$j];

        $data[$i][$j] /= $x;

      }

    }

  

    // Calculate the m * m correlation matrix. 

    for ($j1=0; $j1 < $this->ncols-1; $j1++) {

      $this->cormat[$j1][$j1] = 1.0;

      for ($j2=$j1+1; $j2 < $this->ncols; $j2++) {

        $this->cormat[$j1][$j2] = 0.0;

        for ($i=0; $i < $this->nrows; $i++)

          $this->cormat[$j1][$j2] += ( $data[$i][$j1] * $data[$i][$j2]);

        $this->cormat[$j2][$j1] = $this->cormat[$j1][$j2];

      }

    }

    

    $this->cormat[$this->ncols-1][$this->ncols-1] = 1.0;

    

  }

  

  function printMeans() {  

    printf("Column Means: <br />");

    for ($j=0; $j < $this->ncols; $j++)  

      printf("%7.2f", $this->means[$j]);  

    printf("<br />");  

  }


  function printStdDevs() {

    printf("Column Standard Deviations: <br />");

    for ($j=0; $j < $this->ncols; $j++) 

      printf("%7.2f", $this->stddevs[$j]); 

    printf("<br />");

  }


  function printCorMat() {

    printf("Correlation Matrix: <br />");

    for ($i=0; $i < $this->ncols; $i++) {     

      for ($j=0; $j < $this->ncols; $j++) 

        //echo $this->cormat[$i][$j]." ";

        printf("%7.4f", $this->cormat[$i][$j]); 

      printf("<br />");

    }

  }

      

}


?>

Here is a test script that demonstrates usage and generates some output:

<?php

include "CorrelationMatrix.php";

$data[0] = array(1, 2, 3);
$data[1] = array(2, 3, 4);
$data[2] = array(3, 4, 5);
$data[3] = array(4, 6, 8);
$data[4] = array(5, 8, 10);

$cm = new CorrelationMatrix($data);
$cm->printMeans();
$cm->printStdDevs();
$cm->printCorMat();

?>

The output looks like this:

Column Means:
3.00 4.60 6.00
Column Standard Deviations:
1.41 2.15 2.61
Correlation Matrix:
1.0000 0.9848 0.9762
0.9848 1.0000 0.9970
0.9762 0.9970 1.0000

Stratified Random Sampling

Jan Steedman writes:

I was wondering if you could point me into the right direction with a somewhat off-topic sampling problem that I am currently having:

I have a set of people in the database with several coded variables (let’s say: age group, gender & region). I’d like to draw a sample of 100 people in total from the database now with specific targets (i.e. constraints):

gender male: 50 people
gender female: 50 people

age group 1: 40 people
age group 2: 35 people
age group 3: 25 people

region 1: 10 people
region 2: 30 people
region 3: 60 people

The target size is 100 people in total and all constraints must be met. My problem now is how to select the “correct” set of people from the database in an efficient way? From all possible combinations of people there might only be one combination that will satisfy all constraints.

Here is a

stratified_sample.php

script that I came up with to solve Jan’s problem. I’m not sure that it actually solved Jan’s problem but I though I would publish it anyway.

<?php

// setup the gender, age, and region arrays with
// appropriate number of sampling codes in each
// array

for($i=0; $i<100; $i++) {

  if ($i<50)
    $gender[$i] = "GM";
  else
    $gender[$i] = "GF";

  if ($i<40)
    $age[$i] = "A1";
  elseif($i<75)
    $age[$i] = "A2";
  else
    $age[$i] = "A3";

  if ($i<10)
    $region[$i] = "R1";
  elseif($i<40)
    $region[$i] = "R2";
  else
    $region[$i] = "R3";

}

// randomize the position of sampling codes in
// each array

shuffle($gender);
shuffle($age);
shuffle($region);

// the sample array contains the sampling codes
// for selecting each sample unit

// to create the sample array loop through the
// gender, age, and region arrays and concatenate
// the sampling codes from each array together
// to create the sampling code for that sample unit

for($i=0; $i<100; $i++) {
  $g = $gender[$i];
  $a = $age[$i];
  $r = $region[$i];
  $sample[$i] = "$g$a$r";
}

// the sample array should meet the sampling
// constraints while meeting the constraints
// of randomization as well

echo "<pre>";
print_r($sample);
echo "</pre>";

?> 

The abbreviated output of the script looks like this:

Array
(
[0] => GFA1R2
[1] => GFA1R3
[2] => GFA1R3
[3] => GFA2R2
[4] => GMA2R1
[5] => GMA2R3
[6] => GFA1R2
[7] => GFA2R2
[8] => GMA2R3
[9] => GFA1R2
[10] => GMA1R2
... snip ...
[90] => GMA1R2
[91] => GMA2R1
[92] => GFA3R3
[93] => GFA2R3
[94] => GMA3R2
[95] => GFA1R3
[96] => GMA1R2
[97] => GFA3R2
[98] => GMA2R3
[99] => GFA1R1
)

For this solution to fully work you would have to code each of your sample elements according to your 3 dimensional coding system (e.g., GFA1R3 meaning “Gender Female”, “Area 1”, “Region 3”) and when you are selecting individuals matching these sampling codes you would randomly select a person matching your sampling code from among the pool of people matching the sampling code.

Longest Common Subsequence

The Longest Common Subsequence algorithm compares two strings and finds the longest subsequence shared by both strings. There are lots of applications, however, two are particularly noteworthy:

  1. Computing the similarity between sequences of genetic material.
  2. Computing differences between files (i.e., unix “diff” command).

So, without further ado, here is an algorithm for computing the Longest Common Subsequence:

<?php
/**
* Port of Sedgewick & Wayne's Longest Common Subsequence algorithm 
* found here:
*
* @see http://www.cs.princeton.edu/introcs/96optimization/LCS.java.html
* @see http://www.cs.princeton.edu/introcs/96optimization/
*
* @author Paul Meagher
* @ported Feb 21, 2008
*
* See also:
*
* @see http://www.ics.uci.edu/~eppstein/161/960229.html
*
* @param string $S1 first string 
* @param string $S2 second string 
* @returns string containing common subsequence or empty string
*/
function string_lcs($S1, $S2) {

  $m = strlen($S1);
  $n = strlen($S2);

  // A[i][j] = length of LCS of S1[i..m] and S2[j..n]
  $A = array();

  // compute length of LCS and all subproblems via dynamic programming
  for ($i = $m-1; $i >= 0; $i--) {
    for ($j = $n-1; $j >= 0; $j--) {
      if ($S1[$i] == $S2[$j])
        $A[$i][$j] = $A[$i+1][$j+1] + 1;
      else 
        $A[$i][$j] = max($A[$i+1][$j], $A[$i][$j+1]);
    }
  }

  // recover LCS itself and print it to standard output
  $i = 0;
  $j = 0;
  $LCS = "";
  while($i < $m && $j < $n) {
    if ($S1[$i] == $S2[$j]) {
      $LCS .= $S1[$i];
      $i++;
      $j++;
    } elseif ($A[$i+1][$j] >= $A[$i][$j+1]) 
      $i++;
    else                                 
      $j++;
  }
  
  return $LCS;

}
  
?>  

Here is a test program with the output displayed in the source code:

<?php

include "string_lcs.php";

$S1 = "abcdefghijk";
$S2 = "ijklmnop";

$subsequence = string_lcs($S1, $S2);
echo $subsequence;

// Output: ijk

?>

I’ve taken a few liberties in my port of Sedgewick and Wayne’s

LCS

class. I reimplemented the

LCS

class as a

string_lcs

function as a class seemed like overkill at this point. I also use the word ”

string_

” as a prefix for the function name. I used this prefix in anticipation of eventually building a library of such string functions (in addition to PHP’s collection of string functions). I also renamed some variables to be more mnemonic (e.g.,

$S1

,

$S2

) or standard (e.g.,

$A

,

$m

,

$n

) and changed the capitalization of variable names to conform with whether they are being treated as a scalar (lowercase) or vector/matrix quantity (uppercase).

Consult some of the links contained in the source to learn more about how the algorithm works and about Dynamic Programming more generally.

Order statistics

Order statistics are statistics derived from data ordered from smallest to largest. I’ve recently come across a nice notation for representing order statistics which I thought deserved a blog entry.

The notation involves putting a subscripted bracket around a positional index. Using this scheme, all the measurements in our ordered sample would be denoted as y[1],…,y[n]. In other words, the brackets around the subscripts tips us off that the elements denoted by these indexed y values are not simply the raw sample values in whatever order they were collected, but rather the sample values ordered from smallest to largest.

As an example of how this notation can be used, consider how we might express the formula for computing the first, second and third quartiles (Q1, Q2, Q3). Recall that Q1 is the value that 25% of our values are less than or equal to. Q2 is the value that 50% of our values are less than or equal to and Q3 is the value that 75% of our values are less than or equal to. Or, using our notation:

Q1 = y[(n+1)/4]

Q2 = y[(n+1)/2]

Q3 = y[3(n+1)/4]

If the subscripts are not integers, we average the two closest order statisitcs to obtain the quartile value.

The minimum value

y[1]

, the three quartiles (

Q1, Q2, Q3

), and the maximum value

y[n]

are often reported together and are called the five number summary. The box-and-whisker plot is a graphical way to depict the five number summary.

As a final example of how our order notation can be used consider the formula for the trimmed mean. In the formula below mk is the trimmed mean with k values trimed from the top and bottom of an ordered list of numbers:

mk = ∑i=k+1 to n-k x [ i ] / (n – 2k)

Here is some PHP code for computing a trimmed mean where we remove the top and bottom 2 values from our computed mean (i.e., k=2):

<?php

function trimmed_mean($X, $k) {
  $n = count($X);
  sort($X, SORT_NUMERIC); 
  for($i=$k; $i < $n-$k; $i++) 
    $sum += $X[$i];
  $mean = $sum / ($n - 2 * $k);
  return $mean;
}


$X = array(55, 15, 20, 1, 2, 25, 50);
echo "Trimmed mean is ".trimmed_mean($X, 2).".";

// Output: Trimmed mean is 20.

?>

The next time you compute a mean you might want to consider computing a trimmed mean using a few different values of k to see how affected by outliers your computed mean is.

On the way to NURBS

NURBS is an acronym for “Non-Uniform Rational B-Spline”. NURBS are used extensively in CAD systems to represent surfaces. I hope to someday understand the math and programming behind NURBS better. Towards that end, I have ported some code that manipulates Bernstein polynomials. Bernstein polynomials unify the math behind Bezier approximation schemes and Spline approximation schemes. NURBS are another approximation scheme which requires that you know something about Bernstein polynomials in order to appreciate the math involved.

The

Bernstein

class below can be used to generate the coordinates needed to draw a curve that interpolates and approximates a set of control points. Vector-based image manipulation programs offer a Bezier tool that allows you to create curves by moving around a set of bounding control points. As you move the curve control points, the shape of the Bezier curve changes to interpolate and approximate the new position of the control points. The class below implements the math required to interpolate and approximate the position of the control points. The math looks like this:

The implementation of this math looks like this:

<?php
/**
* Provides methods to manipulate the Bernstein polynomial.
*
* An nth-degree Berstein polynomial is given by:
*
* B(i,n,u) = n! * u^i * (1-u)^(n-i) / i! * (n-i)!
* with  0 <= i <= n
*
* @author R.P. from OpaleTeam
* @see http://opale.belios.de
* @license LPGL
* @date 05/2002
*
* Ported by Paul Meagher on Jan 20, 2008.
*/
class Bernstein {

  /**
  * Returns the evaluation, for a given value, of a Bernstein
  * polynomal defined by the given arguments.
  *
  * @param int $i 
  * @param int $n the degree of the polynomial
  * @param double $u the value for which the polynomial will be computed
  * @return double the computed value
  */
  public function getValue($i, $n, $u) {
  
    $temp[$n-$i] = 1.0;
    $u1          = 1.0 - $u;

    for ($k = 1; $k <= $n; $k++) 
      for ($j = $n; $j >= $k; $j--) 
        $temp[$j] = $u1 * $temp[$j] + $u * $temp[$j-1];       
    
    return $temp[$n];

  }
  
  /**
  * Returns all Bernstein polynomials evaluations, for a given
  * value, of a Bernstein polynomal defined by the given arguments.
  *
  * @param int $n the degree of the polynomial
  * @param double $u the value for which the polynomial will be computed
  * @return double[], the computed value
  */
  public function getAllValues($n, $u) {

    $b[0] = 1.0;
    $u1   = 1.0 - $u;

    for ($i = 1; $i <= $n; $i++) {
      $saved = 0.0;
      for ($k = 0; $k < $i; $k++) {
        $temp  = $b[$k];
        $b[$k] = $saved + $u1 * $temp;
        $saved = $u * $temp;
      }
      $b[$i] = $saved;
    }
    
    return $b;

  }  
  

}

?>

The

bernstein_test.php

example below illustrates usage. In this example, we use the

Bernstein

class to find the coefficients to multiply the

$X[$i]

(i.e.,

$X = array(1, 2, 4, 3)

) and

$Y[$i]

coordinates (i.e.,

$Y = array(1, 3, 3, 1)

) of 4 control points. After we separately multiply the

$X[$i]

and

$Y[$i]

terms by the Bernstein cofficients we get a new point at

$t

that approximates the control points.

The setup value of $n is equal to 1 minus the number of control points. $T is an array of values in the range [0,1] that identify the left (0) to right (1) positions along the approximating and interpolating curve where we want to compute it’s coordinates.

<?php
/**
* Testing Bernstein output against worked example in:
*
* Rogers, David F. An Introduction to NURBS With Historical Perspective.  
* 2001. Morgan Kaufmann, San Francisco. pp. 22-24
*/

include "Bernstein.php";

$berstein = new Bernstein;

$n = 3;

$X = array(1, 2, 4, 3);
$Y = array(1, 3, 3, 1);

?>
<table border='1' cellspacing='1' cellpadding='2'>
  <tr>
    <th>t</th>
    <th>B<sub>3,0</sub></th>
    <th>B<sub>3,1</sub></th>
    <th>B<sub>3,2</sub></th>
    <th>B<sub>3,3</sub></th>
    <th>P(t)</th>   
  </tr>
  <?php
  $T = array(0, 0.15, 0.35, 0.50, 0.65, 0.85, 1);  
  foreach ($T as $t) {
    $B = $berstein->getAllValues($n, $t);
    ?>
    <tr>
      <td align='center'><?php echo $t ?></td>
      <?php
      $i=0;
      $x=0.0;
      $y=0.0;     
      foreach ($B as $b) {
        ?>
        <td align='center'><?php echo $b ?></td>
        <?php
        $x += $b *$X[$i];
        $y += $b *$Y[$i];       
        $i++;       
      }
      ?>
      <td align='center'><?php echo "($x, $y)"; ?></td>
    </tr>
    <?php
  } 
  ?>
</table>

The test script above produces the following HTML table as output:

t B3,0 B3,1 B3,2 B3,3 P(t)
0 1 0 0 0 (1, 1)
0.15 0.614125 0.325125 0.057375 0.003375 (1.504, 1.765)
0.35 0.274625 0.443625 0.238875 0.042875 (2.246, 2.365)
0.5 0.125 0.375 0.375 0.125 (2.75, 2.5)
0.65 0.042875 0.238875 0.443625 0.274625 (3.119, 2.365)
0.85 0.003375 0.057375 0.325125 0.614125 (3.261, 1.765)
1 0 0 0 1 (3, 1)

The

P(t)

column above contains a set of points which we can graph that will approximate the set of control points a user has specified for the curve they want drawn. The x coordinate of each point was obtained by multiplying the 4 Berstein coefficients by the 4 x coordinates. Similarly, the y coordinate of each point was obtained by multiplying the 4 Bernstein coefficients by the 4 y coordinates.

Population sampling

Below is a simple but useful class for generating a population sample:

<?php
/**
* Generates a random sample (with or without replacement) 
* of size n from population array.
*
* @see http://www.math.uah.edu/stat/objects/distributions/Functions.xhtml
*/
class Population {

  const WITHOUT_REPLACEMENT=0;
  const WITH_REPLACEMENT=1;

  function random($min=0, $max=1) {
    return ($min+lcg_value()*(abs($max-$min)));
  }

  /**
  * This method computes a sample of a specified size from a specified population
  * and of a specified type (with or without replacement).
  * @param int[] $p  the population
  * @param int   $n  the sample size
  * @param int   $t  the type (0 without replacement, 1 with replacement);
  * @return int $s 
  */
  public function getSample($p, $n, $t){
    $m = count($p);
    if ($n < 1) $n = 1; elseif ($n > $m) $n = $m;
    //Define the sample
    if ($t == self::WITH_REPLACEMENT){
      for ($i = 0; $i < $n; $i++){
        $u = (int)($m * $this->random());
        $s[$i] = $p[$u];
      }
    } else{
      for ($i=0; $i < $n; $i++){
        //Select a random index from 0 to m - i - 1;
        $k = $m - $i;
        $u = (int)($k * $this->random());
        //Define the sample element
        $s[$i] = $p[$u];
        // Interchange the sampled element p[u] with p[k - 1], at the end of the
        // population so that it will not be sampled again.
        $temp    = $p[$k-1];
        $p[$k-1] = $p[$u];
        $p[$u]   = $temp;
      }
    }
    return $s;
  }

}

?>

Here is some code to demonstrate usage:

<?php 

include "Population.php";

$p = range(1,9);
$n = 3;
$t = 0;

$pop = new Population;
$s   = $pop->getSample($p, $n, $t);

echo "<pre>";
print_r($s);
echo "</pre>";

?>

Here is what the output looks like:

Array
(
[0] => 2
[1] => 9
[2] => 4
)

Perhaps you will find a use for this sampler some day…

Monte Carlo Integration

Monte carlo integration is a way to find the area under a curve using random numbers. The program below provides a nice introductory example of a monte carlo method and how it can be used to solve a calculus problem.

<?php
/**
* Approximates area of the region under the graph of a
* monotonic function and above the x-axis beween a and b.
*
* Adaptation of Monte Carlo Method program by James M. Sconyers
* found in:
*
* Larson, Hostetler, Edwards (2006). Calculus I with Precalculus.
* 2nd Edition. Houghton Mifflin Co, Boston.  p. 490
*/
class MonteCarlo_Integration {

  /**
  * @see http://ca.php.net/manual/en/function.mt-rand.php#75793
  */
  function random_float($min, $max) {
    return ($min+lcg_value()*(abs($max-$min)));
  }
  
  /**
  * Compute area under the curve using monte carlo method.
  * 
  * @param object $f function object
  * @param float $a lower limit
  * @param float $b upper limit
  * @param int $n number of samples
  * @return float area under the curve
  */
  function integrate($f, $a, $b, $n) {
  
    $p = 0;
  
    if ($f->valueAt($a) > $f->valueAt($b))
      $ymax = $f->valueAt($a);
    else 
      $ymax = $f->valueAt($b);
    
    for ($i=1; $i < $n; $i++) {
      $x = $a + ($b - $a) * $this->random_float(0, 1);
      $y = $ymax * $this->random_float(0, 1);
      if ($y < $f->valueAt($x)) 
        $p = $p+1;
    }
     
    $area = ($p/$n)*($b-$a)*$ymax;
    
    return $area;
  
  }

}   

?>    

Here is a program to test the

MonteCarlo_Integration.php

class:

<?php

include "MonteCarlo_Integration.php";

class F {    
    function valueAt($x) {
    return pow($x, 2);
  }
}


$f = new F;
$a = 0;
$b = 2;
$n = 10000;

$mc   = new MonteCarlo_Integration;
$area = $mc->integrate($f, $a, $b, $n);

echo "Approximate Area: $area";

?> 

The output of one execution of the program is:

Approximate Area: 2.6632

The exact answer is 8/3.

One programming project would involve histogramming and summarizing the area estimates produced by the above class where

$n

, the number of samples, is varied. Doing so would give you a feel for how variable the estimates are with different sample sizes and how the monte carlo estimates are distributed. A project like this might offer some insight into more advanced monte carlo applications.