ä¹±æ°ãžã§ãã¬ãŒã¿ãŒã¯ã»ãã¯ã¹ã«ãã䌌ãŠããŸããè¯ããšãã¯çŸãããæªããšãã¯ãŸã ããã§ãïŒGeorge Marsagliaã1984ïŒ
確ççã¢ã«ãŽãªãºã ã®äººæ°ã¯é«ãŸã£ãŠããŸãã ãããã®å€ãã¯ãå€æ°ã®ç°ãªãã©ã³ãã å€æ°ã®çæã«åºã¥ããŠããŸãã åžžã«åäžã«ååžããŠãããšã¯çšé ãã ããã§ã¯ãæ¢ç¥ã®ååžãæã€é«éã§æ£ç¢ºãªã©ã³ãã å€ãžã§ãã¬ãŒã¿ãŒã«é¢ããæ
å ±ãåéããããšããŸããã ã¿ã¹ã¯ã¯ç°ãªãå Žåããããåºæºã¯ç°ãªãå ŽåããããŸãã ãã人ã«ãšã£ãŠã¯ãçææéã¯éèŠã§ããä»ã®äººã«ãšã£ãŠã¯-粟床ãä»ã®äººã«ãšã£ãŠ-æå·ã®å®å®æ§ãä»ã®äººã«ãšã£ãŠ-åæã®é床ã§ãã å人çã«ã¯ã0ããç¹å®ã®RAND_MAXãŸã§åäžã«ååžããæ¬äŒŒä¹±æ°æŽæ°ãè¿ãç¹å®ã®åºæ¬çãªãžã§ãã¬ãŒã¿ãŒããããšããåæããé²ããŸããã
unsigned long long BasicRandGenerator() { unsigned long long randomVariable;
ãããŠããã®ãžã§ãã¬ãŒã¿ãŒã¯ååã«é«éã§ãã ã€ãŸãã察æ°ãèšç®ãããããããã®1ã€ã环ä¹ãããããããããæ°ååã®ä¹±æ°ãçæããæ¹ãå®äŸ¡ã§ãã ãããã¯æšæºã®ãžã§ãã¬ãŒã¿ãŒã§ãïŒstd :: randïŒïŒãMATLABã®randãJava.util.Randomãªã©ã ãã ãããã®ãããªãžã§ãã¬ãŒã¿ãŒã¯æ·±å»ãªäœæ¥ã«é©ããŠããããšã¯ã»ãšãã©ãããŸããã å€ãã®å Žåãç°ãªãçµ±èšãã¹ãã«å€±æããŸãã ãŸãããããã«å®å
šã«äŸåããŠããããšãå¿ããªãã§ãã ãããç¬èªã®ãžã§ãã¬ãŒã¿ãŒã䜿çšããŠããã®åäœãææ¡ããããšããå§ãããŸãã
ãã®èšäºã§ã¯ãã¢ã«ãŽãªãºã ã«ã€ããŠèª¬æããŸããã¢ã«ãŽãªãºã ã®æ¬è³ªã¯ãå°ãªããšã確ççè«ã«åºãããããšããã人ã«ã¯æãããªã¯ãã§ãã èšæž¬ã®çè«ã«ç²Ÿéããå¿
èŠã¯ãããŸãããååãšããŠãååžé¢æ°ãšååžå¯åºŠé¢æ°ãã©ã®ãããªãã®ãã倧ãŸãã«ç解ããã°ååã§ãã
åã¢ã«ãŽãªãºã ã«ã¯ãã³ãŒããå°éã®æ°åŠãããã³çæãããæ°åäžã®ã©ã³ãã å€æ°ã®ãã¹ãã°ã©ã ãæ·»ä»ããŸãã
åäžãªååž
éåžžã«ã·ã³ãã«ã§æ®éçãª
éå€æãµã³ããªã³ã°æ¹æ³ããããããåäžååžã䜿çšããŠã»ãŒãã¹ãŠã®ã©ã³ãã å€æ°ãçæã§ããŸã.0ãã1ã«åäžã«ååžããã©ã³ãã å€æ°Uãçæãããã©ã¡ãŒã¿ãŒUã§éååžé¢æ°ïŒåäœç¹ïŒãè¿ããŸãã確ãã«ïŒ
åé¡ã¯ãåæçã«å¯èœãªéããéååžé¢æ°ã®ã«ãŠã³ããé·ããªãå¯èœæ§ãããããšã§ãã
äžæ§ååžãžã§ãã¬ãŒã¿ãŒã䜿çšãããšãé·æéåæ¢ããå¿
èŠã¯ãããŸããïŒå€æ°ã®ã©ã³ãã å€æ°ãçæããããããïŒb-aïŒ/ RAND_MAXã1åã ãã«ãŠã³ãããããšããå§ãããŸãïŒã
double Uniform(double a, double b) { return a + BasicRandGenerator() * (b - a) / RAND_MAX; }
ãã¡ãããç¶ç¶æ§ã¯åãªãæœè±¡åã§ãã çŸå®ã®äžçã§ã¯ããã®å Žåãå
·äœçã«ã¯ããã¯ããªãå°ããªãµã³ããªã³ã°ã¹ããããæå³ããŸãã éèŠãªããšã¯æ³šç®ã«å€ããŸãã 0ãã1ã«åçã«ååžããä¹±æ°ãçæããå Žåã32ãããã§ã¯ãdoubleããã®ç¯å²ã§åãããšãã§ãããã¹ãŠã®å€ãã«ããŒããã«ã¯äžååã§ãïŒãã ããfloatã«ã¯ååã§ãïŒã å質ãåäžãããã«ã¯ã64ãããæŽæ°ãçæãããã2ã€ã®32ãããæŽæ°ãçµåããå¿
èŠããããŸãã
æ£èŠååž
å転æ³ã§ã¯ãé誀差é¢æ°ã®èšç®ãå¿
èŠã«ãªããŸãã ç¹å¥ãªè¿äŒŒé¢æ°ã䜿çšããªãå Žåãããã¯é£ãããä¿¡ããããªãã»ã©é·ããªããŸãã éåžžã®å€ã®å ŽåãBox-Mullerã¡ãœãããååšããŸãã ããã¯éåžžã«ã·ã³ãã«ã§æ®åããŠããŸãã ãã®æãããªæ¬ ç¹ã¯ãè¶
è¶é¢æ°ã®èšç®ã§ãã Habréã§ã¯ã
ããŒã©ãŒæ³ããã§ã«èšåãããŠããããµã€ã³ãšã³ãµã€ã³ã®èšç®ãé¿ããã®ã«åœ¹ç«ã¡ãŸããã ãã ãã察æ°ãšãã®æ ¹ãæ°ããå¿
èŠããããŸãã åã極æ³ã®äœè
ã§ãããžã§ãŒãžã»ãã«ãµã°ãªã¢ã«ãã£ãŠçºæãããçŸããååã®ãžã°ã©ããæ³ã¯ãã¯ããã«é«éã§ãã
極座æšæ³ã¯ã
åå
¥æåŠãµã³ããªã³ã°ã®äŸã§ãã æåéããå€ãçæããé©åããå Žåã¯ãããåãå
¥ããŸãããã以å€ã®å Žåã¯ãæåŠããŠå床çæããŸãã äž»ãªäŸïŒå¯åºŠfïŒxïŒã®ã©ã³ãã å€æ°ãçæããå¿
èŠããããŸãããåçŽãªå転æ³ã§è¡ãã®ã¯éåžžã«å°é£ã§ãã ããããfïŒxïŒãšããã»ã©å€ãããªãå¯åºŠgïŒxïŒã®ã©ã³ãã å€æ°ãçæã§ããŸãã ãã®å ŽåãM> 1ããã³ã»ãŒãã¹ãŠã®å Žæã§fïŒxïŒ<MgïŒxïŒãšãªãæå°ã®å®æ°MãååŸãã次ã®ã¢ã«ãŽãªãºã ãå®è¡ããŸãã
- ååžgïŒxïŒããã©ã³ãã å€æ°Xãçæãã0ãã1ãŸã§äžæ§ã«ååžããã©ã³ãã å€æ°UãçæããŸãã
- U <fïŒXïŒ/ MgïŒXïŒã®å Žå-Xãè¿ããããã§ãªãå Žå-ç¹°ãè¿ããŸãã
ã©ã³ãã å€æ°ãåã確çïŒ
Mã®éžæãå°ãªãã»ã©ããã®ç¢ºçã¯é«ããªããŸããããžã§ãã¬ãŒã¿ãŒã®åäœã¯éããªããŸãã
ã¢ã«ãŽãªãºã ã®èšŒæïŒ2ã€ã®ã€ãã³ãAããã³Bã®çºç確çã¯
ååžå¯åºŠé¢æ°gïŒxïŒãšååžé¢æ°GïŒxïŒã䜿çšããŠã©ã³ãã å€æ°Xããšã確çãèšç®ããŸãããäžãããããã©ã¡ãŒã¿ãŒxãããå°ããå Žåãæ³å®ããŸãã
ãããŠããã€ãºã®å®çã«ããïŒ
ããšãã°ãæšæºã®æšæºå€ã®ã¢ãžã¥ãŒã«ãçæããŸãã æ£èŠååžã®å¯Ÿç§°æ§ã«ãããåŸãããå€ã¯ãçãã確çã§å€+1ããã³-1ããšãã©ã³ãã å€æ°ã§ä¹ç®ãããæšæºæ£èŠååžå€XãååŸã§ããŸããæ£èŠå€ã¯ãã·ã°ãã«ããæšæºä¹ç®ãšmuã«ããã·ããããååŸãããŸãã ååžå¯åºŠé¢æ°| X |ïŒ
æšæºã®ææ°ååžã®å¯åºŠé¢æ°ã§è¿äŒŒããŠã¿ãŸãããã ææ°ååžã«ã€ããŠã¯ãŸã 話ããŠããªãã®ã§ãå°ãå
ã«é²ãã§ããŸãã åçŽã«æªåé«ãå転æ³ã«ãã£ãŠçæãããŸã-[0ã1]ã«åäžã«ååžããéUãåãã-lnïŒUïŒãè¿ããŸãã
æ¡ä»¶fïŒxïŒ<MgïŒxïŒãæºããMã®æå°å€ã¯ãx = 1ã§éæãããŸãã
次ã«ïŒ
ãŸããéåžžã®ã©ã³ãã å€æ°ãçæããããã®ã¢ã«ãŽãªãºã ã¯æ¬¡ã®ãšããã§ãã
- U-[0ã1]ã«åäžã«ååžããã©ã³ãã å€æ°ãçæããŸãã
- ææ°é¢æ°çã«ååžããã©ã³ãã å€æ°EãçæããŸãïŒ-lnïŒUïŒãã«ãŠã³ããããããé«éãªã¢ã«ãŽãªãºã ã«ã€ããŠã以äžã§èª¬æããŸãïŒã
- U <expïŒ-ïŒE-1ïŒ 2 ïŒã®å Žå| X | = Eããã以å€ã®å Žåã¯æåã®ã¹ãããã«æ»ããŸãã
- æ°ããUãçæããŸããU<0.5ã®å Žåã-| X |ãŸãã¯| X |ãè¿ããŸãã å¥ã®å Žåã
ããã¯ç°¡åã«ããããŸãïŒ
ãããŠããã¯ãUã®ä»£ããã«ãææ°é¢æ°çã«èæ
®ãããªãå¥ã®ææ°ååžéãçæã§ããããšãæå³ããŸãã æ°ããã¢ã«ãŽãªãºã ã¯æ¬¡ã®ããã«ãªããŸãã
- æšæºã®ææ°ååžã©ã³ãã å€æ°E 1ããã³E 2ãçæããŸãã
- E 2 >ïŒE 1-1ïŒ2/2ã®å Žåã| X | = E 1 ããã以å€ã®å Žåã¯æ»ããŸãã
- UãçæããŸããU<0.5ã®å Žåã-| X |ãŸãã¯| X |ãè¿ããŸãã å¥ã®å Žåã
å¥ã®ãã€ã³ãïŒå€E
1ãåãå
¥ãããããšãå·®E
2- ïŒE 1-1ïŒ2/2ãææ°é¢æ°çã«ãã€E
1ãšã¯ç¬ç«ããŠååžããŸãã ãããã£ãŠã次åã¯E
1ã®ä»£ããã«èšæ¶ããŠäœ¿çšã§ããŸãã
蚌æææ°ååžã«ã¯ãã¡ã¢ãªäžè¶³ã®ç¹æ§ããããŸãã
ããã¯ãå·®ååžé¢æ°ã次ã®ããšãæå³ããŸãã
åå·®ã®ãããµã³ããªã³ã°ã®äžè¬çãªåé¡ã¯ãåå·®ãå¯èœãªéãå°ãããªãããã«ååžå¯åºŠgïŒxïŒã®ã©ã³ãã å€æ°ãéžæããããšã§ãã ãã®åé¡ã解決ããå€ãã®æ¡åŒµæ©èœããããŸãã ã¡ãœããèªäœã¯ãZigguratãå«ãã»ãšãã©ãã¹ãŠã®åŸç¶ã¢ã«ãŽãªãºã ã®åºç€ã§ãã åŸè
ã®æ¬è³ªã¯äŸç¶ãšããŠåãã§ããæ£èŠååžã®å¯åºŠé¢æ°ãåæ§ã®åçŽãªé¢æ°ã§ã«ããŒããæ²ç·ã®äžã«ããå€ãè¿ãããã«ããŸãã ãã®é¢æ°ã¯ç¬ç¹ã§ãããå€æ®µæ§æã«äŒŒãŠããŸãããå®éã¯ã¢ã«ãŽãªãºã ã®ååã§ãã
ãžã°ã©ããã¯æ¬¡ã®ããã«æ§æãããŠããŸãã é¢æ°fïŒxïŒã®ãµããšã§ãç¹x
1ããã³y
0 = fïŒx
1 ïŒãéžæãããŸãã é·æ¹åœ¢ã®äžã®é åã¯ïŒ0,0ïŒããïŒx
1 ãy
0 ïŒ+é¢æ°fã®å°Ÿã®äžã®é åïŒx> x
1 ïŒ= Aã§ãããããã£ãŠãããŒã¹ã¬ã€ã€ãŒãæ§ç¯ããŸããã ãã®äžéšã«ã¯å¥ã®é·æ¹åœ¢ãããããã®å¹
ã¯x
1 ãé«ãã¯y
1 = A / y
0ã§ããããããã£ãŠé¢ç©ã¯AãšçãããªããŸãããã®é·æ¹åœ¢ã«ã¯ãé¢æ°fïŒxïŒã®äžã«ããç¹ãæ¢ã«å«ãŸããŠããŸããäŸïŒïŒx
1 ãy
1 ïŒã 2çªç®ã®é·æ¹åœ¢ã¯ããã€ã³ãïŒx
2 ãy
1 ïŒã§é¢æ°fïŒxïŒãšäº€å·®ããŸã-ããã¯ã3çªç®ã®é·æ¹åœ¢ã®å³äžç¹ã®åº§æšã«ãªããŸããé¢æ°ã®æäžéšã«Zigguratãæ§ç¯ããŸããã åã¹ãããã®é¢ç©ã¯Aã«çãããªããŸãããããªãã¢ã«ãŽãªãºã
ïŒããŒã¹ã¬ã€ã€ãŒã«å
¥ãåŠçãªãïŒ ïŒ
- é·æ¹åœ¢iãã©ã³ãã ãã€åçã«éžæãããåäžã«ååžããå€Xã0ããx iãŸã§çæãããŸã
- X <x i + 1ã®å Žåãééããªãæ²ç·ã®äžã«èœã¡ãŸã-Xãè¿ããŸãã
- y iããy i + 1ãŸã§ã®Yã®æ°ããäžæ§ååžå€ãçæããŸãã 座æšïŒXãYïŒãæã€ãã€ã³ããæ²ç·ã®äžã«ããå Žåãã€ãŸãY <fïŒXïŒã®å ŽåãXãè¿ããŸãããã以å€ã®å Žåãæåã®ã¹ãããã«æ»ããŸãã
ããŒã¹ã¬ã€ã€ãŒã«ããå Žåã¯ã©ãããŸããïŒ æ³åäžã®ç¹x
0 = A / y
0ãå
¥åããããšã«ãããããããé¢ç©Aã®é·æ¹åœ¢ãäœæããããšãã§ã
ãŸã ã 次ã«ãïŒ0,0ïŒããïŒx
0 ãy
0 ïŒãŸã§ã®é·æ¹åœ¢ã®é¢ç©ãAã«çãããªããŸããããŒã¹ã¬ã€ã€ãŒã®éãã¯ãæ°ããæ³åäžã®é·æ¹åœ¢ã®æ²ç·ã«è©²åœããªãå ŽåãxãæåŠããŠã¯ãªããªãããšã§ãããã å°Ÿãæã¡ãŸãã å°Ÿã«ã€ããŠã¯ããžã§ãŒãžã»ãã«ãµã°ãªã¢ã¯ã以åã«æ€èšããã®ãšåãæ¹æ³ã䜿çšããããšãææ¡ããŸã-åå·®ã®ãããµã³ããªã³ã°ã ããã€ãã®å€æŽã®ã¿ïŒ
- å¯åºŠx 1ã®æšæºçãªææ°ååžã©ã³ãã å€æ°E 1ãšåäœå¯åºŠã®E 2ãçæããŸãã
- E 2 > E 1 2/2ã®å Žåã| X | = E 1 + x 1 ããã以å€ã®å Žåã¯æ»ããŸãã
- UãçæããŸããU<0.5ã®å Žåã-| X |ãŸãã¯| X |ãè¿ããŸãã å¥ã®å Žåã
å°Ÿã®èšŒæã©ã³ãã å€æ°| X | > x
1 E
1 + x
1ã䜿çšããŠããã®ããã®åå·®ãµã³ããªã³ã°ã¢ã«ãŽãªãºã ãæ§ç¯ããããšããŸããããã§ãE
1ã¯ãå¯åºŠx
1ã®ææ°ååžã©ã³ãã å€æ°ã§ãã ååžå¯åºŠé¢æ°E
1 + x
1 ïŒ
Mã®å€ãç¥ãã«ã¯ãé¢æ°ã®æ倧æ¯ãèŠã€ããå¿
èŠããããŸãã
åæ°ã®æ倧å€ã«å¯Ÿå¿ãããã€ã³ãxã¯ãæ倧ææ°ãæäŸããŸãã 次æ°ã®å°é¢æ°ããŒãã«çãããããšã察å¿ããxãèŠã€ãããŸãã
äžæ§ãªã©ã³ãã å€æ°ã®å¢çãååŸããŸãã
ãããŠãã©ã³ãã å€æ°ãåãããã®æ¡ä»¶ã¯æ¬¡ã®ããã«ãªããŸãã
ãããšãã¢ã«ãŽãªãºã å
šäœã¯æ¬¡ã®ããã«ãªããŸãã
- é·æ¹åœ¢iã¯ã©ã³ãã ãã€åçã«éžæããã0ããx iãŸã§ã®äžæ§ååžå€XãçæãããŸãã
- X <x i + 1ã®å Žåãééããªãæ²ç·ã®äžã«èœã¡ãŸã-Xãè¿ããŸãã
- ããŒã¹ã¬ã€ã€ãŒãã€ãŸãi = 0ã«ãããããå ŽåãããŒã«ã«å¯ŸããŠã¢ã«ãŽãªãºã ãå®è¡ãããã®çµæãè¿ããŸãã
- y Iããy i + 1ãŸã§Yã®æ°ããäžæ§ååžå€ãçæããŸãã 座æšïŒXãYïŒãæã€ãã€ã³ããæ²ç·ã®äžã«ããå Žåãã€ãŸãY <fïŒXïŒã®å ŽåãXãè¿ããŸãããã以å€ã®å Žåãæåã®ã¹ãããã«æ»ããŸãã
åé¡ã¯ãé·æ¹åœ¢ã®æ°ã«å¿ããŠå®æ°Aãšx
1ãèŠã€ããæ¹æ³ã§ããïŒ ãããã¯éåžžã®æ°å€çæ¹æ³ã§èŠã€ããããšãã§ããŸãã æåã®ä»®å®x
1ãååŸããããŒã¹ã¬ã€ã€ãŒãæ§ç¯ããAãèšç®ããŠãå¿
èŠãªæ°ã®åè§åœ¢ãæ§ç¯ãããŸã§ãžã°ã©ãããæ§ç¯ããŸãã é¢æ°ãããé«ãå Žå-ã€ãŸããx
1ã®å€ãå°ããããŠãAã®å€ã倧ããããå Žå-æ°ããå€ã§åæ§ç¯ããããšããŠããŸãã
ã¢ã«ãŽãªãºã èªäœã¯ã32ãããæŽæ°ã䜿çšããŠäžèŠãªä¹ç®ãåé€ããããŸããŸãªããªãã¯ã«ãã£ãŠé«éåã§ããŸãã 詳现ã«ã€ããŠã¯ãGeorge Marsagliaããã³Wai Wan Tsangã®The Ziggurat Method for Generation Random Variablesãåç
§ããŠãã ããã ããã§ã¯ãå®å
šã«æé©åãããŠããããã§ã¯ãããŸããããç解å¯èœãªã³ãŒãã瀺ããŸãïŒææ°ååžãçæã§ããå ŽåïŒã
static double stairWidth[257], stairHeight[256]; const double x1 = 3.6541528853610088; const double A = 4.92867323399e-3; /// area under rectangle void setupNormalTables() { // coordinates of the implicit rectangle in base layer stairHeight[0] = exp(-.5 * x1 * x1); stairWidth[0] = A / stairHeight[0]; // implicit value for the top layer stairWidth[256] = 0; for (unsigned i = 1; i <= 255; ++i) { // such x_i that f(x_i) = y_{i-1} stairWidth[i] = sqrt(-2 * log(stairHeight[i - 1])); stairHeight[i] = stairHeight[i - 1] + A / stairWidth[i]; } } double NormalZiggurat() { int iter = 0; do { unsigned long long B = BasicRandGenerator(); int stairId = B & 255; double x = Uniform(0, stairWidth[stairId]); // get horizontal coordinate if (x < stairWidth[stairId + 1]) return ((signed)B > 0) ? x : -x; if (stairId == 0) // handle the base layer { static double z = -1; double y; if (z > 0) // we don't have to generate another exponential variable as we already have one { x = Exponential(x1); z -= 0.5 * x * x; } if (z <= 0) // if previous generation wasn't successful { do { x = Exponential(x1); y = Exponential(1); z = y - 0.5 * x * x; // we storage this value as after acceptance it becomes exponentially distributed } while (z <= 0); } x += x1; return ((signed)B > 0) ? x : -x; } // handle the wedges of other stairs if (Uniform(stairHeight[stairId - 1], stairHeight[stairId]) < exp(-.5 * x * x)) return ((signed)B > 0) ? x : -x; } while (++iter <= 1e9); /// one billion should be enough return NAN; /// fail due to some error } double Normal(double mu, double sigma) { return mu + NormalZiggurat() * sigma; }
ææ°ååž
ææ°ååžã®å Žåãåäžã«ååžããéã®å¯Ÿæ°ããšãããšãã§ããçæãé«éåã§ãããšãã§ã«èšãããŠããŸãã ä»»æã®ææ°å€ã¯å¯åºŠã«ããæšæºçãªé€ç®ããååŸããããããçæã¯æªåé«ããžã°ã©ããã«ããããšãã§ããŸãã æ«å°Ÿã«å°éããå Žåãã¢ã«ãŽãªãºã ãæ°ããæ¹æ³ã§å®è¡ããååŸããå€ã«x
1ãè¿œå ã§ããŸãã
蚌æE> x
1ã®å Žå ãååžé¢æ°E-x
1ãææ°é¢æ°çã«ååžããããšã蚌æããå¿
èŠããããŸãã ããã¯ãåè¿°ã®ææ°ååžã®ã¡ã¢ãªäžè¶³ã«ããå¯èœã§ãã
ããã«2ã€ã®äºå®ïŒ255åã®é·æ¹åœ¢ã®ããŒãã«ã䜿çšããå Žåãææ°ååžã®æåã®åãå
¥ã確çã¯0.989ã§ãéåžžã®ååžã§ã¯0.993ã§ãã MATLABã§ã¯ãããŒãžã§ã³5以éãæ£èŠååžã«Zigguratã䜿çšãããŠããŸãïŒæ¥µæ³ã䜿çšãããŠããŸããïŒã Rã§ã¯ãéåžžã®éã«ã€ããŠã¯ãç§ã®ç¥ãéããé誀差é¢æ°ãå€é
åŒã§è¿äŒŒããå転æ³ã䜿çšããŸãã
static double stairWidth[257], stairHeight[256]; const double x1 = 7.69711747013104972; const double A = 3.9496598225815571993e-3; /// area under rectangle void setupExpTables() { // coordinates of the implicit rectangle in base layer stairHeight[0] = exp(-x1); stairWidth[0] = A / stairHeight[0]; // implicit value for the top layer stairWidth[256] = 0; for (unsigned i = 1; i <= 255; ++i) { // such x_i that f(x_i) = y_{i-1} stairWidth[i] = -log(stairHeight[i - 1]); stairHeight[i] = stairHeight[i - 1] + A / stairWidth[i]; } } double ExpZiggurat() { int iter = 0; do { int stairId = BasicRandGenerator() & 255; double x = Uniform(0, stairWidth[stairId]); // get horizontal coordinate if (x < stairWidth[stairId + 1]) /// if we are under the upper stair - accept return x; if (stairId == 0) // if we catch the tail return x1 + ExpZiggurat(); if (Uniform(stairHeight[stairId - 1], stairHeight[stairId]) < exp(-x)) // if we are under the curve - accept return x; // rejection - go back } while (++iter <= 1e9); // one billion should be enough to be sure there is a bug return NAN; // fail due to some error } double Exponential(double rate) { return ExpZiggurat() / rate; }
ã¬ã³ãååž
çæã®ããã®ã¢ã«ãŽãªãºã ã¯ããã§ã¯ãã§ã«è€éã§ãããããããã§ã¯ãããã®èšŒæ ã説æããŸãããäŸã®ã¿ã瀺ããŸãã æšæºå€ïŒã·ãŒã¿= 1ïŒãçæããã«ã¯ãããããkã«äŸåãã4ã€ã®ã¢ã«ãŽãªãºã ã䜿çšãããŸãã
- kãŸãã¯2kãæŽæ°ã§ãk <5ãGAã¢ã«ãŽãªãºã ã®å Žåã
- k <1ã®å Žå-GSã¢ã«ãŽãªãºã ã
- 1 <k <3ã®å Žå-GFã¢ã«ãŽãªãºã ã
- k> 3ã®å Žå-GOã¢ã«ãŽãªãºã ã
éæšæºã®ã¬ã³ã確çå€æ°ã¯ãã·ãŒã¿ã«ããæšæºã®ä¹ç®ããååŸãããŸãã
GAã¢ã«ãŽãªãºã
ãã©ã¡ãŒã¿ãŒk1ãšk2ã®ã¬ã³ãååžãæã€2ã€ã®ã©ã³ãã å€æ°ãè¿œå ãããšããã©ã¡ãŒã¿ãŒk1 + k2ã®ã¬ã³ãååžãæã€ã©ã³ãã å€æ°ãåŸãããŸãã å¥ã®ç¹æ§ãšããŠãã·ãŒã¿= k = 1ã®å Žåãååžãææ°é¢æ°çã§ããããšãç°¡åã«æ€èšŒã§ããŸãã ãããã£ãŠãkãæŽæ°ã®å ŽåãåçŽã«æšæºã®ææ°ååžã§kåã®ã©ã³ãã å€æ°ãå ç®ã§ããŸãã
double GA1(int k) { double x = 0; for (int i = 0; i < k; ++i) x += Exponential(1); return x; }
kãæŽæ°ã§ã¯ãªãã2kãæŽæ°ã®å Žåãåèšã§ææ°ã©ã³ãã å€æ°ã®1ã€ã§ã¯ãªããéåžžå€ã®2ä¹ã®ååã䜿çšã§ããŸãã ãªããããå¯èœãã¯ãåŸã§æããã«ãªããŸãã
double GA2(double k) { double x = Normal(0, 1); x *= 0.5 * x; for (int i = 1; i < k; ++i) x += Exponential(1); return x; }
GSã¢ã«ãŽãªãºã
- 0ãã1 + k / eãŸã§äžæ§ã«ååžããEã®æšæºçãªææ°ååžå€ãšUã®å€ãçæããŸãã U <= 1ã®å Žåãæé 2ã«é²ã¿ãŸãããã以å€ã®å Žåãæé 3ã«é²ã¿ãŸãã
- x = U 1 / kãèšå®ããŸãã x <= Eã®å Žåã¯xãè¿ããããã§ãªãå Žåã¯æé 1ã«æ»ããŸãã
- x = -lnïŒïŒ1-UïŒ/ k + 1 / eïŒãèšå®ããŸãã ïŒ1-kïŒ* lnïŒxïŒ<= Eã®å Žåãxãè¿ããŸãããã以å€ã®å Žåãæé 1ã«æ»ããŸãã
double GS(double k) { // Assume that k < 1 double x = 0; int iter = 0; do { // M_E is base of natural logarithm double U = Uniform(0, 1 + k / M_E) double W = Exponential(1) if (U <= 1) { x = pow(U, 1.0 / k); if (x <= W) return x; } else { x = -log((1 - U) / k + 1.0 / M_E); if ((1 - k) * log(x) <= W) return x; } } while (++iter < 1e9); // excessive maximum number of rejections return NAN; // shouldn't end up here }
GFã¢ã«ãŽãªãºã
ç§ã®ç¥ãéãããã®ã¢ã«ãŽãªãºã ã®èè
ã§ããããŒã¹ã«ãã©ã€ã倧åŠã®J. S.ãã£ãã·ã¥ãã³ææã¯ã圌ã®æ¥çžŸãçºè¡šããŠããŸããã ã¢ã«ãŽãªãºã èªäœã¯k> 1ã§æ©èœããŸããããã®å¹³åå®è¡æéã¯sqrtïŒkïŒã«æ¯äŸããŠå¢å ãããããk <3ã«å¯ŸããŠã®ã¿æå¹ã§ãã
- æšæºçãªææ°ååžãæã€2ã€ã®ç¬ç«ããã©ã³ãã å€æ°E 1ããã³E 2ãçæããŸãã
- E 2 <ïŒk-1ïŒ*ïŒE 1 -lnïŒE 1 ïŒ-1ïŒã®å Žåãæé 1ã«æ»ããŸãã
- x = k * E 1ãè¿ããŸã
蚌æå®ç Uã[0ã1]äžã®äžæ§ååžã®ã©ã³ãã å€æ°ãšããWã1 /ã©ã ãã®å¯åºŠã®ææ°ååžã©ã³ãã å€æ°ãšããŸãã ãããŠãã ããïŒ
gïŒWïŒ> = Uã®å ŽåãWã¯ãã©ã¡ãŒã¿ãŒlambdaã®ã¬ã³ãååžãæã¡ãŸãã
蚌æã ååžå¯åºŠé¢æ°WïŒ
ãã®ããã«
Uã«ã¯äžæ§ãªååžãããããã
0 <gïŒxïŒ<1ã®å Žåãç¡æ¡ä»¶ã®ç¢ºçïŒ
çµæãšããŠãæ¡ä»¶ä»ã確çå¯åºŠïŒ
qed
ãžã§ãã¬ãŒã¿ãŒã®å¹çã¯ãU <= gïŒWïŒã§ãããCïŒã©ã ãïŒã«çãã確çã«ãããã®ã§ãã ã¹ã¿ãŒãªã³ã°è¿äŒŒã䜿çšããŠã\ lambdaãã©ã¡ãŒã¿ãŒã®å€ã倧ããå Žåã確çã倧ãŸãã«èšç®ã§ããŸãã
ã¢ã«ãŽãªãºã ã¯ã©ã ãã®å¢å ãšãšãã«ç¡å¹ã«ãªããŸãã
double GF(double k) { // Assume that 1 < k < 3 double E1, E2; do { E1 = Exponential(1); E2 = Exponential(1); } while (E2 < (k - 1) * (E1 - log(E1) - 1)); return k * E1; }
GOã¢ã«ãŽãªãºã
Dieter and Ahrensã¢ã«ãŽãªãºã ã¯ããã©ã¡ãŒã¿ãŒã®å¢å ã«äŒŽãååžã®æŒžè¿æ£èŠæ§ã«åºã¥ããŠãããããkã倧ããã»ã©é«éã§ãã k> 2.533ã§æ©èœããŸãããk <3ã®ãã£ãã·ã£ãŒã¢ã«ãŽãªãºã ã»ã©å¹æçã§ã¯ãããŸããæåã«ãããã€ãã®å®æ°ãèšå®ããå¿
èŠããããŸãïŒkã®ã¿ã«äŸåïŒã
void setupConstants(double k) { m = k - 1; s_2 = sqrt(8.0 * k / 3) + k; s = sqrt(s_2); d = M_SQRT2 * M_SQRT3 * s_2; b = d + m; w = s_2 / (m - 1); v = (s_2 + s_2) / (m * sqrt(k)); c = b + log(s * d / b) - m - m - 3.7203285; } double GO(double k) { // Assume that k > 3 double x = 0; int iter = 0; do { double U = Uniform(0, 1); if (U <= 0.0095722652) { double E1 = Exponential(1); double E2 = Exponential(1); x = b * (1 + E1 / d); if (m * (x / b - log(x / m)) + c <= E2) return x; } else { double N; do { N = Normal(0, 1); x = s * N + m; // ~ Normal(m, s) } while (x < 0 || x > b); U = Uniform(0, 1); double S = 0.5 * N * N; if (N > 0) { if (U < 1 - w * S) return x; } else if (U < 1 + S * (v * N - w)) return x; if (log(U) < m * log(x / m) + m - x + S) return x; } } while (++iter < 1e9); return NAN; // shouldn't end up here; }
以åã®ååžã®å Žåãšåæ§ã«ãã¬ã³ãå€ã¯ã·ãŒã¿ãã©ã¡ãŒã¿ã«ããæšæºã®ä¹ç®ããçæãããŸãã äžæ§ååžãæ£èŠååžãææ°ååžãã¬ã³ãååžãçæã§ããã°ãä»ã®ååžã®ã»ãšãã©ãç°¡åã«ååŸã§ããŸãããããã¯äžèšã§ç°¡åã«è¡šçŸã§ããããã§ãã
ã³ãŒã·ãŒååž
ã³ãŒã·ãŒååžã§ç¢ºçå€æ°ããã°ããååŸãã1ã€ã®æ¹æ³ã¯ã2ã€ã®æ£èŠç¢ºçå€æ°ãååŸããããããäºãã«åå²ããããšã§ãã ãã£ãšéãã§ããŸããïŒ
éåžžã®å転æ¹æ³ã䜿çšã§ããŸãããæ¥ç·ã®èšç®ãå¿
èŠã«ãªããŸããããã¯ããã«é
ãã§ãããã©ããïŒãžã§ãŒãžã»ãã«ãµã°ãªã¢ã®æ¥µæ³ãèŠããŠããŸããïŒåœŒã¯ãBox-Mullerå€æã§ãåäžã«ååžããã©ã³ãã å€æ°ã®ãµã€ã³ãŸãã¯ã³ãµã€ã³ããã°ããååŸããããšãèš±å¯ããŸãããæ¥ç·ãååŸããæ¹æ³ãšãŸã£ããåãã§ããæ£æ¹åœ¢[-1ã1] x [-1ã1]ã«2ã€ã®åçã«ååžããã©ã³ãã 座æšxããã³yãçæããŸããïŒ0ã0ïŒãäžå¿ãšããåãšåäœååŸã«å°éããå Žå-x / yãè¿ããŸãããã以å€ã®å Žå-xãšyãå床çæããŸããããšãã°ã3åç®ã¯ãã§ã«0.01æªæºã§ãããããåã«é¥ããªã確çã double Cauchy(double x0, double gamma) { double x, y; do { x = Uniform(-1,1); y = Uniform(-1,1); } while (x * x + y * y > 1.0 || y == 0.0); return x0 + gamma * x / y; }
ã©ãã©ã¹ååž
ã©ãã©ã¹ååžã¯åãææ°ã§ãããã©ã³ãã ãªç¬Šå·ãæã¡ãŸãã double Laplace(double mu, double b) { double E = Exponential(1.0 / b); return mu + (((signed)BasicRandGenerator() > 0) ? E : -E); }
課çšåé
ååžå¯åºŠé¢æ°ãã©ãã»ã©ã²ã©ããã®ã§ãã£ãŠããã©ã³ãã å€æ°èªäœã¯éåžžã«ç°¡åãã€è¿
éã«çæãããŸãã double Levy(double mu, double c) { double N = Normal(0, 1); return mu + c / (N * N); }
ã«ã€äºä¹ååž
ãåç¥ã®ããã«ããã©ã¡ãŒã¿kã®ã«ã€2ä¹ååžãæã€ç¢ºçå€æ°ã¯ãkåã®æšæºæ£èŠç¢ºçå€æ°ã®å¹³æ¹åã§ããkã§ããããããk / 2ææ°ç¢ºçå€æ°ïŒãŸãã¯ã¢ãŒã©ã³ååžïŒã®2ååã§ããããšã¯ããŸãç¥ãããŠããŸããããã®é¢ä¿ãããåè¿°ã®GA2ã¢ã«ãŽãªãºã ã¯ä»¥äžãå°ãåºããŸãã蚌æ, â :
:
E â :
:
:
-, :
. , :
, :
qed
double ChiSquared(int k) { // ~ Gamma(k / 2, 2) if (k >= 10) // too big parameter return GO(0.5 * k); double x = ((k & 1) ? GA2(0.5 * k) : GA1(k >> 1)); return x + x; }
ãã®ããããã£ãã泚ç®ãã¹ãäºå®ããããŸããå¹³é¢äžã®ç¹ãã©ã³ãã 座æšãšæ³ç·åº§æšïŒxãyïŒã§éžæãããšãïŒ0,0ïŒãããã®ç¹ãŸã§ã®è·é¢ã¯ææ°é¢æ°çã«ååžããŸãã察æ°æ£èŠååž
éèåžå Žã§æ°åŠã¢ãã«ãæ±ã人ã¯ã察æ°æ£èŠååžãçŽæ¥ç¥ã£ãŠããŸãã察æ°æ£èŠååžã察æ°ã³ãŒãååžã察æ°ããžã¹ãã£ãã¯ååžã®å Žåãç°¡åãªæ¹æ³ã1ã€ãããŸããææ°ãåãããšã§ããæ®å¿µãªãããããé«éãªæ¹æ³ã¯ããããŸããããã¬ãŽã£ååžãã«ã€äºä¹ååžã䜿çšããŠåæ§ã®éãçæããæ¹æ³ããããããããŸãããããããã©ãã»ã©äŒŒãŠããããèŠãŠãã ããããããŸã§ã®éããã®ããã«ïŒ double LogNormal(double mu, double sigma) { return exp(Normal(mu, sigma)); }
ããžã¹ãã£ãã¯ååž
ããžã¹ãã£ãã¯ååžã¯æ£èŠååžãšéåžžã«äŒŒãŠããŸãããããŒã«ã倧ãããæšæºã®åäžååžãä»ããŠéåžžã«ç°¡åã«çæãããŸãã double Logistic(double mu, double s) { return mu + s * log(1.0 / Uniform(0, 1) - 1); }
æåŸã«ãåžžã«é«éãšããããã§ã¯ãããŸããããä»ã®äžè¬çãªãã£ã¹ããªãã¥ãŒã·ã§ã³çšã®éåžžã«åçŽãªã¢ã«ãŽãªãºã ã«ã€ããŠç°¡åã«èª¬æããŸãã double Erlang(int k, double l) { return GA1(k) / l; } double Weibull(double l, double k) { return l * pow(Exponential(1), 1.0 / k); } double Rayleigh(double sigma) { return sigma * sqrt(Exponential(0.5)); } double Pareto(double xm, double alpha) { return xm / pow(Uniform(0, 1), 1.0 / alpha); } double StudentT(int v) { if (v == 1) return Cauchy(0, 1); return Normal(0, 1) / sqrt(ChiSquared(v) / v); } double FisherSnedecor(int d1, int d2) { double numerator = d2 * ChiSquared(d1); double denominator = d1 * ChiSquared(d2); return numerator / denominator; } double Beta(double a, double b) { double x = Gamma(a); return x / (x + Gamma(b)); }
C ++ 17ã§ãããããã³ä»ã®ãžã§ãã¬ãŒã¿ãŒãå®è£
ãã