Tidak satu pun dari jawaban ini yang jelas atau sederhana.
Ini adalah metode yang jelas dan sederhana yang dijamin akan berhasil.
akumulasi_normalisasi_probabilitas mengambil kamus p
yang memetakan simbol untuk probabilitas ATAU frekuensi. Ini menghasilkan daftar tuple yang dapat digunakan untuk melakukan seleksi.
def accumulate_normalize_values(p):
pi = p.items() if isinstance(p,dict) else p
accum_pi = []
accum = 0
for i in pi:
accum_pi.append((i[0],i[1]+accum))
accum += i[1]
if accum == 0:
raise Exception( "You are about to explode the universe. Continue ? Y/N " )
normed_a = []
for a in accum_pi:
normed_a.append((a[0],a[1]*1.0/accum))
return normed_a
Hasil:
>>> accumulate_normalize_values( { 'a': 100, 'b' : 300, 'c' : 400, 'd' : 200 } )
[('a', 0.1), ('c', 0.5), ('b', 0.8), ('d', 1.0)]
Mengapa ini berhasil?
Langkah akumulasi mengubah setiap simbol menjadi interval antara dirinya dan probabilitas atau frekuensi simbol sebelumnya (atau 0 dalam kasus simbol pertama). Interval ini dapat digunakan untuk memilih dari (dan dengan demikian sampel distribusi yang disediakan) dengan hanya melangkah melalui daftar sampai angka acak dalam interval 0,0 -> 1,0 (disiapkan sebelumnya) kurang atau sama dengan titik akhir interval simbol saat ini.
The normalisasi melepaskan kita dari kebutuhan untuk memastikan semuanya jumlah untuk beberapa nilai. Setelah normalisasi, "vektor" probabilitas berjumlah 1,0.
The sisa kode untuk seleksi dan menghasilkan sampel sewenang-wenang panjang dari distribusi di bawah ini:
def select(symbol_intervals,random):
print symbol_intervals,random
i = 0
while random > symbol_intervals[i][1]:
i += 1
if i >= len(symbol_intervals):
raise Exception( "What did you DO to that poor list?" )
return symbol_intervals[i][0]
def gen_random(alphabet,length,probabilities=None):
from random import random
from itertools import repeat
if probabilities is None:
probabilities = dict(zip(alphabet,repeat(1.0)))
elif len(probabilities) > 0 and isinstance(probabilities[0],(int,long,float)):
probabilities = dict(zip(alphabet,probabilities)) #ordered
usable_probabilities = accumulate_normalize_values(probabilities)
gen = []
while len(gen) < length:
gen.append(select(usable_probabilities,random()))
return gen
Penggunaan:
>>> gen_random (['a','b','c','d'],10,[100,300,400,200])
['d', 'b', 'b', 'a', 'c', 'c', 'b', 'c', 'c', 'c'] #<--- some of the time
random.choice()
? Anda membangun daftar master dengan jumlah kemunculan yang tepat dan memilih satu. Ini adalah pertanyaan rangkap, tentu saja.