main.py 9.71 KB
``````# -*- coding: utf-8 -*-
"""
Created on Mon May  7 12:46:27 2018

@author: Olav
"""
import numpy as np
from math import floor, ceil, sqrt
import random
from chromsome import Chromosome
#pip install bitstring in anaconda prompt, remember to update pip: pip install --upgrade pip
from bitstring import BitArray

def fitnessCheckBounds(fitness, corners):
reward = 10
rewardAll = 100
allCornersInBound = True

#print(corners)
for corner in range(len(corners)):
if corner >= 7:
break

if corners[corner] >= xTo:
fitness += reward
else:
allCornersInBound = False

if corners[corner+1] >= yHeight:
fitness += reward*2
else:
allCornersInBound = False

if allCornersInBound:
fitness += rewardAll
else:
fitness -= ceil(rewardAll/2)

return fitness

def fitnessCheckLeastEnergyJump(fitness, corners):
reward = 10
heights = np.array([corners, corners, corners, corners])

avgHeights = np.average(heights)
avgHeights = avgHeights - yHeight

fitness += (1/avgHeights) * reward

return fitness

reward = 100

#Check length of all corners
sideLen1 = getSideLength(corners, corners, corners, corners)
sideLen2 = getSideLength(corners, corners, corners, corners)
sideLen3 = getSideLength(corners, corners, corners, corners)
sideLen4 = getSideLength(corners, corners, corners, corners)
allSides = np.array([sideLen1, sideLen2, sideLen3, sideLen4])

#How far away is the sides from chromosome original height
for i in range(0, 4):
diff = getDifferenceSide(sideLen1, agentHeight)
diff = round(diff, 1)
if diff == 0.0:
diff = 0.1
fitness += int((1/diff) * reward)

#Are the sides of same length?
allSidesEqual = True
for i in range(0, 4):
if i != 3:
diff = round(getDifferenceSide(allSides[i], allSides[i+1]), 1)
else:
diff = round(getDifferenceSide(allSides[i], allSides), 1)

if diff == 0.0:
diff = 0.1
else:
allSidesEqual = False

fitness += (1/diff) * reward

if allSidesEqual:
fitness += reward * 1000

return fitness

def getSideLength(x1, y1, x2, y2):
return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))

def getDifferenceSide(side1, side2):
return abs(side1 - side2)

def fitnessValue(chromosome):
chromosomeAgent = chromosome
chromosome = chromosomeAgent.gene

fitness = 0

x1 = float(BitArray(bin=''.join(map(str, chromosome[0:chromosomeBitsValue]))).uint)
y1 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue:chromosomeBitsValue*2]))).uint)

x2 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*2:chromosomeBitsValue*3]))).uint)
y2 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*3:chromosomeBitsValue*4]))).uint)

x3 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*4:chromosomeBitsValue*5]))).uint)
y3 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*5:chromosomeBitsValue*6]))).uint)

x4 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*6:chromosomeBitsValue*7]))).uint)
y4 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*7:chromosomeBitsValue*8]))).uint)

dx1 = x1 + upperLCorner
dy1 = y1 + upperLCorner

dx2 = x2 + upperRCorner
dy2 = y2 + upperRCorner

dx3 = x3 + lowerLCorner
dy3 = y3 + lowerLCorner

dx4 = x4 + lowerRCorner
dy4 = y4 + lowerRCorner

corners = np.array([dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4])

fitness = fitnessCheckBounds(fitness, corners)
fitness = fitnessCheckLeastEnergyJump(fitness, corners)

fitness = int(fitness)
chromosomeAgent.fitness = fitness
return fitness

def fitness(population):
l = list(population)
l.sort(key=lambda chromosome: fitnessValue(chromosome), reverse=True)
population = np.array(l)

return population

def mutation(population):
"""
for i in range(len(population)):
for j in range(len(population[i])):
if random.uniform(0.0, 1.0) <= mutationRatio:
if population[i][j] != 0:
population[i][j] = 0
else:
population[i][j] = 1
"""
chromosomePick = np.random.randint(len(population))
for j in range(populationSize):
if random.uniform(0.0, 1.0) <= mutationRatio:
chromosome = population[chromosomePick]
chromosomeBit = chromosome.geneAt(j)

if chromosomeBit != 0:
chromosome.geneSet(j, 0)
else:
chromosome.geneSet(j, 1)

return population

def roulette(population):
populationSize = len(population)

return population

def crossover(population):
#print("Before: \n" + str(population))
offspring = np.array
splitSize = 2
for i in range(populationProduction):
if i >= populationSize-1:
break

parent1 = population.item(i).gene
parent2 = population.item(i+1).gene

#print('paren1' + str(parent1))
#print('paren2' + str(parent2))

child1 = np.array([], dtype=int)
child2 = np.array([], dtype=int)

itr = 0
count = 0
while (count < chromosomeSize):
if itr%2 != 0:
child1 = np.concatenate((
child1,
parent1[count:count+splitSize], #p1 split x/y
parent2[count+splitSize:count+4] #p2 split x/y
), axis=0)

child2 = np.concatenate((
child2,
parent2[count:count+splitSize], #p1 split x/y
parent1[count+splitSize:count+4] #p2 split x/y
), axis=0)

else:
child1 = np.concatenate((
child1,
parent1[count:count+4], #p1 take the whole x/y
), axis=0)
child2 = np.concatenate((
child2,
parent2[count:count+4], #p1 take the whole x/y
), axis=0)

count += chromosomeBitsValue
itr += 1

#print('child1' + str(child1))
#print('child2' + str(child2))
if i == 0:
offspring = np.vstack([Chromosome(child1), Chromosome(child2)])
else:
offspring = np.vstack([offspring, Chromosome(child1), Chromosome(child2)])

#Remove
#population = np.delete(population, np.s_[len(population)-len(offspring):len(population)], axis = 0)

#Insert
population = np.vstack([offspring, population])

#print("After: \n" + str(population))
return population

# Init agent values
yHeight = 4.0
xStart = 3.0
xTo = 0.0
agentHeight = 0.2
upperLCorner = np.array([xStart-(agentHeight/2), agentHeight])
upperRCorner = np.array([xStart+(agentHeight/2), agentHeight])
lowerLCorner = np.array([xStart-(agentHeight/2), 0.0])
lowerRCorner = np.array([xStart+(agentHeight/2), 0.0])

# Size of population
populationSize = 12

# percentage of parents which will produce two childrens
populationProduce = 0.5

# WARNING: OLD below, not that relevant
# Population production will determine how many chromosomes will be able to mate.
# The chromosomes are "cheating" on eachother so that we pick chromosome 0 - 1 to mate
# then 1 - 2, 2 - 3 and so on. Hence 100% populationProduce (see above) will yield a
# populationProduction of 12 chromosomes, although it says 6. Check crossover function.
populationProduction = floor(ceil(populationSize * populationProduce)/2)
print('populationProduction ' + str(populationProduction))

# How often a bit will flip during a mutation
mutationRatio = 0.3
print('mutationRatio ' + str(mutationRatio))

# How many interation of generations
generationSize = 100

# A value eg. x coordinate for a corner on a rectangle represents 4 bit value
chromosomeBitsValue = 4

# A rectangle has 4 points x,y where one point x is equal to 4 binaries.
# eg. 15 decimal is the highest point
# Times two since a corner has two values and times 4 since a rect has 4 corners
chromosomeSize = chromosomeBitsValue*2*4

# Init random population
#population = np.random.randint(2, size=(populationSize, chromosomeSize))
for i in range(populationSize):
chromosomeGene = np.random.randint(2, size=(chromosomeSize))
if i == 0:
population = np.array(Chromosome(chromosomeGene))
else:
population = np.vstack([population, Chromosome(chromosomeGene)])

# How many cycles until a mutation
mutationCycle = 2

threshold = False
for generation in range(generationSize):

print ('Generation: ' + str(generation))
#population = roulette(population) #roulette wheel
population = crossover(population) #crossing
if generation % mutationCycle == 0:
population = mutation(population)

population = fitness(population) #sort by fitness

#test numb
numb = 0
for c in population:
numb += 1
print(c.fitness)
if numb == populationSize:
break

#if fit >= 260:
#    threshold = True

if threshold:
break

print(population)   ``````