我正在与GA合作,需要修改基因组。我已经将基因组中的最小值设置为表示随机过程的“标志”。因此,当函数接受包含范围[0,8]中的输入时,GA将仅选择值[4,8]。任何“4”的实例都需要用另一个列表中的数字替换为[0,4]。
我目前使用以下代码实现此目的:
#-------------------------------------------------------------------------------
def modify_chromosome(chromosome):
# If value == replace option, replace from another list
for (index,value) in enumerate(chromosome):
# Note "<=" necessary in case GA mutates the values
if value <= flag_option:
chromosome[index] = changed_value[index]
# This changes the actual chromosome in the GA
return chromosome
其中changed_value列表先前已定义为
changed_value = random.randint(0,flag_option,len(num_entries))
上面的代码工作正常,但迭代这样的列表非常耗时(整个运行时间的约10%在此函数中)。
我的问题: 有没有更有效的方法来实现上面的代码块?
提前致谢。
答案 0 :(得分:0)
您可以做的最好的事情是使用izip
遍历两个列表,这样每次运行index
命令时都不会创建enumerate(chromosome)
列表。
from itertools import izip
changed_value = random.randint(0,flag_option,len(num_entries))
chromosome = [c if c <= flag_option else v
for c, v in izip(chromosome, changed_value)]
编辑:所以我使用以下脚本进行了一些基准测试:
from itertools import izip
import random
import timeit
def test_setup(n, flag_option=4):
setup = 'from itertools import izip\nfrom random import randint\n'
setup += 'flag_option = {}\n'.format(flag_option)
setup += 'changed_val = [randint(0, flag_option) for _ in xrange({})]\n'.format(n)
setup += 'chromosome = [randint(0, 8) for _ in xrange({})]\n'.format(n)
return setup
test_izip = '[v if c <= flag_option else c '
test_izip += 'for c, v in izip(chromosome, changed_val)]'
test_zip = '[v if c <= flag_option else c '
test_zip += 'for c, v in zip(chromosome, changed_val)]'
test_enum = '[changed_val[i] if c <= flag_option else c '
test_enum += 'for i,c in enumerate(chromosome)]'
test_orig = 'for (i,c) in enumerate(chromosome):\n'
test_orig += '\tif c <= flag_option:\n'
test_orig += '\t\tchromosome[i] = changed_val[i]'
if '__main__' == __name__:
for n in [10 ** i for i in xrange(7)]:
print 'izip {}: '.format(n),
print min(timeit.Timer(test_izip, setup=test_setup(n)).repeat(7, 1000))
print 'zip {}: '.format(n),
print min(timeit.Timer(test_zip, setup=test_setup(n)).repeat(7, 1000))
print 'enum {}: '.format(n),
print min(timeit.Timer(test_enum, setup=test_setup(n)).repeat(7, 1000))
print 'orig {}: '.format(n),
print min(timeit.Timer(test_orig, setup=test_setup(n)).repeat(7, 1000))
print
结果如下:
izip 10: 0.00132203102112
zip 10: 0.00159502029419
enum 10: 0.00130820274353
orig 10: 0.000921964645386
izip 100: 0.00951504707336
zip 100: 0.01145195961
enum 100: 0.00957798957825
orig 100: 0.00854301452637
izip 1000: 0.0860891342163
zip 1000: 0.109489917755
enum 1000: 0.0958349704742
orig 1000: 0.0862739086151
izip 10000: 0.922410964966
zip 10000: 1.31961488724
enum 10000: 1.00453591347
orig 10000: 0.93142914772
izip 100000: 9.61347794533
zip 100000: 18.9829239845
enum 100000: 10.6979219913
orig 100000: 9.5124809742
izip 1000000: 100.970448971
zip 1000000: 211.297281027
enum 1000000: 122.404583931
orig 1000000: 94.8837227821
所以在所有事情之后,看起来您的原始代码将是最快的。