이전 포스팅(https://kipl.tistory.com/731)에서 단위구에서 두 점 사이거리의 평균을 구하는 과정에서 사이거리에 대한 확률밀도함수를 소개하였고, 또 단위원에서 사이거리에 대한 확률밀도함수를 구체적으로 구했다. 이제 단위원에서의 기법을 이용해서 단위구에서 사이거리 분포에 대한 확률밀도함수를 구하자. 두 점의 사이거리 s의 확률밀도함수는
P(s)=1B31∬unit balld3rd3r′δ(|→r−→r′|−s),B1=4π3
로 쓰인다. 주어진 단위구 내부의 한 지점 →r에 대해서 적분은 S(→r,s)=∫unit balld3r′δ(|→r−→r′|−s)
는 →r에서 반지름 s인 구면이 단위구에 포함된 면적을 나타낸다. 그리고 이 값은 →r의 방향에 무관하게 단위구 중심에서 거리에만 의존함을 쉽게 알 수 있다, 즉
S(→r,s)=S(r,s)
이다. 따라서 r+s가 1보다 작을 때와 클 때 두 경우를 별도로 고려해야 한다. 작은 경우는 반지름 s인 구면이 완전히 단위구 내부에 포함되므로
r+s<1S(r,s)=4πs2
이고, 큰 경우는 (단위원의 경우 그림을 참조하면: https://kipl.tistory.com/732) 4πs2에서 단위구 밖으로 나가는 구면캡(spherical cap)의 면적을 제외하면 된다. 구면캡의 경도각 범위가 cosθ=1−r2−s22rs이므로 구면캡의 입체각은
은 델타함수 제한조건 때문에 을 중심으로 한 반지름 인 원과 단위원의 겹치는 영역의 경계의 길이를 의미함을 알 수 있다. 이 가 구해지면 는 이 값을 단위원에 대해 적분을 하면 되는데, 그 값은 단위원의 중심엣 가 거리에만 의존함을 쉽게 알 수 있다. 따라서 가, 예를 들면 축 위에 있는 경우만 고려하면 충분하다. 또, 이므로
이제 을 중심으로 한 반지름 인 원이 완전히 단위원에 포함이 되는 경우는 원과 단위원의 겹치는 영역이 반지름 인 원이므로
이고, 원호 일부가 단위원 밖으로 나가는 경우는 두 가지 경우(그림의 가 예각 또는 둔각)를 생각할 수 있는데,
이전 포스팅에서 거리 역수의 평균이 임을 보였는데, 평균거리가 이 값의 역수로 주어지지는 않는 점이 의외다.
아래 그림은 거리에 대한 확률밀도함수를 Monte Carlo 시뮬레이션으로 구한 결과이다. 실제로 거리에 따른 확률밀도함수를 임의의 차원에서 구할 수 있는데, 3차원의 단위구는(ref: J. Math. Phys., Vol. 41, No. 4, April 2000, https://kipl.tistory.com/733)
로 계산이 된다. 이 확률밀도함수의 최대값은 이 아니라 에서 나온다. 를 이용하면를 얻고, 거리의 역수의 평균은도 얻을 수 있다.
#define TWO_PI 6.28318530717958647692// picking a random vector inside an unit ball;voidrandomVector(double &x, double &y, double &z){
double a = double(rand()) / RAND_MAX; //[0,1] = radius;double b = double(rand()) / RAND_MAX * 2 - 1; //[-1,1] = cos(theta);double c = double(rand()) / RAND_MAX * TWO_PI; //[0, 2PI] = azimuthal;
a = pow(a, 1.0 / 3.0);
x = a * sqrt(1 - b * b) * cos(c);
y = a * sqrt(1 - b * b) * sin(c);
z = a * b;
}
// Calculate the distance between two randowm points selected // inside an unit ball;doublerandomDistance(){
double x1, y1, z1, x2, y2, z2;
randomVector(x1, y1, z1);
randomVector(x2, y2, z2);
x1 -= x2;
y1 -= y2;
z1 -= z2;
returnsqrt(x1 * x1 + y1 * y1 + z1 * z1);
}
voidmeanDistSphere(CRaster& raster){
double R = 100;
int trials = 5000000;
srand(unsigned(time(NULL)));
std::vector<int> hist(2 * int(R + .5) + 1, 0);
for (int i = trials; i-->0;) {
double d = R * randomDistance();
hist[int(d)]++;
}
double s = 0, sx = 0, sxx = 0;
double maxh = 0;
for (int i = hist.size(); i--> 0; ) {
double h = hist[i];
maxh = max(h, maxh);
s += h;
sx += h * i;
sxx += h * i * i;
}
double mean = sx / s;
double var = (sxx - sx / s) / s;
double sdev = sqrt(var);
// CRaster raster;
raster.SetDimensions(hist.size(), hist.size(), 24);
CSize sz = raster.GetSize();
memset(raster.GetDataPtr(), 0xFF, raster.GetDataSize());
for (int x = sz.cx; x--> 0; ) {
int h = int(double(sz.cy) * hist[x] / maxh);
for (int y = h; y--> 0; )
raster.SetPixel(x, sz.cy-1-y, 0);
}
// SaveRaster(raster, "hist.bmp");
}