Home : Map : Chapter 7 : Java : Tech : Physics
Monte Carlo Integration
JavaTech
Course Map
Chapter 7

Introduction
Event Overview
Event Processing
Button Events
  Demo 1
 Demo 2
Mouse Events
  Demo3

More Components
  Demo 4  Demo 5
  Demo 6  Demo 7

LayoutManagers-1
  Demo 8     Demo 9
  Demo 10  Demo 11
  Demo 12

LayoutManagers-2
  Demo 13  Demo 14
  Demo 15  Demo 16
  Demo 17

Inner Classes
Anonymous Class
Adapter Classes
  Demo 18  Demo 19
Frames & Menus
  Demo 20  Demo 21
Exercises

    Supplements
AWT Components
  Button
     Demo 1
  Canvas
     Demo 2
  AWT GUI Demo
     Demo 3
Swing Dialogs
JOptionPane Dialog
  Demo 1
JDialog
  Demo 2
UI Enhancement: P1
  Demo 1   Demo 2
  Demo 3

UI Enhancement: P2
  Demo 1
     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

The Monte Carlo (MC) approach to integration uses random sampling to obtain a statistical estimate of the integral. It provides a powerful approach when tackling integration of complicated functions in multidimensional spaces.

The MC integral of function f over a volume V goes as [Press]

             

where <f> equals the mean of the function at N randomly sampled points:

             

The standard deviation provides an error estimate:

             

where

               

We can apply this to integration of a function of a single variable as follows:

              

For the MC the mean <f> comes from randomly selected xi rather than a sequence. Nevertheless, for an increasing number of random points the mean values should agree within a decreasingly small error.

Another Monte Carlo approach to the same problem is to view the plot of f(xi)vs xi as a 2-D box of width L and a height h greater than or equal to the largest value of f(xi). (See the demonstration program below.) A given number of points are randomly sampled over the area. The total box area (L*h) times the ratio of the number of points below the f(xi) curve to the total number of points thrown provides an approximation to the integrated area of the function.

We can relate this to the above calculation if we let

    f(x) = frac(x)*h

where frac(x)is the fraction of the box height that the function takes at point x. Then the above integral approximation goes as

   L<f> = L <frac> * h = V * <frac>

where the average fractional value should in the limit of increasing samples equal the fractional area calculated from the scatter point distribution method.

The demonstration program below illustrates this type of integration of a 1-D function. We use a subclass of PlotFormat to display a function and the scatter of points. An interface called Function is used to provide a general type for creating different kinds of functions.

MCPlotApplet.java - integrates 1-D functions using a Monte Carlo approach. The user generates different functions via the buttons.

+ New classes
MCPanel.java - subclass of PlotPanel that draws a function and the scatter of points used for the MC integration. The function plot is created with a Polygon object. By wrapping the points around the boundary we can use the contains() function in Polygon to obtain the number of points below the function curve.

SinFunc.java - function used to generated the curve to integrate. Implements the Function interface.

Function.java - interface to allow different types of functions to be used for the MC demo.

+ Previous classes:
Chapter 6:Tech: PlotPanel.java, PlotFormat.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;

/**
  * Plot a function and integrate it with the Monte Carlo
  * method.
  *
  * The applet uses the MCPanel subclass of PlotPanel for the graphics
  * output.  Includes "Go","Clear", and "Exit"
  * buttons to initiate processing, clear the text area, and exit
  * when in standalone mode. A TextField displays the integral
  * value.
  *
  * The function comes from an implementation of the Function
  * interface.
  *
  * This program will run as an applet in a browser or inside
  * an application frame.
  *
**/
public class MCPlotApplet extends JApplet
             implements ActionListener
{

  MCPanel fMcPanel;

  // A text field for display of the integral value.
  JTextField fTextField;

  // Flag for whether the applet is in a browser
  // or running via the main () below.
  boolean fInBrowser = true;

  //Buttons
  JButton fGoButton;
  JButton fClearButton;
  JButton fExitButton;

  // Upper and lower values of the plot.
  double fLoX=1.0;
  double fHiX=10.0;
  double fLoY=-1.0;
  double fHiY=10.0;

  // An implementation of the Function interface provides
  // the values of the given function.
  Function fFunc;

  // Settings for the function.
  double fOffset = 2.0;

  // Use default of 500 random points for the MC integration.
  int fNumPoints = 500;

  /** Set up the interface. **/
  public void init () {

    JPanel panel = new JPanel (new BorderLayout ());

    fFunc = new SinFunc ();
    fFunc.setOffset (fOffset);

    //  an instance of MCPanel
    fMcPanel = new MCPanel (fFunc, fHiY, fHiX,
                             fLoY, fLoX);

    panel.add (fMcPanel,"Center");

    // Use a textfield for an input parameter.
    fTextField = new JTextField ("Integral value", 15);
    // Only used here for output
    fTextField.setEditable (false);

    // If return hit after entering text, the
    // actionPerformed will be invoked.
    fTextField.addActionListener (this);

    fGoButton = new JButton ("Go");
    fGoButton.addActionListener (this);

    fClearButton = new JButton ("Clear");
    fClearButton.addActionListener (this);

    fExitButton = new JButton ("Exit");
    fExitButton.addActionListener (this);

    JPanel control_panel = new JPanel ();

    control_panel.add (fTextField);
    control_panel.add (fGoButton);
    control_panel.add (fClearButton);
    control_panel.add (fExitButton);

    panel.add (control_panel,"South");

    // Add text area with scrolling to the contentPane.
    add (panel);

    // The exit button only works in the application
    // so disable it so the user is not confused.
    if (fInBrowser) fExitButton.setEnabled (false);

  } // init

  /** Use buttons to run the integrations. **/
  public void actionPerformed (ActionEvent e) {
    Object source = e.getSource ();
    if (source == fGoButton || source == fTextField ) {
      // In general it is better to spin off
      // extensive calculations into a new thread
      // rather than in an event thread. However,
      // we haven't reached the thread chapter yet.
      integrateFunction ();
    }
    else if (source == fClearButton) {
      fMcPanel.setDrawState (MCPanel.DRAW_CLEAR);
      fMcPanel.repaint ();

    }
    else if (!fInBrowser)
      System.exit (0);

  } // actionPerformed

  /** Create a new function and use the MC method to
    * integrate it. Most of the work is done in the
    * the MCPanel class.
   **/
  void integrateFunction () {
    fMcPanel.setDrawState (MCPanel.DRAW_POLY);

    // Create a new function and plot it.
    // Modify the offset each time so that
    // the function is in the mid-range section.
    fOffset =
      Math.random () * 0.8* (fHiY - fLoY) + fLoY + 1.0 ;
    fFunc.setOffset (fOffset);

    fMcPanel.makeFunction ();

    // Now create the scatter of random points and
    // calculate the integral the MC way.
    double integral = fMcPanel.makePoints (fNumPoints);
    String str =
       PlotFormat.getFormatted ( integral, 1000.0 ,3);
    fTextField.setText ("Integral = " + str);
    repaint ();
  } // integrateFunction


  public static void main (String[] args) {

    int frame_width=450;
    int frame_height=300;

    // *** Modify applet subclass name to that of the program
    MCPlotApplet applet = new MCPlotApplet ();
    applet.fInBrowser = false;
    applet.init ();

    // Following anonymous class used to close window & exit program
    JFrame f = new JFrame ("Demo");
    f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    // Add applet to the frame
    f.getContentPane ().add ( applet);
    f.setSize (new Dimension (frame_width,frame_height));
    f.setVisible (true);
  } // main

} // MCPlotApplet

/** Use a sine function class implementing the Function interface. */
class SinFunc implements Function
{
  double fOffset = 0.0;
  public double value (double x) {
    return Math.sin(x)+ offset;
  }

  public void setOffset(double o) {
    offset = o;
  }
} // SinFunc

/** Interface to use for functions. */
public interface Function
{
   // Return a double value
   public double value (double x);
   public void setOffset (double o);
} // Function

import java.awt.*;
import javax.swing.*;

/**
  *  Draws a 1-D function as a polygon and the scatter of
  *  random points of the Monte Carlo using PlotPanel superclass.
  * Does the calculation of the integral using the Polygon's
  *  contains () method to find the number of points below
  *  the function area.
 **/
public class MCPanel extends PlotPanel
{
  String fTitle = "Monte Carlo Plot";
  String fXLabel= "Y vs X";

  Polygon fPoly;

  // Constants to indicate type of drawing
  final static int DRAW_POLY = 1;
  final static int DRAW_PTS  = 2;
  final static int DRAW_CLEAR= 3;

  int fDrawState = DRAW_CLEAR;

  int [][] fRanPoints;
  int fNumRanPoints = 0;

  // Convert from the screen coordinates to the
  // scale of the variables.
  double fYConvert = 0.0;
  double fXConvert = 0.0;

  // Symbol types for plotting the function
  final static int SOLID = 0;
  // Student can add other line types such as
  // dotted and dashed
  int fLineType = 0;

  // These numbers determine the axes ranges.
  double fYDataMax = 1.0;
  double fXDataMax = 1.0;
  double fYDataMin = 0.0;
  double fXDataMin = 0.0;

  // Default numbers to use for plotting axes scale values
  double [] fXScaleValue;
  double [] fYScaleValue;
  int fNumYScaleValues = 5;
  int fNumXScaleValues = 5;

  // Instance of the interface Function
  Function fFunc;

  /**
    * Passes an instance of Function and the limits
    * to the plot.
   **/
  public MCPanel (Function f,
                   double yDataMax, double xDataMax,
                   double yDataMin, double xDataMin){
      fFunc = f;

      fYDataMax = yDataMax;
      fXDataMax = xDataMax;

      fYDataMin = yDataMin;
      fXDataMin = xDataMin;

      getScaling ();
  } // ctor

  /** Reset the function and the limits. **/
  public void setFunction (Function f,
                   double yDataMax, double xDataMax,
                   double yDataMin, double xDataMin) {

    fFunc = f;

    fYDataMax = yDataMax;
    fXDataMax = xDataMax;

    fYDataMin = yDataMin;
    fXDataMin = xDataMin;

    getScaling ();

    repaint ();
  } // setFunction


  /**
    *  Get the values for the scaling numbers on
    *  the plot axes.
   **/
  void getScaling () {
    fYScaleValue = new double[fNumYScaleValues];
    // Use lowest value of 0;
    fYScaleValue[0] = fYDataMin;
    fYScaleValue[fNumYScaleValues-1] = fYDataMax;

    // Then calculate the difference between the values
    double range = fYScaleValue[fNumYScaleValues-1]
                        - fYScaleValue[0];
    double del = range/ (fNumYScaleValues-1);

    // Now set the intermediate scale values.
    for (int i=1; i <  (fNumYScaleValues-1); i++) {
        fYScaleValue[i] = i*del + fYScaleValue[0];
    }

    fXScaleValue = new double[fNumXScaleValues];
      // First get the low and high values;
    fXScaleValue[0] = fXDataMin;
    fXScaleValue[fNumXScaleValues-1] = fXDataMax;

    // Then calculate the difference between the values
    range = fXScaleValue[fNumXScaleValues-1] - fXScaleValue[0];
    del = range/ (fNumXScaleValues-1);

    // Now set the intermediate scale values.
    for (int i=1; i < (fNumXScaleValues-1); i++) {
        fXScaleValue[i] = i*del + fXScaleValue[0];
    }

  } // getScaling

  /** Set switch for draw state. **/
  public void setDrawState (int state) {
     fDrawState = state;
  }

  /**  Find the points used to plot the function. We wrap the
    *  points back around the boundary so that we can use the
    *  contains () method in the Polygon class to find the
    *  number of points below the function curve.  (See the makePoints
    * method.)
   **/
  void makeFunction () {
    // Need conversion factor from data scale to pixel scale
    fYConvert = fFrameHeight/ (fYDataMax - fYDataMin);
    fXConvert = fFrameWidth / (fXDataMax - fXDataMin);

    // Want to draw the plot for the width of the
    // frame plus points to wrap around the lower boundary
    // and back to the first point.
    int numPoints = fFrameWidth + 4;

    int [] x = new int[numPoints];
    int [] y = new int[numPoints];

    int maxY = fFrameY + fFrameHeight;

    // Distance between each pixel
    double dx =  (fXDataMax - fXDataMin)/fFrameWidth;

    // Get the function values to create a polygon
    for (int i=0; i < numPoints-3; i++) {
      double xFunc =  fXConvert* (dx * i);
      x[i] =  (int)xFunc + fFrameX;

      double yFunc = fYConvert * fFunc.value (dx * i + fXDataMin);
      y[i] = maxY -  (int)yFunc;

      if (y[i] < fFrameY) y[i] = fFrameY;
      else
      if (y[i] > maxY) y[i] = maxY;
    }

    // Bottom right corner
    x[numPoints-3] = fFrameX + fFrameWidth;
    y[numPoints-3] = maxY;
    // Bottom left corner
    x[numPoints-2] = fFrameX ;
    y[numPoints-2] = maxY;
    // Back to first point.
    x[numPoints-1] = x[0] ;
    y[numPoints-1] = y[0];

    // Create a polygon object from these point arrays
    fPoly = new Polygon (x,y,numPoints);

  } // makeFunction


  /**  Create the distribution of random points
    *  and calculate the MC integral from the
    *  fraction of the points under the function
    * curve. Use the Polygon class's contains () method.
   **/
  double makePoints (int nPoints) {
    fNumRanPoints = nPoints;

    // Could thrown an exception here but instead
    // return negative value as a flag.
    if (fNumRanPoints <= 0 ) return -1.0 ;

    fRanPoints = new int[fNumRanPoints][2];
    int numInside = 0;

    setDrawState (MCPanel.DRAW_PTS);

    // Make a scatter of points for the MC integration.
    for (int i=0; i< fNumRanPoints; i++) {
      fRanPoints[i][0]=  (int) (Math.random () * fFrameWidth) + fFrameX;
      fRanPoints[i][1]= fFrameY+fFrameHeight -
                          (int) (Math.random () * fFrameHeight) ;

      // Take advantage of the contains () method in Polygon
      // to get the number of points below the function curve.
      if (fPoly.contains ( fRanPoints[i][0], fRanPoints[i][1]) )
          numInside++;
    }

    double fraction =  (double)numInside/ (double)fNumRanPoints;
    double integral = fraction *  (fYDataMax - fYDataMin)* (fXDataMax - fXDataMin);

    repaint ();

    return integral;

  } // makePoints

  /**
    * Draw the function and the scale values. When flag set,
    *  also draw the random points.
   **/
  void paintContents (Graphics g) {
    // No contents or scale values draw when clear flag set.
    if (fDrawState == DRAW_CLEAR) return;

    // Then pass the polygon object for drawing
    g.drawPolygon (fPoly);

    // Draw the numbers along the axes
    drawAxesNumbers (g, fXScaleValue, fYScaleValue);

    if (fDrawState == DRAW_PTS) {
      for (int i=0; i < fNumRanPoints; i++)  {
         g.fillOval (fRanPoints[i][0],fRanPoints[i][1],2,2);
      }
    }

  } // paintContents

  /** Methods overriding those in PlotPanel. **/
  String getTitle ()
  {  return fTitle;}

  String getXLabel ()
  {  return fXLabel;}

  /** Additional methods for setting the title and label. **/
  void setTitle (String title)
  {  fTitle = title;}

  /** Set label along horizontal axis. **/
  void setXLabel (String fXLabel)
  {  this.fXLabel = fXLabel;}

  /** Set the type of line. **/
  void setLineType (int type)  {
    if (type < 0 || type > 0) return;
    fLineType = type;
  }

} // MCPanel

    

 

Similar approaches can work for multi-dimensional integrations. Note that the bounding volume need not be "square" as in the above box example but needs only to exceed the function at all points. In fact, it is best if the bounding volume just slightly exceeds the function since only points inside the function provide "information content" and serve to reduce the error estimate.

Monte Carlo integrations provide powerful tools for many physics analysis situations, especially "event" type phenomena such as in particle scattering studies. We will discuss in Chapter 11 : Physics how Monte Carlo integration with simulations of the particle scattering and the detectors provide the cross sections.

References & Web Resources

Latest update: Feb.16.2003

           Tech
Histogram UI
  Demo 1
Probablity Distrib.
  Demo 2 Demo 3
RejectionMethod
Histogram Stats
  Demo 4
Exercises

           Physics
Sim & Randomness
Custom Prob. Dist.
   Demo 1
Histogram Dist.
   Demo 2
Monte Carlo
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.