forked from csc-training/julia-introduction
-
Notifications
You must be signed in to change notification settings - Fork 7
/
epidemic_no_immunity.jl
147 lines (128 loc) · 3.76 KB
/
epidemic_no_immunity.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using Colors
using Plots
"Enumerate possible states of a single cell"
@enum InfectionStatus uninfected infected dead recovered
"Data structure containing the infection status of a cell"
mutable struct Cell
status::InfectionStatus
infection_time::Int8
end
"Create a 2D array of cells with 1 infected cell in the middle"
function make_cells(width::Integer=7, height::Integer=7)
cells = Matrix{Cell}(undef, width, height)
for i in 1:size(cells)[1]
for j in 1:size(cells)[2]
cells[i,j] = Cell(uninfected, 0)
end
end
cells[width÷2+1,height÷2+1].status = infected
return cells
end
"""Simulate an interaction between two cells. In the other cell is
infected, it may infect the this cell.
"""
function interact!(this_cell::Cell, other_cell::Cell, infection_rate)
if this_cell.status == uninfected && other_cell.status == infected
if rand(1)[1] < infection_rate
this_cell.status = infected
this_cell.infection_time = 0
end
end
end
"Show the cell as an empty or a filled in box for quick viewing"
function Base.show(io::IO, cell::Cell)
if cell.status == infected
print(io, "◼")
else
print(io, "◻")
end
end
"show an array of cells as filled or empty rectangle characters"
function Base.show(io::IO, cells::Array{Cell, 2})
Nx = size(cells)[1]
Ny = size(cells)[2]
# Iterate over rows and columns separately
for j in 1:Ny
for i in 1:Nx
print(cells[i,j])
end
print('\n')
end
end
"Map the cells to colors for plotting"
function to_colors(cell)
if cell.status == uninfected
return RGB(0.0,0.8,0.0)
end
if cell.status == infected
return RGB(0.8,0.0,0.0)
end
if cell.status == dead
return RGB(0.1,0.1,0.1)
end
if cell.status == recovered
return RGB(0.0,0.0,0.8)
end
end
"""
Run the interaction between one cell and a neighbour.
If the neighbour is infected, it infect this cell with the propability parameters.infection_rate.
"""
function interact!(new_cell, other_cell, infection_rate)
if new_cell.status == uninfected && other_cell.status == infected
if rand(1)[1] < infection_rate
new_cell.status = infected
new_cell.infection_time = 0
end
end
end
"""
Update a single cell, not accounting for it's interactions with the neighbours.
"""
function update!(cells, infection_rate)
# Create a copy to remember the old state
old_cells = deepcopy(cells)
# Find the number of cells in each direction
Nx = size(cells)[1]
Ny = size(cells)[2]
# Loop over pairs of cells in the same row. There are Nx-1 pairs.
for j in 1:Ny
# loop over all columns
for i in 1:Nx-1
interact!(cells[i,j], old_cells[i+1,j], infection_rate)
interact!(cells[i+1,j], old_cells[i,j], infection_rate)
end
end
# Loop over pairs of cells in the same row. There are Nx-1 pairs.
for j in 1:Ny-1
# loop over all columns
for i in 1:Nx
interact!(cells[i,j], old_cells[i,j+1], infection_rate)
interact!(cells[i,j+1], old_cells[i,j], infection_rate)
end
end
end
"Count the current number of infections"
function count_infections(cells::Matrix{})
infections = 0
for i in 1:size(cells)[1]
for j in 1:size(cells)[2]
if cells[i,j].status == infected
infections += 1
end
end
end
return infections
end
"Count the number of dead cells"
function count_deaths(cells::Matrix{})
deaths = 0
for i in 1:size(cells)[1]
for j in 1:size(cells)[2]
if cells[i,j].status == dead
deaths += 1
end
end
end
return deaths
end