Skip to content

Commit dbb05d9

Browse files
authored
A generic algorithim mutation
1 parent fcf82a1 commit dbb05d9

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

Diff for: generic mutation.py

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Python3 program to create target string, starting from
2+
# random string using Genetic Algorithm
3+
4+
import random
5+
6+
# Number of individuals in each generation
7+
POPULATION_SIZE = 10
8+
9+
# Valid genes
10+
GENES = '''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
11+
QRSTUVWXYZ 1234567890, .-;:_!"#%&/()=?@${[]}'''
12+
13+
# Target string to be generated
14+
TARGET = "I love GeeksforGeeks"
15+
16+
class Individual(object):
17+
'''
18+
Class representing individual in population
19+
'''
20+
def __init__(self, chromosome):
21+
self.chromosome = chromosome
22+
self.fitness = self.cal_fitness()
23+
24+
@classmethod
25+
def mutated_genes(self):
26+
'''
27+
Create random genes for mutation
28+
'''
29+
global GENES
30+
gene = random.choice(GENES)
31+
return gene
32+
33+
@classmethod
34+
def create_gnome(self):
35+
'''
36+
Create chromosome or string of genes
37+
'''
38+
global TARGET
39+
gnome_len = len(TARGET)
40+
return [self.mutated_genes() for _ in range(gnome_len)]
41+
42+
def mate(self, par2):
43+
'''
44+
Perform mating and produce new offspring
45+
'''
46+
47+
# Chromosome for offspring
48+
child_chromosome = []
49+
for gp1, gp2 in zip(self.chromosome, par2.chromosome):
50+
51+
# Random probability
52+
prob = random.random()
53+
54+
# If prob is less than 0.45, insert gene
55+
# from parent 1
56+
if prob < 0.45:
57+
child_chromosome.append(gp1)
58+
59+
# If prob is between 0.45 and 0.90, insert
60+
# gene from parent 2
61+
elif prob < 0.90:
62+
child_chromosome.append(gp2)
63+
64+
# Otherwise insert random gene (mutate),
65+
# for maintaining diversity
66+
else:
67+
child_chromosome.append(self.mutated_genes())
68+
69+
# Create new Individual (offspring) using
70+
# generated chromosome for offspring
71+
return Individual(child_chromosome)
72+
73+
def cal_fitness(self):
74+
'''
75+
Calculate fitness score, it is the number of
76+
characters in string which differ from target
77+
string.
78+
'''
79+
global TARGET
80+
fitness = 0
81+
for gs, gt in zip(self.chromosome, TARGET):
82+
if gs != gt:
83+
fitness += 1
84+
return fitness
85+
86+
# Driver code
87+
def main():
88+
global POPULATION_SIZE
89+
90+
# Current generation
91+
generation = 1
92+
93+
found = False
94+
population = []
95+
96+
# Create initial population
97+
for _ in range(POPULATION_SIZE):
98+
gnome = Individual.create_gnome() # Fixed this
99+
population.append(Individual(gnome))
100+
101+
while not found:
102+
103+
# Sort the population in increasing order of fitness score
104+
population = sorted(population, key = lambda x:x.fitness)
105+
106+
# If the individual having the lowest fitness score is 0,
107+
# we have reached the target
108+
if population[0].fitness <= 0:
109+
found = True
110+
break
111+
112+
# Otherwise, generate new offsprings for new generation
113+
new_generation = []
114+
115+
# Perform Elitism, that means 10% of fittest population
116+
# goes to the next generation
117+
s = int((10 * POPULATION_SIZE) / 100)
118+
new_generation.extend(population[:s])
119+
120+
# From 50% of the fittest population, individuals
121+
# will mate to produce offspring
122+
s = int((90 * POPULATION_SIZE) / 100)
123+
for _ in range(s):
124+
parent1 = random.choice(population[:50])
125+
parent2 = random.choice(population[:50])
126+
child = parent1.mate(parent2)
127+
new_generation.append(child)
128+
129+
population = new_generation
130+
131+
# Print current generation details
132+
print("Generation: {}\tString: {}\tFitness: {}".format(
133+
generation,
134+
"".join(population[0].chromosome),
135+
population[0].fitness))
136+
137+
generation += 1
138+
139+
# Print final result
140+
print("Generation: {}\tString: {}\tFitness: {}".format(
141+
generation,
142+
"".join(population[0].chromosome),
143+
population[0].fitness))
144+
145+
if __name__ == '__main__':
146+
main()

0 commit comments

Comments
 (0)