I am currently working on a school project which consists of finding the maximum water possible out of porous medium given a fixed porosity (So we find the optimal pore distribution). I used genetic algorithm to solve this problem by modeling the medium as a square matrix filled with 0 for void, 1 for solid medium and 2 for water. I looked up the internet for optimal values of crossover rates, mutation rates,etc. The problem is that sometimes I reach a maximum and then it starts to drop over the generations, and sometimes I am stuck with 0 water out of the medium for all the generations. I don't know where did I go wrong. If you need the code for the evolution process or the crossover, feel free to tell me in the comments. Thanks in advance.
Crossover: This function crossover two mediums and maintains the porosity, the child should have the same porosity as both parents.
def crossover(g,h,n,p,cp):#crossover(parent1,parent2,size of matrix, porosity,crossover rate)
b=n*n
k=int(b*p)
l=g
if cp>rnd.random():
l[n//3:2*n//3] = h[n//3:2*n//3]
count = 0
for i in range(n):
for j in range(n):
if l[i][j] == 1:
count +=1
diff = count-k
if diff>0:
while diff>0:
i=rnd.randint(0,n-1)
j=rnd.randint(0,n-1)
if l[i][j] == 1:
l[i][j] = 0
diff -=1
if diff<0:
while diff<0:
i=rnd.randint(0,n-1)
j=rnd.randint(0,n-1)
if l[i][j] == 0:
l[i][j] = 1
diff+=1
return l
This crossover is a two point crossover.
Evolution code:
def evolve(pop,m,n,p,mp,cp,sp=0.3):#evolve(the population list,population length, matrix size,porosity,mutation probability, crossover probability, rate of individuals to be selected for the upcoming generation)
graded = [ (ratio(pop[i], n), i) for i in range(m)]
graded = [ x[1] for x in sorted(graded)]
retain_length = int(m*sp)
parents = [pop[x] for x in graded[retain_length:]]
# randomly add other individuals to promote genetic diversity
for individual in graded[:retain_length]:
if 0.025 > rnd.random():
parents.append(pop[individual])
# mutate some individuals
for individual in parents:
if mp>rnd.random():
individual = mutate(individual,n,mp)
# crossover parents to create children
parents_length = len(parents)
desired_length = m - parents_length
children = []
while len(children) < desired_length:
male = rnd.randint(0, parents_length-1)
female = rnd.randint(0, parents_length-1)
if male != female:
male = parents[male]
female = parents[female]
children.append(crossover(male,female,n,p,cp))
parents.extend(children)
return parents
Edit: After increasing the mutation rate up to 0.05, the GA gives me good results, but doesn't it mean that I lose some of the parents genes? Another question, what if I chose the population being the result of the first GA run and use it in the next one, would it increase the performance?