Wahrscheinlichkeiten - wie hoch können Sie gehen?

10

Ich habe zuvor eine Frage gestellt, wie man eine Wahrscheinlichkeit schnell und genau berechnet. Offensichtlich war es jedoch zu einfach, da eine Lösung in geschlossener Form gegeben wurde! Hier ist eine schwierigere Version.

Bei dieser Aufgabe geht es darum, Code zu schreiben, um eine Wahrscheinlichkeit genau und schnell zu berechnen . Die Ausgabe sollte eine genaue Wahrscheinlichkeit sein, die als Bruch in ihrer am meisten reduzierten Form geschrieben wird. Das heißt, es sollte nie ausgegeben werden 4/8, sondern 1/2.

nBetrachten Sie für eine positive Ganzzahl eine gleichmäßig zufällige Zeichenfolge mit einer Länge von 1s und -1s nund nennen Sie sie A. Verknüpfen Sie sie jetzt mit Aeiner Kopie von sich selbst. Das ist, A[1] = A[n+1]wenn von 1 indiziert wird, A[2] = A[n+2]und so weiter. Ahat jetzt länge 2n. Nun auch eine zweite zufällige Zeichenfolge der Länge betrachten , nderen erste nWerte -1, 0 oder 1 , mit einer Wahrscheinlichkeit von 1 / 4,1 / 2, 1/4 und jedes nennen es B.

Betrachten Sie nun das innere Produkt von Bmit A[1+j,...,n+j]für anders j =0,1,2,....

Betrachten Sie zum Beispiel n=3. Mögliche Werte für Aund Bkönnten A = [-1,1,1,-1,...]und sein B=[0,1,-1]. In diesem Fall sind die ersten beiden inneren Produkte 0und 2.

Aufgabe

Für jeden j, beginnend mit j=1, Code sollte eine Ausgabe , die Wahrscheinlichkeit , dass alle die ersten j+1inneren Produkte sind Null für jeden n=j,...,50.

Wenn Sie die von Martin Büttner erstellte Tabelle kopieren j=1, erhalten Sie die folgenden Beispielergebnisse.

n   P(n)
1   1/2
2   3/8
3   7/32
4   89/512
5   269/2048
6   903/8192
7   3035/32768
8   169801/2097152

Ergebnis

Ihre Punktzahl ist die größte, die jIhr Code in 1 Minute auf meinem Computer erreicht. Zur Verdeutlichung jerhält jeder eine Minute. Beachten Sie, dass der dynamische Programmiercode in der vorherigen verknüpften Frage dies problemlos erledigt j=1.

Tie Breaker

Wenn zwei Einträge die gleiche jPunktzahl erhalten, ist der Gewinner derjenige, der nin einer Minute auf meinem Computer den höchsten Wert erreicht j. Wenn die beiden besten Beiträge auch nach diesem Kriterium gleich sind, ist der Gewinner die zuerst eingereichte Antwort.

Sprachen und Bibliotheken

Sie können jede frei verfügbare Sprache und Bibliothek verwenden, die Sie mögen. Ich muss in der Lage sein, Ihren Code auszuführen. Bitte geben Sie eine vollständige Erklärung an, wie Sie Ihren Code unter Linux ausführen / kompilieren können, wenn dies überhaupt möglich ist.

Meine Maschine Die Timings werden auf meiner Maschine ausgeführt. Dies ist eine Standard-Ubuntu-Installation auf einem AMD FX-8350 Eight-Core-Prozessor. Dies bedeutet auch, dass ich Ihren Code ausführen kann.

Gewinnerbeiträge

  • j=2in Python von Mitch Schwartz.
  • j=2in Python von feersum. Derzeit der schnellste Eintrag.
Gemeinschaft
quelle
Wenn die Frage in irgendeiner Weise unklar ist, lassen Sie es mich bitte wissen, damit ich sie schnell beheben kann.
2
Sie sind bei weitem mein Lieblingsfrager. Andererseits kann ich Werte genau und schnell berechnen .
Primo
@primo Danke! Bedeutet dies, dass wir in RPython eine Antwort erwarten können? :)
Könnten Sie den Unterschied zwischen dieser und der anderen Frage machen?
Kirbyfan64sos
@ kirbyfan64sos Die andere ist im Wesentlichen die gleiche Frage nur für `j = 1`.

Antworten:

3

Python 2, j = 2

Ich habe versucht, eine Art 'geschlossene Form' für j = 2 zu finden. Vielleicht könnte ich ein MathJax-Bild davon machen, obwohl es bei all dem Index-Fummeln wirklich hässlich wäre. Ich habe diesen nicht optimierten Code nur geschrieben, um die Formel zu testen. Der Vorgang dauert ca. 1 Sekunde. Die Ergebnisse stimmen mit dem Code von Mitch Schwartz überein.

ch = lambda n, k: n>=k>=0 and fac[n]/fac[k]/fac[n-k]
W = lambda l, d: ch(2*l, l+d)
P = lambda n, p: n==0 or ch(n-1, p-1)
ir = lambda a,b: xrange(a,b+1)

N = 50
fac = [1]
for i in ir(1,4*N): fac += [i * fac[-1]]

for n in ir(2, N):
    s = 0
    for i in ir(0,n+1):
     for j in ir(0,min(i,n+1-i)):
      for k in ir(0,n+i%2-i-j):
       t=(2-(k==0))*W(n+i%2-i-j,k)*W(i-(j+i%2),k)*W(j,k)**2*P(i,j+i%2)*P(n+1-i,j+1-i%2)
       s+=t
    denp = 3 * n - 1
    while denp and not s&1: denp -= 1; s>>=1
    print n, '%d/%d'%(s,1<<denp)

Stellen Sie sich eine Sequenz vor, in der das i-te Element ist, ewenn A [i] == A [i + 1] oder nwenn A [i]! = A [i + 1]. iim Programm ist die Anzahl von ns. Wenn gerade iist, muss die Sequenz mit beginnen und mit enden e. Wenn dies iungerade ist, muss die Sequenz mit beginnen und enden n. Sequenzen werden weiter durch die Anzahl von Läufen aufeinanderfolgender es oder ns klassifiziert . Es gibt j+ 1 von einem und jdem anderen.

Wenn die Zufallsbewegung Idee bis 3 Dimensionen ausgedehnt wird, gibt es ein unglückliches Problem , dass es 4 mögliche Richtungen laufen in (eine für jede der ee, en, ne, oder nn) , die Mittel , die sie nicht linear abhängig sind. Der kIndex summiert sich also über die Anzahl der Schritte in eine der Richtungen (1, 1, 1). Dann gibt es eine genaue Anzahl von Schritten, die in den anderen 3 Richtungen ausgeführt werden müssen, um es abzubrechen.

P (n, p) gibt die Anzahl der geordneten Partitionen von n Objekten in p Teile an. W (l, d) gibt die Anzahl der Wege an, auf denen ein zufälliger lSchritt eine Strecke von genau zurücklegen kann d. Nach wie vor gibt es 1 Chance, sich nach links zu bewegen, 1 Chance, sich nach rechts zu bewegen und 2, um dort zu bleiben.

Feersum
quelle
Vielen Dank! Ein Bild der Formel wäre wirklich toll.
Vielen Dank für die Erklärung. Sie lassen es einfach aussehen! Ich habe gerade Ihren Kommentar gesehen, für den Sie eine Lösung finden könnten j=3. Das wäre fantastisch!
3

Python, j = 2

Der dynamische Programmieransatz für j = 1in meiner Antwort auf die vorherige Frage erfordert nicht viele Modifikationen, um für höhere zu arbeiten j, sondern wird schnell langsam. Tabelle als Referenz:

n   p(n)

2   3/8
3   11/64
4   71/512
5   323/4096
6   501/8192
7   2927/65536
8   76519/2097152
9   490655/16777216
10  207313/8388608

Und der Code:

from time import*
from fractions import*
from collections import*

def main():
    N_MAX=50

    T=time()

    n=2
    Y=defaultdict(lambda:0)
    numer=0

    for a1 in [1]:
        for b1 in (1,0):
            for a2 in (1,-1):
                for b2 in (1,0,0,-1):
                    if not a1*b1+a2*b2 and not a2*b1+a1*b2:
                        numer+=1
                    Y[(a1,a2,b1,b2,a1*b1+a2*b2,a2*b1,0)]+=1

    thresh=N_MAX-1

    while time() <= T+60:
        print('%d %s'%(n,Fraction(numer,8**n/4)))

        if thresh<2:
            print('reached N_MAX with %.2f seconds remaining'%(T+60-time()))
            return

        n+=1
        X=Y
        Y=defaultdict(lambda:0)
        numer=0

        for a1,a2,b1,b2,s,t,u in X:
            if not ( abs(s)<thresh and abs(t)<thresh+1 and abs(u)<thresh+2 ):
                continue

            c=X[(a1,a2,b1,b2,s,t,u)]

            # 1,1

            if not s+1 and not t+b2+a1 and not u+b1+a1*b2+a2: numer+=c
            Y[(a1,a2,b2,1,s+1,t+b2,u+b1)]+=c

            # -1,1

            if not s-1 and not t-b2+a1 and not u-b1+a1*b2+a2: numer+=c
            Y[(a1,a2,b2,1,s-1,t-b2,u-b1)]+=c

            # 1,-1

            if not s-1 and not t+b2-a1 and not u+b1+a1*b2-a2: numer+=c
            Y[(a1,a2,b2,-1,s-1,t+b2,u+b1)]+=c

            # -1,-1

            if not s+1 and not t-b2-a1 and not u-b1+a1*b2-a2: numer+=c
            Y[(a1,a2,b2,-1,s+1,t-b2,u-b1)]+=c

            # 1,0

            c+=c

            if not s and not t+b2 and not u+b1+a1*b2: numer+=c
            Y[(a1,a2,b2,0,s,t+b2,u+b1)]+=c

            # -1,0

            if not s and not t-b2 and not u-b1+a1*b2: numer+=c
            Y[(a1,a2,b2,0,s,t-b2,u-b1)]+=c

        thresh-=1

main()

Hier halten wir den Überblick über die ersten beiden Elemente A, die letzten beiden Elemente B(wobei b2das letzte Element), und die inneren Produkte von (A[:n], B), (A[1:n], B[:-1]), und (A[2:n], B[:-2]).

Mitch Schwartz
quelle
.... erreichte N_MAX mit 21,20 Sekunden verbleibenden