class-scheduling / algorithm /GeneticAlgorithm.py
garizz's picture
Upload 31 files
8e7d8ae
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
@property
# 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"