Explorando los autómatas celulares cíclicos con PNGwriter


Esta es una implementación simple de un Autómata Celular Cíclico. Las reglas son las siguientes:

  1. Inicializa un arreglo 2D con valores aleatorios entre 0 y el máximo número de estado que puede alcanzar la célula.
  2. Si una célula tiene por lo menos un vecino cuyo valor es mayor en 1, esa célula es comida por el vecino (el valor cambia a ser el del vecino).
  3. Células con valor máximo de nivel sólo pueden ser comidas por células con valor 0. En ese caso, el valor va a 0, y de ahí el nombre de espacio cíclico.
  4. Repite los últimos dos pasos y eventualmente aparecerán patrones estables.


Para más información sobre los autómatas celulares, ve la página de Wikipedia, Cellular Automaton y el otro ejemplo de PNGwriter de autómatas celulares.

Aquí hay algunas imágenes generadas con 14 niveles.

000000000.png
0 iteraciones
000000015.png
15 iteraciones
000000030.png
30 iteraciones
000000050.png
50 iteraciones


La secuencia de imágenes puede ser fácilmente combinada en una película. Usé Quicktime Player de Apple (File --> Open Image Sequence...). Las películas pueden ser vistas aquí:The movies can be found here: Películas. Están en formato .mov y .avi. Los .avi tienen menor calidad de imagen. El nombre del archivo contiene informacioón acerca de cuántos cuadros contiene, cuántos niveles fueron usados como parte de las reglas, y si se consideraron 4 u 8 vecinos. Mándame un email al email que sale en Contactos si el link a pas películas no funciona, como está en un servidor distinto.

Aquí está el código:
/* Cyclic Space - Example program for PNGwriter
 * http://pngwriter.sourceforge.net/
 * By Paul Blackburn */

#include <pngwriter.h>
#include <stdlib.h>
#include <time.h>

#define rand_max 2147483647



int main()
{
   int width = 300;
   int height = 300;
   int maxiter = 500;
   
   // Create the PNGwriter instance. 
   pngwriter out(width, height, 0, "out.png");
   
   int k, i, j;
  
   
   // Create old and new grids
   
   int ** grid;
   grid = new int * [width];
   for(k = 0; k < width; k++)
     {
	grid[k] = new int [height];
     }

   int ** newgrid;
   newgrid = new int * [width];
   for(k = 0; k < width; k++)
     {
	newgrid[k] = new int [height];
     }

  
   // Seed random number generator
   int maxstates = 14;
   srandom( time(NULL) );   
   
   //Grid initially randomized.
   for(i = 0; i < width; i++)
     {
	for(j = 0; j < height; j++)
	  {
	     grid[i][j] = random()%maxstates;
	  }
     }

   // Copy to other grid
   for(i = 0; i < width; i++)
     {
	for(j = 0; j < height; j++)
	  {
	     newgrid[i][j] = grid[i][j];
	  }
     }
   
   int jp, jm, ip, im;
   
   // Start iterating
   
   for(int iteration = 0; iteration < maxiter; iteration++)
     {
	
	for(i = 0; i < width; i++)
	  {
	     for(j = 0; j < height; j++)
	       {

		  jp = j+1;
		  jm = j-1;
		  ip = i+1;
		  im = i-1;
		  
		  //Cyclic boundary conditions.
		  
		  if(im == -1)
		    {
		       im = width-1;
		    }
		  
		  if(ip == width)
		    {
		       ip = 0;
		    }
		  
		  if(jm == -1)
		    {
		       jm = height-1;
		    }
		  
		  if(jp == height)
		    {
		       jp = 0;
		    }
		  
		  // Rules
		  
		  if( 
		      (  (grid[im][j] == 0) || 
			 (grid[ip][j] == 0) ||
			 (grid[i][jm] == 0) ||
			 (grid[i][jp] == 0)
			 
			 || (grid[im][jm] == 0) || 
			 (grid[ip][jp] == 0) ||
			 (grid[ip][jm] == 0) ||
			 (grid[im][jp] == 0)  )
		      && 
		      (  grid[i][j] == (maxstates-1) )
		      )
		    {
		       newgrid[i][j] = 0;
		       continue;
		    }
		  
		  if( 
		      (  (grid[im][j] == grid[i][j]+1) || 
			 (grid[ip][j] == grid[i][j]+1) ||
			 (grid[i][jm] == grid[i][j]+1) ||
			 (grid[i][jp] == grid[i][j]+1)  
			 
			 || (grid[im][jm] == grid[i][j]+1) || 
			 (grid[ip][jp] == grid[i][j]+1) ||
			 (grid[ip][jm] == grid[i][j]+1) ||
			 (grid[im][jp] == grid[i][j]+1)  
			 
			 
			 )
		      )
		    {
		       newgrid[i][j] = grid[i][j]+1;
		       continue;
		    }
	       }
	  }
	
	// Copy old grid to new grid
	
	for(i = 0; i < width; i++)
	  {
	     for(j = 0; j < height; j++)
	       {
		  grid[i][j] = newgrid[i][j];
	       }
	  }
	
	// Plot the result, with level of red according to the state that pixel is in.
	for(i = 0; i < width; i++)
	  {
	     for(j = 0; j < height; j++)
	       {
		  out.plot(i+1,j+1, ((double) grid[i][j])/(maxstates-1), 0.0, 0.0);
	       }
	  }

	// Rename this instance given the iteration number.
	out.pngwriter_rename((unsigned long int) iteration);   

	// Write the file to disk.
	out.close();
	
     } //iteration
   
   // Delete grids.
   for(k = 0; k < width; k++)
     {
	delete [] grid[k];
     }
   delete [] grid;

   for(k = 0; k < width; k++)
     {
	delete [] newgrid[k];
     }
   delete [] newgrid;

   return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1
Valid CSS!


© 2002, 2003, 2004, 2005, 2006, 2007 Paul Blackburn