By changing values in one array it automatically changes values in another array. How to avoid that happening?

Question:

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")
Asked By: SeraFM

||

Answers:

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."

Answered By: BenoitB

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

Answered By: Or Esperansa

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

  1. Deepcopy
from copy import deepcopy

listB = deepcopy(listA)
  1. Array Slicing
listB = listA[::]
  1. 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.

Answered By: not a tshirt
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.