如何使用概率表创建长度为K的N“随机”字符串? K会是偶数.
prob_table = {'aa': 0.2, 'ab': 0.3, 'ac': 0.5}
假设K = 6,’acacab’的可能性高于’aaaaaa’.
这是我用于基于概率表生成合成序列的更大问题的子问题.我不确定如何使用概率表生成“随机”字符串?
到目前为止我所拥有的:
def seq_prob(fprob_table,K= 6, N= 10):
#fprob_table is the probability dictionary that you input
#K is the length of the sequence
#N is the amount of sequences
seq_list = []
#possibly using itertools or random to generate the semi-"random" strings based on the probabilities
return seq_list
解决方法:
有一些很好的方法来制作at the end of the documentation for the builtin random
module描述的加权随机选择:
A common task is to make a random.choice() with weighted probabilities.
If the weights are small integer ratios, a simple technique is to build a sample population with repeats:
>>> weighted_choices = [('Red', 3), ('Blue', 2), ('Yellow', 1), ('Green', 4)]
>>> population = [val for val, cnt in weighted_choices for i in range(cnt)]
>>> random.choice(population)
'Green'
A more general approach is to arrange the weights in a cumulative distribution with itertools.accumulate(), and then locate the random value with bisect.bisect():
>>> choices, weights = zip(*weighted_choices)
>>> cumdist = list(itertools.accumulate(weights))
>>> x = random.random() * cumdist[-1]
>>> choices[bisect.bisect(cumdist, x)]
'Blue'
为了使后一种方法适应您的具体问题,我会这样做:
import random
import itertools
import bisect
def seq_prob(fprob_table, K=6, N=10):
choices, weights = fprob_table.items()
cumdist = list(itertools.accumulate(weights))
results = []
for _ in range(N):
s = ""
while len(s) < K:
x = random.random() * cumdist[-1]
s += choices[bisect.bisect(cumdist, x)]
results.append(s)
return results
这假设概率表中的关键字符串长度相同如果它们有多个不同的长度,则此代码有时(可能大部分时间!)给出长于K个字符的答案.我想它也假设K是密钥长度的精确倍数,但如果不是真的那么它实际上会起作用(它只会给出比K字符都长的结果字符串,因为没有办法准确地得到K).