Commit 8b8d63153ec80098d310e077ba22ff28d180bce9

Authored by Olav Kjartan Larseng
1 parent 0caafc34

Done. Added roulette, fixed fitness and positional problems with the box

GAassignment5_ola014.pdf 0 → 100644
No preview for this file type
__pycache__/chromsome.cpython-36.pyc
No preview for this file type
chromsome.py
... ... @@ -45,17 +45,30 @@ class Chromosome:
45 45 y4 = float(BitArray(bin=''.join(map(str, self.gene[self.chromosomeBitsValue*7:self.chromosomeBitsValue*8]))).uint)
46 46  
47 47  
48   - dx1 = x1 + upperLCorner[0]
49   - dy1 = y1 + upperLCorner[1]
  48 + dx1 = round(x1 - upperLCorner[0], 1)
  49 + dy1 = round(y1 + upperLCorner[1], 1)
50 50  
51   - dx2 = x2 + upperRCorner[0]
52   - dy2 = y2 + upperRCorner[1]
  51 + dx2 = round(x2 - upperRCorner[0], 1)
  52 + dy2 = round(y2 + upperRCorner[1], 1)
53 53  
54   - dx3 = x3 + lowerLCorner[0]
55   - dy3 = y3 + lowerLCorner[1]
  54 + dx3 = round(x3 - lowerLCorner[0], 1)
  55 + dy3 = round(y3 - lowerLCorner[1], 1)
56 56  
57   - dx4 = x4 + lowerRCorner[0]
58   - dy4 = y4 + lowerRCorner[1]
  57 + dx4 = round(x4 - lowerRCorner[0], 1)
  58 + dy4 = round(y4 - lowerRCorner[1], 1)
  59 + """
  60 + dx1 = x1 - agentHeight
  61 + dy1 = y1 + agentHeight
  62 +
  63 + dx2 = x2 + agentHeight
  64 + dy2 = y2 + agentHeight
  65 +
  66 + dx3 = x3 - agentHeight
  67 + dy3 = y3 - agentHeight
  68 +
  69 + dx4 = x4 + agentHeight
  70 + dy4 = y4 - agentHeight
  71 + """
59 72  
60 73 return 'x1: ' + str(dx1) + ' y1: ' + str(dy1) + ' x2: ' + str(dx2) + ' y2: ' + str(dy2) + ' x3: ' + str(dx3) + ' y3: ' + str(dy3) + ' x4: ' + str(dx4) + ' y4: ' + str(dy4)
61 74  
... ...
ex5geneticalgo_ola014.zip 0 → 100644
No preview for this file type
... ... @@ -5,7 +5,7 @@ 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, sqrt
  8 +from math import floor, ceil, sqrt, isinf
9 9 import random
10 10 from chromsome import Chromosome
11 11 #pip install bitstring in anaconda prompt, remember to update pip: pip install --upgrade pip
... ... @@ -13,24 +13,22 @@ from bitstring import BitArray
13 13  
14 14 def fitnessCheckBounds(fitness, corners):
15 15 reward = 100
16   - rewardAll = 1000
17 16 allCornersInBound = True
18 17  
19 18 #print(corners)
20   - for pos in range(len(corners) - 1):
21   -
  19 + for pos in range(0, len(corners), 2):
22 20 # Seeking the difference in x
23 21 diff = getDifferenceSide(corners[pos], xTo)
24   - diff = round(diff, 2)
25   - if diff == 0.00:
26   - diff = 0.10
  22 + diff = round(diff, 1)
  23 + if diff == 0.0:
  24 + diff = 0.09
27 25 fitness += int((1/diff) * reward)
28 26  
29 27 # In bound of x
30 28 if corners[pos] <= xTo + agentHeight:
31   - fitness += reward * 2
  29 + fitness += reward * 10
32 30 else:
33   - fitness -= reward * 2
  31 + fitness -= reward * 10
34 32 allCornersInBound = False
35 33  
36 34  
... ... @@ -38,21 +36,21 @@ def fitnessCheckBounds(fitness, corners):
38 36 diff = getDifferenceSide(corners[pos+1], yHeight)
39 37 diff = round(diff, 1)
40 38 if diff == 0.0:
41   - diff = 0.1
42   - fitness += int((1/diff) * reward * 10)
  39 + diff = 0.09
  40 + fitness += int((1/diff) * reward)
43 41  
44 42 # In bound of y
45 43 if corners[pos+1] >= yHeight:
46   - fitness += reward * 20
  44 + fitness += reward * 10
47 45 else:
48   - fitness -= reward * 20
  46 + fitness -= reward * 10
49 47 allCornersInBound = False
50 48  
51 49  
52 50 if allCornersInBound:
53   - fitness += rewardAll
  51 + fitness += reward * 10
54 52 else:
55   - fitness -= ceil(rewardAll/2)
  53 + fitness -= reward * 10
56 54  
57 55 return fitness
58 56  
... ... @@ -60,10 +58,15 @@ def fitnessCheckLeastEnergyJump(fitness, corners):
60 58 reward = 10
61 59 heights = np.array([corners[1], corners[3], corners[5], corners[7]])
62 60  
63   - avgHeights = np.average(heights)
  61 + avgHeights = round(np.average(heights), 1)
64 62 avgHeights = avgHeights - yHeight
65 63  
66   - fitness += (1/avgHeights) * reward
  64 + if (1/avgHeights) * reward == float("inf"):
  65 + addFitness = reward*10
  66 + else:
  67 + addFitness = int((1/avgHeights) * reward)
  68 +
  69 + fitness += addFitness
67 70  
68 71 return fitness
69 72  
... ... @@ -82,8 +85,8 @@ def fitnessCheckQuadrant(fitness, corners):
82 85 diff = getDifferenceSide(sideLen1, agentHeight)
83 86 diff = round(diff, 1)
84 87 if diff == 0.0:
85   - diff = 0.1
86   - fitness += int((1/diff) * reward)
  88 + diff = 0.09
  89 + fitness += int((1/diff) * reward * 10)
87 90  
88 91 #Are the sides of same length?
89 92 allSidesEqual = True
... ... @@ -94,24 +97,29 @@ def fitnessCheckQuadrant(fitness, corners):
94 97 diff = round(getDifferenceSide(allSides[i], allSides[0]), 1)
95 98  
96 99 if diff == 0.0:
97   - diff = 0.1
  100 + diff = 0.09
98 101 else:
99 102 allSidesEqual = False
100 103  
101   - fitness += (1/diff) * reward
  104 + fitness += int((1/diff) * reward * 2)
102 105  
103 106  
104 107  
105 108 if allSidesEqual:
106   - fitness += reward * 1000
  109 + fitness += reward * 15
107 110  
  111 +
108 112 return fitness
109 113  
110 114 def getSideLength(x1, y1, x2, y2):
111 115 return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))
112 116  
113 117 def getDifferenceSide(side1, side2):
114   - return abs(side1 - side2)
  118 + value = abs(side1 - side2)
  119 + if value == float("inf"):
  120 + return 0.0
  121 + else:
  122 + return value
115 123  
116 124 def fitnessValue(chromosome):
117 125 chromosomeAgent = chromosome[0]
... ... @@ -132,26 +140,53 @@ def fitnessValue(chromosome):
132 140 y4 = float(BitArray(bin=''.join(map(str, chromosome[chromosomeBitsValue*7:chromosomeBitsValue*8]))).uint)
133 141  
134 142  
135   - dx1 = x1 + upperLCorner[0]
136   - dy1 = y1 + upperLCorner[1]
  143 + dx1 = round(x1 - upperLCorner[0], 1)
  144 + dy1 = round(y1 + upperLCorner[1], 1)
  145 +
  146 + dx2 = round(x2 - upperRCorner[0], 1)
  147 + dy2 = round(y2 + upperRCorner[1], 1)
  148 +
  149 + dx3 = round(x3 - lowerLCorner[0], 1)
  150 + dy3 = round(y3 - lowerLCorner[1], 1)
  151 +
  152 + dx4 = round(x4 - lowerRCorner[0], 1)
  153 + dy4 = round(y4 - lowerRCorner[1], 1)
  154 +
  155 + """
  156 + dx1 = x1 - agentHeight
  157 + dy1 = y1 + agentHeight
137 158  
138   - dx2 = x2 + upperRCorner[0]
139   - dy2 = y2 + upperRCorner[1]
  159 + dx2 = x2 + agentHeight
  160 + dy2 = y2 + agentHeight
140 161  
141   - dx3 = x3 + lowerLCorner[0]
142   - dy3 = y3 + lowerLCorner[1]
  162 + dx3 = x3 - agentHeight
  163 + dy3 = y3 - agentHeight
143 164  
144   - dx4 = x4 + lowerRCorner[0]
145   - dy4 = y4 + lowerRCorner[1]
  165 + dx4 = x4 + agentHeight
  166 + dy4 = y4 - agentHeight
146 167  
  168 +
  169 + dx1 = x1
  170 + dy1 = y1
  171 +
  172 + dx2 = x2
  173 + dy2 = y2
  174 +
  175 + dx3 = x3
  176 + dy3 = y3
  177 +
  178 + dx4 = x4
  179 + dy4 = y4
  180 + """
147 181 corners = np.array([dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4])
148 182  
149 183 fitness = fitnessCheckBounds(fitness, corners)
150   - fitness = fitnessCheckLeastEnergyJump(fitness, corners)
151   - fitness = fitnessCheckQuadrant(fitness, corners)
  184 + fitness += fitnessCheckLeastEnergyJump(fitness, corners)
  185 + fitness += fitnessCheckQuadrant(fitness, corners)
152 186  
  187 +
153 188 fitness = int(fitness)
154   - chromosomeAgent.fitness = fitness
  189 + chromosomeAgent.fitness = round(fitness / highestAccFitness, 4)
155 190 return fitness
156 191  
157 192 def fitness(population):
... ... @@ -204,13 +239,28 @@ def mutationSingle(population):
204 239  
205 240 return population
206 241  
  242 +def mutationFromWhole(index, population):
  243 + for i in range(index, len(population)):
  244 + for j in range(len(population[i][0].gene)):
  245 + ran = random.uniform(0.0, 1.0)
  246 + if ran <= mutationRatio:
  247 + chromosome = population[i][0]
  248 + chromosomeBit = chromosome.geneAt(j)
  249 + if random.uniform(0.0, 1.0) <= mutationRatio:
  250 + if chromosomeBit != 0:
  251 + chromosome.geneSet(j, 0)
  252 + else:
  253 + chromosome.geneSet(j, 1)
  254 + return population
  255 +
207 256 def mutation(population):
208 257 #population = mutationWhole(population)
209   - population = mutationSingle(population)
  258 + #population = mutationSingle(population)
  259 + population = mutationFromWhole(populationProduction, population)
210 260 return population
211 261  
212 262 # Using roulette based on the fittest population array, where fitness is sorted
213   -# Chossing a random chromosome from a most likely group based on fitness
  263 +# Choosing a random chromosome from a most likely group based on fitness
214 264 def roulette(population):
215 265 lp = list(population)
216 266 groupSize = 4
... ... @@ -273,15 +323,17 @@ def getAccumulatedLength2D(arr, index):
273 323 def crossover(population):
274 324 #print("Before: \n" + str(population))
275 325 offspring = np.array
276   - splitSize = 2
  326 + splitSize = np.random.randint(0,3)
  327 + #populationProduction = floor(ceil(len(population) * populationProduce)/2)
  328 +
277 329 for i in range(populationProduction):
278 330 if i >= populationSize-1:
279 331 break
280 332  
281   - parent1 = population.item(i).gene
282   - parent2 = population.item(i+1).gene
283   - #parent1 = population.item(roulette(population)).gene
284   - #parent2 = population.item(roulette(population)).gene
  333 + #parent1 = population.item(i).gene
  334 + #parent2 = population.item(i+1).gene
  335 + parent1 = population.item(roulette(population)).gene
  336 + parent2 = population.item(roulette(population)).gene
285 337  
286 338 #print('paren1' + str(parent1))
287 339 #print('paren2' + str(parent2))
... ... @@ -292,19 +344,19 @@ def crossover(population):
292 344 itr = 0
293 345 count = 0
294 346 while (count < chromosomeSize):
295   - if itr%2 != 0:
296   - child1 = np.concatenate((
297   - child1,
298   - parent1[count:count+splitSize], #p1 split x/y
299   - parent2[count+splitSize:count+4] #p2 split x/y
300   - ), axis=0)
301   -
302   - child2 = np.concatenate((
303   - child2,
304   - parent2[count:count+splitSize], #p1 split x/y
305   - parent1[count+splitSize:count+4] #p2 split x/y
306   - ), axis=0)
307   -
  347 + #if itr%2 != 0:
  348 + child1 = np.concatenate((
  349 + child1,
  350 + parent1[count:count+splitSize], #p1 split x/y
  351 + parent2[count+splitSize:count+chromosomeBitsValue] #p2 split x/y
  352 + ), axis=0)
  353 +
  354 + child2 = np.concatenate((
  355 + child2,
  356 + parent2[count:count+splitSize], #p1 split x/y
  357 + parent1[count+splitSize:count+chromosomeBitsValue] #p2 split x/y
  358 + ), axis=0)
  359 + """
308 360 else:
309 361 child1 = np.concatenate((
310 362 child1,
... ... @@ -314,6 +366,7 @@ def crossover(population):
314 366 child2,
315 367 parent2[count:count+4], #p1 take the whole x/y
316 368 ), axis=0)
  369 + """
317 370  
318 371 count += chromosomeBitsValue
319 372 itr += 1
... ... @@ -327,20 +380,20 @@ def crossover(population):
327 380 offspring = np.vstack([offspring, Chromosome(child1), Chromosome(child2)])
328 381  
329 382 #Remove
330   - #population = np.delete(population, np.s_[len(population)-len(offspring):len(population)], axis = 0)
  383 + population = np.delete(population, np.s_[len(population)-len(offspring):len(population)], axis = 0)
331 384  
332 385 #Insert
333   - population = np.vstack([offspring, population])
  386 + population = np.vstack([population, offspring])
334 387  
335 388 #print("After: \n" + str(population))
336 389 return population
337 390  
338 391  
339 392  
340   -# Init agent values, you'll have to change them in chromosome too
341   -yHeight = 4.0
  393 +# Init agent values, WARNING: !!!you'll have to change them in chromosome too!!!
  394 +yHeight = 3.0
342 395 xStart = 4.0 # chromosome
343   -xTo = 1.0
  396 +xTo = 2.0 # Where the hurdle stands
344 397 agentHeight = 0.2 #chromosome
345 398 upperLCorner = np.array([xStart-(agentHeight/2), agentHeight])
346 399 upperRCorner = np.array([xStart+(agentHeight/2), agentHeight])
... ... @@ -349,10 +402,10 @@ lowerRCorner = np.array([xStart+(agentHeight/2), 0.0])
349 402  
350 403  
351 404 # Size of population
352   -populationSize = 12
  405 +populationSize = 30
353 406  
354 407 # percentage of parents which will produce two childrens
355   -populationProduce = 0.4
  408 +populationProduce = 0.5
356 409  
357 410 # WARNING: OLD below, not that relevant. I am now using roulette to choose mates.
358 411 # Population production will determine how many chromosomes will be able to mate.
... ... @@ -363,11 +416,11 @@ populationProduction = floor(ceil(populationSize * populationProduce)/2)
363 416 print('populationProduction ' + str(populationProduction))
364 417  
365 418 # How often a bit will flip during a mutation
366   -mutationRatio = 0.5
  419 +mutationRatio = 0.3
367 420 print('mutationRatio ' + str(mutationRatio))
368 421  
369 422 # How many interation of generations
370   -generationSize = 200
  423 +generationSize = 5000
371 424  
372 425 # A value eg. x coordinate for a corner on a rectangle represents 4 bit value
373 426 chromosomeBitsValue = 4
... ... @@ -387,15 +440,27 @@ for i in range(populationSize):
387 440  
388 441  
389 442 # How many cycles until a mutation
390   -mutationCycle = 4
  443 +mutationCycle = 3
  444 +
  445 +# Highest overall fitness in all the generation
391 446 highestFitness = 0
392 447  
  448 +# Highest accumulated fitness possible (although might be inacc, manually calc coordinates)
  449 +# for a chromosome.
  450 +# I divide highestAccFitness on all the chromosomes fitness to get a value between 0 and 1
  451 +# WARNING: !!!You'll need to change the init values if you want to change best fitting chromosomes.!!!
  452 +#A: yHeight = 4.0 | xTo = 1.0
  453 +bestChromTaskA = np.array([0,1,0,1, 0,1,0,0, 0,1,0,1, 0,1,0,0, 0,1,0,1, 0,1,0,0, 0,1,0,1, 0,1,0,0])
  454 +#B: yHeight = 3.0 | xTo = 2.0
  455 +bestChromTaskB = np.array([0,1,1,0, 0,0,1,1, 0,1,1,0, 0,0,1,1, 0,1,1,0, 0,0,1,1, 0,1,1,0, 0,0,1,1])
  456 +highestAccFitness = fitnessValue(np.array([Chromosome(bestChromTaskB)]))
  457 +print('highestAccFitness: ' + str(highestAccFitness))
  458 +
393 459 threshold = False
394 460 for generation in range(generationSize):
395   -
396 461 print ('Generation: ' + str(generation))
397   - #population = roulette(population) #roulette wheel
398 462 population = crossover(population) #crossing
  463 + population = fitness(population) #sorting again because of the mutationFromWhole function
399 464 if generation % mutationCycle == 0:
400 465 population = mutation(population)
401 466  
... ... @@ -411,15 +476,16 @@ for generation in range(generationSize):
411 476 if c[0].fitness > highestFitness:
412 477 highestFitness = c[0].fitness
413 478  
  479 +
414 480 if numb == populationSize:
415 481 break
416 482  
417   - #if fit >= 260:
418   - # threshold = True
  483 + if c[0].fitness >= 0.99:
  484 + threshold = True
419 485  
420 486 print('highestFitness: ' + str(highestFitness))
421 487 if threshold:
  488 + print('threshold met!')
422 489 break
423 490  
424 491  
425   -#print(population)
... ...