Problem with getting other classes information within another class

edited October 2013 in Questions about Code

Hello friends,

this is my very first post and I hope I'll do it fine. So here is my problem:

I am programming something like a evolutionary cellular automaton with multiple populations. Those populations move on the pixel grid and there are (by now) to options:

  • An individual of the population wants to move to a empty pixel-cell.
  • An individual of the population wants to move to a pixel-cell that ins not empty.

For the first case I see no problems. But for the second I would like the "world" to check the individuals fitness and decide who is allowed to "inhabit" the pixel-cell.

Again : Individual gets to cell which is == 0 => no problem Individual gets to cell which is != 0 => if it has better fitness the individual with lower fitness has to leave.

How can I get access to the cells fitnesses in the "world"?

Here is a reduced version of what I have right now.

(Sorry for my english by the way).

        int[] indexState;
        PImage img;
        World w;

        void setup()
        {
          size(400, 400);
          img = createImage(width, height, RGB);
          indexState = new int[width*height];

          w = new World();

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


          image(img, 0, 0);
          loadPixels();
        }

        void draw()
        {
          w.run();

          updateImage();
          updatePixels();
        }

        void updateImage()
        {
          for (int i = 0;i<indexState.length;i++) {
            if (indexState[i] == 0) {
              pixels[i] = color(0);
            }
            else if (indexState[i] == 1) {
              pixels[i] = color(255, 0, 0);
            }
            else if (indexState[i] == 2) {
              pixels[i] = color(0, 255, 0);
            }
          }
        }


        class Cell
        {
          int index;
          int fitness;

          Cell(int _index)
          {
            index = _index;
            fitness = int(random(100));
          }

          int getIndex()
          {
            return index;
          }

          int getFitness()
          {
            return fitness;
          }
        } 


        class Population
        {
          ArrayList<Cell> population = new ArrayList<Cell>();
          int popIndex;

          Population() {
            int cellPosition = int(random(width*height));
            population.add(new Cell(cellPosition));
          }

          void checkCellStats()
          {
            for (int i = 0;i<population.size();i++) {
              Cell c = population.get(i);
              int cIndex = c.getIndex();
              indexState[cIndex] =  popIndex;
            }
          }

          void myIndexIs(int _popIndex) {
            popIndex = _popIndex;
          }
        }


        class World
        {
          ArrayList<Population> world = new ArrayList<Population>();

          World()
          {
            world.add(new Population());
            world.add(new Population());
          }

          void run()
          {
            for (int i = 0;i<world.size();i++) {
              Population p = world.get(i);
              int newIndex = i+1;                  // +1 because 0 is reserved for empty cells
              p.myIndexIs(newIndex);
              p.checkCellStats();
            }

            // Here is my problem
            for (int i = 0;i<indexState.length;i++) {
              if (indexState[i] != 0) {                                        // if there is somebody
                int whoIsThere = indexState[i];                                // Which population is here?
                Population atIndex = world.get(whoIsThere-1);
                println("POPULATION " + whoIsThere + " IS AT INDEX " + i);
                /* get Cell and its fitness?*/
              }
            }
          }
        }

Answers

  • edited October 2013

    You have indexState[] to check the state of each cell: empty, population 1, or population 2. However, you don't have an associated fitness array so looking up that information at the moment would be complicated / inefficient.

    Maybe make another array for fitness that gets updated whenever indexState[] gets updated.

    Edit: I did not address removing cells. Give me a minute and I'll put some code for a different way to think about the simulation.

  • Answer ✓

    Here is a simple grid version. Instead of there being a variable number of cells, everything is a cell but almost all of them are empty at the start. Two of them are initialized as being from different populations.

    The advantage of this is that doing neighbor checks is simple. I did not go into details for cells on the edges and the growth rules should be changed to not bias the results. Right now, the double loop order affects assignment of new cells (left to right then top to bottom is the bias assignment order).

    Cell[] allCells;
    PImage img;
    
    void setup() {
      size(400, 400);
    
      // All cells initialize as empty (state 0)
      allCells = new Cell[width*height];
      for (int i = 0; i < allCells.length; i++) allCells[i] = new Cell(i, 0);
    
      // Initialize two populations (states 1 and 2)
      int randCell = (int)random(allCells.length);
      allCells[randCell].state = 1;
      allCells[randCell].fitness = (int)random(100);
    
      randCell = (int)random(allCells.length);
      allCells[randCell].state = 2;
      allCells[randCell].fitness = (int)random(100);
    
      // Initialize image
      img = createImage(width, height, RGB);
      image(img, 0, 0);
    }
    
    void draw() {
      growPopulations();
      updateImage();
    }
    
    void growPopulations() {
      for (int i = 1; i < width-1; i++) {
        for (int j = 1; j < height-1; j++) {
          int ijIndex = i+j*height;
    
          int upIndex = ijIndex-width;
          int rightIndex = ijIndex+1;
          int downIndex = ijIndex+width;
          int leftIndex = ijIndex-1;
    
          if (allCells[ijIndex].fitness > allCells[upIndex].fitness) {
            allCells[upIndex].state = allCells[ijIndex].state;
            allCells[upIndex].fitness = (int)random(100);
          }
          if (allCells[ijIndex].fitness > allCells[rightIndex].fitness) {
            allCells[rightIndex].state = allCells[ijIndex].state;
            allCells[rightIndex].fitness = (int)random(100);
          }
          if (allCells[ijIndex].fitness > allCells[downIndex].fitness) {
            allCells[downIndex].state = allCells[ijIndex].state;
            allCells[downIndex].fitness = (int)random(100);
          }
          if (allCells[ijIndex].fitness > allCells[leftIndex].fitness) {
            allCells[leftIndex].state = allCells[ijIndex].state;
            allCells[leftIndex].fitness = (int)random(100);
          }
        }
      }
    }
    
    void updateImage() {
      loadPixels();
      for (int i = 0; i < allCells.length; i++) {
        if (allCells[i].state == 0) pixels[i] = color(0);
        else if (allCells[i].state == 1) pixels[i] = color(255, 0, 0);
        else if (allCells[i].state == 2) pixels[i] = color(0, 255, 0);
      }
      updatePixels();
    }
    
    class Cell {
      int index, state, fitness;
    
      Cell(int inIndex, int inState) {
        index = inIndex;
        state = inState;
      }
    }
    
  • Hello there!

    Thank you for answering! I think your code seems to be pretty uncomplicated compared to mine. I ' ll try it your way. Thank you very much!

  • // Here is my problem
    for (int i = 0;i<indexState.length;i++) {
      if (indexState[i] != 0) {                                        // if there is somebody
        int whoIsThere = indexState[i];                                // Which population is here?
        Population atIndex = world.get(whoIsThere-1);
        println("POPULATION " + whoIsThere + " IS AT INDEX " + i);
        /* get Cell and its fitness?*/
      }
    }
    

    Population has an array list of Cells. Either you expose the array list itself, or you add a getCell(int index) method to Population (and an access to the size of the list). This will allow to loop on the Population's Cells, and to get their values.

  • Thank you for answering!

    Could you explain what you mean by "exposing the array list"?

    I was trying to add a getCell method - but I coudn't figure out how to get access to the Cells position in the array list.

    Would I maybe make sense to implement a personal "ID" in the cell constructor?

    something like:

    Cell(int index, int cellID) .. (by "ID" I mean the position in the array list.)

    Than i could get two Cells from their Population classes in the World class and compare their fitnesses. Am I thinking right?

    Sorry for my ignorance. This is kind of the first time I ll try to go my "own way of thinking" .. :)

    By the way.. sorry for the duplicated post.

    greetz!

  • Just add:

    ArrayList<Cell> getCells() { return population; }
    

    (properly formatted, lazy here...) to your Population class. (Actually, you can access it directly, but it is more "Java-ish", cleaner, this way...)

    So you can get the list of cells in your atIndex population and iterate on it:

    for (Cell cell : atIndex.getCells())
    {
      // Do something with your cell
    }
    

    No need for an id for the cells, just access them this way, or by their index (get(i)).

  • Hello PhiLho - thank you for responding! That seems to be what I was searching for. But now it seems I made an error in reasoning, too.

    Where and when would I decide if a Cell is allowed to stay at a location?

    I would implement a "move" class in Population which would look something like that:

    void move() {
      for (int i = 0;i<population.size();i++) {
        Cell c = population.get(i);
        int cIndex = c.getIndex();
    
        int x = cIndex % width;
        int y = cIndex / width;
    
        int up = cIndex - width;
        int right = cIndex + 1 ;
        int left = cIndex - 1 ;
        int down = cIndex + width;
    
        if (indexState[up] = 0) {            // If location is not taken
          population.add(new Cell(up));      // place cell there
          indexState[up] = popIndex;
        }
        else if ((indexState[up] != 0) && (indexState[up] != popIndex)) {    // if locaiton is taken, and not taken by this population
          /* which population is here?
           which cell is here?
           what is its fitness? 
           Here I would compare the Cell of this Population with the Cell from the other one
    
    
           */
        }
      }
    }
    

    Is something like that possibile or do I have the World class make the decision? What would be the most efficient way, especially if i had thousands of cells.

    Thank you very much for helping!

    Greets

Sign In or Register to comment.