Zasadniczo pytasz o „pół-losowy” generator zdarzeń, który generuje zdarzenia o następujących właściwościach:
Średnie tempo wystąpienia każdego zdarzenia jest określone z góry.
To samo zdarzenie jest mniej prawdopodobne, że wystąpi dwa razy z rzędu, niż byłoby przypadkowe.
Wydarzenia nie są w pełni przewidywalne.
Jednym ze sposobów na to jest najpierw zaimplementowanie generatora nieprzypadkowych zdarzeń, który spełnia cele 1 i 2, a następnie dodanie losowości, aby osiągnąć cel 3.
W przypadku generatora zdarzeń nieprzypadkowych możemy zastosować prosty algorytm ditheringu . W szczególności niech p 1 , p 2 , ..., p n będą względnymi prawdopodobieństwami zdarzeń 1 do n , a niech s = p 1 + p 2 + ... + p n będzie sumą wag. Następnie możemy wygenerować nieprzypadkową, maksymalnie równorzędną sekwencję zdarzeń, stosując następujący algorytm:
Początkowo niech e 1 = e 2 = ... = e n = 0.
Aby wygenerować zdarzenie, zwiększ każde e i o p i wyślij zdarzenie k, dla którego e k jest największe (zerwanie powiązań w dowolny sposób).
Decrement e k o s , a następnie powtórz czynności od punktu 2.
Na przykład, biorąc pod uwagę trzy zdarzenia A, B i C, przy p A = 5, p B = 4 i p C = 1, ten algorytm generuje coś w rodzaju następującej sekwencji wyników:
A B A B C A B A B A A B A B C A B A B A A B A B C A B A B A
Zauważ, że ta sekwencja 30 zdarzeń zawiera dokładnie 15 As, 12 Bs i 3 Cs. Nie do końca optymalnie się rozprowadza - jest kilka przypadków dwóch jak z rzędu, których można było uniknąć - ale się zbliża.
Teraz, aby dodać losowość do tej sekwencji, masz kilka (niekoniecznie wykluczających się) opcji:
Możesz śledzić porady Philippa i utrzymać „talię” z N nadchodzących wydarzeniach, na pewnym odpowiednim rozmiarze numerem N . Za każdym razem, gdy musisz wygenerować zdarzenie, wybierasz losowe zdarzenie z talii, a następnie zamieniasz je na wyjście następnego zdarzenia za pomocą algorytmu ditheringu powyżej.
Zastosowanie tego do powyższego przykładu, przy N = 3, daje np .:
A B A B C A B B A B A B C A A A A B B A B A C A B A B A B A
podczas gdy N = 10 daje bardziej losowy wygląd:
A A B A C A A B B B A A A A A A C B A B A A B A C A C B B B
Zwróć uwagę, że wspólne zdarzenia A i B kończą się znacznie większą liczbą przebiegów z powodu przetasowania, podczas gdy rzadkie zdarzenia C są wciąż dość dobrze rozłożone.
Możesz wprowadzić losowość bezpośrednio do algorytmu ditheringu. Na przykład, zamiast zwiększając e I o p ı w etapie 2, można ją zwiększyć p ı x losowej (0, 2), w której losowy ( , b ) jest równomiernie rozproszony liczby losowej o wartości pomiędzy i b ; dałoby to wynik podobny do następującego:
A B B C A B A A B A A B A B A A B A A A B C A B A B A C A B
lub możesz zwiększyć e i o p i + losowo (- c , c ), co dałoby (dla c = 0,1 × s ):
B A A B C A B A B A B A B A C A B A B A B A A B C A B A B A
lub, dla c = 0,5 × s :
B A B A B A C A B A B A A C B C A A B C B A B B A B A B C A
Zauważ, że schemat addytywny ma znacznie silniejszy efekt losowy dla rzadkich zdarzeń C niż dla wspólnych zdarzeń A i B, w porównaniu do multiplikatywnego; to może, ale nie musi być pożądane. Oczywiście, można również korzystać z niektórych kombinacji tych systemów, lub jakiegokolwiek innego dostosowywania do przyrostów, jak długo zachowuje właściwość, że średni przyrost e ja równa P I .
Alternatywnie można zakłócać wyjście algorytmu ditheringu, czasami zastępując wybrane zdarzenie k losowym (wybranym zgodnie z surowymi wagami p i ). Tak długo, jak użyjesz tego samego k w kroku 3, jak wypisujesz w kroku 2, proces ditheringu będzie miał tendencję do wyrównywania przypadkowych fluktuacji.
Na przykład, oto przykładowy wynik, z 10% szansą na losowe wybranie każdego zdarzenia:
B A C A B A B A C B A A B B A B A B A B C B A B A B C A B A
a oto przykład z 50% szansą, że każde wyjście będzie losowe:
C B A B A C A B B B A A B A A A A A B B A C C A B B A B B C
Można również rozważyć karmienie mieszankę czysto losowych i wygładzony wydarzeń na pokładzie / mieszania basenie, jak opisano powyżej, lub może losowanie algorytm ditheringu wybierając k losowo, jako ważone przez e i s (leczenia negatywnych ciężarów jako zero).
Ps. Oto kilka całkowicie losowych sekwencji zdarzeń, z tymi samymi średnimi wskaźnikami, dla porównania:
A C A A C A B B A A A A B B C B A B B A B A B A A A A A A A
B C B A B C B A A B C A B A B C B A B A A A A B B B B B B B
C A A B A A B B C B B B A B A B A A B A A B A B A C A A B A
Styczna: Ponieważ w komentarzach pojawiła się debata na temat tego, czy w przypadku rozwiązań pokładowych konieczne jest umożliwienie opróżnienia pokładu przed ponownym napełnieniem, postanowiłem dokonać graficznego porównania kilku strategii napełniania pokładu:
Wykres kilku strategii generowania pół losowych rzutów monetą (przy średnim stosunku główek do reszek wynoszącym 50:50). Oś pozioma to liczba przewrotów, oś pionowa to skumulowana odległość od oczekiwanego stosunku, mierzona jako (głowice - ogony) / 2 = głowice - przewroty / 2.
Czerwone i zielone linie na wykresie pokazują dwa niepoparte na pokładzie algorytmy do porównania:
- Czerwona linia, deterministyczne dithering : wyniki parzyste są zawsze główkami, wyniki nieparzyste zawsze są ogonami.
- Zielona linia, niezależne losowe rzuty : każdy wynik jest wybierany niezależnie losowo, z 50% szansą na głowy i 50% szansą na reszkę.
Pozostałe trzy linie (niebieski, fioletowy i cyjan) pokazują wyniki trzech strategii opartych na talii, z których każda została wdrożona przy użyciu talii 40 kart, która początkowo jest wypełniona 20 kartami „głów” i 20 kartami „ogonów”:
- Niebieska linia, wypełnij, gdy jest pusta : Karty losowane są do momentu, aż talia będzie pusta, a następnie do talii zostaną napełnione 20 kart „głów” i 20 kart „ogonów”.
- Purpurowa linia, wypełnij, gdy połowa będzie pusta : Karty losowane są do momentu, gdy w talii pozostanie 20 kart; następnie talię uzupełnia się 10 kartami „głów” i 10 kartami „ogonami”.
- Cyjan-linia, wypełniaj w sposób ciągły : karty losowane są losowo; losowanie parzyste jest natychmiast zastępowane kartą „głów”, a losowanie nieparzyste kartą „reszka”.
Oczywiście powyższy wykres jest tylko pojedynczą realizacją losowego procesu, ale jest dość reprezentatywny. W szczególności widać, że wszystkie procesy pokładowe mają ograniczone odchylenie i pozostają dość blisko czerwonej (deterministycznej) linii, podczas gdy czysto losowa zielona linia ostatecznie odchodzi.
(W rzeczywistości odchylenie linii niebieskiej, purpurowej i niebieskiej od zera jest ściśle ograniczone rozmiarem talii: niebieska linia nigdy nie może dryfować więcej niż 10 kroków od zera, fioletowa linia może uzyskać tylko 15 kroków od zera , a linia cyjanowa może dryfować co najwyżej o 20 kroków od zera. Oczywiście w praktyce żadna z linii, która faktycznie osiąga swój limit, jest bardzo mało prawdopodobna, ponieważ istnieje silna tendencja do powrotu bliżej zera, jeśli wędrują zbyt daleko poza.)
Na pierwszy rzut oka nie ma oczywistej różnicy między różnymi strategiami opartymi na talii (chociaż średnio niebieska linia pozostaje nieco bliżej czerwonej linii, a linia cyjanowa pozostaje nieco dalej), ale dokładniejsze sprawdzenie niebieskiej linii ujawnia wyraźny deterministyczny wzór: co 40 rysunków (oznaczonych przerywanymi szarymi pionowymi liniami) niebieska linia dokładnie spotyka czerwoną linię na zero. Linie fioletowe i cyjanowe nie są tak ściśle ograniczone i mogą trzymać się zera w dowolnym momencie.
We wszystkich strategiach opartych na talii ważną cechą, która ogranicza ich warianty, jest fakt, że podczas losowania kart z talii, determinacja jest uzupełniana . Gdyby karty użyte do uzupełnienia talii były wybierane losowo, wszystkie strategie oparte na talii byłyby nie do odróżnienia od czystego losowego wyboru (zielona linia).