ฉันจะจำลองการพลิกจนกว่าจะประสบความสำเร็จ N ได้อย่างไร


17

คุณและฉันตัดสินใจที่จะเล่นเกมที่เราผลัดกันพลิกเหรียญ ผู้เล่นคนแรกที่พลิก 10 หัวรวมเป็นผู้ชนะในเกม โดยธรรมชาติมีข้อโต้แย้งว่าใครควรไปก่อน

แบบจำลองของเกมนี้แสดงให้เห็นว่าผู้เล่นที่จะโยนครั้งแรกชนะ 6% มากกว่าผู้เล่นที่พลิกที่สอง (ผู้เล่นคนแรกชนะประมาณ 53% ของเวลา) ฉันสนใจในการสร้างแบบจำลองการวิเคราะห์นี้

นี่ไม่ใช่ตัวแปรสุ่มแบบทวินามเนื่องจากไม่มีการทดลองจำนวนคงที่ (พลิกจนกว่าจะมีใครได้รับ 10 หัว) ฉันจะทำแบบนี้ได้อย่างไร มันคือการกระจายตัวแบบทวินามลบหรือไม่


เพื่อที่จะสามารถสร้างผลลัพธ์ของฉันใหม่นี่คือรหัสหลามของฉัน:

import numpy as np
from numba import jit


@jit
def sim(N):

    P1_wins = 0
    P2_wins = 0

    for i in range(N):

        P1_heads = 0
        P2_heads = 0
        while True:

            P1_heads += np.random.randint(0,2)

            if P1_heads == 10:
                P1_wins+=1
                break

            P2_heads+= np.random.randint(0,2)
            if P2_heads==10:
                P2_wins+=1
                break
    return P1_wins/N, P2_wins/N


a,b = sim(1000000)

3
เมื่อคุณโยนเหรียญจนกว่าความล้มเหลวและแล้วมองไปที่การกระจายของจำนวนความสำเร็จที่เกิดขึ้นก่อนที่จะจบการทดลองดังกล่าวแล้วนี้คือโดยความหมายเชิงลบกระจายทวินาม r
ทิม

2
ฉันไม่สามารถทำซ้ำค่า 2% ฉันพบว่าผู้เล่นคนแรกชนะของเวลา 53.290977425133892%
whuber

1
@ โฮ่ใช่ฉันเชื่อว่าคุณพูดถูก ฉันใช้เวลาในการจำลองน้อยกว่าที่ควร ผลลัพธ์ของฉันสอดคล้องกับของคุณ
Demetri Pananos

1
หากใครชนะ 53% ของเวลาอื่น ๆ ควรจะ 47% ดังนั้นคำอธิบายไม่ควรอ่าน "ผู้เล่นคนแรกชนะ 6% มากกว่าผู้เล่นคนที่สอง" หรือ "3% มากกว่าครึ่งเวลา"? ไม่ (ตามที่กล่าวไว้ในปัจจุบัน) "มากกว่า 3% ของผู้เล่นที่พลิกสอง"
JesseM

3
คุณได้รับคำถามนี้จาก FiveThirtyEight Riddler Expressหรือไม่?
foutandabout

คำตอบ:


19

การกระจายของจำนวนหางก่อนที่จะบรรลุหัวเป็นเชิงลบทวินามกับพารามิเตอร์ที่และ1/2Letเป็นฟังก์ชั่นน่าจะเป็นและฟังก์ชั่นการอยู่รอด: สำหรับแต่ละ ,เป็นโอกาสของผู้เล่นของหางก่อนหัวและเป็นโอกาสของผู้เล่นของหรือก้อยมากขึ้นก่อนที่หัว .10 1 / 2 G n 0 F ( n ) n 10 G ( n ) n 1010101/2fGn0f(n)n10G(n)n10

เพราะผู้เล่นม้วนอิสระโอกาสชนะผู้เล่นคนแรกที่มีการรีดตรงหางจะได้รับจากการคูณโอกาสว่าโดยโอกาสที่ผู้เล่นที่สองม้วนหรือก้อยมากขึ้นเท่ากับ(n)n f ( n ) G ( n )nnf(n)G(n)

การรวมทั้งหมดที่เป็นไปได้ทำให้ผู้เล่นคนแรกมีโอกาสชนะเช่นกันn

n=0f(n)G(n)53.290977425133892%.

นั่นคือประมาณมากกว่าครึ่งเวลา3%

โดยทั่วไปแล้วการแทนที่ด้วยจำนวนเต็มบวกคำตอบสามารถให้ในรูปของฟังก์ชัน Hypergeometric: มันเท่ากับ10m

1/2+22m12F1(m,m,1,1/4).

เมื่อใช้เหรียญที่มีลำเอียงที่มีโอกาสหัวนี่เป็นการสรุปถึงp

12+12(p2m)2F1(m,m,1,(1p)2).

นี่คือการRจำลองเกมดังกล่าวหนึ่งล้านเกม จะรายงานการประมาณการของ0.5325การทดสอบสมมติฐานแบบทวินามเพื่อเปรียบเทียบกับผลทางทฤษฎีมีคะแนน Zซึ่งแตกต่างกันเล็กน้อย- 0.8430.53250.843

n.sim <- 1e6
set.seed(17)
xy <- matrix(rnbinom(2*n.sim, 10, 1/2), nrow=2)
p <- mean(xy[1,] <= xy[2,])
cat("Estimate:", signif(p, 4), 
    "Z-score:", signif((p - 0.532909774) / sqrt(p*(1-p)) * sqrt(n.sim), 3))

1
คำตอบของเราเห็นด้วยตัวเลข: (.53290977425133892 - .5) เช่นเดียวกับที่ทราบซึ่งอาจไม่ชัดเจน
Dougal

1
@Dougal ขอบคุณสำหรับการชี้ให้เห็นว่า ฉันดูคำตอบของคุณเห็นและรู้ว่ามันไม่เห็นด้วยกับรูปแบบของคำตอบที่ร้องขอในคำถามฉันไม่รู้จักว่าคุณคำนวณอย่างถูกต้อง โดยทั่วไปมันเป็นความคิดที่ดีที่จะวางกรอบคำตอบสำหรับคำถามใด ๆ ในแบบฟอร์มที่มีการร้องขอถ้าเป็นไปได้: ซึ่งทำให้ง่ายต่อการจดจำเมื่อมันถูกต้องและง่ายต่อการเปรียบเทียบคำตอบ 6.6%
whuber

1
@ เมื่อฉันตอบสนองต่อวลี "สถานการณ์จำลองของเกมนี้แสดงให้เห็นว่าผู้เล่นจะได้รับรางวัลแรกชนะ 2% (แก้ไข: 3% มากขึ้นหลังจากจำลองเกมมากขึ้น) มากกว่าผู้เล่นที่พลิกสอง" ฉันจะตีความ "ชนะ 2% อีก" เป็น ; ค่าที่ถูกต้องคือ 6.6% ฉันไม่แน่ใจว่าวิธีการตีความ "ชนะ 2% มากขึ้น" หมายถึง "ชนะ 52% ของเวลา" แต่เห็นได้ชัดว่านั่นคือสิ่งที่ตั้งใจไว้ Pr(A wins)Pr(B wins)=2%
Dougal

@ ผิดกฎหมายฉันเห็นด้วยว่าคำอธิบายของ OP สับสนและผิดไป อย่างไรก็ตามรหัสและผลลัพธ์ของเขาทำให้เขาชัดเจนว่าเขาหมายถึง "3% มากกว่าครึ่งเวลา" มากกว่า "3% มากกว่าผู้เล่นอื่น"
whuber

1
@ เห็นด้วย น่าเสียดายที่ฉันตอบคำถามก่อนที่จะโพสต์โค้ดและไม่ได้ทำการจำลองด้วยตัวเอง :)
Dougal

15

เราสามารถจำลองเกมดังนี้:

  • ผู้เล่น A โยนเหรียญซ้ำ ๆ เพื่อรับผลลัพธ์จนกว่าพวกเขาจะได้รับทั้งหมด 10 หัว ให้ดัชนีเวลาของหัวที่ 10 เป็นตัวแปรสุ่มXA1,A2,X
  • ผู้เล่น B ทำเช่นเดียวกัน ให้ดัชนีเวลาของหัวที่ 10 เป็นตัวแปรสุ่มซึ่งเป็นสำเนา IID ของXYX
  • ถ้า , ผู้เล่น A ชนะ; มิฉะนั้นผู้เล่น B ชนะ นั่นคือXY
    Pr(A wins)=Pr(XY)=Pr(X>Y)+Pr(X=Y)Pr(B wins)=Pr(Y>X)=Pr(X>Y).

ช่องว่างในอัตราการชนะจึงเป็น

Pr(X=Y)=kPr(X=k,Y=k)=kPr(X=k)2.

ในขณะที่คุณสงสัยว่า (และ ) มีการกระจายเป็นหลักตามการกระจายทวินามลบ สัญลักษณ์สำหรับสิ่งนี้แตกต่างกันไป แต่ในการกำหนดพารามิเตอร์ของ Wikipediaเรามีหัวข้อว่า "ล้มเหลว" และก้อยเป็น "ความสำเร็จ"; เราต้อง "ความล้มเหลว" (หัว) ก่อนการทดลองจะหยุดการทำงานและความน่าจะเป็นความสำเร็จ\ จากนั้นจำนวน "ความสำเร็จ" ซึ่งก็คือมี และความน่าจะเป็นของการชนคือ ซึ่ง Mathematica บอกเราว่าเป็นประโยชน์XYr = 10 p = 1r=10p=12X10

Pr(X10=k)=(k+9k)210k,
Pr(X=Y)=k=0(k+9k)222k20,
7649952511622614676.6%.

ดังนั้นอัตราการชนะของผู้เล่น B คือและผู้เล่น A คือ%Pr(Y>X)46.7%619380496116226146753.3%


หัวไม่จำเป็นต้องอยู่ในแถวรวมเพียง 10 ฉันคิดว่านั่นคือสิ่งที่คุณกำลังแก้ไข
Demetri Pananos

6
(+1) ฉันชอบวิธีนี้ดีกว่าวิธีที่ฉันโพสต์เพราะมันง่ายกว่าการคำนวณ: มันต้องการเพียงฟังก์ชันความน่าจะเป็นซึ่งมีการแสดงออกอย่างง่ายในแง่ของสัมประสิทธิ์ทวินาม
whuber

1
ฉันได้ส่งการแก้ไขโดยแทนที่วรรคสุดท้ายซึ่งตั้งคำถามถึงความแตกต่างจากคำตอบอื่นพร้อมคำอธิบายว่าผลลัพธ์ของพวกเขาเหมือนกันอย่างไร
Monty Harder

1

ปล่อยให้เป็นเหตุการณ์ที่ผู้เล่นพลิกหัวฉันก่อนที่ผู้เล่นคนอื่นจะพลิกหัว j และให้เป็นสองคนแรกที่มีพื้นที่ตัวอย่างพลิกตัวอย่างโดยที่ h หมายถึงหัว และหางเสื้อและให้{IJ})EijX{hh,ht,th,tt}pijPr(Eij)

จากนั้น pij=Pr(Ei1j1|X=hh)Pr(X=hh)+Pr(Ei1j|X=ht)Pr(X=ht)+Pr(Eij1|X=th)Pr(X=th)+Pr(Eij|X=tt)Pr(X=tt)

สมมติว่าเหรียญมาตรฐานหมายความว่าPr(X=)=1/4pij=1/4[pi1j1+pi1j+pij1+pij]

กำลังหา ,pij=1/3[pi1j1+pi1j+pij1]

แต่และแสดงว่าการเรียกซ้ำสิ้นสุดลงอย่างสมบูรณ์ อย่างไรก็ตามการดำเนินการแบบเรียกซ้ำแบบไร้เดียงสาโดยตรงจะให้ประสิทธิภาพที่ต่ำเนื่องจากสาขาตัดกันp0j=p00=1pi0=0

การดำเนินงานที่มีประสิทธิภาพจะมีความซับซ้อนและหน่วยความจำความซับซ้อนj)) นี่คือการพับแบบง่าย ๆ ที่ใช้ใน Haskell:O(ij)O(min(i,j))

Prelude> let p i j = last. head. drop j $ iterate ((1:).(f 1)) start where
  start = 1 : replicate i 0;
  f c v = case v of (a:[]) -> [];
                    (a:b:rest) -> sum : f sum (b:rest) where
                     sum = (a+b+c)/3 
Prelude> p 0 0
1.0
Prelude> p 1 0
0.0
Prelude> p 10 10
0.5329097742513388
Prelude> 

UPDATE: มีคนในความคิดเห็นข้างต้นถามว่ามีใครคิดว่าจะหมุน 10 หัวในหนึ่งแถวหรือไม่ ดังนั้นขอให้เป็นเหตุการณ์ที่ผู้เล่นในม้วนพลิกหัวฉันในแถวก่อนที่ผู้เล่นอื่นพลิกหัวฉันในแถวเนื่องจากพวกเขาพลิกหัวต่อเนื่องกัน k และ l ตามลำดับEkl

ดำเนินการเหมือนก่อนหน้านี้ แต่คราวนี้เป็นการปรับเงื่อนไขในการพลิกครั้งแรกเท่านั้น โดยที่pk,l=11/2[pl,k+1+pl,0]pil=pii=1,pki=0

นี่คือระบบเชิงเส้นที่มี unknowns และหนึ่งโซลูชันที่ไม่ซ้ำกันi2

หากต้องการแปลงเป็นรูปแบบวนซ้ำเพียงเพิ่มหมายเลขซ้ำและปัจจัยความไว :nϵ

pk,l,n+1=1/(1+ϵ)[ϵpk,l,n+11/2(pl,k+1,n+pl,0,n)]

เลือกและอย่างชาญฉลาดและรันการวนซ้ำในไม่กี่ขั้นตอนและตรวจสอบคำแก้ไข ϵpk,l,0

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.