我正在使用python的random.sample(population,k)函数从列表中生成一组随机值,以创建该列表的新排列。问题是,每次循环运行时,它都会生成完全相同的随机序列。为什么是这样?我甚至使用了random.seed(i),这样i变量(每次通过循环改变)每次都会为它生成不同的值。仍然是相同的序列。是什么给了!@
以下是我如何使用它:
def initialBuild(self):
alphabet = self.alphabet
for i in range (self.length):
value = random.sample(alphabet, 1)
alphabet.remove(value[0])
self.finalWord.append(value[0])
print "Final word = ", self.finalWord
只是从Individual类的init方法调用。正如这样调用init方法......
def buildPopulation(self, alphabet):
#Initialize empty individuals
for i in range(POPULATION_SIZE):
self.population.append(Individual(alphabet))
并且init方法看起来像这样......
def __init__(self, alphabet = []):
self.length = len(alphabet)
self.alphabet = alphabet
self.initialBuild()
最后,我正在打印最后一句话。以下是运行此方法两次的输出:
最后的词= [[1150,1160],[720, [635],[95,260],[595,360],[770, 610],[830,610],[25,185],[520, 585],[605,625],[410,250],[555, 815],[880,660],[300,465],[1220, 580],[1215,245],[1250,400],[565, [575],[1605,620],[845,680],[1170, 65],[795,645],[525,1000],[760, 650],[580,1175],[420,555],[25, 230],[345,750],[700,500],[725, 370],[1530,5],[1740,245],[875, 920],[415,635],[1340,725],[975, 580],[575,665],[1465,200],[830, 485],[660,180],[475,960],[685, [595],[145,665],[510,875],[845, 655],[650,1130],[945,685],[480, 415],[700,580],[560,365],[685, 610],[835,625],[1320,315]]
最后的词= [[1150,1160],[720, [635],[95,260],[595,360],[770, 610],[830,610],[25,185],[520, 585],[605,625],[410,250],[555, 815],[880,660],[300,465],[1220, 580],[1215,245],[1250,400],[565, [575],[1605,620],[845,680],[1170, 65],[795,645],[525,1000],[760, 650],[580,1175],[420,555],[25, 230],[345,750],[700,500],[725, 370],[1530,5],[1740,245],[875, 920],[415,635],[1340,725],[975, 580],[575,665],[1465,200],[830, 485],[660,180],[475,960],[685, [595],[145,665],[510,875],[845, 655],[650,1130],[945,685],[480, 415],[700,580],[560,365],[685, 610],[835,625],[1320,315]]
请注意,这两者完全相同..
编辑:由于我很难选择我觉得有用的代码,但是很短的时间才能进入这篇文章,我已经在pastebin上发布了一堆代码。 http://pastebin.com/f5f068391希望这是一个更好的选择..再次感谢
答案 0 :(得分:13)
我不确定你的意思是“生成完全相同的随机序列”。由于您只提供了一个无法自行运行的代码段,因此很可能代码的其他部分中存在您选择不向我们显示的错误 - 我尝试添加绝对最少量的代码需要让你的代码片段运行,即:
import random
import string
def self(): pass
self.alphabet = list(string.lowercase)
self.finalWord = []
self.length = 4
for x in range(5):
alphabet = self.alphabet
for i in range (self.length):
value = random.sample(alphabet, 1)
alphabet.remove(value[0])
self.finalWord.append(value[0])
print "Final word = ", self.finalWord
这就是我在运行这个自给自足的脚本时看到的内容:
$ python sa.py
Final word = ['y', 'm', 'u', 'z']
Final word = ['y', 'm', 'u', 'z', 'h', 'b', 'c', 's']
Final word = ['y', 'm', 'u', 'z', 'h', 'b', 'c', 's', 'x', 'l', 'r', 'n']
Final word = ['y', 'm', 'u', 'z', 'h', 'b', 'c', 's', 'x', 'l', 'r', 'n', 'q', 'a', 'k', 'e']
Final word = ['y', 'm', 'u', 'z', 'h', 'b', 'c', 's', 'x', 'l', 'r', 'n', 'q', 'a', 'k', 'e', 'p', 'd', 'j', 'w']
$ python sa.py
Final word = ['k', 'v', 'o', 'd']
Final word = ['k', 'v', 'o', 'd', 'q', 'p', 'w', 'l']
Final word = ['k', 'v', 'o', 'd', 'q', 'p', 'w', 'l', 'n', 'u', 'g', 't']
Final word = ['k', 'v', 'o', 'd', 'q', 'p', 'w', 'l', 'n', 'u', 'g', 't', 'i', 'r', 'e', 'f']
Final word = ['k', 'v', 'o', 'd', 'q', 'p', 'w', 'l', 'n', 'u', 'g', 't', 'i', 'r', 'e', 'f', 's', 'c', 'j', 'z']
$ python sa.py
Final word = ['o', 'a', 'g', 't']
Final word = ['o', 'a', 'g', 't', 'k', 'j', 'y', 'w']
Final word = ['o', 'a', 'g', 't', 'k', 'j', 'y', 'w', 'z', 'l', 'i', 's']
Final word = ['o', 'a', 'g', 't', 'k', 'j', 'y', 'w', 'z', 'l', 'i', 's', 'u', 'p', 'f', 'm']
Final word = ['o', 'a', 'g', 't', 'k', 'j', 'y', 'w', 'z', 'l', 'i', 's', 'u', 'p', 'f', 'm', 'h', 'e', 'q', 'v']
如您所见,这是但“完全相同的随机序列” - 它正在改变每次运行,就像预期一样。
我想我在尝试使你的代码可执行时错误地读了你的思绪,并且你的意思是它的使用方式与我的小脚本使用的方式完全不同 - 但是那时思维阅读是一种不可靠的艺术(这是为什么如果你发布了一个独立的,可运行的示例,尽管它仍然可以复制你的问题,而不是强迫我们尝试阅读你的思想,那会好得多! - )。
为什么不调整我刚刚发布的最小所需数量的独立脚本,以使其更接近您的预期用途,并重现您观察到的问题? 那么我们可以更轻松,更高效地发现您的代码可能存在的任何问题,并提出解决问题的最佳方法!
编辑:粘贴在pastebin中的OP代码有两个与random
完全无关的错误,并组合起来产生OP观察到的行为。以下是代码的相关部分,编辑:
class Phenotype:
...
chromosome = []
def __init__(self, alleles = []):
self.length = len(alleles)
self.alleles = alleles
self.initialBuild()
def initialBuild(self):
alleleSet = self.alleles
for i in range (self.length):
value = random.sample(alleleSet, 1)
alleleSet.remove(value[0])
self.chromosome.append(value[0])
好的,这里还有另一个错误(在新代码中使用旧的遗留类,而不是应该总是使用的闪亮的新样式类),但这不是什么在咬OP(还),所以我们只是提到它顺便过去; - )。
错误1:由于__init__
和任何其他方法都没有执行任务self.chromosome = ...
,因此代码中self.chromosome
的所有提及实际上都是指唯一列表{{1}其中Phenotype.chromosome
类的所有实例共享。所以不可避免地所有这样的实例总是具有完全相同,相同的Phenotype
,无论如何。修复:在chromosome
中添加self.chromosome = []
(更好的是删除类级变量,因为它们没有任何好处,只会混淆问题)。
错误2:再次查看以下代码行以发现它:
__init__
知道了吗? self.alleles = alleles
...
alleleSet = self.alleles
...
alleleSet.remove(value[0])
和本地名称self.alleles
都是对完全所引用的同一个alleleSet
集(或实际列表)的引用 - 所以alleles
调用i 更改传入的集合。因此,在第一个Phenotype实例化后,该集合将保持空白(这就是为什么尽管Bug 1染色体不会继续增长:因为等位基因收集永远空了。)
修复:制作副本,例如remove
,以避免损坏原始集合。
更好的解决方法:你正在做的是一种非常错综复杂的方式来拼写更简单的代码,例如:
alleleSet = list(self.alleles)
即,只是随机排列。通过执行N个单独的样本并从集合中删除每个样本来构建随机排列,这是一种非常简单,缓慢而复杂的方法来攻击极其简单的问题! - )
答案 1 :(得分:6)
不要更改每个样品的种子。这打破了随机数生成器并绝对保证它不是随机的。
将种子恰好设置一次。并且在应用程序运行时永远不会再次更改该值。
随机数生成器以已知的常量种子开始。每次运行时,都应该得到相同的序列。不设置种子会产生可预测的序列。设置任何常量种子(例如示例中的i
)会产生可预测的序列。
如果你想要一个不可预测的序列,你需要一个不可预测的种子。使用时间或从/ dev / random读取的一些字节作为种子值。一次。
将此视为简化。
word = random.sample( alphabet, length )
它似乎为我产生了不同的序列。
>>> import string, random
>>> alphabet = string.ascii_lowercase
>>> random.sample( alphabet, 5 )
['x', 'p', 's', 'k', 'h']
>>> random.sample( alphabet, 5 )
['y', 'h', 'u', 'n', 'd']
答案 2 :(得分:1)
value = random.sample(alphabet, 1)
根据我通过反复试验收集的内容,这会从您的人口中迭代一个随机数,并将其分配给“值”。在那之后,“值”将永远是第一个随机val。它不会再次随机迭代,它只是坚持赋值的val。
而不是:
self.finalWord.append(value[0])
试试这个:
self.finalWord.append(random.sample(alphabet, 1)[0])
我没有测试过这个,所以我不能100%肯定它会起作用。但无论如何,如果我没有弄错的话,它应该解释你的问题。
答案 3 :(得分:1)
我想知道同样的事情,然后我意识到这是因为Python会锁定随机值,直到你再次运行随机数码。换句话说,随机数函数需要在while循环中,而不是在它之上。执行后者会导致相同的已建立随机数在循环开始后一次又一次地重复。
这是一个简单的例子,它在1到10之间运行20个随机整数的试验:
#CORRECT version:
x = 1
y = 1
while x<=20:
number = random.randint(1,10)
print("Trial", y, "is", number)
x = x + 1
y = y + 1
#INCORRECT version:
number = random.randint(1,10)
x = 1
y = 1
while x<=20:
print("Trial", y, "is", number)
x = x + 1
y = y + 1