파이썬인데 난생 처음으로 객체지향을 염두에 두고 해봤습니다. 아직 클래스 쓰는법을 잘 몰라서 엉성하긴 한데 역시 함수 떡칠보단 편하긴 하네요.
개체 : 유전자들을 갖는 리스트. 유전자는 정수만 가능
세대 : 개체들의 집합
부모 수 : 2의 배수여야 함
1세대당 개체의 수 : 2를 곱했을때 부모 수에 나눠 떨어져야 함
적합도 평가 함수 : 우수 개체를 가려내는 함수. 리턴 값이 높은 개체가 선택됩니다
이렇게 정의하면 바로 사용할 수 있게 디자인 해봤습니다
간단하게 한번 예제를 써볼게요
object1 = [0,1,0,1,1,0]
object2 = [1,1,0,1,1,0]
object3 = [0,0,0,1,1,1]
object4 = [1,1,1,1,0,0]
myList = [object1,object2,object3,object4]
generation = Generation(myList,mutchance=0.1,maxnum = 100,minnum=1)
#세대 집합을 인자로 주고 Generation객체 generation을 생성합니다. 뒤에 세 인자들은 넣어도 되고 안넣어도 되는데, 디폴트는 돌연변이 확률 1프로, 최대값 100, 최솟값 1입니다. 여기서 최대 최소는 돌연변이의 범위입니다. 예를들어 님이 2진수 유전자로 프로그램을 구현했는데 돌연변이로 49라는 인자가 박히면 에러가 나겠죠? 그땐 저길 1,0으로 설정해줘야 합니다.
이렇게 객체 생성하면 이제 메서드 한개만 알면 됩니다.
generation.makeSon(func,pNum=2)
세대를 진화시키는 함수입니다. 직접 만든 적합도 평가 함수를 인자로 넘겨주시면 쟤가 받고 알아서 연산합니다. 저기 pNum은 부모 수인데 디폴트가 2명입니다. 2명이면 엄마 아빠니까 한쌍입니다. 과부는 출산을 못하므로 위에서 정의했던 대로 2의 배수로 넣어줘야합니다.
저는 적합도 평가 함수로 goodness라는걸 하나 만들어봤습니다.
def goodness(object):
return sum(object)
개체 한마리를 인자로 받아서 유전자 다 더한값을 넘겨줍니다. 그니까 유전자 안에 1이 많을수록 적합도가 올라가게 됩니다.
이제 한 5000세대까지 진화를 시켜보겠습니다.
for i in range(5000):
generation.makeSon(goodness,2)
진화 연산을 5000번 수행하고 루프를 빠져나온 모습입니다.
print generation
[1,1,1,1,1,1]
적합도가 높은 쪽으로 진화해 있을 겁니다. 객체를 출력하면 그 세대의 0번째 개체를 출력해줍니다.
안돌려봐서 모르겠는데 아마 위의 코드는 문제 없이 돌아갈 확률이 높습니다
---------------------------------------
#Module
import random
def chance(k):
a = random.random()*100
return a<k
def exchange(father,mother):
son = []
for i in range(len(father)):
if chance(50)==1:
son.append(father[i])
else:
son.append(mother[i])
return son
def mutator(gene,mutchance,maxnum,minnum):
count = 0
if chance(mutchance)!=1:
return gene
a = random.randrange(minnum,maxnum+1)
j = random.randrange(len(gene))
while a==gene[j]:
j = random.randrange(len(gene))
a = random.randrange(minnum,maxnum+1)
gene[j] = a
return gene
class Generation():
def __str__(self):
return str(a.Generation[0])
def __init__(self,generation,mutchance = 1.0,maxnum = 100,minnum=1):
self.Generation = generation
self.mutchance = mutchance
self.maxnum = maxnum
self.minnum = minnum
self.count = 1
def choice(self,func,pNum=2):
result = []
k = []
choosen = []
for i in self.Generation:
k.append(func(i))
result.append(func(i))
k.sort()
for i in range(pNum):
choosen.append(result.index(k[-1]))
result[result.index(k[-1])] = -99999
k.pop()
result = []
for i in choosen:
result.append(self.Generation[i])
return result
def makeSon(self,func,pNum=2):
count = 0
parentList = self.choice(func,pNum)
if len(self.Generation)%(len(parentList)/2)!=0:
print len(self.Generation),len(parentList),pNum
return
result = []
son = []
father = []
mother = []
for i in range(len(parentList)/2):
father = parentList[-1]
mother = parentList[-2]
son.append(father)
son.append(mother)
for j in range((2*len(self.Generation)/pNum)-2):
son.append(exchange(father,mother))
parentList.pop()
parentList.pop()
for i in son:
result.append(mutator(i,self.mutchance,self.maxnum,self.minnum))
self.Generation = result
self.count +=1
잘하셨네요 가져가서써봐도?
그래주시면 영광
대단하시네요