diff --git a/predator_prey.jl b/predator_prey.jl index 863272c..64d8893 100644 --- a/predator_prey.jl +++ b/predator_prey.jl @@ -177,6 +177,7 @@ end # directions. function initialize_model(; + events = [], n_sheep = 100, n_wolves = 50, dims = (20, 20), @@ -196,6 +197,7 @@ function initialize_model(; ## Notice how the properties are a `NamedTuple` to ensure type stability. ## define as dictionary(mutable) instead of tuples(immutable) as per https://github.com/JuliaDynamics/Agents.jl/issues/727 properties = Dict( + :events => events, :fully_grown => falses(dims), :countdown => zeros(Int, dims), :regrowth_time => regrowth_time, @@ -207,9 +209,10 @@ function initialize_model(; :wolf_perception => wolf_perception ) model = StandardABM(Union{Sheep, Wolf}, space; - agent_step! = sheepwolf_step!, model_step! = grass_step!, + agent_step! = sheepwolf_step!, model_step! = custom_model_step!, properties, rng, scheduler = Schedulers.Randomly(), warn = false ) + ## Add agents for _ in 1:n_sheep energy = rand(abmrng(model), 1:(Δenergy_sheep*2)) - 1 @@ -260,6 +263,11 @@ function sheepwolf_step!(wolf::Wolf, model) reproduce!(wolf, model) end +function custom_model_step!(model) + event_handler!(model) + grass_step!(model) +end + # The behavior of grass function differently. If it is fully grown, it is consumable. # Otherwise, it cannot be consumed until it regrows after a delay specified by # `regrowth_time`. The dynamics of the grass is our `model_step!` function. @@ -275,3 +283,67 @@ function grass_step!(model) end end end + +# Check current step and start event at step t +function event_handler!(model) + + for event in model.events + if event.timer == event.t_start # start event + if event.name == "Drought" + model.regrowth_time = event.value + model.wolf_perception += 1 + model.sheep_perception += 1 + + elseif event.name == "Flood" + model.regrowth_time = event.value + model.Δenergy_wolf = model.Δenergy_wolf - 1 + model.Δenergy_sheep = model.Δenergy_sheep - 1 + + elseif event.name == "PreyReproduceSeasonal" + model.sheep_reproduce = event.value + + elseif event.name == "PredatorReproduceSeasonal" + model.wolf_reproduce = event.value + + end + end + + if event.timer == event.t_end # end event + if event.name == "Drought" + model.regrowth_time = event.pre_value + model.wolf_perception -= 1 + model.sheep_perception -= 1 + + elseif event.name == "Flood" + model.regrowth_time = event.pre_value + model.Δenergy_wolf = model.Δenergy_wolf + 1 + model.Δenergy_sheep = model.Δenergy_sheep + 1 + + elseif event.name == "PreyReproduceSeasonal" + model.sheep_reproduce = event.pre_value + + elseif event.name == "PredatorReproduceSeasonal" + model.wolf_reproduce = event.pre_value + + end + end + + if event.timer == event.t_cycle # reset cycle + event.timer = 1 + else + event.timer += 1 + end + end +end + + +mutable struct RecurringEvent + name::String + value::Float64 + pre_value::Float64 + t_start::Int64 + t_end::Int64 + t_cycle::Int64 + timer::Int64 +end + diff --git a/test.ipynb b/test.ipynb index 43fd483..9ded5ab 100644 --- a/test.ipynb +++ b/test.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -60,45 +60,68 @@ "Pkg.status([\"Agents\",\"GLMakie\"]; mode = Pkg.Types.PKGMODE_MANIFEST, io=stdout)\n", "using GLMakie\n", "GLMakie.activate!()\n", + "\n", + "# Event(name, value, pre_value, t_start, t_end, t_cycle, timerstart)\n", + "events = RecurringEvent[]\n", + "#push!(events, RecurringEvent(\"Drought\", 80, 30, 30, 50, 120, 1))\n", + "#push!(events, RecurringEvent(\"Flood\", 50, 30, 70, 80, 120, 1))\n", + "push!(events, RecurringEvent(\"PreyReproduceSeasonal\", 0.5, 0.1, 1, 4, 12, 1))\n", + "push!(events, RecurringEvent(\"PredatorReproduceSeasonal\", 0.1, 0.07, 4, 6, 12, 1))\n", + "\n", "stable_params = (;\n", - " n_sheep = 140,\n", + " events = events,\n", + " n_sheep = 30,\n", " n_wolves = 3,\n", " dims = (30, 30),\n", - " Δenergy_sheep = 5,\n", - " sheep_reproduce = 0.31,\n", + " regrowth_time = 30,\n", + " Δenergy_sheep = 6,\n", + " sheep_reproduce = 0.3,\n", " sheep_perception = 0,\n", - " wolf_reproduce = 0.06,\n", - " Δenergy_wolf = 30,\n", + " wolf_reproduce = 0.07,\n", + " Δenergy_wolf = 20,\n", " wolf_perception = 0,\n", " seed = 71758,\n", ")\n", + "\n", "params = Dict(\n", " :regrowth_time => 0:1:100,\n", " :Δenergy_sheep => 0:1:50,\n", " :sheep_reproduce => 0:0.01:1,\n", " :sheep_perception => 0:1:8,\n", - " :Δenergy_wolf => 0:1:50,\n", - " :wolf_reproduce => 0:0.01:1,\n", + " :Δenergy_wolf => 0:1:50, \n", + " :wolf_reproduce => 0:0.01:1, \n", " :wolf_perception => 0:1:8,\n", ")\n", + "\n", "sheep(a) = a isa Sheep\n", "wolf(a) = a isa Wolf\n", "count_grass(model) = count(model.fully_grown)\n", "adata = [(sheep, count), (wolf, count)]\n", "mdata = [count_grass]\n", "model = initialize_model(;stable_params...)\n", - "fig, abmobs = abmexploration(model;params, plotkwargs..., adata, alabels = [\"Sheep\", \"Wolf\"], mdata, mlabels = [\"Grass\"])\n", + "fig, abmobs = abmexploration(\n", + " model;\n", + " params,\n", + " plotkwargs...,\n", + " adata,\n", + " alabels = [\"Sheep\", \"Wolf\"],\n", + " mdata, mlabels = [\"Grass\"]\n", + ")\n", + "#, step! = (model) -> begin event_handler!(model, \"Dürre\") model.wolf_reproduce = 0.1 Agents.step!() end\n", "#fig, ax, abmobs = abmplot(model; add_controls=true, plotkwargs...)\n", + "\n", "fig" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 143, "metadata": {}, "outputs": [], "source": [ "include(\"./predator_prey.jl\")\n", + "\n", + "using CairoMakie\n", "CairoMakie.activate!() # hide\n", "sheepwolfgrass = initialize_model(;stable_params...)\n", "\n", @@ -114,7 +137,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": {}, "outputs": [], "source": [ @@ -155,7 +178,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Julia 1.10.3", + "display_name": "Julia 1.10.2", "language": "julia", "name": "julia-1.10" }, @@ -163,7 +186,7 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.10.3" + "version": "1.10.2" } }, "nbformat": 4,