Elementary cellular automaton
using EasyABM
Step 1: Create Model
In this model, we work with patches only. We set grid_size
to (50,50) and set space_type
to NPeriodic.
model = create_2d_model(size = (50,50), space_type=NPeriodic)
Step 2: Initialise the model
We assign two attributes namely color
and val
to all patches. The patches with val 0 are white while those with val 1 are black. Initially, we set all patches to have val = 0, color = cl"white"
except for the patch at position (25,1) which is assigned val = 1, color = cl"black"
. Since, the color
and val
attributes are not independent, we tell EasyABM to record only color attribute of the patches through the argument props_to_record
to the init_model!
function.
function initialiser!(model)
for j in 1:model.size[2]
for i in 1:model.size[1]
model.patches[i,j].color = cl"white"
model.patches[i,j].val = 0
end
end
model.patches[25,1].color = cl"black"
model.patches[25,1].val = 1
end
init_model!(model, initialiser = initialiser!, props_to_record = Dict("patches" => Set([:color])))
Step 3: Defining the step_rule! and running the model
The dictionary rules
defines the update rule. It is known as rule number 30 in the classification of elementary cellular automata. The val
property (and hence the color
) of jth patch in (i+1)th row is set equal to the value in rules
corresponding to the key (a, b, c)
where in the ith row a
is val
of (j-1)th patch, b
is val
of jth patch and c
is the val
of (j+1)th patch. Since the size of our space is finite, after a certain number of iterations we have to copy each row to the row below and update the topmost row.
rules = Dict((1,1,1)=>0, (1,1,0)=>0, (1,0,1)=>0, (0,1,1)=>1,
(1,0,0)=>1, (0,1,0)=>1, (0,0,1)=>1, (0,0,0)=>0) # rule 30
function update_from_row_below(row, model)
for j in 2:(model.size[1]-1)
vals = (model.patches[j-1, row-1].val,
model.patches[j, row-1].val,
model.patches[j+1, row-1].val)
val = rules[vals]
model.patches[j, row].val = val
model.patches[j, row].color = val==0 ? cl"white" : cl"black"
end
end
function copy_to_row_below(row, model)
for j in 1:model.size[1]
model.patches[j, row-1].val = model.patches[j, row].val
model.patches[j, row-1].color = model.patches[j, row].color
end
end
function step_rule!(model)
if model.tick < model.size[1]
row = model.tick+1
update_from_row_below(row, model)
else
for i in 2:model.size[1]
copy_to_row_below(i, model)
end
update_from_row_below(model.size[1], model)
end
end
runmodel!(model, steps = 200, steprule = step_rule!)
Step 4: Visualisation
In order to draw the model at a specific frame, say 4th, one can use draw_frame(model, frame = 4 )
. If one wants to see the animation of the model run, it can be done as
animate_sim(model)
Step 5: Fetch Data
It is easy to fetch any recorded data after running the model. For example, the numbers of patches with color cl"white"
can be got as follows
df = get_nums_patches(model,
patch-> patch.color == cl"white",
labels=["white"], plot_result=true)
References
https://en.wikipedia.org/wiki/Elementarycellularautomaton