
A Monte Carlo Simulation is performed to try and calculate the value of pi. To perform the simulation, a regular 2D graph was created with a circle plotted in it. One thousand random hits are taken at the graph. Hits that land inside the circle are used in the calculation, while hits outside the circle are not.
If you have Origin or the Origin Evaluation/Demo, open the sample project called "VAlue of Pi.OPJ" in the \Origin\Samples\Programming\Value of Pi\ subfolder. Alternatively, download the example in ZIP form, extract its contents, and open Value of Pi.OPJ. The project contains a graph with a button on it that allows you to start the demonstration. Additional instructions are provided in a Notes window.
When you look at the project and the C code (PDF) some things to notice are that:
In the Start Button
- The function call is made inside the Start button
ValueOfPi();
- The text label that indicates the final value of pi is updated after that:
page.active=1;
txtPi.text$= \g(p)\-(simulation) = $(data1_pival[10000]);
In the C Code
- Dataset objects are mapped to Origin worksheet columns
Dataset dsInX("Data1_InX"); // holds x pos of hits inside circle
Dataset dsInY("Data1_InY"); // holds y pos of hits inside circle
Dataset dsOutX("Data1_OutX"); // holds x pos of hits outside circle
Dataset dsOutY("Data1_OutY"); // holds y pos of hits outside circle
Dataset dsNThrow("Data1_nThrow"); // total hits
Dataset dsPiVal("Data1_PiVal"); // value of pi from hit ratio
- The first "hit" on the graph is generated using a timer and a random number generator
uint wTick =GetTickCount();
double dR = rnd(wTick);
- Subsequent hits are generated using a 'for' loop and the random number generator. A calculation is performed to determine the distance each hit is away from the origin (X=0, Y=0). This distance indicates whether or not the hit was inside or outside the circle. If inside, a variable called iCircle is incremented. After the hit determination is made, the value of pi is calculated.
for(int iTotal=1; iTotal<10001; iTotal++)
{
// generate x,y random pair between -1 and +1
double dRx = 1 - 2 * rnd();
double dRy = 1 - 2 * rnd();
// compute distance from origin to determine if within circle
double dDist = sqrt( dRx^2 + dRy^2 );
if(dDist <= 1) // is inside circle
{
iCircle += 1;
dsInX.SetSize(iCircle); // plot point inside circle
dsInY.SetSize(iCircle);
dsInX[iCircle - 1] = dRx;
dsInY[iCircle - 1] = dRy;
}
else // is not inside circle
{
dsOutX.SetSize(iTotal - iCircle); // plot point outside circle
dsOutY.SetSize(iTotal - iCircle);
dsOutX[iTotal-iCircle - 1] = dRx;
dsOutY[iTotal-iCircle - 1] = dRy;
}
// now compute pi
double dPiValue = 4.0 * iCircle / iTotal;
// update datasets
dsNThrow.SetSize(iTotal);
dsPiVal.SetSize(iTotal);
dsNThrow[iTotal - 1] = iTotal;
dsPiVal[iTotal - 1] = dPiValue;
// update both graphs periodically based on the value of the number of shots
int iPlot = log10(iTotal);
iPlot = 10^iPlot;
if ( (iTotal % iPlot) == 0) LT_execute("page.active=1; plot -l; page.active=2; plot -l;");
}