How the 1d GOL is built.
Usually when the process of building a program is discussed we talk in plain English about the abstractions involved, then use some sort of flowchart to describe the algorithm, then begin to write the program in a non-existent generalised programming language - a technique called "pseudocoding".
There is no space here for a detailed discussion so I am going to jump straight to the pseudocoding. But I will use Matlab as the pseudocode so that each section of the code will actually run.
First we think of a name for the program, then put in some beginning statements, add a middle, and then and end. The outline pseudocode looks like this
function theGolProgram()
number_of_cells = 80;
number_of_gens = 100;
% the complex middle bit goes here
end
This is the first version of our program. Notice that it is easy to read. We can type it in to a Matlab script and save it - the script *must* have the right name because it is written as a function. The function is called theGolProgram
so the file must have the same name. We can run it by typing theGolProgram
at the command prompt (it doesn't do much).
So what goes in the middle? At the heart of the program is a loop, which repeats as many times as there are generations - we will choose 100 generations as an example. The first generation doesn't require any calculation so we start the loop at 2.
theGolProgram
number_of_cells = 80;
number_of_gens = 100;
% the middle - everything else goes here
for curr_gen = 2:number_of_gens
% the complex middle bit goes here inside a loop
end
end
Something gets calculated many times. You can also run this code but it still doesn't do much!
We need to calculate all the births and deaths (we will call this 'the rule book') and draw a picture of what is happening on the screen. We add two lines to the code to do these two things:
function theGolProgram()
number_of_cells = 80;
number_of_gens = 100;
% the middle - everything else goes here
for curr_gen = 2:number_of_gens
% do something this many times
apply_rulebook;
update_screen;
end
end
Note that we have no idea how to "apply_rulebook" or "update_screen" when we write this. This doesn't matter. Now the code will not run until we have written two new procedures which have matching names. The easy one first:
function update_screen
% imagesc is the name of a Matlab function which creates a
% picture from an array of numbers
imagesc(population);
drawnow;
end
That was easy! Now the slightly more complicated one. First the start and end:
function apply_rulebook
% rule number 1
% rule number 2
end
There are two rules - first:
- If a cell is alive in one generation, it will be dead in the next i.e. each cell has a lifespan of one iteration.
we can code this like so:
function apply_rulebook
% rule number 1
last_gen = curr_gen-1;
for p_cell = 1:num_of_cells
% for live cells only
if population(last_gen, p_cell)==1
population(curr_gen, p_cell)==0;
end
end
% rule number 2
end
The second rule is more tricky:
- If a cell is dead but has one and only one live neighbour, it will come alive in the next generation i.e. new lives are born where there is no overcrowding.
function apply_rulebook
% rule number 1
last_gen = curr_gen-1;
for p_cell = 1:num_of_cells
% for live cells only
if population(last_gen, p_cell)==1
population(curr_gen, p_cell)==0;
end
end
% rule number 2
for p_cell = 1:num_of_cells
% for dead cells only
if population(last_gen, p_cell)==0
% handle special cases for first and last cell
% to put population in a ring
if p_cell ==1
leftn = population(last_gen, number_of_cells);
else
leftn = population(last_gen, p_cell-1);
end
if p_cell == number_of_cells
rghtn = population(last_gen, 1);
else
rghtn = population(last_gen, p_cell+1);
end
% only one neighbour?
% then a cell is born
if (rghtn + leftn) == 1
population(curr_gen, p_cell) = 1;
end
end
end
end
This is really the only tricky bit of the code. I have made it so that the first and last cell are joined together in a ring - that is why there are two if ... then ... else
statements.
The code described above will ALMOST run in Matlab - but we need to add just a few other statements that make sure we have some initial values, and that these values are available where they are needed.
The code below can be copied and pasted in to Matlab, saved as theGolProram.m
and run from the command window by typing theGolProram
function theGolProgram()
% the parameters
number_of_cells = 80;
number_of_gens = 100;
% set up the structure to hold the results
% and give it some initial values
population = zeros(number_of_gens+1, number_of_cells);
population(1,10)=1; population(1,40) = 1;
% the middle - everything else goes here
for curr_gen = 2:number_of_gens
% do something this many times
population = apply_rulebook(population, number_of_cells, curr_gen);
update_screen(population);
end
end
function update_screen(population)
% imagesc is the name of a Matlab function which creates a
% picture from an array of numbers
imagesc(population);
drawnow;
end
function population = apply_rulebook(population, number_of_cells, curr_gen)
% rule number 1
last_gen = curr_gen-1;
for curr_cell = 1:number_of_cells;
% for live cells only
if population(last_gen, curr_cell)==1
population(curr_gen, curr_cell)=0;
end
end
% rule number 2
for curr_cell = 1:number_of_cells;
% rule 2 applies to dead cells only
if population(last_gen, curr_cell)==0
% handle special cases for first and last cell
% to put population in a ring
if curr_cell ==1
leftn = population(last_gen, number_of_cells);
else
leftn = population(last_gen, curr_cell-1);
end
if curr_cell == number_of_cells
rghtn = population(last_gen, 1);
else
rghtn = population(last_gen, curr_cell+1);
end
% only one neighbour?
% then a cell is born
if (rghtn + leftn) == 1
population(curr_gen, curr_cell) = 1;
end
end
end
end