Spaces:
Sleeping
Sleeping
| from model.Schedule import Schedule | |
| import random | |
| from random import randrange | |
| from time import time | |
| # Lakshmi, R. et al. “A New Biological Operator in Genetic Algorithm for Class Scheduling Problem.” | |
| # International Journal of Computer Applications 60 (2012): 6-11. | |
| # Genetic algorithm | |
| class GeneticAlgorithm: | |
| def initAlgorithm(self, prototype, numberOfChromosomes=100, replaceByGeneration=8, trackBest=5): | |
| # Number of best chromosomes currently saved in best chromosome group | |
| self._currentBestSize = 0 | |
| # Prototype of chromosomes in population | |
| self._prototype = prototype | |
| # there should be at least 2 chromosomes in population | |
| if numberOfChromosomes < 2: | |
| numberOfChromosomes = 2 | |
| # and algorithm should track at least on of best chromosomes | |
| if trackBest < 1: | |
| trackBest = 1 | |
| # Population of chromosomes | |
| self._chromosomes = numberOfChromosomes * [None] | |
| # Inidicates whether chromosome belongs to best chromosome group | |
| self._bestFlags = numberOfChromosomes * [False] | |
| # Indices of best chromosomes | |
| self._bestChromosomes = trackBest * [0] | |
| # Number of chromosomes which are replaced in each generation by offspring | |
| self.set_replace_by_generation(replaceByGeneration) | |
| # Initializes genetic algorithm | |
| def __init__(self, configuration, numberOfCrossoverPoints=2, mutationSize=2, crossoverProbability=80, | |
| mutationProbability=3): | |
| self.initAlgorithm(Schedule(configuration)) | |
| self._mutationSize = mutationSize | |
| self._numberOfCrossoverPoints = numberOfCrossoverPoints | |
| self._crossoverProbability = crossoverProbability | |
| self._mutationProbability = mutationProbability | |
| # Returns pointer to best chromosomes in population | |
| def result(self): | |
| return self._chromosomes[self._bestChromosomes[0]] | |
| def set_replace_by_generation(self, value): | |
| numberOfChromosomes = len(self._chromosomes) | |
| trackBest = len(self._bestChromosomes) | |
| if (value > numberOfChromosomes - trackBest): | |
| value = numberOfChromosomes - trackBest | |
| self._replaceByGeneration = value | |
| # Tries to add chromosomes in best chromosome group | |
| def addToBest(self, chromosomeIndex): | |
| bestChromosomes = self._bestChromosomes | |
| length_best = len(bestChromosomes) | |
| bestFlags = self._bestFlags | |
| chromosomes = self._chromosomes | |
| # don't add if new chromosome hasn't fitness big enough for best chromosome group | |
| # or it is already in the group? | |
| if (self._currentBestSize == length_best and chromosomes[bestChromosomes[self._currentBestSize - 1]].fitness >= | |
| chromosomes[chromosomeIndex].fitness) or bestFlags[chromosomeIndex]: | |
| return | |
| # find place for new chromosome | |
| j = self._currentBestSize | |
| for i in range(j, -1, -1): | |
| j = i | |
| pos = bestChromosomes[i - 1] | |
| # group is not full? | |
| if i < length_best: | |
| # position of new chromosomes is found? | |
| if chromosomes[pos].fitness > chromosomes[chromosomeIndex].fitness: | |
| break | |
| # move chromosomes to make room for new | |
| bestChromosomes[i] = pos | |
| else: | |
| # group is full remove worst chromosomes in the group | |
| bestFlags[pos] = False | |
| # store chromosome in best chromosome group | |
| bestChromosomes[j] = chromosomeIndex | |
| bestFlags[chromosomeIndex] = True | |
| # increase current size if it has not reached the limit yet | |
| if self._currentBestSize < length_best: | |
| self._currentBestSize += 1 | |
| # Returns TRUE if chromosome belongs to best chromosome group | |
| def isInBest(self, chromosomeIndex) -> bool: | |
| return self._bestFlags[chromosomeIndex] | |
| # Clears best chromosome group | |
| def clearBest(self): | |
| self._bestFlags = len(self._bestFlags) * [False] | |
| self._currentBestSize = 0 | |
| # initialize new population with chromosomes randomly built using prototype | |
| def initialize(self, population): | |
| # addToBest = self.addToBest | |
| prototype = self._prototype | |
| length_chromosomes = len(population) | |
| for i in range(0, length_chromosomes): | |
| # add new chromosome to population | |
| population[i] = prototype.makeNewFromPrototype() | |
| # addToBest(i) | |
| def selection(self, population): | |
| length_chromosomes = len(population) | |
| return (population[randrange(32768) % length_chromosomes], population[randrange(32768) % length_chromosomes]) | |
| def replacement(self, population, replaceByGeneration) -> []: | |
| mutationSize = self._mutationSize | |
| numberOfCrossoverPoints = self._numberOfCrossoverPoints | |
| crossoverProbability = self._crossoverProbability | |
| mutationProbability = self._mutationProbability | |
| selection = self.selection | |
| isInBest = self.isInBest | |
| length_chromosomes = len(population) | |
| # produce offspring | |
| offspring = replaceByGeneration * [None] | |
| for j in range(replaceByGeneration): | |
| # selects parent randomly | |
| parent = selection(population) | |
| offspring[j] = parent[0].crossover(parent[1], numberOfCrossoverPoints, crossoverProbability) | |
| offspring[j].mutation(mutationSize, mutationProbability) | |
| # replace chromosomes of current operation with offspring | |
| # select chromosome for replacement randomly | |
| ci = randrange(32768) % length_chromosomes | |
| while isInBest(ci): | |
| ci = randrange(32768) % length_chromosomes | |
| # replace chromosomes | |
| population[ci] = offspring[j] | |
| # try to add new chromosomes in best chromosome group | |
| self.addToBest(ci) | |
| return offspring | |
| # Starts and executes algorithm | |
| def run(self, maxRepeat=9999, minFitness=0.999): | |
| # clear best chromosome group from previous execution | |
| self.clearBest() | |
| length_chromosomes = len(self._chromosomes) | |
| self.initialize(self._chromosomes) | |
| random.seed(round(time() * 1000)) | |
| # Current generation | |
| currentGeneration = 0 | |
| repeat = 0 | |
| lastBestFit = 0.0 | |
| while 1: | |
| best = self.result | |
| print("Fitness:", "{:f}\t".format(best.fitness), "Generation:", currentGeneration, end="\r") | |
| # algorithm has reached criteria? | |
| if best.fitness > minFitness: | |
| break | |
| difference = abs(best.fitness - lastBestFit) | |
| if difference <= 0.0000001: | |
| repeat += 1 | |
| else: | |
| repeat = 0 | |
| if repeat > (maxRepeat / 100): | |
| random.seed(round(time() * 1000)) | |
| self.set_replace_by_generation(self._replaceByGeneration * 3) | |
| self._crossoverProbability += 1 | |
| self.replacement(self._chromosomes, self._replaceByGeneration) | |
| lastBestFit = best.fitness | |
| currentGeneration += 1 | |
| def __str__(self): | |
| return "Genetic Algorithm" | |