git-svn-id: http://moon:8086/svn/projects/GeneticAlgorithm@251 fda53097-d464-4ada-af97-ba876c37ca34
192 lines
4.1 KiB
Python
192 lines
4.1 KiB
Python
import numpy as np
|
|
import copy
|
|
|
|
class FinessEvaluator(object):
|
|
def __init__(self):
|
|
self.x = np.linspace(-10,10,21)
|
|
pass
|
|
|
|
def process(self, c):
|
|
mse = 0
|
|
for x in self.x:
|
|
y = c.process(x)
|
|
mse += (y - self.fx(x))**2
|
|
|
|
mse *= 1/len(self.x)
|
|
fit = 1/(1 + mse)
|
|
return fit
|
|
|
|
def fx(self, x):
|
|
y = 5 + 3 * x + 7 * x**2
|
|
return y
|
|
|
|
class Cromosome(object):
|
|
def __init__(self, id, param=None):
|
|
self.id = id
|
|
self.fit = 0
|
|
self.fitAccum = 0
|
|
self.param = param
|
|
|
|
def process(self, x):
|
|
result = self.param[0] + self.param[1]*x + self.param[2]*x**2
|
|
return result[0]
|
|
|
|
def cross(self, other):
|
|
a = 0.5
|
|
param1 = (1-a)*self.param + a*other.param
|
|
param2 = (1-a)*other.param + a*self.param
|
|
ca = Cromosome(self.id, param1)
|
|
cb = Cromosome(other.id, param2)
|
|
return ca, cb
|
|
|
|
def diversity(self, other):
|
|
d = self.param - other.param
|
|
s = np.mean(d**2)
|
|
return s
|
|
|
|
def mutate(self):
|
|
gene = int(np.random.rand() * 3)
|
|
allele = int(5*(0.5 - np.random.rand()))
|
|
self.param[gene] += allele
|
|
|
|
def __copy__(self):
|
|
print('__copy__()')
|
|
return Cromosome(self.name)
|
|
|
|
def __deepcopy__(self, arg):
|
|
print('__deepcopy__({})'.format(arg))
|
|
return Cromosome(copy.deepcopy(self.name, arg))
|
|
|
|
def __str__(self):
|
|
return "Id: {}, f={:0.6f}, fitAccum={:0.6f}, param=\n{}".format(self.id, self.fitness, self.fitAccum, str(self.param))
|
|
|
|
|
|
class Population(object):
|
|
def __init__(self, numCromosomes):
|
|
self.bestFit = 0
|
|
self.sumFit = 0
|
|
self.cromosomes = []
|
|
for i in range(0, numCromosomes):
|
|
self.cromosomes.append(Cromosome(str(i), np.random.rand(3,1)))
|
|
|
|
def print(self):
|
|
print ("Population fitness = {:0.6f}".format(self.sumFit))
|
|
print ("Best indiv. fitness = {:0.6f}".format(self.bestFit))
|
|
|
|
def process(self):
|
|
for c in self.cromosomes:
|
|
y = c.process(1)
|
|
return
|
|
|
|
def fitness(self, fitnessEval):
|
|
self.sumFit = 0
|
|
self.bestFit = 0
|
|
for c in self.cromosomes:
|
|
f = fitnessEval.process(c)
|
|
c.fitness = f
|
|
self.sumFit += f
|
|
if f > self.bestFit:
|
|
self.bestFit = f
|
|
|
|
# 1.) Sort by fitness
|
|
sorted = self.sort(self.cromosomes)
|
|
|
|
# 2.) Assign accumulated fitness
|
|
sum = 0
|
|
for c in sorted:
|
|
sum += c.fitness
|
|
c.fitAccum = sum
|
|
|
|
self.cromosomes = sorted
|
|
|
|
return self.sumFit
|
|
|
|
def mate(self, chanceOfReproduction=0.3):
|
|
newPop = self.cromosomes
|
|
count = 0
|
|
for i in range(0, int(len(self.cromosomes)/2)):
|
|
p = np.random.rand()
|
|
|
|
if p < chanceOfReproduction:
|
|
# 3.) Select parents
|
|
mom = self.select(self.cromosomes)
|
|
|
|
cand = []
|
|
div = np.empty(0)
|
|
# Make diversity selection 1 of 3 candidates
|
|
for i in range(0,3):
|
|
dad = mom
|
|
while(dad == mom):
|
|
# Select returns fitter cromosomes with higher probabilty
|
|
dad = self.select(self.cromosomes)
|
|
cand.append(dad)
|
|
div = np.append(div, mom.diversity(dad))
|
|
|
|
# Use best, diverse cromosom
|
|
bestCand = np.argmax(div)
|
|
ca, cb = mom.cross(cand[bestCand])
|
|
newPop[count+0] = ca
|
|
newPop[count+1] = cb
|
|
count += 2
|
|
|
|
self.cromosomes = newPop
|
|
return newPop
|
|
|
|
def select(self, sorted):
|
|
p = self.sumFit * np.random.rand()
|
|
for c in sorted:
|
|
if c.fitAccum > p:
|
|
break
|
|
|
|
return c
|
|
|
|
def mutate(self, chanceOfMutation=0.06):
|
|
for c in self.cromosomes:
|
|
p = np.random.rand()
|
|
|
|
if p < chanceOfMutation:
|
|
c.mutate()
|
|
|
|
pass
|
|
|
|
def best(self):
|
|
return self.cromosomes[len(self.cromosomes)-1]
|
|
|
|
def starve(self):
|
|
pass
|
|
|
|
def sort(self, array):
|
|
less = []
|
|
equal = []
|
|
greater = []
|
|
|
|
if len(array) > 1:
|
|
pivot = array[0].fitness
|
|
for x in array:
|
|
if x.fitness < pivot:
|
|
less.append(x)
|
|
elif x.fitness == pivot:
|
|
equal.append(x)
|
|
elif x.fitness > pivot:
|
|
greater.append(x)
|
|
# Don't forget to return something!
|
|
return self.sort(less)+equal+self.sort(greater) # Just use the + operator to join lists
|
|
# Note that you want equal ^^^^^ not pivot
|
|
else: # You need to hande the part at the end of the recursion - when you only have one element in your array, just return the array.
|
|
return array
|
|
|
|
|
|
if __name__ == '__main__':
|
|
f = FinessEvaluator()
|
|
p = Population(50)
|
|
|
|
for i in range(0, 500):
|
|
p.mutate(0.1)
|
|
p.fitness(f)
|
|
p.mate()
|
|
p.print()
|
|
|
|
p.fitness(f)
|
|
p.print()
|
|
print(p.best())
|
|
print ("End of Program") |