On Cellular Automata

posted by on 2013.04.27, under Processing
27:

The last few days for me have been all about Cellular Automata, due mostly to a long term obsession of mine: complex behaviours of systems at large scale which do not require hierarchy or centralized organization to exist, but “emerge” from local behaviours of the system’s constituents. (Here‘s a TEdTalk by Steven Strogatz on large scale complexity in birds flocks and also inanimate objects.)
What is then a cellular automaton? You can see it as a conceptual building block: it’s an entity capable of being in a given (finite) number of states, and of interacting with its close “neighbours” according to certain very simple rules. The result of the interaction will in general cause a change in the state of the given automaton, and consequently an (discrete time) evolution of the system. The neighbours, once defined, don’t change during the evolution of the system, so, in other words, a cellular automaton is not capable of moving, but it is fixed to a grid, the most common being 1 and 2 dimensional. Moreover, the grid is actually positioned on a circle or torus, so to avoid having to impose boundary conditions, i.e. a modification of the rules for the automata living on the edge of the grid.
Some systems of rules, like Conway’s Game Of Life, which is the one I have used in the code below, and probably the most famous one, exhibit some incredibly interesting global behaviours and patterns.
The code below tries to use Cellular Automata for artistic purposes: some of the parameters of the automaton, as for instance its state, the number of “alive” neighbours, and the number of frames it has been alive, have been used to draw geometric shapes (squares, in this case) of different dimensions, colors,etc. .
Notice that the set of rules is slightly perturbed, so, given an initial state, its evolution is not completely deterministic.

int dim;
Cell[][] cells;
int cellsize=20;
int r=0;
int acc=0;

void setup(){
size(600,600);
background(0);
dim=floor(width/(cellsize/2));
cells=new Cell[dim][dim];
for (int i=0;i<dim;i++)
{
  for (int j=0;j<dim;j++)
  {
    if(random(0,1)<0.7) {r=0;} else {r=1;};
    cells[i][j]=new Cell(cellsize/2+i*cellsize/2,cellsize/2+j*cellsize/2,r);
  };
};

for (int i=0;i<dim;i++)
{
  for (int j=0;j<dim;j++)
  {
    cells[i][j].paint();
  };
};

};

void draw(){
background(0);
nextstateCalc();
for (int i=0;i<dim;i++)
{
  for (int j=0;j<dim;j++)
  cells[i][j].paint();
};
perturb();
};
;

void nextstateCalc(){
  for (int i=0;i<dim;i++)
{
  for (int j=0;j<dim;j++)
  {
    int liveCount=0;

    liveCount=cells[(i+dim) % dim][(j+1+dim) % dim].state+cells[(i+1+dim) % dim][(j+1+dim) % dim].state+cells[(i+1+dim) % dim][(j+dim) % dim].state+cells[(i+1+dim) % dim][(j-1+dim) % dim].state+
    cells[(i+dim) % dim][(j-1+dim) % dim].state+cells[(i-1+dim) % dim][(j-1+dim) % dim].state+cells[(i-1+dim) % dim][(j+dim) % dim].state+cells[(i-1+dim) % dim][(j+1+dim) % dim].state;
   
    if (cells[i][j].state==1){
      cells[i][j].frameAlive++;
        if (liveCount == 2 || liveCount == 3) {
        cells[i][j].nextstate=1;
      }
        else {
        cells[i][j].nextstate=0;
      }
    };
   
    if (cells[i][j].state==0){
      cells[i][j].frameAlive=0;
        if (liveCount == 3) {
      cells[i][j].nextstate=1;
       };
      cells[i][j].neigh=liveCount;
      };
};
};

};

void perturb(){

  if (random(0,1)<0.1+acc){
    int a=int(random(0,dim));
    int b=int(random(0,dim));
      cells[a][b].state=0;
};
if (acc<=0.9) {
      acc+=0.01;
    }
   else {
     acc=0;
   }
};

/* Define the cellular automaton class
*/
class Cell{
float x;
float y;
int state;
int nextstate;
int neigh=1;
int frameAlive=0;

Cell (float _x,float _y,int _alive){
x=_x;
y=_y;
state=_alive;
nextstate=_alive;
};

void paint(){
  state=nextstate;
noStroke();
fill(150*(neigh),160*(neigh),110*(neigh),4*state);
  pushMatrix();
  translate(x,y);
  rotate(radians(neigh-frameAlive));
  rectMode(CENTER);
  rect(0,0,3*(1+neigh*(frameAlive % 100)),3*(1+neigh*(frameAlive % 100)));
  popMatrix();
};
};

Since the code needs to perform quite a certain load of computations, I have done a render of it, rather than having it running in real time. The music is not strictly speaking related to the animation, but I was inspired by the video to play some piano. 😉
Finally, the use of Cellular Automata was inspired by the reading of Matt Pearson’s very nice Generative Art: A Practical Guide (see also Daniel Shiffmann’s The Nature of Code). I will come back to this topic in a following post, talking about boids and autonomous agents, a somehow related concept. Also, I would like to apply Cellular Automata techniques to sound: I have some ideas, so stay tuned! 😉

pagetop