Yüklü zar için veri yapısı?


130

Varsayalım ki, her bir k tarafının onu yuvarladığımda bir miktar p k gelme olasılığına sahip olduğu n-taraflı yüklü bir kalıbım var. Bu bilgiyi statik olarak depolamak için iyi bir algoritma olup olmadığını merak ediyorum (yani sabit bir olasılıklar kümesi için), böylece kalıbın rastgele bir rulosunu verimli bir şekilde simüle edebilirim.

Şu anda, bu sorun için bir O (lg n) çözümüm var. Buradaki fikir, tüm k için ilk k taraflarının kümülatif olasılığının bir tablosunu saklamak, [0, 1) aralığında rastgele bir gerçek sayı oluşturmak ve kümülatif olan en büyük indeksi elde etmek için tablo üzerinde ikili bir arama yapmaktır. değer seçilen değerden büyük değil. Bu çözümü tercih ediyorum, ancak çalışma zamanının olasılıkları hesaba katmaması garip görünüyor. Özellikle, bir tarafın her zaman ortaya çıktığı veya değerlerin eşit olarak dağıtıldığı aşırı durumlarda, O (1) 'de yuvarlanmanın sonucunu naif bir yaklaşım kullanarak oluşturmak mümkündür, ancak benim çözümüm hala logaritmik olarak birçok adım atacaktır.

Bu sorunun çalışma zamanında bir şekilde "uyarlanabilir" bir şekilde nasıl çözüleceğine dair herhangi bir önerisi olan var mı?

DÜZENLEME : Bu sorunun yanıtlarına dayanarak, analizleriyle birlikte bu soruna yönelik birçok yaklaşımı açıklayan bir makale yazdım . Görünüşe göre Vose'un takma ad yöntemini uygulaması, gerçekten etkileyici olan Θ (n) ön işleme süresi ve kalıp silindiri başına O (1) süresi veriyor. Umarım bu, cevaplarda yer alan bilgilere faydalı bir eklentidir!


2
Her özel durum için bir O (1) çözümünün olması mantıklıdır .
Tim

Yanıtlar:


117

Tek seferlik bir O (n) kurulumuyla sabit bir ayrık olasılık dağılımı oluşturmak için bir O (1) yöntemi sağlayan takma ad yöntemini arıyorsunuz ( sabit zamanda n uzunluğundaki bir dizideki girişlere erişebileceğinizi varsayarak) . Bunu belgelenen bulabilirsiniz bölüm 3 (PDF) ait "Non-Uniform Rastgele Değişken Üretimi" Luc Devroye tarafından.

Buradaki fikir, olasılık dizinizi p k alıp üç yeni n elemanlı dizi, q k , a k ve b k üretmektir . Her q k , 0 ile 1 arasında bir olasılıktır ve her bir a k ve b k , 1 ile n arasında bir tam sayıdır.

0 ile 1 arasında r ve s olmak üzere iki rasgele sayı üreterek 1 ile n arasında rasgele sayılar üretiriz. İ = floor (r * N) +1 olsun. Eğer q i <s ise a i, başka bir b i döndür . Takma ad yöntemindeki çalışma, q k , a k ve b k'yi nasıl üreteceğimizi bulmaktır .


Bu kadar kullanışlı bir algoritma için, Takma Ad Yöntemi şaşırtıcı bir şekilde çok iyi bilinmemektedir.
mhum

Kayıt için: apps.jcns.fz-juelich.de/ransampl takma ad yöntemini kullanarak rastgele örnekleme için küçük bir C kitaplığı yayınladım .
Joachim W

1
alias yönteminin belirli bir uygulaması,n algoritmaların uygulanmasında yer alan sabit faktörlere bağlı olarak üretilecek belirli ve seçilmiş bir rastgele sayı sayısı için Rulet Çarkı gibi daha kötü zaman karmaşıklığına sahip bir yöntemden daha yavaş olabilir .
jfs

4

Dengeli bir ikili arama ağacı (veya bir dizide ikili arama) kullanın ve O (log n) karmaşıklığını elde edin. Her bir kalıp sonucu için bir düğüme sahip olun ve anahtarların bu sonucu tetikleyecek aralık olmasını sağlayın.

function get_result(node, seed):
    if seed < node.interval.start:
        return get_result(node.left_child, seed)
    else if seed < node.interval.end:
        // start <= seed < end
        return node.result
    else:
        return get_result(node.right_child, seed)

Bu çözümün iyi yanı, uygulanması çok basit, ancak yine de iyi bir karmaşıklığa sahip olmasıdır.


Yukarıdaki gibi el yapımı ikili ağacın uygulanması basittir ancak dengeli olması garanti edilmez
yusong

Doğru sırayla kurarsanız dengeli olduğunu garanti edebilirsiniz.
hugomg

3

Masanı granüle etmeyi düşünüyorum.

Her bir kalıp değeri için kümülatif bir tabloya sahip olmak yerine, xN uzunluğunda bir tamsayı dizisi oluşturabilirsiniz; burada x, ideal olarak olasılığın doğruluğunu artırmak için yüksek bir sayıdır.

Bu diziyi, kümülatif değer olarak indeksi (xN ile normalize edilmiş) kullanarak doldurun ve dizideki her bir 'yuvada, bu dizin gelirse zar atma olasılığını saklayın.

Belki bir örnekle daha kolay açıklayabilirim:

Üç zar kullanıldığında: P (1) = 0.2, P (2) = 0.5, P (3) = 0.3

Bir dizi oluşturun, bu durumda 10 gibi basit bir uzunluk seçeceğim (yani, x = 3.33333)

arr[0] = 1,
arr[1] = 1,
arr[2] = 2,
arr[3] = 2,
arr[4] = 2,
arr[5] = 2,
arr[6] = 2,
arr[7] = 3,
arr[8] = 3,
arr[9] = 3

Ardından olasılığı elde etmek için, 0 ile 10 arasında bir sayıyı rastgele sıralayın ve bu dizine erişin.

Bu yöntem doğruluğu kaybedebilir, ancak x'in artırılması ve doğruluk yeterli olacaktır.


1
Tam doğruluk için dizi aramasını ilk adım olarak yapabilirsiniz ve birden çok tarafa karşılık gelen dizi aralıkları için burada bir arama yapabilirsiniz.
aaz

1

Özel bir dağıtımla rastgele bir tam sayı oluşturmanın birçok yolu vardır ( ayrık dağıtım olarak da bilinir) . Seçim, aralarından seçim yapılacak tam sayıların sayısı, dağıtımın şekli ve dağıtımın zamanla değişip değişmeyeceği gibi birçok şeye bağlıdır.

Özel ağırlık işlevine sahip bir tam sayı seçmenin en basit yollarından f(x)biri, reddetme örnekleme yöntemidir. Aşağıdaki mümkün olan en yüksek değer olduğunu varsayar folduğunu max. Reddetme örneklemesi için zaman karmaşıklığı ortalama olarak sabittir, ancak büyük ölçüde dağılımın şekline bağlıdır ve sonsuza kadar devam etmenin en kötü hali vardır. kRet örneklemesini kullanarak [1, ] 'de bir tam sayı seçmek için :

  1. i[1, k] 'de tek tip rastgele bir tamsayı seçin .
  2. Olasılıkla f(i)/maxgeri dönün i. Aksi takdirde, 1. adıma gidin.

Diğer algoritmalar, dağıtıma çok fazla bağlı olmayan (genellikle sabit veya logaritmik) ortalama bir örnekleme süresine sahiptir, ancak genellikle bir kurulum adımında ağırlıkları önceden hesaplamanızı ve bunları bir veri yapısında depolamanızı gerektirir. Bazıları, ortalama olarak kullandıkları rastgele bit sayısı açısından da ekonomiktir. Bu algoritmaların çoğu 2011'den sonra kullanıma sunuldu ve şunları içerir:

  • Bringmann-Larsen kısa ve öz veri yapısı ("Kesikli Dağılımlardan Kısa Örnekleme", 2012),
  • Yunpeng Tang'ın çok seviyeli araması ("Kesikli Dağılımları Değiştirmek İçin Rastgele Örnekleme Yöntemlerinin Ampirik Çalışması", 2019) ve
  • Hızlı Loaded Zar Merdane (2020).

Diğer algoritmalar arasında takma ad yöntemi (makalenizde daha önce bahsedilmiştir), Knuth-Yao algoritması, MVN veri yapısı ve daha fazlası bulunur. Anket için " Ağırlıklı Seçim Algoritmaları Üzerine Bir Not " bölümüne bakın .

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.