Önceki olaylar tarafından önyargılı bir “rastgele” üreteci nasıl yapabilirim?


37

Önceki olayın önyargılı olduğu, şansa dayalı bir sistemi hayata geçirmek istiyorum.

Arkaplan: Birkaç yıl önce, World of Warcraft için bir güncelleme hatırlıyorum, çünkü olayların dikenli zincirlerine karşı koyacak yeni bir şans hesaplayıcı kullandıklarını duyurdum. (örneğin kritik grevler yapmak veya arka arkaya birkaç kez kaçmak). Buradaki fikir, bir vuruntuyu atlatmanız durumunda, bir sonraki vuruşu atlatmanız olasılığının azalması, ancak her iki şekilde de işe yaramasıydı. Bir isabet atlatmamak, bir sonraki isabetten kaçma şansını eşit olarak arttırır. Buradaki en önemli numara, birkaç denemede dodge şansının, oyuncuya kendi statüsünde verilen oranla hala aynı olmasıydı.

Bu tür bir sistem o zamanlar beni çok etkiledi ve şimdi böyle bir çözüme ihtiyaç duyma durumundayım.

İşte benim sıkıntılarım:

  • Sanırım böyle bir sistemin uygulanmasında çevrimiçi kaynaklar bulabileceğimi tahmin ediyorum, ancak onu bulmak için alakalı buzz kelimelerinden yoksun olabilirim.
  • Ayrıca, bu yaklaşıma binom olmayan (yani iki sonuç) olan bir sisteme uymak için ihtiyacım var, bunun yerine karşılıklı olarak 4 özel olay içeriyor.

Şu anki yaklaşımım, bir piyango bileti sistemine benzer. Bir olay meydana geldiğinde ağırlıkları diğer bütün olayların lehine değiştiririm. Dört olay eşit derecede muhtemel olsaydı bu olabilirdi, ama benim durumumda, çok daha yaygın olması gerekiyordu. Ancak, yaygın etkinlik daha sık gerçekleştiğinden, diğerinin ağırlığını amaçlanandan çok daha fazla kaydırır ve ortalama biletin etkinliğin başlangıç ​​değerleri etrafında sayılmasını sağlamak için gereken ağırlık kaymalarının sayılarını bulamıyorum. verilen.

Birkaç yön işaretçisi veya net bir kesim örneği çok takdir edilecektir.


4
Nüanslı veya sofistike bir cevap istiyorsanız, Matematik'te sormakta daha fazla şansınız olabilir. Oradaki matematikçiler olasılıkla ilgili karmaşık soruları cevaplarken rahatlar. math.stackexchange.com
Kevin - Monica'yı yeniden


6
Cevapları anlama ihtimaliniz daha yüksek olan Matematik sitesine alternatif bir programcıdır . Algoritma tasarımı, özellikle Math'da konuyla ilgili değildir ve yararlı bir girdi elde etmek için muhtemelen bir ilk tasarım bulmanız gerekir.
Lilienthal

1
Kevin ve Lilienthal ile orada daha iyi bir cevap alabileceğinize katılıyorum, ancak mklingen'in cevabını okumak, burada anlatılanın bir Markov zinciri olarak modellenebileceğini ve oyun geliştiricilerin bilmesi için kullanışlı bir araç olabileceğini anladım. Bunu daha sonra daha ayrıntılı olarak yazmaya çalışacağım.
Hoşgeldiniz,

1
Buradaki bazı cevapların rakamlarını çalıştırdığım için, birtakım farklı kısıtlamalar olduğunu ve hepsini çözen bir çözümün ihtiyacınız olandan daha karmaşık olabileceğini düşünüyorum. Kullanım durumunuzla ilgili daha ayrıntılı bilgi, en iyi seçeneklerin daraltılmasına yardımcı olabilir. Örneğin, etkinliklerinizin olasılıkları oldukça benzer mi (örneğin, her biri% 20 şansla 5 farklı sonuç) veya çok farklı mı (ör.% 10 özledim% 80'i% 10 kritik vurdu)? Koşuyu en aza indirmek ister misiniz (ör. Arka arkaya 3 özledim) veya kümeleri / bekletmeleri (ör. 8 denemeden 3 özeti veya kritik olmadan 20 denemeyi).
DMGregory

Yanıtlar:


19

Temel olarak, istediğiniz şey, aşağıdaki özelliklere sahip olaylar oluşturan "yarı rastgele" bir etkinlik oluşturucusudur:

  1. Her olayın gerçekleştiği ortalama oran önceden belirlenir.

  2. Aynı olayın art arda iki kez artması muhtemeldir.

  3. Olaylar tam olarak tahmin edilebilir değildir.

Bunu yapmanın bir yolu, ilk önce 1. ve 2. hedefleri karşılayan rastgele olmayan bir olay üreteci uygulamak ve ardından 3. hedefi yerine getirmek için bazı rasgelelikler eklemektir.


Rasgele olmayan olay üreteci için basit bir titreme algoritması kullanabiliriz. Spesifik olarak, p 1 , p 2 , ..., p n , 1 ila n olaylarının nispi olasılıkları ve s = p 1 + p 2 + ... + p n ağırlıkların toplamı olsun. Daha sonra aşağıdaki algoritmayı kullanarak rastgele olmayan bir maksimum eşitlik dağıtılmış olay dizisi oluşturabiliriz:

  1. Başlangıçta, e 1 = e 2 = ... = e n = 0 olsun.

  2. Bir olayı oluşturmak için, her bir arttırmak e ı ile p I ve çıkış olay k olan E k (bağları istediğiniz şekilde kırma) en büyüğüdür.

  3. Eksiltme e k ile s ve basamak 2'den elde edilen tekrar.

Örneğin, üç A, B ve C olayı göz önüne alındığında, p A = 5, p B = 4 ve p C = 1 ile, bu algoritma aşağıdaki çıktı dizisi gibi bir şey üretir:

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

Bu 30 olay dizisinin tam olarak 15 As, 12 Bs ve 3 C içerdiğine dikkat edin. O değil oldukça optimal dağıtır - önlenebilirdi olabilirdi üst üste iki As birkaç oluşumları vardır - ama yakın alır.


Şimdi, bu diziye rasgelelik eklemek için, birkaç (zorunlu olarak birbirini dışlayan değil) seçeneğiniz vardır:

  • Sen takip edebilirsiniz Philipp'in tavsiyesi ve bir "güverte" korumak N bazı uygun boyutta sayı için, yaklaşan etkinlikler N . Bir etkinlik oluşturmak istediğiniz her seferde, desteden rastgele bir etkinlik seçersiniz ve ardından yukarıdaki dithering algoritmasıyla bir sonraki etkinlik çıktısıyla değiştirirsiniz.

    Bunu yukarıdaki örneğe N = 3 ile uygulamak, örneğin:

    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

    oysa , N 10 verim = daha rasgele görünümlü:

    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

    Yaygın A ve B olaylarının karışma nedeniyle daha çok nasıl sonuçlandığını, oysaki nadir görülen C olaylarının hala oldukça iyi aralıklarla yapıldığını unutmayın.

  • Bazı rasgeleliği doğrudan dithering algoritmasına enjekte edebilirsiniz. Örneğin, yerine artan bir e i ile p ı aşama 2'de, bunu aşağıdaki şekilde artırmak olabilir p ı (rastgele x rastgele (0, 2), bir , b ) bir muntazam biçimde rastgele sayı dağıtılır bir ve b ; bu, aşağıdaki gibi çıktı verir:

    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

    ya da olabilir artış e ı ile p i + rasgele - ( C , C (için üretecektir), c = 0.1 x 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

    veya, c = 0.5 × s için :

    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

    Katkı şemasının, nadir olay C için, ortak olay A ve B'den ziyade, çoğaltıcı olana kıyasla daha güçlü bir randomize etkiye sahip olduğuna dikkat edin; bu arzu edilebilir veya olmayabilir. O mülkü korur olarak Tabii ki, aynı zamanda sürece, bu şemalarda veya artışlarla başka herhangi bir ayarlama bazı kombinasyonlarını kullanabilirsiniz ortalama sayısının artmaya e i eşittir P i .

  • Alternatif olarak, perturb olabilir çıkış bazen seçilen olay yerine Titreme algoritma k (ham ağırlıkları göre seçilen rastgele bir ile p i ). Sürece aynı kullandıkça k 2. adımda size çıktı olarak 3. adımda, titreme işlemi bile hala rasgele dalgalanmaların dışarı eğiliminde olacaktır.

    Örneğin, bazı örnek çıktılar, rastgele seçilen her olayın% 10'uyla:

    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

    ve işte her bir çıkışın% 50 tesadüf rastgele olduğu bir örnek:

    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

    Yukarıda tarif edildiği gibi, aynı zamanda, bir güverte / karıştırma havuza tamamen rastgele ve titretilmiş etkinlikleri kanşımını besleme dikkate veya belki seçerek Titreme algoritması randomize olabilir k ile tartılır olarak, rastgele e ı s (sıfır negatif ağırlıkları tedavisi).

Ps. Karşılaştırma için aynı ortalama oranlara sahip bazı tamamen rastgele olay dizileri:

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

Tanjant: olmuştur yana yorumlarda bazı tartışmalar o doldurulmuş edilmeden önce güverte boşaltmak için izin vermek, güverte tabanlı çözümler için gerekli olup olmadığı hakkında, ben birkaç güverte-dolum stratejilerinin grafiksel karşılaştırma yapmaya karar:

Arsa
Yarı rastgele bozuk para üretme stratejilerinin bir kısmı (ortalama olarak 50:50 kafa oranı kuyruk oranıyla). Yatay eksen, kat sayısıdır, dikey eksen, beklenen orandan kümülatif mesafedir, (kafalar - kuyruklar) / 2 = kafalar - parmaklar / 2 olarak ölçülür.

Çizimdeki kırmızı ve yeşil çizgiler karşılaştırma için iki güverte temelli olmayan algoritmalar göstermektedir:

  • Kırmızı çizgi, deterministik titizlik : çift numaralı sonuçlar her zaman kafa, tek sayılı sonuçlar her zaman kuyruktur.
  • Yeşil çizgi, bağımsız rasgele çevirmeler : her sonuç,% 50 kafa şansı ve% 50 kuyruk şansı ile rastgele bağımsız olarak seçilir.

Diğer üç satır (mavi, mor ve camgöbeği), her biri başlangıçta 20 adet "kafa" kartı ve 20 adet "kuyruk" kartıyla doldurulmuş 40'lık desteden oluşan üç deste tabanlı stratejinin sonuçlarını göstermektedir:

  • Mavi çizgi, boşken doldurun : Deste boşalana kadar kartlar rasgele çekilir, daha sonra deste 20 "kafa" kartı ve 20 "kuyruk" kartı ile doldurulur.
  • Mor çizgi, yarı boş olduğunda doldur : Kartlar destede 20 tane kalıncaya kadar rastgele çekilir; daha sonra desteye 10 adet "kafa" kartı ve 10 adet "kuyruk" kartı yerleştirilir.
  • Mavi çizgi, sürekli doldurma : Kartlar rastgele çekilir; çift ​​sayılı çekilişler hemen "kafa" kartıyla değiştirilir ve tek sayılı çekilişler "uç" kartıyla derhal değiştirilir.

Tabii ki, yukarıdaki komplo rastgele bir sürecin sadece tek bir gerçekleşmesidir, ancak makul temsilcisidir. Özellikle, tüm güverte tabanlı işlemlerin sınırlı önyargıya sahip olduğunu görebilir ve kırmızı (deterministik) çizgiye oldukça yakın kalabilirsiniz, oysa tamamen rastgele yeşil çizgi sonunda kaybolur.

(Aslında, mavi, mor ve mavi çizgilerin sıfırdan uzağa sapması kesinlikle güverte boyutuyla sınırlıdır: mavi çizgi asla sıfırdan 10 adımdan daha fazla uzaklaşamaz, mor çizgi sıfırdan sadece 15 adım alabilir ve camgöbeği çizgisi sıfıra en fazla 20 adım mesafede sürüklenebilir.Tabii ki, pratikte, sınırına ulaşan çizgilerin herhangi birinin son derece düşük olması muhtemeldir, çünkü çok fazla dolaşırlarsa sıfıra yaklaşma eğilimi güçlüdür. kapatır.)

Bir bakışta, farklı güverteye dayalı stratejiler arasında belirgin bir fark yoktur (ortalama olarak mavi çizgi kırmızı çizgiye biraz daha yakın dursa da ve mavi çizgi biraz uzağa kalsa da), ancak mavi çizginin daha yakından incelenmesi belirgin bir deterministik desen ortaya koyuyor: her 40 çizimde (noktalı gri dikey çizgilerle işaretlenmiştir), mavi çizgi tam olarak kırmızı çizgide sıfır noktasında buluşuyor. Mor ve mavi çizgiler çok sıkı bir şekilde sınırlandırılmamıştır ve herhangi bir noktada sıfırdan uzak kalabilir.

Tüm güverte tabanlı stratejiler için değişkenliklerini sınırlayan önemli özellik, kartların desteden rasgele çekilirken destenin belirleyici olarak doldurulmasıdır . Desteyi yeniden doldurmak için kullanılan kartların kendileri rastgele seçildiyse, desteye dayalı stratejilerin tümü saf rastgele seçimden (yeşil hat) ayırt edilemez hale gelirdi.


Çok ayrıntılı cevap. Titreşim algoritmasına rastgele faktörler eklemek oldukça basit görünüyor. :)
15'de Sonat, 08:05

Cevabınız ile gitmeye karar verdi. :) Ama yönteme genel bakış eklerini en üste koymanı tavsiye ederim. Cevabınıza dayanarak yapacağım şey hem "Kırmızı" hem de "Mor" çözümü denemek.
Son

53

Zar atma, kart dağıtma.

RNG'nizin olası tüm sonuçlarını alın, bir listeye yerleştirin, rastgele karıştırın ve sonuçları rasgele sırayla alın. Listenin sonunda, tekrarlayın.

Sonuçlar hala eşit olarak dağıtılacak, ancak listenin sonuncusu da bir sonrakinin ilki olmadıkça, bireysel sonuçlar tekrarlanmayacak.

Bu, zevkinize göre biraz fazla öngörülebilir olduğunda n, olası sonuçların sayısının çarpımını gösteren bir listeyi kullanabilir ve her olası sonucu nkarıştırmadan önce bu sürelere koyabilirsiniz . Ya da tamamen yenilenmeden listeyi değiştirebilirsin.


1
"shuffle bag" araması (bu sitede bile)
Şubat'ta

3
Bu, Tetris oyunlarının çoğunun müzikçaları anahtar parçaları için çok uzun süre aç bırakmasından kaçınmasıdır. Olayları belirli bir süre zarfında kontrol etmek istiyorsanız, yeni kart takmadan önce Philipp'in önerdiği gibi torbayı / desteyi boşaltmak önemlidir. Kartları ilerledikçe yeniden takarak (veya ağırlıkları yeniden ayarlayarak), olasılık dağılımını hesaplanması zor ve yanlış anlaşılması kolay şekillerde bozabilirsiniz.
DMGregory

2
@DMGregory: Aslında, güverte boşaltılmadan önce yeni kartlarla karıştırmak tamamen iyidir (ve aslında, sonuçları daha doğal ve tahmin etmeyi zorlaştırmak için bunu yapmayı tavsiye ederim). Önemli olan karıştırılır yeni kartların (ortalama) fraksiyon emin olmaktır içine güverte çizmek istediğiniz istenen fraksiyonu eşittir dışarı bunun.
Ilmari Karonen

4
Illmari Karonen: Eşyaları değiştirdiğinizde, aynı sonuçların sınırlandırılması veya belirli sonuçlar arasındaki uzun boşlukların sınırlandırılması açısından karışık poşetin faydalarını kaybedebilirsiniz. Eğer yenileme oranınız hedef olasılık dağılımına eşitse, şimdi her sonucu bağımsız olarak rastgele oluşturmakla aynı pozisyondasınız demektir. Hedef olasılık dağılımına eşit değilse, o zaman etkili olasılıkları buna göre tahmin etmenin ve dengelemenin zor olduğu şekillerde çözebilirsiniz - asker tam olarak bu konuyla mücadele etmeyi açıklar.
DMGregory

2
@DMGregory ile anlaştı. Yeni kartlara karıştırarak, sistemin kendisini geçersiz kılarsınız. Kart işlem sistemi, istenen sonuç için özel olarak ve mükemmel şekilde uygundur. Örneğin, bir kraliçeyi (örneğin geleneksel kartları kullanmak için) desteden çıkardığınızda, bir kraliçenin çizilme olasılığı azalır ve bir kraliçeden başka bir kart çekme olasılığı artar. İstersen, kendini ayarlayan bir sistem.
Volte

17

Bir Markov Rastgele Grafiği deneyebilirsiniz . Grafikte bir düğüm olarak oluşabilecek her olayı göz önünde bulundurun. Her olaydan sonra, olayı takip edebilecek başka bir olayla bağlantı kurun. Bu bağlantıların her biri, geçiş olasılığı olarak adlandırılan bir şey tarafından ağırlıklandırılır . Ardından, geçiş modeline göre grafiğin rastgele bir yürüyüşünü gerçekleştirirsiniz.

Örneğin, bir saldırının sonucunu temsil eden bir grafiğe sahip olabilirsiniz (kritik vuruş, kaçma vb.). Oyuncunun istatistiklerini verilen başlangıç ​​düğümünü rastgele seçilen birine başlat (sadece "zar at"). Ardından, bir sonraki saldırıda, geçiş modeli göz önüne alındığında ne olacağına karar verin.

Geçişlerin nasıl ağırlıklandırılacağına karar vermek için özen gösterilmelidir. Bir şey için, bir düğümden gelen tüm geçişlerin 1 olasılığını arttırması gerekir. Yapabileceğiniz basit bir şey, bu düğümlerin gerçekleşmesi olasılığına eşdeğer ağırlıklar ile her düğümden diğer düğümlere bir geçiş yapmaktır. Mevcut olayın bir daha gerçekleşemeyeceği düşünüldüğünde, bir priori .

Örneğin, üç etkinliğiniz varsa:

  Critical, P = 0.1
  Hit,      P = 0.3
  Miss,     P = 0.6

Geçiş modelini, kritik bir vuruşun, olasılık kütlesini diğer olaylara eşit şekilde yeniden dağıtarak yeniden gerçekleştirmeyeceği şekilde tekrar oluşmayacak şekilde ayarlayabilirsiniz:

  Critical -> Critical,   P = 0.0
  Critical -> Hit,        P = 0.35
  Critical -> Miss,       P = 0.65

EDIT: Aşağıdaki yorumlar, bu modelin istenen davranışı sağlayacak kadar karmaşık değildir. Bunun yerine, birden fazla ek durum eklemeniz gerekebilir!


1
Teklif ettiğiniz yeniden değerlendirme programı, her bir durumun istenen olasılıklarını korumaz. Bu sayılarla ampirik bir test yaparak, özlüyor zamanın yaklaşık% 41'i ve Kritikler% 25'i gibi, giriş değerlerinden uzaklaşıyor. Olasılıklarıyla orantılı kalan devletlere geçiş (örneğin, Miss'in Kritere gitme şansı% 25, ​​Hit'e gitme şansı% 75),% 44'lük bir oran ve% 17'lik eleştirmen ile biraz daha iyi, ancak hala Girdide istenen olasılıkları yansıtmaz.
DMGregory

Ben Bayes :( daha sonra tekrar yeniden hesaplamak Will kural unuttum o CCHM veya CHHM veya çok büyük olasılıkla MMHM vb gibi olası dizilerin dışarı yaprakları haliyle geçiş modeli, çünkü önceki olasılık dağılımını sağlamak mümkün olmayabilir.
mklingen

"Hiçbir tekrar yok" kısıtlaması, burada aşırı yüksek ve düşük ağırlıklara bağlı olarak ellerini bağlayabilir. 10 denemeden 1'inin Kritik olmasını istiyorsanız, bu yöntemin yerine getirmenin tek yolu, 5 & 5 isabetini değiştirmektir; Ardışık özlemler olmadan hiçbir dizi, buradaki girdi gereksinimlerini karşılayamaz.
DMGregory

4
@mklingen, DMGregory ile aynı fikirdeyim, "kesinlikle tekrar yok" burada istenmiyor. Daha ziyade, aynı sonuçtaki uzun zincirlerin, tekdüze bir rastgele olasılıkla olacağından daha az muhtemel olmasını isterler. Sen bakışlar ister ki (yönlendirilir) bir Markov Zinciri ile bu yapabileceğini bu . Bu, "Hit 1" den "Hit 2" ye ve "Hit 2" den "Hit 3+" e geçiş olasılıklarının düştüğü ve "Hit 1" ve "Crit" e dönüş olasılıklarının düştüğü tekrarlanan olayları temsil etmek için birden fazla durum kullanır. 1 "yukarı çık.
karşılama

@ hoş geldiniz bu harika bir fikir.
mklingen

3

İşte C # ile yarattığım bir uygulama:

  • Olasılıklara dayalı olayları etkinleştirme
  • Tekrarlanan olayların şansını azaltmak için bu olasılıkları ayarlayın
  • Orijinal olasılıklardan çok uzak değil

Ne yaptığımı görebilmeniz için birkaç yorum ekledim.

    int percentageEvent1 = 15; //These are the starter values. So given a scenario, the
    int percentageEvent2 = 40; //player would have around a 15 percent chance of event
    int percentageEvent3 = 10; //one occuring, a 40 percent chance of event two occuring
    int percentageEvent4 = 35; //10 percent for event three, and 35 percent for event four.

    private void ResetValues()
    {
        percentageEvent1 = 15;
        percentageEvent2 = 40;
        percentageEvent3 = 10;
        percentageEvent4 = 35;
    }

    int resetCount = 0; //Reset the probabilities every so often so that they don't stray too far.

    int variability = 1; //This influences how much the chance of an event will increase or decrease
                           //based off of past events.

    Random RandomNumberGenerator = new Random();

    private void Activate() //When this is called, an "Event" will be activated based off of current probability.
    {
        int[] percent = new int[100];
        for (int i = 0; i < 100; i++) //Generate an array of 100 items, and select a random event from it.
        {
            if (i < percentageEvent1)
            {
                percent[i] = 1; //Event 1
            }
            else if (i < percentageEvent1 + percentageEvent2)
            {
                percent[i] = 2; //Event 2
            }
            else if (i < percentageEvent1 + percentageEvent2 + percentageEvent3)
            {
                percent[i] = 3; //Event 3
            }
            else
            {
                percent[i] = 4; //Event 4
            }
        }
        int SelectEvent = percent[RandomNumberGenerator.Next(0, 100)]; //Select a random event based on current probability.

        if (SelectEvent == 1)
        {
            if (!(percentageEvent1 - (3 * variability) < 1)) //Make sure that no matter what, probability for a certain event
            {                                                //does not go below one percent.
                percentageEvent1 -= 3 * variability;
                percentageEvent2 += variability;
                percentageEvent3 += variability;
                percentageEvent4 += variability;
            }
        }
        else if (SelectEvent == 2)
        {
            if (!(percentageEvent2 - (3 * variability) < 1))
            {
                percentageEvent2 -= 3 * variability;
                percentageEvent1 += variability;
                percentageEvent3 += variability;
                percentageEvent4 += variability;
            }
        }
        else if (SelectEvent == 3)
        {
            if (!(percentageEvent3 - (3 * variability) < 1))
            {
                percentageEvent3 -= 3 * variability;
                percentageEvent1 += variability;
                percentageEvent2 += variability;
                percentageEvent4 += variability;
            }
        }
        else
        {
            if (!(percentageEvent4 - (3 * variability) < 1))
            {
                percentageEvent4 -= 3 * variability;
                percentageEvent1 += variability;
                percentageEvent2 += variability;
                percentageEvent3 += variability;
            }
        }

        resetCount++;
        if (resetCount == 10)
        {
            resetCount = 0;
            ResetValues();
        }

        RunEvent(SelectEvent); //Run the event that was selected.
    }

Bu yardımcı olur umarım, lütfen yorumlarda bu koda iyileştirmeler önerin, teşekkürler!


1
Bu yeniden canlandırma şeması olayların denkleştirilebilir olmasına yol açma eğilimindedir. Ağırlıkların periyodik olarak sıfırlanması gerçekten ne kadar kötüye gittiğini sınırlayan bir yara bandıdır ve 10 rulodan 1'inin yeniden yapılanmadan hiçbir şekilde faydalanmamasını sağlar. Ayrıca, bir algoritma notu: rastgele seçiminizi yapmak için 100 girişli bir tablo doldurarak çok fazla iş harcıyorsunuz. Bunun yerine, rastgele bir rulo oluşturabilir ve ardından 4 sonucunuz üzerinde yineleyerek, ilerledikçe olasılıklarını toplayabilirsiniz. Toplama toplamdan daha az olduğu sürece, sonuç size aittir. Tablo doldurma gerekmez.
DMGregory

3

Mklings'ın cevabını biraz genelleştireyim . Temel olarak, burada daha genel bir yöntem sunacağım halde , Kumarbazın Hatalılığını uygulamak istiyorsunuz :

Diyelim ki nmuhtemel olaylar var p_1, p_2, ..., p_n. Olay igerçekleştiğinde, olasılığı bir faktörle 0≤a_i≤1/p_iartacaktır (ikincisi önemlidir, aksi takdirde bir taneden büyük bir olasılıkla sonuçlanırsınız ve diğer olayların negatif olasılıklara sahip olması gerekir , bu temelde " anti " olayları veya başka bir şey anlamına gelir ). tipik olarak a_i<1. Örneğin a_i=p_i, ikinci bir kez meydana gelen bir olayın olasılığının, olayın arka arkaya tam olarak iki kez meydana geldiği orijinal olasılığını, örneğin, ikinci bir madeni para fırınının 1/2 yerine 1/4 olasılığına sahip olacağını seçebilirsiniz . Öte yandan, a_i>1"şans / talihsizlik felç" tetiklemek anlamına da gelir, bazı da olabilir .

Diğer tüm olaylar birbirine göre eşit olarak muhtemel kalacaktır; yani b_i, tüm olasılıkların toplamının bir diğerine eşit olacağı şekilde aynı faktörle yeniden ölçeklendirilmeleri gerekir.

1 = a_i*p_i + b_i*(1-p_i)  # Σ_{j≠i) p_j  = 1 - p_i
 b_i = (1 - a_i*p_i) / (1 - p_i).   (1)

Şimdiye kadar, çok basit. Ancak şimdi başka bir gereklilik ekleyelim: İki olayın tüm olası dizileri göz önüne alındığında, bunlardan elde edilen tek olay olasılıkları orijinal olasılıklar olacaktır.

İzin Vermek

        / p_i * b_i * p_j  (ji)
p_ij = <
        \ a_i * (p_i     (j=i)

olaydan jsonra olayı olasılığını belirtir ve ( neyin ima ettiği ) olmadığını inot edin . Bu aynı zamanda Bayes teoreminin gerektirdiği şeydir ve bu da ima eder.p_ij≠p_jib_i=b_j (2)(1)a_j = 1 - a_i*p_i + (1-a_i)*p_i/p_j

Σ_j p_ij = p_i * b_i * (1 - p_i) + a_i * (p_i
         = b_i * p_i + (a_i - b_i) * (p_i
         = p_i  # using (1)

tam istediğiniz gibi. Bunun birisinin a_idiğerlerini nasıl düzelttiği anlamına geldiğine dikkat edin .


Şimdi bu prosedürü birkaç kez uyguladığımızda, yani üç ve daha fazla olayın dizileri için ne olacağını görelim. Üçüncü etkinliğin hileli olasılıklarının seçimi için temel olarak iki seçenek vardır:

a) İlk olayı unutun ve kulenin yalnızca ikincisinin gerçekleştiğini düşünün, örn.

         / p_ij * a_j * p_j  (j=k)
p_ijk = <
         \ p_ij * b_j * p_l  (jk)

Bunun genellikle Bayes'i ihlal ettiğini unutmayın, çünkü p_jik≠p_ikjçoğu durumda.

b) Olası olay için yeni olasılıkları elde ettiğiniz yeni olasılıklar olarak olasılıkları p_ij(sabit için ) kullanın . Değiştirip değiştirmemek size kalmış, ancak değiştirilenden dolayı yenilerin kesinlikle farklı olduğunu unutmayın . Sonra tekrar, muhtemelen aynı olasılıkta meydana gelen tüm permütasyonları gerektirerek seçimi sınırlandırır . Bakalım...ipi_jpi_jkkai_jbi_jpi_jai_jijk

         / p_ij * bi_j * pi_k  (jk)
p_ijk = <
         \ (p_ij * ai_j      (j=k)

         / b_i * bi_j * p_i * p_j * pi_k  (ijki)
         | b_i * ai_j * p_i * (p_j      (ij=k)
      = <  a_i * (p_i * bi_i * pi_k     (i=jk)
         | b_i * p_i * bi_j * p_k * pi_i  (i=kj)
         \ a_i * ai_i * (p_i * pi_i     (i=k=j)

ve bunların ilgili durumlar için eşit olması gereken döngüsel permütasyonları.

Korkarım bu konuda devam edeceğim bir süre beklemek zorunda kalacak ...


Bunu deneysel olarak test etmek, bu hala birçok olasılık üzerinde girdi olasılıklarından uzakta bir çarpıtma ile sonuçlanmaktadır. Örneğin, eğer a_i / p_i = 0.5 ise (ve mklingen'in cevabındaki sayıları kullanarak)% 60'lık bir giriş oranı% 50.1'lik bir gözlenen orana,% 10'luk bir girdi kritik oranı% 13.8 olarak gözlenir. Bunu, ortaya çıkan geçiş matrisini yüksek bir güce ulaştırarak doğrulayabilirsiniz. A_i: p_i oranlarının 1'e yakın seçilmesi, daha az bozulma ile sonuçlanır, aynı zamanda azaltma işlemlerinde daha az etkinlik ile sonuçlanır.
DMGregory

@DMGregory iyi nokta: basitçe geçiş matrisinin yetkilerini alamazsınız. Cevabımı daha sonra genişleyeceğim
Tobias Kienzler

@DMGregory Tüm süreci anlatmaya başladım (b değişkeni), ancak oldukça sıkıcı oluyor ve şu anda zamanım kısa: /
Tobias Kienzler

1

Bence en iyi seçenek, rastgele ağırlıklı eşya seçimini kullanmak. Burada C # için bir uygulama var , ancak diğer diller için de kolayca bulunabilir veya yapılabilir.

Buradaki fikir, bir seçeneğin her seçildiği zaman ağırlığını azaltmak ve her seçilmediğinde onu arttırmak olacaktır.

Örneğin, seçilen seçeneğin ağırlığını azaltıp, NumOptions-1diğer her seçeneğin ağırlığını 1 oranında artırırsanız (<0 olan öğeleri kaldırmaya dikkat edin ve 0'ın üstüne çıktığında bunları okuyun) , her seçenek yaklaşık olarak seçilecektir. Uzun bir süre boyunca aynı sayıda, ancak son zamanlarda seçilen seçeneklerin seçilmesi çok daha düşük olacaktır.


Diğer birçok cevabın önerdiği gibi rastgele bir sıralamanın kullanılmasındaki problem, her seçeneğin seçilmesinden sonra bir tanesinin seçilmesinden sonra,% 100 kesinlikte daha sonra hangi seçeneğin seçileceğini tahmin edebilmenizdir. Bu çok rastgele değil.


1

Cevabım yanlış, sınavım hatalıydı.

Bu cevabı, bu tasarımdaki kusurları belirten tartışma ve yorumlar için burada bırakıyorum, ancak gerçek test yanlıştı.

Aradığın şey, ağırlıklı bir ağırlıktır: dört olası sonucunuz için ağırlıkların, yine de genel olarak uygun ağırlıklar kalırken, önceki sonuçlara göre daha da ayarlanması gerekir.

Bunu başarmanın en kolay yolu, her bir rulo için tüm ağırlıkları değiştirerek, haddelenmiş olan spesifik değerin ağırlığını azaltarak ve diğer ağırlıkları artırarak değiştirmektir .

Örnek olarak, 4 ağırlığınız olduğunu varsayalım: Fumble, Miss, Hit ve Crit. Diyelim ki onlar için istediğiniz genel ağırlıkları Fumble =% 10, Bayan =% 50, Hit =% 30 ve Crit =% 10'dur.

1 ile 100 arasında değerler üretmek için rastgele bir sayı üreteci (RNG) kullanıyorsanız ve bu değeri bu aralığın içindeki bölgeyle karşılaştırırsanız (1-10 Fumble, 11-60 miss, 61-90 hit, 91-100 crit ), bireysel bir rulo üretiyorsunuz.

O ruloyu yaptığınızda, o zaman aralıkları hemen haddelenmiş değere göre ayarlarsanız, gelecekteki ruloları ağırlıklandıracaksınız, ancak hadde ağırlığını diğer ağırlıkları artıracağınız toplam miktar kadar azaltmanız da gerekir . Yani yukarıdaki örneğimizde, haddelenmiş ağırlığı 3 azaltacak ve diğer ağırlıkları her biri 1 artıracaksınız.

Bunu her bir rulo için yaparsanız, yine de çizgi çekme şansına sahip olacaksınız, ancak bunlar büyük ölçüde azalacak çünkü her bir rulo için gelecekteki ruloların mevcut rulodan başka bir şey olma şansını arttırıyorsunuz. Bu etkiyi artırabilir ve böylece ağırlıkları daha büyük bir faktörle artırarak / azaltarak (örneğin akımı 6 azaltıp diğerlerini 2 artırabiliriz) daha fazla azaltabilirsiniz.

Bu yaklaşımı doğrulamak için hızlı bir uygulama çalıştırdım ve bu ağırlıklar ile 32000 yinelemeden sonra, aşağıdaki grafikleri üretiyor. Üstteki grafik her bir silindirdeki 4 ağırlığın hemen değerlerini gösterir ve altdaki grafik o noktaya getirilen her sonuç türünün toplam sayısını gösterir.

Gördüğünüz gibi, ağırlıklar istenen değerlerin etrafında hafifçe dalgalanır, ancak genel ağırlıklar istenen aralıklar içinde kalır ve başlangıç ​​numaralarının başlangıçtaki çeşitli çeşitlilikleri ortaya çıktıktan sonra, sonuçlar istenen yüzdelere neredeyse mükemmel bir şekilde uyar.

Bu örneğin, orada gerçekten daha iyi RNG'lerden biri olmayan .NET System.Random sınıfı kullanılarak üretildiğine dikkat edin, bu nedenle muhtemelen daha iyi bir RNG kullanarak daha doğru sonuçlar alabilirsiniz. Ayrıca, 32000'in bu araçla çizebileceğim maksimum sonuç olduğunu unutmayın, ancak test aracım aynı genel düzende 500 milyondan fazla sonuç üretti.


Bunun sadece + 1'ler / -3'lerinizin en son kullanılan ağırlıklar yerine orijinal ağırlıklara göre uygulanması durumunda işe yaradığını unutmayın. (Ağırlıkları sürekli olarak bu şekilde tek tip olarak değiştirmek, onları eşitlenebilir olmalarına doğru sürüklenir hale getirir). Bu, uzun vadede olasılığı hedefte tutarken, koşuyu azaltmak için çok az şey yapar. Bir kez özlediğimden dolayı, arka arkaya iki kez daha özleyeceğim şansı bu şema ile% 22, bağımsız çizimlerle% 25'tir. Ağırlık kaymasının daha büyük bir etki için arttırılması (+ 3 / -9'a kadar), uzun süreli olasılığın önlenmesine neden olur.
DMGregory

Aslında yukarıda sunulan veriler her rulo işlenişinde + 1 / -3 en son ağırlığa uygulanır. Bu nedenle, ilk% 50 ağırlıkta bir kez özlüyorsanız, bir sonraki özledim ağırlık% 47 ve tekrar özlerseniz, aşağıdaki ağırlık% 44 vb. Olacaktır. Çalışmaları azaltır (ayrı metrik, çalışmalarda% 24'lük bir azalma kadar bulunan izleme çalışmalarıydı), ancak yine de kaçınılmazlar, çünkü bu program 4 ağırlığın her birini sıfır olmayan bir olasılıkla bırakma konusunda güçlü bir şansa sahipler ( Örneğin, üst üste dört kabuk, kritik ağırlık sıfır sıfır oluşma şansı bırakacaktır).
David C Ellis,

Amacın buysa, uygulamanın bir hata yaptı. Grafiğe bakın - Fumble ağırlık sadece 7 ile 11 arasında zıplar, bunun dışında hiçbir değer yok. Tanımladığınız sürekli modifikasyonu kullanarak bir simülasyon yaptım ve grafikler, her bir durumun ilk yüz denemede her biri% 25'e yaklaşma olasılığıyla büyük ölçüde farklı.
DMGregory

Dangit, belirttiğiniz gibi gerçekten tıkanmıştı. Peki, bu cevabı vur.
David C Ellis,

@DavidCEllis, uygulamanızın kusurlu olduğunu mu düşünüyorsun yoksa fikrin kendisi mi? Peçete arkası sezgim, kabaca tanımladığınız modele geldi (çizildiğinde bir olasılığı ayarlayın, zamanla tüm olasılıkları yavaş yavaş orijinal değerlerine geri döndürün) ve hala bana mantıklı geliyor.
dimo414

0

Esasen bir filtre olanı yapabilirsiniz. Geçmiş n olayları takip edin. Olasılık, bu olaylara uygulanan bazı filtrelerin bazılarıdır. 0 filtresi temel olasılıktır, eğer 0 ise kaçar, eğer başarısız olursanız. Diyelim ki baz% 25 idi ve filtre her yinelemenin yarısında azaldı. Filtre o zaman olur:

[.25 .125 .0625 .03125] 

İsterseniz devam etmekten çekinmeyin. Bu şemanın genel olasılığı, .25 temel olasılığından biraz daha yüksektir. Aslında, aynı şemaya göre verilen olasılık şöyledir (ben x'i gerçek olasılık olarak adlandırıyorum, p olasılık girişidir):

x=p+(1-x)*(p/2+p/4+p/8)

X için çözme, cevabın p(1+1/2+1/4+1/8)/(1+p(1/2+1/4+1/8), veya bizim durumumuz için olduğunu bulur x=0.38461538461. Ama gerçekte istediğin, x verilen p'yi bulmak Bu daha zor bir sorun olarak ortaya çıkıyor. Sonsuz bir filtre varsayarsanız, sorun x+x*p=2*pveya olur p=x/(2-x). Böylece, filtrenizi arttırmak, daha sonra ortalama olarak size aynı sonuçları verecek olan p sayısını çözebilir, ancak son zamanlarda ne kadar başarıya ulaştığına bağlı olarak.

Temel olarak, bu değerin kabul eşiğinin ne olduğunu belirlemek için önceki değerleri kullanır ve rastgele bir değer alırsınız. Ardından filtre verilen bir sonraki rasgele değeri üretin.


-1

Kendini önerdiğin gibi, buna yaklaşımlardan biri de ağırlıklı bir rasgele uygulamak. Fikir, ağırlıkların ve sonuçların değiştirilebileceği rastgele bir sayı (veya sonuç) üreteci yapmaktır.

İşte Java'da bunun bir uygulaması.

import java.util.Map;
import java.util.Random;

/**
 * A psuedorandom weighted outcome generator
 * @param <E> object type to return
 */
public class WeightedRandom<E> {

    private Random random;
    private Map<E, Double> weights;

    public WeightedRandom(Map<E, Double> weights) {
        this.random = new Random();
        this.weights = weights;
    }

    /**
     * Returns a random outcome based on the weight of the outcomes
     * @return
     */
    public E nextOutcome() {
        double totalweight = 0;

        // determine the total weigth
        for (double w : weights.values()) totalweight += w;

        // determine a value between 0.0 and the total weight
        double remaining = random.nextDouble() * totalweight;

        for (E entry : weights.keySet()) {
            // subtract the weight of this entry
            remaining -= weights.get(entry);

            // if the remaining is smaller than 0, return this entry
            if (remaining <= 0) return entry;
        }

        return null;
    }

    /**
     * Returns the weight of an outcome
     * @param outcome the outcome to query
     * @return the weight of the outcome, if it exists
     */
    public double getWeight(E outcome) {
        return weights.get(outcome);
    }

    /**
     * Sets the weight of an outcome
     * @param outcome the outcome to change
     * @param weight the new weigth
     */
    public void setWeight(E outcome, double weight) {
        weights.put(outcome, weight);
    }
}

DÜZENLEME Ağırlıkları otomatik olarak ayarlamak istediğinizde, örneğin sonuç B olduğunda A şansını arttırın.

  1. nextOutcome()Yöntemin davranışını değiştirir, böylece sonucu, ağırlığa göre değiştirir.
  2. setWeight()Sonuçlara göre ağırlığını değiştirmek için kullanın .

Bence soruyu yanlış anlamış olabilirsiniz: OP, ağırlıklı rasgele sonuçların nasıl üretileceğini değil, aynı sırada art arda birkaç kez meydana gelme olasılığını azaltmak için ağırlıkların nasıl ayarlanacağını soruyor.
Ilmari Karonen

Görüyorum, bu sistemi kullanarak bunun nasıl mümkün olacağını açıklamak için cevabımın bir kısmını değiştirdim.
erikgaal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.