Processing: Cellular Automata

ca_grab

CELLULAR AUTOMATA
A cellular automaton (pl. cellular automata, abbrev. CA) is a discrete model studied in computability theory, mathematics, physics, complexity science, theoretical biology and microstructure modeling. It consists of a regular grid of cells, each in one of a finite number of states, such as “On” and “Off” (in contrast to a coupled map lattice). The grid can be in any finite number of dimensions. For each cell, a set of cells called its neighborhood (usually including the cell itself) is defined relative to the specified cell. For example, the neighborhood of a cell might be defined as the set of cells a distance of 2 or less from the cell. An initial state (time t=0) is selected by assigning a state for each cell. A new generation is created (advancing t by 1), according to some fixed rule (generally, a mathematical function) that determines the new state of each cell in terms of the current state of the cell and the states of the cells in its neighborhood. For example, the rule might be that the cell is “On” in the next generation if exactly two of the cells in the neighborhood are “On” in the current generation, otherwise the cell is “Off” in the next generation. Typically, the rule for updating the state of cells is the same for each cell and does not change over time, and is applied to the whole grid simultaneously, though exceptions are known.

For further reading on CAs try:

  • Wikipedia
  • Game of Life
  • WOLFRAM
  • WOLFRAM -HOW SIMPLE PROGRAMS BEHAVE
  • CA_1D_00011110

    EXAMPLE 01: ONE-DIMENSIONAL CELLULAR AUTOMATA
    …coming soon…

    ca_grab

    EXAMPLE 02: TWO-DIMENSIONAL CELLULAR AUTOMATA

    SKETCH COMPONENT 01: CA CELL
    The CA cell itself, here we functions to assign neighbours to each cell, and write the behaviours that the cell will use to check those neighbours, and based on the results apply a rule set to update itself.

     
    class SuperCell{
     
      /*------------------------------------------------------------------------------------------------------------------------------
       *** CLASS VARIABLES ***
       ------------------------------------------------------------------------------------------------------------------------------*/
     
      PVector pos;
      float sizeXX, sizeYY;
      boolean currState, nextState;
      int cellCol, indexI, indexJ;
      String myID;
      SuperCell[] neighbours;
     
      /*------------------------------------------------------------------------------------------------------------------------------
       *** CLASS CONSTRUCTOR ***
       ------------------------------------------------------------------------------------------------------------------------------*/
      SuperCell( String _ID, boolean _S, PVector _P, float _SX, float _SY, int _II, int _JJ ){
     
        pos        = _P;
        indexI     = _II;  
        indexJ     = _JJ;
        myID       = _ID;
        currState  = _S;
     
        sizeXX     = _SX;
        sizeYY     = _SY;
        cellCol    = 250;
     
        //------------------------------------Neighbourhood
        neighbours = new SuperCell[8];
      }
     
      /*------------------------------------------------------------------------------------------------------------------------------
       *** CLASS BEHAVIORS ***
       ------------------------------------------------------------------------------------------------------------------------------*/
     
     
      //------------------------------------ draw the cell
      void render(){
        if( this.getCurrentState() ){
          stroke(0,0,cellCol);
          fill(0,0,cellCol,95);
          ellipse(pos.x, pos.y, sizeXX/3, sizeYY/3);
        }
        else{      
          stroke(0,0,cellCol/5);
          fill(0,0,cellCol/5,70); 
        ellipse(pos.x, pos.y, sizeXX/6, sizeYY/6);  
        } 
      }
     
      //------------------------------------ update current state to the next state
      void updateCell(){
        int counter = 0;
        for(int i = 0; i < neighbours.length; i++){
          boolean bVal = neighbours[i].getCurrentState();
          if( bVal ) counter++;
        }
        this.applyRules(counter);
      }
     
      //------------------------------------ apply rules of life
      void applyRules(int C){
     
        if( C < 2  ) setNextState(false);       // loneliness
        if( C > 3  ) setNextState(false);       // overpopulation
        if( C == 3 ) setNextState(true);       // reproduce
     
      }
     
      //------------------------------------ toggle cell state
      void toggleCellState(){
        boolean bVal = nextState;
        currState = bVal;
        //setCurrentState(bVal);
      }
     
      //------------------------------------ applyRules
      void assignNeighbours(){
        // println("assigning neighbours!");
        // BELOW 
        neighbours[0] = cellPop[ (indexI+COLS-1) % COLS ] [ (indexJ+ROWS-1) % ROWS ];
        neighbours[1] = cellPop[ indexI                 ] [ (indexJ+ROWS-1) % ROWS ];
        neighbours[2] = cellPop[ (indexI+1) % COLS      ] [ (indexJ+ROWS-1) % ROWS ];
        // LEFT & RIGHT
        neighbours[3] = cellPop[ (indexI+COLS-1) % COLS ] [ indexJ ];
        neighbours[4] = cellPop[ (indexI+1) % COLS      ] [ indexJ ];
        // ABOVE
        neighbours[5] = cellPop[ (indexI+COLS-1) % COLS ] [ (indexJ+1) % ROWS ];
        neighbours[6] = cellPop[ indexI                 ] [ (indexJ+1) % ROWS ];
        neighbours[7] = cellPop[ (indexI+1) % COLS      ] [ (indexJ+1) % ROWS ];   
      }
     
      //------------------------------------ set cell states
      void setCurrentState(boolean B){
        currState = B;
      }
      void setNextState(boolean B){
        nextState = B;
      }
     
      //------------------------------------ retrieve cell states
      boolean getCurrentState(){
        return currState;
      }  
      boolean getNextState(){
        return nextState;
      }  
     
    }

    SKETCH COMPONENT 02: SETUP
    All the upfront initialization methods to create a Processing sketch. Plus we have parameters relating to the CA setup itself; size, number of cells, etc….

     
    /*------------------------------------------------------------------------------------------------------------------------------
     *** GLOBAL VARIABLES***
     ------------------------------------------------------------------------------------------------------------------------------*/
     
    //--------------------------- Applet
    int ENVX = 500;
    int ENVY = 500;
    int COLS = 100;
    int ROWS = 100;
    float colStep, rowStep;
     
    //--------------------------- CA Cells
    SuperCell[][] cellPop;
    float PERCENT = 0.25;  // percent to be alive at start of sim
     
    /*------------------------------------------------------------------------------------------------------------------------------
     *** GLOBAL INIT ***
     ------------------------------------------------------------------------------------------------------------------------------*/
    void setup(){
     
      background(0);
      size(ENVX, ENVY);
      frameRate(2);  
      rectMode(CENTER);
     
      //-----------------------------------------make cells
      cellPop = new SuperCell[COLS][ROWS];    
      makeCells();
     
    }
     
     
    /*------------------------------------------------------------------------------------------------------------------------------
     *** GLOBAL MAIN ***
     ------------------------------------------------------------------------------------------------------------------------------*/
    void draw(){
     
      background(0);
     
      //----------------------------------------- RUN CELLS
      for(int i = 0; i < COLS; i++){
        for(int j = 0; j < ROWS; j++){
          // cellPop[i][j].printCell(); // use text labels
          cellPop[i][j].render();
        }
      }
     
      //----------------------------------------- check cells
      for(int i = 0; i < COLS; i++){
        for(int j = 0; j < ROWS; j++){
          cellPop[i][j].updateCell();
        }
      }
     
        //----------------------------------------- toggle cell states
        for(int i = 0; i < COLS; i++){
          for(int j = 0; j < ROWS; j++){
            cellPop[i][j].toggleCellState();
          }
        }
     
    }
     
     
    /*------------------------------------------------------------------------------------------------------------------------------
     *** UTILITIES ***
     ------------------------------------------------------------------------------------------------------------------------------*/
     
    void makeCells(){
     
      boolean blnSwitch;
      colStep = float(ENVX)/COLS; 
      rowStep = float(ENVY)/ROWS;
     
      //----------------------------------------- make cells
      for(int i = 0; i < COLS; i++){
        for(int j = 0; j < ROWS; j++){     
          if(random(1) < PERCENT) blnSwitch = true;
          else blnSwitch = false;      
          cellPop[i][j] = new SuperCell( str(i) + "_" + str(j), blnSwitch, new PVector( (colStep/2) + colStep*i, (rowStep/2) + rowStep*j ), colStep, rowStep, i, j );
        }
      }
     
      //----------------------------------------- assign neighbours to each cells
      for(int i = 0; i < COLS; i++){
        for(int j = 0; j < ROWS; j++){ 
          cellPop[i][j].assignNeighbours();
        }
      }
     
    }

    About this entry