Bir eğrinin altında yer alan alanı istatiksel bir yöntemle hesaplamak için Monte Carlo integral algoritması kullanılabilir. Bu algoritma ile, rasgele üretilen N adet noktanın kaç tanesinin fonksiyon eğrisinin altında yer aldığına bakılır. Rasgele seçilen noktaların yüzde kaçının eğri altında yer aldığına bakılarak, yaklaşık olarak alan hesabı yapılabilir.
Algoritma adımları aşağıdaki şekilde sıralanabilir:
- Fonksiyonun verilen aralıktaki tüm değerlerini içine alacak şekilde bir dikdörtgen belirlenir.
- Bu dörtgen içerisinde, N adet nokta rastgele olarak oluşturulur.
- Bu noktaların ne kadarının, fonksiyonun belirlediği alanın altında olduğuna bakılır.
- N değerinin, eğri altında olan nokta sayısına oranı, bize yaklaşık olarak, dikdörtgenin alanın fonksiyon eğrisi alanına oranını verecektir.
Aşağıda, Monte Carlo algoritmasının C# dilinde yazılmış kaynak kodu yer almaktadır.
using System;
namespace SG.Algoritma
{
partial class MonteCarlo
{
// Deneme adet
public uint N { get; set; }
public MonteCarlo(uint n)
{
if (n == 0)
{
throw new ArgumentException(nameof(N));
}
this.N = n;
}
/// <summary>
/// Verilen fonksiyon eğrisinin altında bulunan alan hesaplanıyor.
/// </summary>
/// <param name="func">Fonksiyon</param>
/// <param name="x1">X ekseni üzerinde, aralık başlangıcı</param>
/// <param name="x2">Aralık bitiş</param>
public double CalculateArea(Func<double, double> func, double x1, double x2)
{
// Verilen aralıkta, fonksiyonun aldığı minimum ve maksimum değerler
double min;
double max;
// Fonksiyonun minimum ve maksimum değeri hesaplanıyor
this.CalculateMinMaxValue(func, x1, x2, out min, out max);
// Denemelerden kaç tanesi, fonksiyon eğrisinin altında
var hit = 0;
// Rasgele sayı üretici
var rand = new Random();
// N adet dememe yap
for (int i = 0; i < this.N; i++)
{
// Dikdörtgen içerisinde rasgele bir nokta üret
var x = x1 + (x2 - x1) * rand.NextDouble();
var y = min + (max - min) * rand.NextDouble();
// Rasgele seçilen nokta ve fonksiyonun değeri, eğrinin aynı tarafındaysa. (İki negatif sayının çarpımı pozitiftir)
if (func(x) * y > 0)
{
// Fonksiyon değeri pozitifse
if (func(x) > 0)
{
// Rasgele üretilen y değeri fonsiyon eğrisinin altındaysa
if (func(x) > y) hit++;
}
else
{
// Rasgele üretilen y değeri fonsiyon eğrisinin üstündeyse
if (y < 0 && func(x) < y) hit++;
}
}
}
var areaRectangle = Math.Abs(x2 - x1) * (max - min);
// Seçilen rasgelen noktaların yüzde hit / N kadarı dikdörtgenin içerisinde.
// Noktaların yüzde kaçının dikdörtgen içerisinde olduğuna bakılarak alan hesabı yapılıyor.
return areaRectangle * (double)hit / this.N;
}
/// <summary>
/// Verilen aralıkta, fornksiyonun minimum ve maksimum değerleri hesaplanıyor.
/// </summary>
/// <param name="func">Fonksiyon</param>
/// <param name="x1">Aralık başlangıç</param>
/// <param name="x2">Aralık bitiş</param>
/// <param name="min">Hesaplanan minimum değer</param>
/// <param name="max">Hesaplanan maksimum değer</param>
private void CalculateMinMaxValue(Func<double, double> func, double x1, double x2, out double min, out double max)
{
min = double.MaxValue;
max = double.MinValue;
// Aralık N parçaya bölünüyor.
var h = (x2 - x1) / this.N;
// Verilen aralıkta, N adet nokta için, her bir noktanın fonksiyon değeri hesaplanıyor.
for (int i = 0; i <= this.N; i++)
{
var x = x1 + i * h;
var y = func(x);
if (y < min) min = y;
if (y > max) max = y;
}
}
}
}
Monte Carlo alan hesabı algoritması ile, istediğiniz fonksiyon grafiği altında yer alan bölgenin alanını çok rahat bir şekilde hesaplayabiliriz. Fonksiyonun ne kadar karmaşık olduğunu bir önemi yok. Örneğin f(x) = x - sin(x) - 1
fonksiyon eğrisinin x ekseni {0,3} aralığındaki alanı hesaplamak için, alan hesaplama metodunu aşağıdaki gibi çalıştırabiliriz.
var mc = new MonteCarlo(1000);
var area = mc.CalculateArea(x => x - Math.Sin(x) - 1, 0, 3);
Bu durumda aşağıdaki eğri altında yer alan alan yaklaşık olarak hesaplanacaktır. Daha hassas bir hesaplamak için N değerinin artırılması gerekmektedir.
Aynı algoritmada yapılacak küçük bir değişiklikle, fonksiyonun integral değeri de rahatlıkla hesaplanabilir. İntegral hesabında, pozitif alanlardan negatif alanlar çıkarılacağı için, bu alanlara düşen noktalar ayrı ayrı sayılır.