Skip to content

Instantly share code, notes, and snippets.

@juriad
Created March 15, 2015 17:28
Show Gist options
  • Select an option

  • Save juriad/3870b6851fb11d0d2a26 to your computer and use it in GitHub Desktop.

Select an option

Save juriad/3870b6851fb11d0d2a26 to your computer and use it in GitHub Desktop.
Skript na Evoluční robotiku
from pylab import *
from numpy import random
from itertools import *
def matrixCreate(rows, cols, mi=-1, ma=1):
'''
Generates a matrix of size a x b filled with random numbers with uniform distribution in specified range.
'''
return rand(rows, cols) * (ma - mi) + mi
def fitness(population, axis=None):
'''
Calculates mean in whole specified population.
Change axis to 1 in order to calculate row-wise.
'''
return mean(population, axis)
def matrixPerturb(matrix, prob, mi=-1, ma=1):
'''
Changes an element to a random one with certain probability.
'''
out = array(matrix);
for x in np.nditer(out, op_flags=['readwrite']):
if rand() < prob:
x[...] = rand() * (ma - mi) + mi
return out
def hillClimber(initialPopulation, fitnessFunc, probMutation):
'''
Randomly changes the population.
If the fitness gets better, accepts the change.
'''
population = initialPopulation;
fit = fitnessFunc(population)
for gen in count(0):
yield (gen, fit, population[0])
child = matrixPerturb(population, probMutation)
childFit = fitnessFunc(child)
if childFit > fit:
population = child
fit = childFit
def tourSel(population, fitnessCached, probBetter):
'''
Randomly selects two elements and compares them.
The better one is returned with certain probability.
'''
two = random.choice(population.shape[0], 2, False)
fitA = fitnessCached[two[0]]
fitB = fitnessCached[two[1]]
return population[two[0] if (fitA > fitB) == (rand() < probBetter) else two[1]]
def mutate(vector, probMutation, stdDev, mi=-1, ma=1):
'''
Randomly mutates the vector each gene with certain probability.
Change is a random number from normal distribution added to the original one.
'''
out = array(vector);
for i in range(vector.shape[0]):
if rand() < probMutation:
out[i] = max(min(vector[i] + randn() * stdDev, ma), mi)
return out
def crossover(first, second, probCrossover):
'''
Crosses over the two vectors at random point with certain probability.
'''
if rand() > probCrossover:
return (first, second)
out1 = array(first)
out2 = array(second)
point = randint(1, out1.shape[0])
for i in range(0, out1.shape[0]):
out1[i] = first[i] if i < point else second[i]
out2[i] = second[i] if i < point else first[i]
return (out1, out2)
def select(population, fitnessCached, probBetter):
'''
Selects the better one out of two random ones with certain probability.
'''
bestIndex = argmax(fitnessCached);
rest = (tourSel(population, fitnessCached, probBetter)
for i in range(population.shape[0] - 1))
return (population[bestIndex], rest)
def pairwise(iterable):
'''
s -> (s0,s1), (s2,s3), (s4, s5), ...
'''
a = iter(iterable)
return zip(a, a)
def genAlg(initialPopulation, fitnessFunc, probBetter, probMutation, stdDev, probCrossover):
'''
Generates a new population based on previous one by applying selection, crossing over and mutation.
'''
population = initialPopulation;
for gen in count(0):
fitnessCached = fitnessFunc(population, 1)
children = zeros(population.shape)
best, rest = select(population, fitnessCached, probBetter)
yield (gen, max(fitnessCached), best, population)
children[0] = best
crossed = (v
for v1, v2 in pairwise(rest)
for v in crossover(v1, v2, probCrossover))
mutated = (mutate(v, probMutation, stdDev)
for v in crossed)
for i, v in zip(count(1), mutated):
children[i] = v
population = children
def countedCall(func):
'''
Counts number of calls
'''
counter = [0]
def inner(*args):
counter[0] += 1
return func(*args)
return (inner, counter)
def betterOf(n, initialSize, alg, fitnessFunc, *rest):
'''
Runs n copies of alg in parallel and chooses the best one in population.
'''
itersWithCounters = [(alg(matrixCreate(*initialSize), func, *rest), counter)
for _ in range(n)
for func, counter in [countedCall(fitnessFunc)]];
iters = [iwc[0] for iwc in itersWithCounters]
counters = [iwc[1] for iwc in itersWithCounters]
for generation in zip(*iters):
g = max(generation, key=lambda x:x[1])
h = g[:3] + (sum(c[0] for c in counters),) + g[3:]
yield h
def showGeneProgress(result):
'''
Show progress of gene values in time for previously defined algorithms
'''
m = zeros((len(result), len(result[0][2])))
for gen, _, best, *_ in result:
m[gen] = best
imshow(transpose(m), cmap=cm.gray, aspect='auto', interpolation='nearest')
xlabel("Generation")
ylabel("Gene")
show()
def showFitnessProgress(*results):
'''
Show progress of fitness in time for previously defined algorithms
'''
for i, result in zip(count(1), results):
n = len(result)
x = zeros((n, 1))
y = zeros((n, 1))
for gen, fit, _, *_ in result:
x[gen] = gen
y[gen] = fit
plot(x, y, label='Run {0}'.format(i))
xlabel("Generation")
ylabel("Fitness")
legend(loc='lower right')
show()
def usage():
print("p = list(takewhile(lambda x: x[1] < 0.9, betterOf(10, (15, 12), genAlg, fitness, 0.8, 0.05, 0.9, 0.7)))")
print("p = list(takewhile(lambda x: x[1] < 0.9, betterOf(10, (1, 12), hillClimber, fitness, 0.05)))")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment