├── Elite and average Value plot for all generations .png ├── Plot of Average Values of each Generation .png ├── Plot of Values of Elite Chromosomesin every Generation .png ├── README.md └── knapsack with GA.py /Elite and average Value plot for all generations .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/11f3bce3b2969ff0b760273eb1e05fe5059af829/Elite and average Value plot for all generations .png -------------------------------------------------------------------------------- /Plot of Average Values of each Generation .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/11f3bce3b2969ff0b760273eb1e05fe5059af829/Plot of Average Values of each Generation .png -------------------------------------------------------------------------------- /Plot of Values of Elite Chromosomesin every Generation .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/11f3bce3b2969ff0b760273eb1e05fe5059af829/Plot of Values of Elite Chromosomesin every Generation .png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python 2 | Solving knapsack problem with "n" items and limited capacity with evolutionary strategy(genetic algorithm) 3 | ### Average Value over 100 generations 4 | ![Average Value over 100 generations](https://github.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/blob/main/Plot%20of%20Average%20Values%20of%20each%20Generation%20.png) 5 | ### Elite Chromosome over 100 generations 6 | ![Elite Chromosome over 100 generations](https://github.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/blob/main/Plot%20of%20Values%20of%20Elite%20Chromosomesin%20every%20Generation%20.png) 7 | ### Average and Elite values over 100 generations 8 | ![Average and Elite values over 100 generations](https://github.com/Elktrn/knapsack-problem-solved-with-evolutionary-strategy-Genetic-algorithm-in-python/blob/main/Elite%20and%20average%20Value%20plot%20for%20all%20generations%20.png) 9 | -------------------------------------------------------------------------------- /knapsack with GA.py: -------------------------------------------------------------------------------- 1 | # solving knapsack problem with n item and random values with GA(genetic algorithm) 2 | 3 | import random 4 | 5 | from matplotlib import pyplot as plt 6 | 7 | 8 | class Chromosome: 9 | def __init__(self, solution, value, weight, absoluteWorth): 10 | self.solution = solution 11 | self.value = value 12 | self.weight = weight 13 | self.absoluteWorth = absoluteWorth 14 | 15 | 16 | class GeneticSolver: 17 | def __init__(self, populationSize, generationCount, mutationRate, itemCount, threshold): 18 | self.populationSize = populationSize 19 | self.generationCount = generationCount 20 | self.mutationRate = mutationRate 21 | self.threshold = threshold 22 | self.population = [] 23 | self.elitePopulation = [] 24 | self.generationAverage = [] 25 | self.invalidPopulation = [] 26 | self.itemCount = itemCount 27 | self.objects = [] #[{43: 29}, {53: 36}, {55: 28}, {68: 38}, {46: 29}, {64: 23}, {69: 21}, {40: 36}, {77: 21}, {80: 36}, {65: 37}, {49: 25}, {68: 35}, {61: 25}, {67: 37}, {72: 34}, {57: 33}, {45: 22}, {46: 31}, {51: 24}] 28 | 29 | self.initialPopulation() 30 | 31 | def initialPopulation(self): 32 | for i in range(0, self.itemCount): 33 | self.objects.append({random.randint(int(self.threshold / 10),int(self.threshold / 5)): random.randint( 34 | int(self.threshold / 20), int(self.threshold /10))}) 35 | index = 0 36 | while index < self.populationSize: 37 | solution = [] 38 | for number in range(0, self.itemCount): 39 | solution.append(random.randint(0, 1)) 40 | tmpChromosome = self.generateChromosome(solution) 41 | if (tmpChromosome.value != 0) and tmpChromosome.weight <= self.threshold and ( 42 | not self.isChromosomeExist(self.population, tmpChromosome)): 43 | self.population.append(tmpChromosome) 44 | index += 1 45 | self.population.sort(key=lambda chrom: chrom.absoluteWorth, reverse=True) 46 | self.elitePopulation.append(self.population[0]) 47 | self.generationAverage.append((sum(chrom.absoluteWorth for chrom in self.population)) / self.populationSize) 48 | 49 | def getSolutionProperties(self, solution): 50 | chromosomeValue = 0 51 | chromosomeWeight = 0 52 | chromosomeAbsoluteWeight = 0 53 | index = 0 54 | for case in solution: 55 | if case == 1: 56 | value, weight = zip(*(self.objects[index].items())) 57 | chromosomeValue += value[0] 58 | chromosomeWeight += weight[0] 59 | index += 1 60 | if (chromosomeWeight != 0): 61 | chromosomeAbsoluteWeight = (chromosomeValue * chromosomeWeight - ( 62 | chromosomeValue * abs(self.threshold - chromosomeWeight))) / chromosomeWeight 63 | return [chromosomeValue, chromosomeWeight, chromosomeAbsoluteWeight] 64 | 65 | def generateChromosome(self, solution): 66 | chromosomeProperties = self.getSolutionProperties(solution) 67 | return Chromosome(solution[::], chromosomeProperties[0], chromosomeProperties[1], chromosomeProperties[2]) 68 | 69 | def mutate(self, population, chromosome): 70 | tmpChromosome = self.generateChromosome(chromosome.solution[::]) 71 | while self.isChromosomeExist(population, tmpChromosome) or ( 72 | not (1 in tmpChromosome.solution)) or tmpChromosome.weight > self.threshold: 73 | mutationIndex = random.randint(0, len(chromosome.solution) - 1) 74 | if tmpChromosome.solution[mutationIndex] == 1: 75 | tmpChromosome.solution[mutationIndex] = 0 76 | else: 77 | tmpChromosome.solution[mutationIndex] = 1 78 | tmpChromosome = self.generateChromosome(tmpChromosome.solution[::]) 79 | return self.generateChromosome(tmpChromosome.solution[::]) 80 | 81 | def isChromosomeExist(self, population, chromosome): 82 | for gene in population: 83 | if gene.solution == chromosome.solution: 84 | return True 85 | return False 86 | 87 | def printPopulation(self): 88 | for chromosome in self.population: 89 | print( 90 | f"{chromosome.solution} with value: {chromosome.value} and weight: {chromosome.weight} and absolute worth: {chromosome.absoluteWorth}") 91 | 92 | def printElitePopulation(self): 93 | generation = 0 94 | print("******************************************************************************************") 95 | print(f"printing elite chromosomes of all generations") 96 | for chromosome in self.elitePopulation: 97 | print( 98 | f"elite chromosome of generation:{generation} is: {chromosome.solution} with value: {chromosome.value} and weight: {chromosome.weight} and absolute worth: {chromosome.absoluteWorth}") 99 | generation += 1 100 | print("******************************************************************************************") 101 | index = 0 102 | answer = "" 103 | for innercase in (self.elitePopulation.pop().solution): 104 | if innercase == 1: 105 | value, weight = zip(*(self.objects[index].items())) 106 | print( 107 | f"object{index} value: {value[0]} and weight: {weight[0]} and absolute worth: {chromosome.absoluteWorth}") 108 | index += 1 109 | 110 | def crossOver(self, firstParent, secondParent): 111 | crossOverPosition = int(len(firstParent.solution) / 2) 112 | return firstParent.solution[0:crossOverPosition] + secondParent.solution[ 113 | crossOverPosition:len(firstParent.solution)] 114 | 115 | def lunchEvolution(self): 116 | generation = 0 117 | while generation < self.generationCount: 118 | print("******************************************************************************************") 119 | print(f"generation: {generation}") 120 | newPopulation = self.population[::] 121 | crossoverIndex = 0 122 | while crossoverIndex < self.populationSize: 123 | firstChildPprobability = random.randint(0, 100) 124 | secondChildPprobability = random.randint(0, 100) 125 | child1 = self.generateChromosome( 126 | self.crossOver(self.population[crossoverIndex], self.population[crossoverIndex + 1])) 127 | if (child1.value == 0) or (firstChildPprobability < self.mutationRate) or self.isChromosomeExist( 128 | newPopulation, child1) or child1.weight > self.threshold: 129 | child1 = self.mutate(newPopulation, child1) 130 | newPopulation.append(child1) 131 | child2 = self.generateChromosome( 132 | self.crossOver(self.population[crossoverIndex + 1], self.population[crossoverIndex])) 133 | if (child2.value == 0) or (secondChildPprobability < self.mutationRate) or self.isChromosomeExist( 134 | newPopulation, child2) or child2.weight > self.threshold: 135 | child2 = self.mutate(newPopulation, child2) 136 | newPopulation.append(child2) 137 | crossoverIndex += 2 138 | newPopulation.sort(key=lambda chromosome: chromosome.absoluteWorth, reverse=True) 139 | self.population.clear() 140 | self.population = newPopulation[0:self.populationSize] 141 | self.elitePopulation.append(self.population[0]) 142 | self.generationAverage.append((sum(x.absoluteWorth for x in self.population)) / self.populationSize) 143 | print( 144 | f"the best arrange of generation: {generation} is{self.elitePopulation[generation].solution} " 145 | f"wit" f"h {self.elitePopulation[generation].value} values and wight: {self.elitePopulation[generation].weight} and absolute worth: {self.elitePopulation[generation].absoluteWorth}") 146 | print( 147 | f"the average worth of generation: {generation} is {self.generationAverage[generation]} ") 148 | self.printPopulation() 149 | generation += 1 150 | 151 | def solve(self): 152 | self.lunchEvolution() 153 | plt.plot([x.absoluteWorth for x in self.elitePopulation], label="Elites") 154 | plt.xlabel('x - Generations') 155 | plt.ylabel('y - Absolute Worth ') 156 | plt.title('Evolution of elite chromosomes') 157 | plt.show() 158 | 159 | plt.plot([x for x in self.generationAverage], label="Average of Absolute Worth") 160 | plt.title('Averge Absolute Worth of each generatins') 161 | plt.xlabel('x - Generation') 162 | plt.ylabel('y - Absolute Worth ') 163 | plt.show() 164 | 165 | plt.plot([x.absoluteWorth for x in self.elitePopulation], label="Elites") 166 | plt.xlabel('x - Generations') 167 | plt.ylabel('y - Absolute Worth ') 168 | plt.title('Evolution of elite chromosomes') 169 | plt.legend() 170 | plt.plot([x for x in self.generationAverage], label="Average worthes") 171 | plt.xlabel('x - Generations') 172 | plt.ylabel('y - Absolute Worth ') 173 | plt.title('Averge Absolute Worth of each generatins') 174 | plt.legend() 175 | plt.show() 176 | print(self.objects) 177 | 178 | # populationSize, generationCount, mutationRate, itemCount, threshold 179 | #knapsack = GeneticSolver(6, 200, 10, 10, 100) 180 | knapsack = GeneticSolver(10, 100, 20, 20, 400) #generated objects are produced for this properties 181 | # knapsack = GeneticSolver(10, 80, 10, 25, 600) 182 | 183 | knapsack.solve() 184 | # knapsack.printElitePopulation() 185 | --------------------------------------------------------------------------------