diff --git a/docs/literate/game_of_life.jl b/docs/literate/game_of_life.jl index f7b3cc4..91c6b3e 100644 --- a/docs/literate/game_of_life.jl +++ b/docs/literate/game_of_life.jl @@ -416,7 +416,7 @@ match_coords(birth, G) # This is easy! Pass in our model and our initial state. We optionally could # limit the run via some maximum number of steps or time, but this one will # achieve steady state within 3 time steps. -res = run!(GoL_coords, G); +res = run!(GoL_coords, G; maxevent=100); @test length(res) == 13 # ## View results diff --git a/src/ABMs.jl b/src/ABMs.jl index 98b2235..5e378a2 100644 --- a/src/ABMs.jl +++ b/src/ABMs.jl @@ -470,7 +470,7 @@ Base.isempty(t::Traj) = isempty(t.events) Base.length(t::Traj) = length(t.events) -const MAXEVENT = 100 +const MAXEVENT = typemax(Int) """ Run an ABM, creating a fresh runtime + trajectory. @@ -480,13 +480,18 @@ dt - timestep for checking discrete events when running ODE dynamics. """ function run!(abm::ABM, init::T; save=_->nothing, maxevent=MAXEVENT, maxtime=Inf, kw...) where T<:ACSet + maxevent == typemax(Int) && isinf(maxtime) && error( + "run! requires at least one finite bound; specify maxevent and/or maxtime." + ) run!(abm::ABM, RuntimeABM(abm, init; kw...), Traj(init); save, maxtime, maxevent) end function run!(abm::ABM, rt::RuntimeABM, output::Traj; save=_->nothing, maxevent=MAXEVENT, maxtime=Inf, dt=0.1) - maxevent = isinf(maxtime) ? maxevent : typemax(Int) + maxevent == typemax(Int) && isinf(maxtime) && error( + "run! requires at least one finite bound; specify maxevent and/or maxtime." + ) # Helper functions that automatically incorporate the runtime `rt` getname(rule::Int)::String = string(isnothing(abm.rules[rule].name) ? rule : abm.rules[rule].name) @@ -606,4 +611,4 @@ function run!(abm::ABM, rt::RuntimeABM, output::Traj; return output end -end # module \ No newline at end of file +end # module diff --git a/test/ABMs.jl b/test/ABMs.jl index edf95f8..0ffc2dc 100644 --- a/test/ABMs.jl +++ b/test/ABMs.jl @@ -73,13 +73,28 @@ push!(new_abm, do_nothing) traj = run!(abm, G; maxevent=10); -traj = run!(ABM([rem_edge]), G); +traj = run!(ABM([rem_edge]), G; maxevent=10); @test length(traj) == 3 -traj = run!(ABM([add_loop]), G); +traj = run!(ABM([add_loop]), G; maxevent=10); @test length(traj) > 3 # after we add a loop, the match persists + is resampled +let traj = run!(ABM([create_loop]), Graph(); maxevent=2, maxtime=10.0) + @test length(traj) == 2 + @test traj.events[end][1] == 2.0 +end + +let err = try + run!(ABM([create_loop]), Graph()) + nothing + catch e + e + end + @test err isa ErrorException + @test occursin("specify maxevent and/or maxtime", sprint(showerror, err)) +end + # Test events in parallel