This repository has been archived by the owner on Jun 26, 2021. It is now read-only.
/
caSandPile.jl
95 lines (82 loc) · 2.18 KB
/
caSandPile.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
# %%
push!(LOAD_PATH, ".");
# %%
@time using CellularBase
#@time using Plots
#@time using LsqFit
@time using Random
# %%
mutable struct SandPile <: AbstractGrid{Int8, 2}
state::Array{Int8,2}
h_c::Int8
neighborhood::AbstractNeighborhood
bc::BoundaryCondition
function SandPile(state::Array{Int8,2}, h_c::Int8)
new(state, h_c, VonNeumannNeighborhood(1, 2), FixedMin)
end
end
CellularBase.possible_states(sp::SandPile) = 0:sp.h_c
@inline iscritical(val::Int8, g::SandPile) = val >= g.h_c
@inline iscritical(g::SandPile) = p -> iscritical(p, g)
function (_g::SandPile)(current::Int8, neighbors::Array{Int8}; kwargs...)
h = iscritical(_g)
if h(current) kwargs[:topple][end] += 1 end
return current + (h(current) ? -4 : 0) + count(h, neighbors)
end
function ready_next(grid::SandPile, step::Int; topple::Array{Int64}, max_steps)
if count(iscritical(grid), state(grid)) == 0
# No critical left
if length(topple) == max_steps
# Enough, my god
return :interrupt
else
# Moar, moar, MOAR!
xrand, yrand = rand.(Base.OneTo.(size(grid)))
# Potentially destabilize - HAHAHAA
grid.state[xrand, yrand] += 1
# Make new counter
push!(topple, 0)
end
end
return :continue
end
# %%
Random.seed!(0)
h_c = Int8(4)
topple_count = Int[0]
w = 20
rand_arr = rand(Int8.(1:h_c-1), w, w)
zero_arr = zeros(Int8, w, w)
grid = SandPile(rand_arr, h_c)
@time simulate!(
grid, typemax(Int),
postrunhook=ready_next, topple=topple_count,
max_steps=100_000, store_results=false);
# %%
function freqtable(k::Array{T}) where T
d = Dict{T,Int}()
for i ∈ k
d[i] = get(d, i, 0) + 1
end
return d
end
topple_freq = freqtable(topple_count)
topple_freq = filter!((p) -> p[1] * p[2] != 0, topple_freq)
x = log.(keys(topple_freq))
y = log.(values(topple_freq))
plot(x,y, st=:scatter)
# %%
@. model(x, p) = p[1] * x + p[2]
fit = curve_fit(model, x, y, [0.,0.])
println(fit.param)
xp = 0:0.01:maximum(x)
yp = model(xp, fit.param)
plot!(xp, yp)
# %%
#=
anim = @animate for frame ∈ results
wireframe(frame, zlims=(0,4))
end
gif(anim, fps=30)
=#
#%%