Metoda polarna Marsaglii

Metoda polarna Marsaglii to metoda próbkowania liczb pseudolosowych służąca do generowania pary niezależnych standardowych normalnych zmiennych losowych .

Standardowe normalne zmienne losowe są często wykorzystywane w informatyce , statystyce obliczeniowej , aw szczególności w zastosowaniach metody Monte Carlo .

Metoda biegunowa polega na wybieraniu losowych punktów ( x , y ) w kwadracie −1 < x < 1, −1 < y < 1 do

a następnie zwrócenie wymaganej pary normalnych zmiennych losowych jako

lub równoważnie,

gdzie i reprezentują cosinus i sinus kąta, pod którym wektor ( x , y ) tworzy z osią x .

Podstawy teoretyczne

Podstawową teorię można podsumować w następujący sposób:

Jeśli u jest równomiernie rozłożone w przedziale 0 ≤ u < 1, to punkt (cos(2π u ), sin(2π u )) jest równomiernie rozłożony na obwodzie jednostki x 2 + y 2 = 1 i pomnożenie tego punktu przez niezależna zmienna losowa ρ, której rozkład to

wygeneruje punkt

którego współrzędne są wspólnie rozłożone jako dwie niezależne standardowe normalne zmienne losowe.

Historia

Pomysł ten pochodzi od Laplace'a , któremu Gauss przypisuje odkrycie powyższego

biorąc pierwiastek kwadratowy z

Transformacja do współrzędnych biegunowych pokazuje, że θ jest równomiernie rozłożona (stała gęstość) od 0 do 2π, a odległość promieniowa r ma gęstość

( r 2 ma odpowiedni rozkład chi-kwadrat .)

Ta metoda tworzenia pary niezależnych standardowych zmiennych normalnych poprzez promieniowe rzutowanie losowego punktu na obwodzie jednostki na odległość określoną przez pierwiastek kwadratowy zmiennej chi-kwadrat-2 nazywana jest polarną metodą generowania pary normalnych zmiennych losowych ,

Względy praktyczne

Bezpośrednie zastosowanie tego pomysłu

nazywa się transformacją Boxa-Mullera , w której zmienna chi jest zwykle generowana jako

ale ta transformacja wymaga funkcji logarytmu, pierwiastka kwadratowego, sinusa i cosinusa. W niektórych procesorach cosinus i sinus tego samego argumentu można obliczyć równolegle przy użyciu jednej instrukcji. Szczególnie w przypadku maszyn opartych na Intelu można użyć instrukcji asemblera fsincos lub instrukcji expi (dostępnej np. w D), aby obliczyć złożone

i po prostu oddziel rzeczywistą i urojoną część.

Uwaga: Aby jawnie obliczyć zespoloną postać biegunową, użyj następujących podstawień w postaci ogólnej,

Niech i Następnie

W przeciwieństwie do tego metoda biegunowa eliminuje tutaj potrzebę obliczania cosinusa i sinusa. Zamiast tego, rozwiązując punkt na okręgu jednostkowym, te dwie funkcje można zastąpić współrzędnymi x i y znormalizowanymi do promień. W szczególności losowy punkt ( x , y ) wewnątrz okręgu jednostkowego jest rzutowany na obwód jednostkowy przez ustawienie i tworząc punkt

co jest szybszą procedurą niż obliczanie cosinusa i sinusa. Niektórzy badacze twierdzą, że instrukcja warunkowa if (do odrzucania punktu poza okręgiem jednostkowym) może spowolnić programy na nowoczesnych procesorach wyposażonych w potokowanie i przewidywanie rozgałęzień. generatora liczb losowych (tylko wygenerowanych leży wewnątrz okręgu jednostkowego)

Ten przypadkowy punkt na obwodzie jest następnie rzutowany promieniowo na wymaganą przypadkową odległość za pomocą

używając tego samego s , ponieważ to s jest niezależne od przypadkowego punktu na obwodzie i samo w sobie jest równomiernie rozłożone od 0 do 1.

Realizacja

Prosta implementacja w Javie z wykorzystaniem średniej i odchylenia standardowego:

   
     

        
      
          
             
     prywatny  statyczny  podwójny  zapasowy  ;  private  static  boolean  hasSpare  =  false  ;  publiczne  statyczne  zsynchronizowane  podwójne  generowanie Gaussa  (  podwójna  średnia  ,  podwójne  stdDev  )  {  if  (  hasSpare  )  {  hasSpare  =  false  ;  zwróć  zapas  *  stdev  +  średnia  ;  }   
           
         
                  
                  
                    
               else  {  podwójne  u  ,  v  ,  s  ;  zrobić  {  u  =  matematyka  .  losowo  ()  *  2  -  1  ;  v  =  Matematyka  .  losowo  ()  *  2  -  1  ;  s  =  u  *  u  +  v  *  v  ;  }  podczas  (  s  >=  1  ||  s   0
              
            
          
               
    
 ==  );  s  =  Matematyka  .  sqrt  (  -2.0  *  Math  .  log  (  s  )  /  s  )  ;  zapas  =  v  *  s  ;  maZapas  =  true  ;  zwróć  średnią  +  stdDev  *  u  *  s  ;  }  } 

nieobsługująca wątków w C++ przy użyciu średniej i odchylenia standardowego:

     
      
        

      
          
             
      
            podwójne  generowanie Gaussa  (  podwójna  średnia  ,  podwójne  stdDev  )  {  statyczne  podwójne  zapasowe  ;  static  bool  hasSpare  =  false  ;  if  (  maZapas  )  {  maZapas  =  fałsz  ;  zwróć  zapas  *  stdev  +  średnia  ;  }  else  {  podwójne  u  ,  v  ,  s 
         
                    
                    
                    
           ;  do  {  u  =  (  rand  ()  /  ((  double  )  RAND_MAX  ))  *  2,0  -  1,0  ;  v  =  (  rand  ()  /  ((  double  )  RAND_MAX  ))  *  2,0  -  1,0  ;  s  =  u  *  u  +  v  *  v  ;  }  podczas  (  s       
              
            
          
               
    
 >=  1,0  ||  s  ==  0,0  );  s  =  sqrt  (  -2.0  *  log  (  s  )  /  s  );  zapas  =  v  *  s  ;  maZapas  =  true  ;  zwróć  średnią  +  stdDev  *  u  *  s  ;  }  } 

Implementacja std::normal_distribution w C++11 GNU GCC libstdc++ używa polarnej metody Marsaglii, cytowanej tutaj .