의사 난수 생성기-지수 분포
나는 의사 난수를 생성하고 싶다. 지금까지 나는 .Net 라이브러리의 Random.Next(int min, int max)
기능 에 매우 만족했다 . 이 다양한 PRNG도이되는 가정 사용되는 균일 한 분포를 ,하지만 난 아주 많이 좋아는 사용하여 몇 가지 숫자를 생성하는 것 지수 분포를 .
의사 코드 나 C ++, Java 등을 허용하지만 C #으로 프로그래밍하고 있습니다.
제안 / 코드 스 니펫 / 알고리즘 / 생각?
균일 난수 생성기에 액세스 할 수 있으므로 CDF를 알고있는 다른 분포와 함께 분포 된 난수를 생성하는 것은 반전 방법을 사용하면 쉽습니다 .
따라서, 균일 한 난수를 생성 u
,에 [0,1)
, 다음 계산 x
에 의해 :
x = log(1-u)/(
−λ )
,
여기서 λ는 지수 분포의 비율 매개 변수입니다. 이제 x
지수 분포를 가진 난수입니다. 참고 있다는 log
것입니다 위 ln
, 자연 로그.
표본 추출의 기본 정리는 원하는 분포를 정규화, 통합 및 반전 할 수 있다면 집에서 자유 롭다고 주장합니다.
원하는 분포 F(x)
가 [a,b]
. 당신은 계산
C(y) = \int_a^y F(x) dx
그것을 얻기 위해 반전하고 C^{-1}
, z
[0,1)에 균일하게 던지고
x_i = C^{-1}(z_i)
원하는 분포를 갖게됩니다.
귀하의 경우 : F(x) = ke^{-kx}
그리고 나는 당신이 [0,infinity]
. 우리는 :
C(y) = 1 - e^{-ky}
뒤집을 수있는
x = -1/k ln(1 - z)
z에 대해 [0,1)
.
그러나 솔직히 잘 디버깅 된 라이브러리를 사용하는 것이 자신의 수정을 위해이 작업을 수행하지 않는 한 더 똑똑합니다.
좋은 난수를 원한다면 gsl 루틴 ( http://www.gnu.org/software/gsl/)에 연결하는 것을 고려 하십시오 . 그들에게는 루틴이 gsl_ran_exponential
있습니다. [0, 1)에 균일 분포가있는 내장 생성기를 사용하여 난수를 생성하려면 (예 : u = Random.Next (0, N-1) / N, 일부 큰 N) 다음을 사용하십시오.
-mu * log (1-u)
gsl 소스에서 randist / exponential.c를 참조하십시오.
편집 : 일부 나중에 답변과 비교하기 위해-이것은 mu = 1 / lambda와 동일합니다. 여기서 mu는 OP가 연결된 wikipedia 페이지에서 scale 매개 변수라고도하는 분포의 평균이고, lambda는 비율 매개 변수입니다.
지수 분포의 한 가지 흥미로운 속성 : 지수 간 도착 시간이있는 도착 프로세스를 고려하십시오. 임의의 기간 (t1, t2)과 해당 기간의 도착을 취하십시오. 이러한 도착은 t1과 t2 사이에 균일하게 분배됩니다. (Sheldon Ross, 확률 적 과정).
의사 난수 생성기가 있고 어떤 이유로 (예 : 내 소프트웨어가 로그를 계산할 수 없음) 위의 변환을 원하지 않는 경우 평균 1.0의 지수 rv를 원합니다.
다음을 수행 할 수 있습니다.
1) 1001 U (0,1) 확률 변수를 만듭니다.
2) 순서대로 정렬
3) 첫 번째에서 두 번째를 빼고 두 번째에서 세 번째를 빼서 1000 개의 차이를 얻습니다.
4) 이러한 차이는 평균이 1.0 인 분포의 지수 RV입니다.
덜 효율적이라고 생각하지만 같은 목적을위한 수단입니다.
Dan Dyer 의 오픈 소스 Uncommons Maths 라이브러리 는 Java에 대한 난수 생성기, 확률 분포, 조합 및 통계를 제공합니다.
다른 귀중한 클래스 중에서 ExponentialGenerator
는 @Alok Singhal이 설명하는 아이디어를 본질적으로 구현했습니다. 에서 의 튜토리얼 블로그 , 코드 조각은 평균 10 회 분에 일어난 어떤 임의의 이벤트를 시뮬레이션하기 위해 주어진다 :
final long oneMinute = 60000;
Random rng = new MersenneTwisterRNG();
// Generate events at an average rate of 10 per minute.
ExponentialGenerator gen = new ExponentialGenerator(10, rng);
boolean running = true;
while (true)
{
long interval = Math.round(gen.nextValue() * oneMinute);
Thread.sleep(interval);
// Fire event here.
}
물론 시간 단위 per second
( a minute
여기 대신) 를 선호하는 경우 final long oneMinute = 1000
.
에 깊은 간다 소스 코드 방법의 nextValue()
의 ExponentialGenerator
, 당신은 소위 찾을 수 역 시료 채취 변환 에 설명 Generating_exponential_variates [위키]를 :
public Double nextValue()
{
double u;
do
{
// Get a uniformly-distributed random double between
// zero (inclusive) and 1 (exclusive)
u = rng.nextDouble();
} while (u == 0d); // Reject zero, u must be positive for this to work.
return (-Math.log(u)) / rate.nextValue();
}
P.S.: Recently I am using the Uncommons Maths library. Thanks Dan Dyer.
If I understand your problem, and you can accept a finite number of PRNG's, you could follow an approach like:
- Create an array where every element is in your exponential distribution
- Generate a PRNG which is an integer index into the array. Return the element in the array at that index.
This was what I used when faced with similar requirements:
// sorry.. pseudocode, mine was in Tcl:
int weighted_random (int max) {
float random_number = rand();
return floor(max - ceil( max * random_number * random_number))
}
Of course this is the formula of squaring the random number so you're generating a random number along a quadratic curve.
ReferenceURL : https://stackoverflow.com/questions/2106503/pseudorandom-number-generator-exponential-distribution
'UFO ET IT' 카테고리의 다른 글
nohup과 데몬의 차이점은 무엇입니까? (0) | 2020.12.15 |
---|---|
Python과 C ++ 통합 (0) | 2020.12.15 |
'색인'보기 또는 해당 마스터를 찾을 수 없습니다. (0) | 2020.12.15 |
메소드 이름은 findBy 또는 findOneBy로 시작해야합니다. (0) | 2020.12.14 |
두 div의 스크롤 위치를 어떻게 동기화합니까? (0) | 2020.12.14 |