3

I am trying to do a basic Genetic algorithm, one of the steps is to generate the next population trough genetic crossing at n points, I have chosen arbitrarily 4. The problem is that my code runs indefinitely unless I stop it. I thought this would only generate 3 offspring. Can anyone tell me why it's being recursive?

let population = [
    [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
    [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
    [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
    [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
]


kidsFactory()

function kidsFactory() {
    let newKid = []
    let parents = population
    for(i=0; i<(parents.length - 1);i++){
        parent1 = parents[i]
        parent2 = parents[i+1]
        console.log('parent1 '+parent1);
        console.log('parent2 '+parent2);
        newKid.push(parent1[0], parent1[1], parent2[2], parent2[3], parent1[4], parent1[5], parent2[6], parent2[7], parent1[8], parent1[9])
        console.log(newKid);
        population.push(newKid)
        newKid=[]
        console.log(population);
    }
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
  • 1
    `let parents = population` does not create a new array. Both varibales point to the same array and you are incresing it's length in every iteration `population.push(newKid)` – adiga Jul 31 '20 at 18:47
  • Oh that's my mistake, why does it not create a new array ? and how do I duplicate an array under a different name ? – David Romero Jul 31 '20 at 18:49
  • 1
    @DavidRomero You can use spread syntax to create a shallow copy, as shown in my answer. – Unmitigated Jul 31 '20 at 18:50
  • 1
    [Copy array by value](https://stackoverflow.com/questions/7486085) and [Fastest way to duplicate an array in JavaScript - slice vs. 'for' loop](https://stackoverflow.com/questions/3978492) – adiga Jul 31 '20 at 18:51
  • Thank you so much for the answers and the links both of you, specially @hev1 for the modifications to my code . Didn't know it pointed to the same array. – David Romero Jul 31 '20 at 18:59

2 Answers2

1

The issue is that you are modifying the array while iterating over it, which changes its length. Although it seems you are only modifying population, parents and populations both refer to the same array. You can instead store the length beforehand.

for(let i = 0, len = parents.length; i < len - 1; i++){

let population = [
    [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
    [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
    [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
    [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
]


kidsFactory()

function kidsFactory() {
    let newKid = []
    let parents = population
    for(let i = 0, len = parents.length; i < len - 1; i++){
        parent1 = parents[i]
        parent2 = parents[i+1]
        console.log('parent1 '+parent1);
        console.log('parent2 '+parent2);
        newKid.push(parent1[0], parent1[1], parent2[2], parent2[3], parent1[4], parent1[5], parent2[6], parent2[7], parent1[8], parent1[9])
        console.log(newKid);
        population.push(newKid)
        newKid=[]
        console.log(population);
    }
}
.as-console-wrapper{max-height: 100%;top: 0;}

You can also use spread syntax to create a shallow copy of the array.

let parents = [...population];
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
1

You are pushing to the same array while iterating. parents and population point to the same instance of an array. You can try creating new array while iterating.

let parents = [...population]

let population = [
  [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
  [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
  [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
  [0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
]


kidsFactory()

function kidsFactory() {
  let newKid = []
  let parents = [...population];
  for (i = 0; i < (parents.length - 1); i++) {
    parent1 = parents[i]
    parent2 = parents[i + 1]
    console.log('parent1 ' + parent1);
    console.log('parent2 ' + parent2);
    newKid.push(parent1[0], parent1[1], parent2[2], parent2[3], parent1[4], parent1[5], parent2[6], parent2[7], parent1[8], parent1[9])
    console.log(newKid);
    population.push(newKid)
    newKid = []
    console.log(population);
  }
}
Akshay Bande
  • 2,491
  • 2
  • 12
  • 29