fix movement, but updating model parameters with GLMakie broken

main
Michael Brehm 2024-06-20 20:47:23 +02:00
parent fbf2453ccd
commit 2906c96aa4
2 changed files with 66 additions and 48 deletions

View File

@ -30,14 +30,16 @@ end
death_cause::Union{DeathCause,Nothing} death_cause::Union{DeathCause,Nothing}
nearby_dangers nearby_dangers
nearby_food nearby_food
food_scores
danger_scores
end end
function perceive!(a::Animal,model) function perceive!(a::Animal,model)
if perception(a) > 0 if perception(a) > 0
nearby = collect(nearby_agents(a, model, perception(a))) nearby = collect(nearby_agents(a, model, perception(a)))
a.nearby_dangers = map(x -> x.pos, filter(x -> isa(x, Animal) && x.def.type a.def.dangers && isnothing(x.death_cause), nearby)) a.nearby_dangers = map(x -> x.pos, filter(x -> isa(x, Animal) && x.def.type a.def.dangers, nearby))
a.nearby_food = map(x -> x.pos, filter(x -> isa(x, Animal) && x.def.type a.def.food && isnothing(x.death_cause), nearby)) a.nearby_food = map(x -> x.pos, filter(x -> isa(x, Animal) && x.def.type a.def.food, nearby))
if "Grass" a.def.food if "Grass" a.def.food
a.nearby_food = [a.nearby_food; nearby_fully_grown(a, model)] a.nearby_food = [a.nearby_food; nearby_fully_grown(a, model)]
end end
@ -64,22 +66,36 @@ function calculate_best_pos(a::Animal,model)
positions = collect(nearby_positions(a, model, 1)) positions = collect(nearby_positions(a, model, 1))
# weight scores with utility functions # weight scores with utility functions
for pos in positions for pos in positions
if !isempty(a.nearby_dangers) danger_score = 0
danger_score = sum(map(danger -> findmax(abs.(pos.-danger))[1], a.nearby_dangers)) for danger in a.nearby_dangers
push!(danger_scores,danger_score) distance = findmax(abs.(pos.-danger))[1]
if distance != 0
danger_score=danger_score-1/distance
else
danger_score-=2
end end
if !isempty(a.nearby_food) end
food_score = sum(map(food -> findmax(abs.(pos.-food))[1], a.nearby_food)) food_score = 0
for food in a.nearby_food
distance = findmax(abs.(pos.-food))[1]
if distance != 0
food_score=food_score+1/distance
else
food_score+=2
end
end
push!(danger_scores,danger_score)
push!(food_scores,food_score) push!(food_scores,food_score)
end end
end a.danger_scores = danger_scores
a.food_scores = food_scores
#findall(==(minimum(x)),x) to find all mins #findall(==(minimum(x)),x) to find all mins
#best to filter out all positions where there is already an agent and take into account the current position, so sheeps dont just stand still when the position is occupied #best to filter out all positions where there is already an agent and take into account the current position, so sheeps dont just stand still when the position is occupied
if !isempty(a.nearby_dangers) #&& a.energy > a.def.energy_threshold if !isempty(a.nearby_dangers) #&& a.energy > a.def.energy_threshold
safest_position = positions[findmax(danger_scores)[2]] safest_position = positions[findmax(danger_scores)[2]]
return safest_position return safest_position
elseif !isempty(a.nearby_food) #&& a.energy < a.def.energy_threshold elseif !isempty(a.nearby_food) #&& a.energy < a.def.energy_threshold
foodiest_position = positions[findmin(food_scores)[2]] foodiest_position = positions[findmax(food_scores)[2]]
return foodiest_position return foodiest_position
else else
return nothing return nothing
@ -106,12 +122,27 @@ function reproduce!(a::Animal, model)
end end
function Agents.agent2string(agent::Animal) function Agents.agent2string(agent::Animal)
food_scores = ""
danger_scores = ""
f(x) = string(round(x,digits=2))
if !isempty(agent.food_scores)
food_scores = "\n" * f(agent.food_scores[6]) * "|" * f(agent.food_scores[7]) * "|" * f(agent.food_scores[8]) * "\n" *
f(agent.food_scores[4]) * "|" * " " * "|" * f(agent.food_scores[5]) * "\n" *
f(agent.food_scores[1]) * "|" * f(agent.food_scores[2]) * "|" * f(agent.food_scores[3])
end
if !isempty(agent.danger_scores)
danger_scores = "\n" * f(agent.danger_scores[6]) * "|" * f(agent.danger_scores[7]) * "|" * f(agent.danger_scores[8]) * "\n" *
f(agent.danger_scores[4]) * "|" * " " * "|" * f(agent.danger_scores[5]) * "\n" *
f(agent.danger_scores[1]) * "|" * f(agent.danger_scores[2]) * "|" * f(agent.danger_scores[3])
end
""" """
Type = $(agent.def.type) Type = $(agent.def.type)
ID = $(agent.id) ID = $(agent.id)
energy = $(agent.energy) energy = $(agent.energy)
perception = $(agent.def.perception) perception = $(agent.def.perception)
death = $(agent.death_cause) death = $(agent.death_cause)
food_scores = $(food_scores)
danger_scores = $(danger_scores)
""" """
end end
@ -174,14 +205,14 @@ function initialize_model(;
push!(animal_defs,start_def.def) push!(animal_defs,start_def.def)
end end
animal_properties = generate_animal_parameters(animal_defs) animal_properties = generate_animal_parameters(animal_defs)
properties = Dict( model_properties = Dict(
:events => events, :events => events,
:fully_grown => falses(dims), :fully_grown => falses(dims),
:countdown => zeros(Int, dims), :countdown => zeros(Int, dims),
:regrowth_time => regrowth_time, :regrowth_time => regrowth_time,
:Δenergy_grass => Δenergy_grass, :Δenergy_grass => Δenergy_grass,
) )
properties = merge(properties,animal_properties) properties = merge(model_properties,animal_properties)
model = StandardABM(Animal, space; model = StandardABM(Animal, space;
agent_step! = animal_step!, model_step! = model_step!, agent_step! = animal_step!, model_step! = model_step!,
properties, rng, scheduler = Schedulers.Randomly(), warn = false, agents_first = false properties, rng, scheduler = Schedulers.Randomly(), warn = false, agents_first = false
@ -189,7 +220,7 @@ function initialize_model(;
for start_def in start_defs for start_def in start_defs
for _ in 1:start_def.n for _ in 1:start_def.n
energy = rand(abmrng(model), 1:(start_def.def.Δenergy*2)) - 1 energy = rand(abmrng(model), 1:(start_def.def.Δenergy*2)) - 1
add_agent!(Animal, model, energy, start_def.def, nothing, [], []) add_agent!(Animal, model, energy, start_def.def, nothing, [], [], [], [])
end end
end end
## Add grass with random initial growth ## Add grass with random initial growth
@ -217,7 +248,7 @@ function animal_step!(a::Animal, model)
#remove_agent!(a, model) #remove_agent!(a, model)
#return #return
end end
perceive!(a, model) #perceive!(a, model)
move!(a, model) move!(a, model)
if a.energy < 0 if a.energy < 0
a.death_cause = Starvation a.death_cause = Starvation
@ -238,8 +269,12 @@ end
function grass_step!(model) function grass_step!(model)
ids = collect(allids(model)) ids = collect(allids(model))
dead_animals = filter(id -> !isnothing(model[id].death_cause), ids) dead_animals = filter(id -> !isnothing(model[id].death_cause), ids)
for a in dead_animals for id in ids
remove_agent!(a, model) if !isnothing(model[id].death_cause)
remove_agent!(id, model)
else
perceive!(model[id], model)
end
end end
@inbounds for p in positions(model) # we don't have to enable bound checking @inbounds for p in positions(model) # we don't have to enable bound checking
if !(model.fully_grown[p...]) if !(model.fully_grown[p...])
@ -261,25 +296,25 @@ function event_handler!(model)
if event.name == "Drought" if event.name == "Drought"
model.regrowth_time = event.value model.regrowth_time = event.value
for id in ids for id in ids
model[id].def.perception += 1 abmproperties(model)[Symbol(model[id].def.type*"_"*"perception")] += 1
end end
elseif event.name == "Flood" elseif event.name == "Flood"
model.regrowth_time = event.value model.regrowth_time = event.value
for id in ids for id in ids
model[id].def.Δenergy -= 1 abmproperties(model)[Symbol(model[id].def.type*"_"*"Δenergy")] -= 1
end end
elseif event.name == "PreyReproduceSeasonal" elseif event.name == "PreyReproduceSeasonal"
prey = filter(id -> "Grass" model[id].def.food, ids) prey = filter(id -> "Grass" model[id].def.food, ids)
for id in prey for id in prey
model[id].def.reproduction_prob = event.value abmproperties(model)[Symbol(model[id].def.type*"_"*"reproduction_prob")] = event.value
end end
elseif event.name == "PredatorReproduceSeasonal" elseif event.name == "PredatorReproduceSeasonal"
predators = filter(id -> !("Grass" model[id].def.food), ids) predators = filter(id -> !("Grass" model[id].def.food), ids)
for id in predators for id in predators
model[id].def.reproduction_prob = event.value abmproperties(model)[Symbol(model[id].def.type*"_"*"reproduction_prob")] = event.value
end end
end end
@ -289,25 +324,25 @@ function event_handler!(model)
if event.name == "Drought" if event.name == "Drought"
model.regrowth_time = event.pre_value model.regrowth_time = event.pre_value
for id in ids for id in ids
model[id].def.perception -= 1 abmproperties(model)[Symbol(model[id].def.type*"_"*"perception")] -= 1
end end
elseif event.name == "Flood" elseif event.name == "Flood"
model.regrowth_time = event.pre_value model.regrowth_time = event.pre_value
for id in ids for id in ids
model[id].def.Δenergy += 1 abmproperties(model)[Symbol(model[id].def.type*"_"*"Δenergy")] += 1
end end
elseif event.name == "PreyReproduceSeasonal" elseif event.name == "PreyReproduceSeasonal"
prey = filter(id -> "Grass" model[id].def.food, ids) prey = filter(id -> "Grass" model[id].def.food, ids)
for id in prey for id in prey
model[id].def.reproduction_prob = event.pre_value abmproperties(model)[Symbol(model[id].def.type*"_"*"reproduction_prob")] = event.pre_value
end end
elseif event.name == "PredatorReproduceSeasonal" elseif event.name == "PredatorReproduceSeasonal"
predators = filter(id -> !("Grass" model[id].def.food), ids) predators = filter(id -> !("Grass" model[id].def.food), ids)
for id in predators for id in predators
model[id].def.reproduction_prob = event.pre_value abmproperties(model)[Symbol(model[id].def.type*"_"*"reproduction_prob")] = event.pre_value
end end
end end

View File

@ -9,28 +9,7 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"\u001b[32m\u001b[1m Activating\u001b[22m\u001b[39m project at `~/Studium/SCJ-PredatorPrey/env`\n", "\u001b[32m\u001b[1m Activating\u001b[22m\u001b[39m project at `~/Studium/SCJ-PredatorPrey/env`\n"
"\u001b[32m\u001b[1mPrecompiling\u001b[22m\u001b[39m project...\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mSpecialFunctions\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mColorVectorSpace → SpecialFunctionsExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mSpecialFunctions → SpecialFunctionsChainRulesCoreExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mDualNumbers\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mHypergeometricFunctions\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mStatsFuns\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mStatsFuns → StatsFunsInverseFunctionsExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mStatsFuns → StatsFunsChainRulesCoreExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mDistributions\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mDistributions → DistributionsTestExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mDistributions → DistributionsChainRulesCoreExt\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mKernelDensity\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mStreamSampling\u001b[39m\n",
"\u001b[32m ✓ \u001b[39mAgents\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mMakie\u001b[39m\n",
"\u001b[32m ✓ \u001b[39m\u001b[90mAgents → AgentsVisualizations\u001b[39m\n",
"\u001b[32m ✓ \u001b[39mAgentsExampleZoo\n",
"\u001b[32m ✓ \u001b[39mCairoMakie\n",
"\u001b[32m ✓ \u001b[39mGLMakie\n",
" 19 dependencies successfully precompiled in 272 seconds. 270 already precompiled.\n"
] ]
} }
], ],
@ -81,7 +60,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 17,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -101,7 +80,11 @@
"\n", "\n",
"stable_params = (;\n", "stable_params = (;\n",
" events = events,\n", " events = events,\n",
" start_defs = [StartDefinition(30,sheep_def),StartDefinition(3,wolf_def),StartDefinition(3,bear_def)],\n", " start_defs = [\n",
" StartDefinition(30,sheep_def),\n",
" StartDefinition(3,wolf_def),\n",
" #StartDefinition(3,bear_def)\n",
" ],\n",
" dims = (30, 30),\n", " dims = (30, 30),\n",
" regrowth_time = 30,\n", " regrowth_time = 30,\n",
" Δenergy_grass = 6,\n", " Δenergy_grass = 6,\n",
@ -133,7 +116,7 @@
"#fig, ax, abmobs = abmplot(model; add_controls=true, plotkwargs...)\n", "#fig, ax, abmobs = abmplot(model; add_controls=true, plotkwargs...)\n",
"\n", "\n",
"fig\n", "fig\n",
"#run!(model, 100)" "#run!(model, 2)"
] ]
} }
], ],