Vous êtes sur la page 1sur 4

James

Lamb

Computer Programming and Numerical Methods Assessed Problems



For the longer assessed problems my first task was to find the value of using
Monte-Carlo integration of a circle within a square. Monet-Carlo integration is a
numerical method of evaluating an integral. In one dimension, it takes a sample of
random points over an area containing a function. It then takes the ratio of the
number of points under the function to the total number of points, and multiplies it
by the area the points are sampled over. This gives an estimate to the total area
below the function and hence the value of the integral.
1

In order to get an estimate to the value of then the
0.5
integral of a circle of radius 1 can be taken, as the area of
this circle is . The function for a circle is = ! + ! . X
0
and y coordinates are produced by a random number
-1 -0.5
0
0.5
1
generator in the code, giving values between 0 and 1. To
-0.5
get values that cover the area of the square, these are
multiplied by 2, then 1 is subtracted to give values
-1
between -1 and 1. These are then compared to the
function to see whether they lie inside or outside of the circle. If ! + ! is greater
than r (where r=1) then they lie outside, and if it is less than or equal to r they lie
inside. The total count of the number of points within the function is given by the
variable ratio in the code, and for every value of ! + ! 1, 1 is added to the
value of ratio. Then the final value of ratio divided by the total number of points
generated multiplied by the area of the square (2x2=4) gives the estimate of .

The random numbers are generated using functions written into fortran. The
random number generator is initiated by calling the sub program RANDOM_SEED.
Now the subprogram RANDOM_NUMBER can be called to generate a random
number. The problem with this is that each time the program is run the random
numbers generated are exactly the same, so will not be truly random. In order to
compensate for this, the code uses the system clock to assign a value for the initial
seed. As the clock is constantly changing it generates a different initial seed each
time the program is run, and therefore a new set of random numbers.

Clearly the more random points you generate the more accurate the estimate of the
integral will be, as the ratio will better represent the area under the function. The
next task was to see how the value of the estimate changes with the total number of
points (N). The first program asks you to input N at the beginning, and it was seen
that results gets closer to the larger the value of N. The calculation took longer as
N increased however, so the CPU_TIME sub program was used to time the
calculation to help compare.

The second program instead takes a starting value of N=10, and then runs through
the same algorithm as the first program 30 times, doubling N each time. The graph
below shows how the estimate changes, converging towards the red line () as N
increases.

James Lamb
3.5

Value of Estimate

3.3
3.1
2.9
2.7
2.5
2.3
10

1000

100000

10000000

1E+09

log[N]



Zooming in on the values above 10,000,000 shows a similar convergence pattern,
just over a smaller range for the values of the estimate, and by 108<N<109 we know
to 4 decimal places (3.1416).

3.144

Value of Estimate

3.1435
3.143
3.1425
3.142
3.1415
3.141
3.1405
1000000

10000000

100000000

1E+09

1E+10

log[N]



The next part of the project involved modifying this code so it can be used on an
integral between specified limits, in both one and two dimensions. The one-
dimensional code was developed first, as described below, and then this was further
modified to allow two-dimensional integrals to be calculated.

The first modification was to allow the user to input the limits the integral is
calculated between, a for the lower limit and b for the upper. This was done in the
same way as reading the users input for N. When calculating , because = ! +

James Lamb
! then r is always positive for any value of x or y as they are both squared. In reality
a function can be negative as well. When calculating the net integral, then the value
should be the area above y=0 minus the area below y=0. Therefore I calculate two
integrals, int_plus for the total area above y=0 and int_minus for the total area
below y=0. This means I need to calculate N_plus and ratio_plus for the total number
of points and the number of points within the function for y>0, and similarly
N_minus and ratio_minus for y<0.

These then need to be multiplied by the area that contains the function above and
below y=0. We have the width of the rectangles as specified by a and b, but we need
the heights. To do this I sample 20 points along the function and determine the
maximum and minimum values of the function within the specified limits. As this
cannot definitely give the exact max/minimum, I multiply both by 2 to find an area
that completely contains the function. Although this is still not certain to contain the
whole function, for most applications it should work. The area above the curve is
then given by (b-a)*y_max, and below by (b-a)*y_min. If the minimum value is above
y=0, then y_min must be set to 0 so the area encloses all values above y=0, similarly
if y_max is below 0 then it must be set to 0 for the same reasoning.

The random number generator works in exactly the same way as for the program
calculating . To get the range of x values specified by the limits then the random
number is multiplied by (b-a) and then a is added. To get the range of y values that
contain the function then the random number is multiplied by (y_max-y_min) and
then y_min is added. Then for each x value the function is calculated, and a series of
if statements decides whether ratio_plus or ratio_minus is increased, with N_plus or
N_minus increasing each time the algorithm is run.

The values of the area above and below the curves is then evaluated, and the net
integral then calculated as the area above - area below: integral=int_plus-int_minus.
This was done for various types of functions to test its applicability, and done for 3
values of N to see how the number of points effects the result. I have tried to
incorporate the most common functions we would potentially use; quadratic (which
is used to represent any polynomial type), exponential, logarithmic, Gaussian and
sinusoidal. The codes are exactly the same just with different equations. The only
difference is in the logarithmic code, where there is a condition on the possible
values for the limits so that the log of a negative number or 0 does not occur. This
would again be different if the equation contained negative coefficients inside the
log, but the adjustments to be made would be simple. The results are as follows:

Limits
Number of steps
Function
a
b
10000
1000000
100000000
Mathematica
x^2 + 2x + 1
-3 3 23.654400
24.008640
24.005002
24
e^(2x + 1)
-2 2 75.275154
74.530714
74.241391
74.1817
2ln(x^2+4)
1
5 20.392344
20.269558
20.266000
20.2672
e^[-((x - 1)^2)/2] -2 4
2.461200
2.502924
2.500104
2.49986
4sin((x-2)^2+2)
-3 3
4.189269
4.121586
4.120763
4.11871

James Lamb
These are all compared to the value Mathematica gives for the integral. As with as
N increases the value gets more accurate.

This code was then further modified to allow integration in two dimensions. The user
is able to enter the limits for both the x and y axis now. The value of the function is
evaluated over the area enclosed by these limits to find z_max and z_min similarly to
the one-dimensional code. These are then doubled or set to 0 as before.

In the algorithm for the calculation of int_plus and int_minus, an extra random
number is generated for the z coordinate. This is the compared to the function at the
same x and y coordinates to see whether ratio_plus or ratio_minus is increased,
again with N_plus or N_minus increasing every time. Int_plus and int_minus are
calculated slightly differently, as the ratio needs to be multiplied by the volume the
random points are sampled from - (b-a)*(d-c)*z_max/min*ratio/N.

The integral is calculated in the same way as the one-dinemsional code though
(integral=int_plus-int_minus). Just as before this was then tested for a range of
functions with varying N. Again, the only difference was the equation used in the
calculations and the condition preventing the log of a negative number or 0. The
results are as follows:

Limits
Number of steps
Function
a b c d
10000
1000000
100000000 Mathematica
x^2 + 2y^2 - 7xy + x + 1 -3 3 -3 3 312.130679 358.742575 360.026173
360
2e^(-2x + y) + 2
-1 1 -1 1 24.189328 24.930864 25.042368
25.0492
ln(3x + y + 2)
1 5 1 5 40.900674 41.688618 41.639042
41.6382
E^(-((x-3)^2 + (y-1)^2)/5) -3 3 -3 3 7.156872
7.016393
7.003003
6.99955
-3sin(4x + y^2)
-3 3 -3 3 0.843718
1.156977
1.235367
1.24522

As can be seen both sets of results clearly show that as N increases the value gets
closer to the real integral, and by 108 the values are very close to those obtained
using Mathematica.

The submitted programs are named as follows:

Pi.f90 this is the first part of the project which is just the program to evaluate pi.

PiChanges.f90 this is the modified version of Pi.f90 which does the same
calculation for an increasing value of N.

1D-log.f90 this is the one-dimensional integration code. The logarithmic one is
chosen as this is the only one to have the constraint on the limits input by the user.
The other codes are exactly the same just with different equations in the calculations
within the program and no constraint on the limits.

2D_log.f90 this is the two-dimensional version, again the log code is submitted due
to the addition code in order to apply the constraint.

Vous aimerez peut-être aussi