Skip to content

Commit

Permalink
Merge pull request #25 from AlgebraicJulia/jb/interpreter
Browse files Browse the repository at this point in the history
Make ABMs Fast
  • Loading branch information
kris-brown committed Feb 8, 2024
2 parents ddce48e + 998016d commit 97c584d
Show file tree
Hide file tree
Showing 26 changed files with 1,230 additions and 668 deletions.
7 changes: 5 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ name = "AlgebraicRewriting"
uuid = "725a01d3-f174-5bbd-84e1-b9417bad95d9"
license = "MIT"
authors = ["Kris Brown <kris@topos.institute>"]
version = "0.3.0"
version = "0.3.1"

[deps]
ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8"
Catlab = "134e5e36-593f-5add-ad60-77f754baafbe"
CompTime = "0fb5dd42-039a-4ca4-a1d7-89a96eae6d39"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
StructEquality = "6ec83bb0-ed9f-11e9-3b4c-2b04cb4e219c"
Expand All @@ -23,7 +25,8 @@ AlgebraicRewritingDataMigrationsExt = "DataMigrations"

[compat]
ACSets = "0.2.9"
Catlab = "0.16.1"
Catlab = "0.16.7"
DataMigrations = "0.0.2"
DataStructures = "0.17, 0.18"
Reexport = "^1"
StructEquality = "2.1"
Expand Down
14 changes: 5 additions & 9 deletions docs/literate/game_of_life.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ end
Coords::AttrType
coords::Attr(V, Coords)
end
@acset_type Life(SchLife) <: AbstractSymmetricGraph
@acset_type AbsLifeCoords(SchLifeCoords) <: AbstractSymmetricGraph
@acset_type Life(SchLife, part_type=BitSetParts) <: AbstractSymmetricGraph
@acset_type AbsLifeCoords(SchLifeCoords, part_type=BitSetParts) <: AbstractSymmetricGraph
const LifeCoords = AbsLifeCoords{Tuple{Int,Int}}
F = Migrate(
Dict(x => x for x in Symbol.(generators(SchLife, :Ob))),
Expand Down Expand Up @@ -188,13 +188,9 @@ rBirth, rPersist, rClearCurr, rClearNext, rCopyNext =
update_next = agent(rBirth rPersist, Life(1); n=:Cell)
next_step = agent(compose(rClearCurr, rCopyNext, rClearNext), Life(1); n=:Cell)
life(n::Int) = for_schedule(update_next next_step, n) |> F
const L1 = life(1)
const L = life(1)

G = make_grid([1 0 1 0 1; 0 1 0 1 0; 0 1 0 1 0; 1 0 1 0 1; 1 0 1 0 1])

res, = apply_schedule(L1, G; steps=1000)
traj = last(res).edge.o.val

view_life(i, traj) = view_life(traj.steps[i].world)

# view_traj(L1, res, view_life; agent=true)
res = interpret(L, G; maxstep=100);
view_traj(L, res[1:10], view_life; agent=true)
178 changes: 100 additions & 78 deletions docs/literate/lotka_volterra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ end

to_graphviz(TheoryLV; prog="dot")

@acset_type LV_Generic(TheoryLV) <: HasGraph
@acset_type LV_Generic(TheoryLV, part_type=BitSetParts) <: HasGraph
const LV = LV_Generic{Symbol,Int}

@acset_type LV′_Generic(TheoryLV′) <: HasGraph
@acset_type LV′_Generic(TheoryLV′, part_type=BitSetParts) <: HasGraph
const LV′ = LV′_Generic{Symbol,Int,Tuple{Int,Int}}

F = Migrate(
Expand Down Expand Up @@ -191,6 +191,7 @@ function view_LV(p::LV′, pth=tempname(); name="G", title="", star=nothing)
open(pth, "w") do io
show(io, "image/svg+xml", g)
end
g
end

i1 = initialize(2, 0.5, 0.5)
Expand Down Expand Up @@ -230,15 +231,18 @@ par_sched = (sheep_rotate_l ⊗ sheep_rotate_r)
#src view_sched(par_sched; names=N)

begin
ex = @acset_colim yLV begin
ex = @acset_colim yLV begin
e::E
s::Sheep
sheep_loc(s) == src(e)
sheep_dir(s) == :N
end
expected = copy(ex)
end;

expected = copy(ex);
expected[:sheep_dir] = :W
@test is_isomorphic(rewrite(rl, ex), expected)
rewrite!(rl, ex)
@test is_isomorphic(ex, expected)
end

# ## Moving forward
Expand Down Expand Up @@ -293,6 +297,8 @@ begin # test
sheep_eng(s) == 9
end
@test is_isomorphic(expected, rewrite(sheep_fwd_rule, ex))
rewrite!(sheep_fwd_rule, ex)
@test is_isomorphic(ex, expected)
end

#=
Expand Down Expand Up @@ -328,6 +334,8 @@ begin # test
end

@test is_isomorphic(expected, rewrite(se_rule, ex))
rewrite!(se_rule, ex)
@test is_isomorphic(ex, expected)
end

#=
Expand All @@ -344,36 +352,35 @@ we_rule = Rule(homomorphism(W, w_eat_l), id(W); expr=(Eng=[vs -> vs[3] + 20, vs
wolf_eat = tryrule(RuleApp(:Wolf_eat, we_rule, W))

# ### A test
ex = @acset LV begin
Sheep = 1
Wolf = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
sheep_loc = 2
sheep_eng = [3]
grass_eng = [9, 10, 11]
dir = fill(:N, 2)
sheep_dir = [:N]
wolf_loc = [2]
wolf_eng = [16]
wolf_dir = [:S]
end
expected = @acset LV begin
Wolf = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
grass_eng = [9, 10, 11]
dir = fill(:N, 2)
sheep_dir = [:N]
wolf_loc = [2]
wolf_eng = [36]
wolf_dir = [:S]
begin # test
ex = @acset LV begin
Sheep=1; Wolf=1; V=3; E=2;
src=[1,2];
tgt=[2,3];
sheep_loc=2
sheep_eng=[3];
grass_eng=[9,10,11];
dir=[:N,:N];
sheep_dir=[:N]
wolf_loc=[2];
wolf_eng=[16];
wolf_dir=[:S]
end
expected = @acset LV begin
Wolf=1; V=3; E=2;
src=[1,2];
tgt=[2,3];
grass_eng=[9,10,11];
dir=[:N,:N];
sheep_dir=[:N]
wolf_loc=[2];
wolf_eng=[36];
wolf_dir=[:S]
end
@test is_isomorphic(rewrite(we_rule,ex), expected)
rewrite!(we_rule, ex)
@test is_isomorphic(ex,expected)
end
@test is_isomorphic(rewrite(we_rule, ex), expected)

# Die if 0 eng
s_die_l = @acset_colim yLV begin
Expand All @@ -387,12 +394,18 @@ sheep_starve = (RuleApp(:starve, sheep_die_rule,
(id([I]) Weaken(create(S))) merge_wires(I))

begin # test
ex = s_die_l W
expected = G W
@test is_isomorphic(rewrite(sheep_die_rule, ex), expected)
begin # test
compile_rewrite(sheep_die_rule)
ex = @acset_colim yLV begin
s::Sheep; w::Wolf
sheep_eng(s) == 0; sheep_dir(s) == :W
end
expected = @acset_colim yLV begin v::V; w::Wolf end
@test is_isomorphic(rewrite(sheep_die_rule,ex), expected)
rewrite!(sheep_die_rule,ex)
@test is_isomorphic(ex, expected)
end

# Reproduction

s_reprod_r = @acset_colim yLV begin
Expand All @@ -410,22 +423,22 @@ sheep_reprod_rule = Rule(
sheep_reprod = RuleApp(:reproduce, sheep_reprod_rule,
id(S), homomorphism(S, s_reprod_r)) |> tryrule

begin # test
ex = @acset_colim yLV begin
s::Sheep
w::Wolf
sheep_eng(s) == 10
begin # test
ex = @acset_colim yLV begin
s::Sheep; w::Wolf; sheep_eng(s) == 10; sheep_dir(s) == :W
end
expected = @acset_colim yLV begin
(s1, s2)::Sheep
w::Wolf
expected = @acset_colim yLV begin
(s1,s2)::Sheep; w::Wolf;
sheep_loc(s1) == sheep_loc(s2)
sheep_eng(s1) == 5
sheep_eng(s2) == 5
sheep_dir(s1) == sheep_dir(s2)
sheep_eng(s1) == sheep_eng(s2)
sheep_dir(s1) == :W; sheep_eng(s1) == 5;
end
@test is_isomorphic(rewrite(sheep_reprod_rule, ex), expected)
@test is_isomorphic(rewrite(sheep_reprod_rule,ex),expected)
rewrite!(sheep_reprod_rule,ex)
@test is_isomorphic(ex, expected)
end

# Grass increment

g_inc_n = deepcopy(G)
Expand All @@ -437,33 +450,35 @@ g_inc_rule = Rule(id(G), id(G);
expr=(Eng=[vs -> only(vs) - 1],))
g_inc = RuleApp(:GrassIncrements, g_inc_rule, G) |> tryrule


ex = @acset LV begin
Sheep = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
sheep_loc = 2
sheep_eng = [3]
grass_eng = [1, 10, 2]
dir = fill(:N, 2)
sheep_dir = [:N]
end
expected = @acset LV begin
Sheep = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
sheep_loc = 2
sheep_eng = [3]
grass_eng = [0, 10, 2]
dir = fill(:N, 2)
sheep_dir = [:N]
begin
ex = @acset LV begin
Sheep = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
sheep_loc = 2
sheep_eng = [3]
grass_eng = [1, 10, 2]
dir = fill(:N, 2)
sheep_dir = [:N]
end
expected = @acset LV begin
Sheep = 1
V = 3
E = 2
src = [1, 2]
tgt = [2, 3]
sheep_loc = 2
sheep_eng = [3]
grass_eng = [0, 10, 2]
dir = fill(:N, 2)
sheep_dir = [:N]
end
@test is_isomorphic(rewrite(g_inc_rule, ex), expected)
rewrite!(g_inc_rule, ex)
@test is_isomorphic(ex, expected)
end
@test is_isomorphic(rewrite(g_inc_rule, ex), expected)


# Scheduling Rules

Expand Down Expand Up @@ -495,4 +510,11 @@ cycle = (agent(sheep; n=:sheep, ret=I)
overall = while_schedule(cycle, curr -> nparts(curr, :Wolf) >= 0) |> F2 # wrap in a while loop

X = initialize(3, 0.25, 0.25);
res, = apply_schedule(overall, X; steps=50);
# Force something exciting to happen
X[1, :wolf_loc] = X[1, :sheep_loc]
X[1, :wolf_dir] = X[1, :sheep_dir]

res = interpret(overall, X; maxstep=100);

# Run this line to view the trajectory
view_traj(overall, res[1:10], view_LV; agent=true, names=F2(N))
3 changes: 3 additions & 0 deletions docs/literate/ptg_simple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ K = @acset BreadWorld begin
BreadLoaf = 1
Countertop = 1
Stool = 1
BreadLoafIsThing = [1]
CountertopIsThing = [2]
StoolIsThing = [3]
end

# ### Right ACSet
Expand Down
Loading

0 comments on commit 97c584d

Please sign in to comment.