Commit 8eca4f08d57da4a4bb88c151bcd3a0161e014d75

Authored by Olav Kjartan Larseng
1 parent 3c8fa9fa

redesign with class chromosome

__pycache__/chromsome.cpython-36.pyc 0 → 100644
No preview for this file type
chromsome.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +"""
  3 +Created on Thu May 10 16:49:45 2018
  4 +
  5 +@author: Olav
  6 +"""
  7 +import numpy as np
  8 +
  9 +class Chromosome:
  10 + fitness = 0
  11 + gene = np.array
  12 +
  13 + def __init__(self, _gene):
  14 + self.gene = _gene
  15 +
  16 + def __repr__(self):
  17 + return 'Gene: ' + str(self.gene) + ' Fitness: ' + str(self.fitness)
  18 +
  19 + def geneAt(self, index):
  20 + return self.gene[index]
  21 +
  22 + def geneSet(self, index, value):
  23 + self.gene[index] = value
... ...
... ... @@ -5,8 +5,9 @@ Created on Mon May 7 12:46:27 2018
5 5 @author: Olav
6 6 """
7 7 import numpy as np
8   -from math import floor, ceil
  8 +from math import floor, ceil, sqrt
9 9 import random
  10 +from chromsome import Chromosome
10 11 #pip install bitstring in anaconda prompt, remember to update pip: pip install --upgrade pip
11 12 from bitstring import BitArray
12 13  
... ... @@ -26,7 +27,7 @@ def fitnessCheckBounds(fitness, corners):
26 27 allCornersInBound = False
27 28  
28 29 if corners[corner+1] >= yHeight:
29   - fitness += reward
  30 + fitness += reward*2
30 31 else:
31 32 allCornersInBound = False
32 33  
... ... @@ -50,43 +51,53 @@ def fitnessCheckLeastEnergyJump(fitness, corners):
50 51 return fitness
51 52  
52 53 def fitnessCheckQuadrant(fitness, corners):
53   - #reward = 300
54   - rewardOne = 10
55   - rewardTwo = -20
56   - #isAQuadrant = True
57   -
58   - cornerDx1 = corners[0] - corners[2]
59   - cornerDy1 = corners[1] - corners[3]
60   -
61   - cornerDx2 = corners[2] - corners[4]
62   - cornerDy2 = corners[3] - corners[5]
63   -
64   - cornerDx3 = corners[4] - corners[6]
65   - cornerDy3 = corners[5] - corners[7]
66   -
67   - if cornerDx1 == cornerDx2:
68   - fitness += rewardOne
69   - else:
70   - fitness += rewardTwo
71   -
72   - if cornerDy1 == cornerDy2:
73   - fitness += rewardOne
74   - else:
75   - fitness += rewardTwo
76   -
77   - if cornerDx2 == cornerDx3:
78   - fitness += rewardOne
79   - else:
80   - fitness += rewardTwo
81   -
82   - if cornerDy2 == cornerDy3:
83   - fitness += rewardOne
84   - else:
85   - fitness += rewardTwo
86   -
  54 + reward = 100
  55 +
  56 + #Check length of all corners
  57 + sideLen1 = getSideLength(corners[0], corners[1], corners[2], corners[3])
  58 + sideLen2 = getSideLength(corners[2], corners[3], corners[4], corners[5])
  59 + sideLen3 = getSideLength(corners[4], corners[5], corners[6], corners[7])
  60 + sideLen4 = getSideLength(corners[6], corners[7], corners[0], corners[1])
  61 + allSides = np.array([sideLen1, sideLen2, sideLen3, sideLen4])
  62 +
  63 + #How far away is the sides from chromosome original height
  64 + for i in range(0, 4):
  65 + diff = getDifferenceSide(sideLen1, agentHeight)
  66 + diff = round(diff, 1)
  67 + if diff == 0.0:
  68 + diff = 0.1
  69 + fitness += int((1/diff) * reward)
  70 +
  71 + #Are the sides of same length?
  72 + allSidesEqual = True
  73 + for i in range(0, 4):
  74 + if i != 3:
  75 + diff = round(getDifferenceSide(allSides[i], allSides[i+1]), 1)
  76 + else:
  77 + diff = round(getDifferenceSide(allSides[i], allSides[0]), 1)
  78 +
  79 + if diff == 0.0:
  80 + diff = 0.1
  81 + else:
  82 + allSidesEqual = False
  83 +
  84 + fitness += (1/diff) * reward
  85 +
  86 + if allSidesEqual:
  87 + fitness += reward * 1000
  88 +
87 89 return fitness
88 90  
  91 +def getSideLength(x1, y1, x2, y2):
  92 + return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))
  93 +
  94 +def getDifferenceSide(side1, side2):
  95 + return abs(side1 - side2)
  96 +
89 97 def fitnessValue(chromosome):
  98 + chromosomeAgent = chromosome[0]
  99 + chromosome = chromosomeAgent.gene
  100 +
90 101 fitness = 0
91 102  
92 103 x1 = float(BitArray(bin=''.join(map(str, chromosome[0:chromosomeBitsValue]))).uint)
... ... @@ -120,7 +131,8 @@ def fitnessValue(chromosome):
120 131 fitness = fitnessCheckLeastEnergyJump(fitness, corners)
121 132 fitness = fitnessCheckQuadrant(fitness, corners)
122 133  
123   -
  134 + fitness = int(fitness)
  135 + chromosomeAgent.fitness = fitness
124 136 return fitness
125 137  
126 138 def fitness(population):
... ... @@ -131,6 +143,7 @@ def fitness(population):
131 143 return population
132 144  
133 145 def mutation(population):
  146 + """
134 147 for i in range(len(population)):
135 148 for j in range(len(population[i])):
136 149 if random.uniform(0.0, 1.0) <= mutationRatio:
... ... @@ -138,6 +151,23 @@ def mutation(population):
138 151 population[i][j] = 0
139 152 else:
140 153 population[i][j] = 1
  154 + """
  155 + chromosomePick = np.random.randint(len(population))
  156 + for j in range(populationSize):
  157 + if random.uniform(0.0, 1.0) <= mutationRatio:
  158 + chromosome = population[chromosomePick][0]
  159 + chromosomeBit = chromosome.geneAt(j)
  160 +
  161 + if chromosomeBit != 0:
  162 + chromosome.geneSet(j, 0)
  163 + else:
  164 + chromosome.geneSet(j, 1)
  165 +
  166 +
  167 + return population
  168 +
  169 +def roulette(population):
  170 + populationSize = len(population)
141 171  
142 172 return population
143 173  
... ... @@ -149,8 +179,9 @@ def crossover(population):
149 179 if i >= populationSize-1:
150 180 break
151 181  
152   - parent1 = population[i]
153   - parent2 = population[i+1]
  182 + parent1 = population.item(i).gene
  183 + parent2 = population.item(i+1).gene
  184 +
154 185 #print('paren1' + str(parent1))
155 186 #print('paren2' + str(parent2))
156 187  
... ... @@ -183,19 +214,19 @@ def crossover(population):
183 214 parent2[count:count+4], #p1 take the whole x/y
184 215 ), axis=0)
185 216  
186   - count += 4
  217 + count += chromosomeBitsValue
187 218 itr += 1
188 219  
189 220  
190 221 #print('child1' + str(child1))
191 222 #print('child2' + str(child2))
192 223 if i == 0:
193   - offspring = np.vstack([child1, child2])
  224 + offspring = np.vstack([Chromosome(child1), Chromosome(child2)])
194 225 else:
195   - offspring = np.vstack([offspring, child1, child2])
  226 + offspring = np.vstack([offspring, Chromosome(child1), Chromosome(child2)])
196 227  
197 228 #Remove
198   - population = np.delete(population, np.s_[len(population)-len(offspring):len(population)], axis = 0)
  229 + #population = np.delete(population, np.s_[len(population)-len(offspring):len(population)], axis = 0)
199 230  
200 231 #Insert
201 232 population = np.vstack([offspring, population])
... ... @@ -205,6 +236,7 @@ def crossover(population):
205 236  
206 237  
207 238  
  239 +# Init agent values
208 240 yHeight = 4.0
209 241 xStart = 3.0
210 242 xTo = 0.0
... ... @@ -215,46 +247,69 @@ lowerLCorner = np.array([xStart-(agentHeight/2), 0.0])
215 247 lowerRCorner = np.array([xStart+(agentHeight/2), 0.0])
216 248  
217 249  
  250 +# Size of population
  251 +populationSize = 12
218 252  
219   -populationSize = 20
220   -#percentage of parents which will produce two childrens
221   -populationProduce = 0.2
222   -populationProduction = floor(ceil(populationSize * populationProduce)/2)
  253 +# percentage of parents which will produce two childrens
  254 +populationProduce = 0.5
223 255  
224   -mutationRatio = 0.05
  256 +# WARNING: OLD below, not that relevant
  257 +# Population production will determine how many chromosomes will be able to mate.
  258 +# The chromosomes are "cheating" on eachother so that we pick chromosome 0 - 1 to mate
  259 +# then 1 - 2, 2 - 3 and so on. Hence 100% populationProduce (see above) will yield a
  260 +# populationProduction of 12 chromosomes, although it says 6. Check crossover function.
  261 +populationProduction = floor(ceil(populationSize * populationProduce)/2)
225 262 print('populationProduction ' + str(populationProduction))
226   -print('mutationRatio ' + str(mutationRatio))
227 263  
228   -generationSize = 1000
229   -highestFitness = 0
  264 +# How often a bit will flip during a mutation
  265 +mutationRatio = 0.3
  266 +print('mutationRatio ' + str(mutationRatio))
230 267  
  268 +# How many interation of generations
  269 +generationSize = 100
231 270  
232 271 # A value eg. x coordinate for a corner on a rectangle represents 4 bit value
233 272 chromosomeBitsValue = 4
  273 +
234 274 # A rectangle has 4 points x,y where one point x is equal to 4 binaries.
235 275 # eg. 15 decimal is the highest point
236 276 # Times two since a corner has two values and times 4 since a rect has 4 corners
237 277 chromosomeSize = chromosomeBitsValue*2*4
238 278  
239   -#sorting for later
240   -#self._stack.sort(key=lambda x: self.fv(x))
  279 +# Init random population
  280 +#population = np.random.randint(2, size=(populationSize, chromosomeSize))
  281 +for i in range(populationSize):
  282 + chromosomeGene = np.random.randint(2, size=(chromosomeSize))
  283 + if i == 0:
  284 + population = np.array(Chromosome(chromosomeGene))
  285 + else:
  286 + population = np.vstack([population, Chromosome(chromosomeGene)])
241 287  
242   -#initialize random population
243 288  
244   -population = np.random.randint(2, size=(populationSize, chromosomeSize))
  289 +# How many cycles until a mutation
  290 +mutationCycle = 2
245 291  
246 292 threshold = False
247 293 for generation in range(generationSize):
248 294  
249 295 print ('Generation: ' + str(generation))
250   - population = crossover(population)
251   - population = mutation(population)
252   - population = fitness(population)
  296 + #population = roulette(population) #roulette wheel
  297 + population = crossover(population) #crossing
  298 + if generation % mutationCycle == 0:
  299 + population = mutation(population)
  300 +
  301 + population = fitness(population) #sort by fitness
  302 +
  303 + #test numb
  304 + numb = 0
253 305 for c in population:
254   - fit = int(fitnessValue(c))
255   - print(fit)
256   - if fit >= 260:
257   - threshold = True
  306 + numb += 1
  307 + print(c[0].fitness)
  308 + if numb == populationSize:
  309 + break
  310 +
  311 + #if fit >= 260:
  312 + # threshold = True
258 313  
259 314 if threshold:
260 315 break
... ... @@ -262,7 +317,3 @@ for generation in range(generationSize):
262 317  
263 318  
264 319 print(population)
265   -
266   -#Fi = qi /Sum(qj)
267   -
268   -
... ...