2014-02-25 3 views
2

저는 GA로 작업 중이므로 게놈을 수정해야합니다. 게놈의 최소값을 임의의 프로세스를 나타내는 "플래그"로 설정했습니다. 따라서 함수가 포함 된 범위 [0,8]에서 입력을받는 동안 GA는 값 [4,8] 만 선택합니다. "4"의 인스턴스는 [0,4]가 될 다른 목록의 번호로 바꿔야합니다. 이것은 매우처럼목록의 항목을 다른 목록 (Python)의 해당 항목으로 바꿉니다.

#------------------------------------------------------------------------------- 
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 %가이 기능에 포함됨).

내 질문 : 위 코드 블록을 구현하는 효율적인 방법이 있습니까?

미리 감사드립니다.

+1

분명히 무엇을 하든지, 반복해야합니까? –

+5

작업 코드 개선에 관한 질문은 [codereview.se]에 더 적합합니다. –

+4

이 질문은 스택 Exchange 네트워크의 다른 사이트에 속해 있습니다. http://codereview.stackexchange.com – zmo

답변

0

enumerate(chromosome) 명령을 실행할 때마다 index 목록을 만들지 않도록 가장 좋은 방법은 izip을 사용하여 두 목록을 반복하는 것입니다.

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 

그래서 모든 후, 그것은처럼 보이는

원래 코드가 가장 빠릅니다.

+0

다른 기능적 결과를 산출 할 때마다 각 통과를 통해 randint를 생성하고 싶지 않습니다. /// 동일한 값을 바꿀 가능성이 있습니다 (예 : 3 => 3). 그러나 GA는 가끔 입력을 "변경"하기 때문에 2 => 3을 허용하고 싶지 않습니다. /// 입력은 "조치"를 나타냅니다. 여기서 5-8은 "적극적인 조치"이고 "4"는 "조치 없음"을 나타냅니다. 나는 "무작위로 나쁜 행동"(4 가지 옵션)으로 "아무런 행동도하지 않는다. 나는 "나쁜 이벤트"가 최적화 과정에서 일정하지만, 각 위치에서 무작위가되기를 바란다. 그러므로 changed_value리스트. – planetes42

+0

미리 생성 된 경우 첫 번째 경우에 해당 조건이 어떻게 보장됩니까? 대신에'random.randint (c, flag_option)'를 사용할 수 있습니까? – cdhagmann

+0

질문을 이해할 수 없습니다. 내 의도는 _no action_이 선택된 경우 각 _ 위치에서 동일한 _bad event_가 발생하도록하는 것입니다. 염색체 'c'의 항목을 무작위로 생성 된 숫자로 바꾸면 각 반복마다 다른 _bad 이벤트 _ 대체 값을 갖게됩니다. 'changed_value'의 목록을 미리 생성함으로써 ~ 10K 반복을 통해 _no action_이 선택 될 때마다 그 노드에서 동일한 _bad event_가 발생하는지 확인합니다. – planetes42

관련 문제