I have created a genetic algorithm to create children from parents. At the start of the algorithm a random workload(arrays of sub-arrays) is created. Workload L=2, population size N=30, InputsNumber=3 and mutation rate m=0.05. Then I do some score calculations for the population to pick the 2 workloads(the parents) with highest score. Now the new population are the parents only. After that form the 2 parents I create children with crossover function and mutation function and I add the children to the population with the parents. Now I do the same thing for 10 times and every time I pick the 2 best to be the parents from the population. Now the problem is that when I change the children values in mutation function, all of a sudden the parents change their values to children values. How to avoid that? The parents are correct BEFORE I call the mutation() function and AFTER the mutation function they change. I can't understand why this is happening. Please help me find why this is happening!
HERE IS AN EXAMPLE OUTPUT: https://ibb.co/m5T0hSq
Parent or child array example: [[0 0 0],[0 0 0]] Parents or children array example: [ [[0 0 0],[0 0 0]], [[0 0 0],[0 0 0]] ]
def generateRandomWorkload(inputsNumber, L, N):
global population
individualWorkload = []
for n in range(N):
for i in range(L):
individual = [0 for _ in range(len(inputsNumber))]
individualWorkload.append(individual)
population.append(individualWorkload)
individualWorkload = []
def crossover(L):
global parents, children
children = []
for i in range(2):
C = random.randint(0, 1)
R = random.randint(0, L)
if C == 0:
child = parents[0][0:R] parents[1][R:L]
children.append(child)
elif C == 1:
child = parents[1][0:R] parents[0][R:L]
children.append(child)
return children
def mutation(mutation_rate):
global children
for i in range(len(children)):
for j in range(len(children[i])):
for k in range(len(children[i][j])):
r = random.uniform(0, 1)
if r <= mutation_rate:
children[i][j][k] = 1 - children[i][j][k]
return children
def geneticAlgorithm(inputsNumber, L, N):
global parents, children, population
generateRandomWorkload(inputsNumber, L, N)
print("SEED POPULATION: ", population, "\n \n")
for generation in range(10):
print(bcolors.OKGREEN "MEASUREMENTS OF ", generation 1, " GENERATION" bcolors.ENDC)
for individualWorkload in population:
### HERE I CALCULATE SOME SCORES (scoreI) ###
# Parents
print("PARENTS SELECTION... \n")
scoreI.sort(key=lambda x: x[1])
parents = [scoreI[-1][0], scoreI[-2][0]]
population = [parents[0], parents[1]]
print("SELECTED PARENTS: \n", parents, "\n")
print("PARENTS IN POPULATION:", population)
# Crossover
print("BEGIN CROSSOVER... \n")
print("PARENTS: ", parents)
children = crossover(L)
print("CROSSOVER CHILDREN:\n", children, "\n")
# Mutation
print("BEGIN MUTATION...\n")
print("PARENTS: ", parents)
children = mutation(0.05)
print("MUTATION CHILDREN:\n", children, "\n")
# New population
population.append(children[0])
population.append(children[1])
print("PARENTS: ", parents)
print("NEW POPULATION: \n", population, "\n")
CodePudding user response:
If I understand correctly, this is due to something in python called mutability.
I haven't actually researched it, however I believe it stems from C pointers, as python is written in C and has very good integration with C code (look up CPython for example).
Basically, what it means is that when you say:
listB = listA
listA
and listB
are actually the same list, because they aren't actually a list,
but a number that points to a particular memory address.
You can get around this in many different ways
- Deepcopy
from copy import deepcopy
listB = deepcopy(listA)
- Array Slicing
listB = listA[::]
- Iterate with a for loop (I wouldn't recommend it, but here it is)
listB = []
for element in listA:
listB.append(element)
You can also do a quick google search to find out more, these are just some options I can think of right now.
CodePudding user response:
Perhaps confusion of copy by address and by values ? Don't do direct affectation when working with arrays because they are linked.
"Using the copy() function is another way of copying an array in Python. In this case, a new array object is created from the original array and this type of copy is called deep copy. If any value is modified in the original or copied array, then it does not create any change on another array."
CodePudding user response:
When copying an array to another array, simply by only using the equal sign it will not copy the values, but it copies the position this values are positioned therefore making the appearance of the array being copied but if tried to change the array, it will change both. To avoid it happening go over every element in the array and copy the value individually