Function overwriting values outside of its vision

#1

Hello,

i have problem with overwriting totaly unrelated values with one function.

In my class Populace i create class vector

Prihrada[] prihrada_array;

and single object

Prihrada BIS;

Then i run it through my script and end up with naturalSelection function, where i create new object vector

Prihrada[] newPrihrada_array = new Prihrada[prihrada_array.length];

and find the most fitting object from the aray and set it as BIS object.

BIS = new Prihrada(prihrada_array[bestPrihrada].DNA);

and i set it on first spot of new array newPrihrada_array

newPrihrada_array[0] = new Prihrada(META.DNA);

The DNA is an object that store input values for the new object. It consist of several int vectors.

All other object in newPrihrada_array are made by following steps:

-select random prihrada_array object

-set its DNA object as mummy / daddy

DNA mummy = selectParent();

-do krizeni (crossover) and mutace (mutation)

mummy.krizeni(daddy);
mummy.mutace(0);

-finish up with separace (separation)

mummy.separace(0);

All those steps are made withing the selected DNA object, in this case called mummy

class Populace {
    Prihrada[] prihrada_array;
    Prihrada META;

.
.
.

void naturalSelection() {
    Prihrada[] newPrihrada_array = new Prihrada[prihrada_array.length];
    setBestPrihrada();
    fitnessSum();

    newPrihrada_array[0] = new Prihrada(META.DNA);

    for (int i = 1; i < newPrihrada_array.length; i++) {
      DNA mummy = selectParent();
      DNA daddy = selectParent();
      mummy.krizeni(daddy);
      mummy.mutace(0);
      mummy.separace(0);
      mummy.kolize();
      newPrihrada_array[i] = new Prihrada(mummy);
    }

    prihrada_array = newPrihrada_array;

    gen++;
  }
void setBestPrihrada() {
    float[] fitness = new float[prihrada_array.length];

    for (int i = 0; i < prihrada_array.length; i++) {
      fitness[i] = prihrada_array[i].fitness;
    }

    float maxFitness = max(fitness);

    int bestPrihrada = 0;

    for (int i = 0; i < prihrada_array.length; i++) {
      if (fitness[i] == maxFitness) {
        bestPrihrada = i;
      }
    }

    println("Gen " + gen + " maxFitness = " + maxFitness);

    if (prihrada_array[bestPrihrada].fitness > fitnessmax) {
      fitnessmax = prihrada_array[bestPrihrada].fitness;
      BIS = new Prihrada(prihrada_array[bestPrihrada].DNA);
    }
  }

My problem is that if i run the for cycle, values in the Prihrada BIS changes and it ocures during the
separace function.

void separace(int j) {
    int Jsize = joint_x.length - 3;
    int[] gene = new int[chromosome.length];

    for (int i = 0; i < gene.length; i++) {
      gene[i] = chromosome[i][j];
    }

    arrayCopy(gene, 0, joint_x, 3, 1);
    arrayCopy(gene, Jsize, joint_z, 3, 1);
    arrayCopy(gene, 2 * Jsize, prurez, 1, prurez.length - 1);
    prurez[0] = prurez[1];
  }

If it would change values in the Prihrada array i would say that there is something wrong with the code, but how can it change values from the object i dont even mention in there?

Before separace function

After separace function both values in BIS changed to value of curently processed DNA object

Also in separace function:

Before

After. If the x value chanes, the other changes too

What i find odd is that it changes values stored in “this” which to my knowledge are only avaiable through “this” function which i dont even use.

1 Like

#2

can you upload the entire code it’s a bit difficult to follow like this. maybe someone else can see the problem but i think there is something not being show which is crucial.

0 Likes

#3

There is it. There is “alot” of stuff going…

I skiped whole Prihrada object. I hope its fine

Funkce funkce = new Funkce();
Populace test;
Prihrada best;

int size = 5;  //Velikost výberu

void setup() {
  fullScreen();
  frameRate(200);
  
  test = new Populace(size);
}

void draw() {
  translate(20, height-300);
  background(255);
  
  if(test.gen > 100){
    test.show();
    saveFrame();
    test = new Populace(size);
  }
  
  
  if (test.vsechny_porusene()) {

//this is wher the problem begins
    test.naturalSelection();
    println(test.gen);
    test.aktivace();
  } else {
    test.update();
    test.show();
  }
}
class Populace {
    Prihrada[] prihrada_array;
    Prihrada BIS;

  int aktivni_prvky;

  float fitnessSum;
  int gen = 1;

  float fitnessmax;

  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  Populace(int size) {
    prihrada_array = new Prihrada[size];
    for (int i = 0; i < size; i++) {
      DNA DNA = new DNA();

      DNA.prvni_generace();


      prihrada_array[i] = new Prihrada(DNA);

      prihrada_array[i].aktivace_prutu();
      prihrada_array[i].globalni_matice_tuhosti();
    }
  }

  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  void show() {
    for (int i = 0; i < prihrada_array.length; i++) {
      if (prihrada_array[i].poruseni == false) {
        prihrada_array[i].show();
      }
    }
    if (gen > 1) {
      BIS.showBest();
    }
  }

  //--------------------------------------------------------------------------------------------------------------------------------------------------------------

  void update() {
    for (int i = 0; i < prihrada_array.length; i++) {
      if (prihrada_array[i].poruseni == false) {
        prihrada_array[i].update();
      }
    }
  }
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  boolean vsechny_porusene() {
    for (int i = 0; i < prihrada_array.length; i++) {
      if (prihrada_array[i].poruseni == false) {
        return false;
      }
    }
    return true;
  }
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  //---------------------------------------------------------------------------Genetika-------------------------------------------------------------------
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------


  void naturalSelection() {
    Prihrada[] newPrihrada_array = new Prihrada[prihrada_array.length];
    setBestPrihrada();
    fitnessSum();

    newPrihrada_array[0] = new Prihrada(BIS.DNA);

    for (int i = 1; i < newPrihrada_array.length; i++) {
      DNA mummy = selectParent();
      DNA daddy = selectParent();
      mummy.krizeni(daddy);
      mummy.mutace(0);
      mummy.separace(0);
      mummy.kolize();
      newPrihrada_array[i] = new Prihrada(mummy);
    }

    prihrada_array = newPrihrada_array;

    gen++;
  }
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  void setBestPrihrada() {
    float[] fitness = new float[prihrada_array.length];

    for (int i = 0; i < prihrada_array.length; i++) {
      fitness[i] = prihrada_array[i].fitness;
    }

    float maxFitness = max(fitness);

    int bestPrihrada = 0;

    for (int i = 0; i < prihrada_array.length; i++) {
      if (fitness[i] == maxFitness) {
        bestPrihrada = i;
      }
    }

    println("Gen " + gen + " maxFitness = " + maxFitness);

    if (prihrada_array[bestPrihrada].fitness > fitnessmax) {
      fitnessmax = prihrada_array[bestPrihrada].fitness;
      BIS = new Prihrada(prihrada_array[bestPrihrada].DNA);

      BIS.generace = gen;
      BIS.fitness = fitnessmax;
      BIS.aktivace_prutu();
    }
  }


  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  void fitnessSum() {
    fitnessSum = 0;
    for (int i = 0; i < prihrada_array.length; i++) {
      fitnessSum = fitnessSum + prihrada_array[i].fitness;
    }
  }

  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  DNA selectParent() {
    float rand = random(fitnessSum);

    float runningSum = 0;

    for (int i = 0; i < prihrada_array.length; i++) {
      runningSum = runningSum + prihrada_array[i].fitness;

      if (runningSum > rand) {
        return prihrada_array[i].DNA;
      }
    }
    return null;
  }
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
  void aktivace() {
    for (int i = 0; i < prihrada_array.length; i++) {
      prihrada_array[i].aktivace_prutu();
      prihrada_array[i].globalni_matice_tuhosti();
    }
  }
  //--------------------------------------------------------------------------------------------------------------------------------------------------------------
}
class DNA {
  int[] joint_x;
  int[] joint_z;
  int[] type;


  int[] joint_A;
  int[] joint_B;
  int[] prurez;

  float mutationRate = 1;

  int[][] chromosome;


  //-------------------------------------------------------------------------------------------------------------------------------------

  void prvni_generace() {
    joint();
    prurez();
    prut();
  }
  //-------------------------------------------------------------------------------------------------------------------------------------

  void joint() {
    int pocet_jointu = round(random(4, 4));

    joint_default(pocet_jointu);

    for (int i = 3; i < pocet_jointu; i++) {
      joint_x[i] = round(random(750));
      joint_z[i] = -round(random(-height/2, height/2));
      if (joint_z[3] == 0) {
      }
      type[i] = 3;
    }
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void joint_default(int pocet_jointu) {

    joint_x = new int[pocet_jointu];
    joint_z = new int[pocet_jointu];
    type = new int[pocet_jointu];

    joint_x[0] = 0;
    joint_z[0] = 0;
    type[0] = 0;

    joint_x[1] = 375;
    joint_z[1] = 0;
    type[1] = 4;

    joint_x[2] = 750;
    joint_z[2] = 0;
    type[2] = 1;
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void prurez() {
    int pocet_prutu = round(random(5, 5));

    prurez = new int[pocet_prutu];

    for (int i = 1; i < pocet_prutu; i++) {
      float rng = random(1);

      if (rng > 0.5) {
        prurez[i] = 1;
      }
    }

    prurez[0] = prurez[1];
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void prut() {
    prut_default(prurez.length);

    for (int i = 2; i < prurez.length; i++) {
      if (i == 2) {
        joint_A[i] = 0;
        joint_B[i] = 3;
      } else if (i == 3) {
        joint_A[i] = 2;
        joint_B[i] = 3;
      } else if (i == 4) {
        joint_A[i] = 1;
        joint_B[i] = 3;
      }
    }
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void prut_default(int pocet_prutu) {
    joint_A = new int[pocet_prutu];
    joint_B = new int[pocet_prutu];

    joint_A[0] = 0;
    joint_B[0] = 1;

    joint_A[1] = 1;
    joint_B[1] = 2;
  }

  //-------------------------------------------------------------------------------------------------------------------------------------
  //-------------------------------------------------------------------------------------------------------------------------------------
  //-------------------------------------------------------------------------------------------------------------------------------------

  void def() {
    joint_default(4);
    prurez_default();
    prut_default(5);
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void prurez_default() {
    int pocet_prutu = 5;

    prurez = new int[pocet_prutu];

    for (int i = 0; i < pocet_prutu; i++) {
      prurez[i] = 7;
    }
  }

  //-------------------------------------------------------------------------------------------------------------------------------------
  //-------------------------------------------------------------------------------------------------------------------------------------
  //-------------------------------------------------------------------------------------------------------------------------------------

  void krizeni(DNA daddy) {
    int[] xM = subset(joint_x, 3);
    int[] zM = subset(joint_z, 3);
    int[] pM = subset(prurez, 1);

    int[] xD = subset(daddy.joint_x, 3);
    int[] zD = subset(daddy.joint_z, 3);
    int[] pD = subset(daddy.prurez, 1);

    int[] mum = concat(concat(xM, zM), pM);
    int[] dad = concat(concat(xD, zD), pD);

    int Bstart = 2 * xM.length;

    crossover(mum, dad, Bstart);
  }


  //-------------------------------------------------------------------------------------------------------------------------------------
  void crossover(int[] mum, int[] dad, int Bstart) {
    int size = mum.length;

    chromosome = new int[size][5];

    int rng1 = round(random(size));
    int rng2 = round(random(rng1, size));

    crossover_binarni(mum, dad, rng1, rng2);
    crossover_linearni(mum, dad, rng1, rng2, Bstart);
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void crossover_binarni(int[] mum, int[] dad, int rng1, int rng2) {
    int size = mum.length;

    for (int i = 0; i < size; i++) {
      if (i < rng1 || i > rng2) {
        chromosome[i][0] = mum[i];
        chromosome[i][1] = dad[i];
      } else {
        chromosome[i][0] = dad[i];
        chromosome[i][1] = mum[i];
      }
    }
  }
  //-------------------------------------------------------------------------------------------------------------------------------------
  void crossover_linearni(int[] mum, int[] dad, int rng1, int rng2, int Bstart) {

    //joint x, z - linearni
    for (int i = 0; i < Bstart; i++) {
      if (i < rng1 || i > rng2) {
        chromosome[i][2] = mum[i];
        chromosome[i][3] = mum[i];
        chromosome[i][4] = mum[i];
      } else {
        chromosome[i][2] = (1/2 * mum[i]) + (1/2 * dad[i]); 
        chromosome[i][3] = (3/2 * mum[i]) + (-1/2 * dad[i]);
        chromosome[i][4] = (-1/2 * mum[i]) + (3/2 * dad[i]);
      }
    }

    for (int i = Bstart; i < mum.length; i++) {
      if (i < rng1 || i > rng2) {
        chromosome[i][2] = mum[i];
        chromosome[i][3] = mum[i];
        chromosome[i][4] = mum[i];
      } else {
        chromosome[i][2] = dad[i]; 
        chromosome[i][3] = dad[i];
        chromosome[i][4] = dad[i];
      }
    }
  }

  //-------------------------------------------------------------------------------------------------------------------------------------
  void separace(int j) {
    int Jsize = joint_x.length - 3;
    int[] gene = new int[chromosome.length];

    for (int i = 0; i < gene.length; i++) {
      gene[i] = chromosome[i][j];
    }

    arrayCopy(gene, 0, joint_x, 3, 1);
    arrayCopy(gene, Jsize, joint_z, 3, 1);
    arrayCopy(gene, 2 * Jsize, prurez, 1, prurez.length - 1);
    prurez[0] = prurez[1];
  }

  //-------------------------------------------------------------------------------------------------------------------------------------
  void mutace(int j) {
    int Jsize = joint_x.length - 3;

    for (int i = 0; i < Jsize; i++) {
      float rngx = random(1);

      if (rngx < mutationRate) {
        chromosome[i][j] = round(random(750));
      }
    }

    for (int i = Jsize; i < 2 * Jsize; i++) {
      float rngz = random(1);

      if (rngz < mutationRate) {
        chromosome[i][j] = -round(random(-height/2, height/2));
      }
    }

    for (int i = 2 * Jsize; i < chromosome.length; i++) {
      float rngp = random(1);

      if (rngp < mutationRate) {
        if (rngp < mutationRate/2) {
          chromosome[i][j] = 0;
        } else {
          chromosome[i][j] = 1;
        }
      }
    }
  }

  //-------------------------------------------------------------------------------------------------------------------------------------
  void kolize() {

    for (int i = 0; i < joint_x.length; i++) {
      for (int j = 0; j < joint_x.length; j++) {
        if (i != j && dist(joint_x[i], joint_z[i], joint_x[j], joint_z[j]) < 15) {

          float c = sq(joint_x[i]) + sq(joint_z[j] - joint_z[i]) - 225;
          float b = 2 * joint_x[i];

          int x1 = ceil((b + sqrt(sq(b) - 4*c)) / 2);
          int x2 = floor((b - sqrt(sq(b) - 4*c)) / 2);

          if (min(abs(x1), abs(x2)) == x1) {
            joint_x[j] = x1;
          } else {
            joint_x[j] = x2;
          }
        }
      }

      for (int j = 0; j < joint_z.length; j++) {
        if (i != j && dist(joint_x[i], joint_z[i], joint_x[j], joint_z[j]) < 15) {

          float c = sq(joint_z[i]) + sq(joint_x[j] - joint_x[i]) - 225;
          float b = 2 * joint_z[i];

          int z1 = ceil((b + sqrt(sq(b) - 4*c)) / 2);
          int z2 = floor((b - sqrt(sq(b) - 4*c)) / 2);

          if (min(abs(z1), abs(z2)) == z1) {
            joint_z[j] = z1;
          } else {
            joint_z[j] = z2;
          }
        }
      }
    }
  }
}
0 Likes

#4

without seeing the whole code i have to guess that when you instantiate a new Prihrada the DNA is a shallow copy (actually a reference i guess) and as such when the array from which it is drawn is changed it also changes the BIS. Sorry I can’t be of more help. hopefully someone else can sort it out for you.

1 Like

#5

I wasnt sure if you literaly need the whole thing or just parts that effect the problem.

I uploaded the folder here -> https://ufile.io/t6bb4kyw

Or i can add missing pages of script to the comment

0 Likes

#6

Hi,

I also think the problem comes from shallow copy of objects.

In the function void naturalSelection() you have that part:

for (int i = 1; i < newPrihrada_array.length; i++) {
      DNA mummy = selectParent();
      DNA daddy = selectParent();
      mummy.krizeni(daddy);
      mummy.mutace(0);
      mummy.separace(0);
      mummy.kolize();
      newPrihrada_array[i] = new Prihrada(mummy);
    }

On the last line newPrihrada_array[i] = new Prihrada(mummy); you create a new Prihrada object with the DNA mummy.

The thing is that the object is not really copied so every modification of the original mummy DNA will be applied to the DNA of the new Prihrada object and The other way around.

You should create a copy() function in your DNA class that return a new object with the exact same values than the original DNA object.

1 Like

#7

Something like that?

void naturalSelection() {
    Prihrada[] newPrihrada_array = new Prihrada[prihrada_array.length];
    setBestPrihrada();
    fitnessSum();

    newPrihrada_array[0] = new Prihrada(BIS.DNA);

    for (int i = 1; i < newPrihrada_array.length; i++) {
      DNA mummy = selectParent();
      DNA daddy = selectParent();
      mummy.krizeni(daddy);
      mummy.mutace(0);
      mummy.separace(0);
      mummy.kolize();
      newPrihrada_array[i] = new Prihrada(  mummy.kid()  );
    }

    prihrada_array = newPrihrada_array;

    gen++;
  }
 DNA kid() {
    DNA kid = new DNA();

    kid.joint_x = joint_x;
    kid.joint_z = joint_z;
    kid.type = type;

    kid.joint_A = joint_A;
    kid.joint_B = joint_B;
    kid.prurez = prurez;
    
    return kid;
  }
0 Likes

#8

Exactly.

And you should apply this to every part of your code. For example when you mix the DNA of the dad and mum, be sure to not mess up the original ones but to really create a new version on which you will apply the mixture of dad and mum.

1 Like

#9

i don’t think that will be enough. check out this and see how that goes for you.

1 Like

#10

It working! I know my code is a huge pile of mess, but what did you do??

0 Likes

#11

basically what me and jb4x were talking about. i added a copy function to the dna so that each Prihrada had it’s own dna instead of just a reference. it’s minimal code change if you just have a lookey loo you will see it.

3 Likes

#12

Thank you very much guys!

0 Likes