羊和狼的游戏
在这个例子中,我们将考虑一个模型,其模拟的本质是显示捕食者-猎物-植物情景。 这是一个基于代理的模型,模拟具有三个关键组件的生态系统:
- 羊(受害者)-它们以植物为食并以充足的能量繁殖
- 狼(捕食者)-狩猎羊,需要更多的能量才能生存
- 植物-随着时间的推移再生,作为羊的食物
这里的关键机制是营养循环,表示如下狼→羊→植物和种群动态,在达到能量阈值时通过能量消耗(饥饿)和繁殖自动调节,以及药剂的随机移动
该模型展示了生态学的经典原理:
-食物链
-资源竞争
-动态人口均衡
-物种灭绝的瓶颈效应
Pkg.add("StatsBase")
using Random
using StatsBase
现在我们将声明模型对象的主要参数和结构。
-
世界参数:
WIDTH和HEIGHT-二维世界的尺寸(以单元格为单位)MAX_STEPS-模拟迭代的限制SAVE_EVERY-可视化保存状态的频率
-
代理:
-所有代理都有坐标(x,y),并从基类型继承
AgentSheep和Wolf包含参数energy-一个关键指标:
-生存(在能量<0时,代理死亡)
-再生(需要足够的能量水平)Bush有一面旗帜active-可以吃吗
-
型号:
-包含所有代理的数组(
sheep,wolves)
-矩阵bushes(植物)的尺寸宽度×高度
-步进计数器step
-字典params具有可配置的参数:
*事件的概率(繁殖,植物的恢复)
*能源参数(消耗,消耗,阈值)
*生态系统平衡(生存难度可以调整)
这些结构构成了:
-模拟代理运动
-食物系统(狼→羊→植物)
-繁殖和死亡的机制
-生态系统状态的可视化
const WIDTH = 50
const HEIGHT = 50
const MAX_STEPS = 2000
const SAVE_EVERY = 100
abstract type Agent end
mutable struct Sheep <: Agent
x::Int
y::Int
energy::Int
end
mutable struct Wolf <: Agent
x::Int
y::Int
energy::Int
end
mutable struct Bush <: Agent
x::Int
y::Int
active::Bool
end
mutable struct Model
sheep::Vector{Sheep}
wolves::Vector{Wolf}
bushes::Matrix{Bush}
step::Int
params::Dict{Symbol,Float64}
end
功能 init_model 用三种类型的代理创建生态系统模型的初始状态:羊、狼和植物。
功能做什么:
-
初始化世界,创建一个测量宽度×高度的植物矩阵(数字设置在
n_bushes) -
创建代理:羊(
n_sheep件)与启动能量sheep_energy,狼(n_wolves件)与启动能量wolf_energy,随机将它们放置在地图上 -
通过字典调整模型参数
params:-植物恢复和动物繁殖的概率
-饥饿期间的能源消耗
-营养期间的能量增加
-繁殖的能量阈值
**返回:**对象类型 Model 随着生态系统的初始状态,所有这些功能参数都允许您在启动前灵活调整生态系统平衡。
function init_model(;
n_sheep = 50,
n_wolves = 10,
n_bushes = 500,
sheep_energy = 10,
wolf_energy = 50,
bush_regrowth = 0.01,
sheep_reprod = 0.04,
wolf_reprod = 0.05,
sheep_hunger = 1,
wolf_hunger = 2,
sheep_eat_gain = 5,
wolf_eat_gain = 20,
sheep_reprod_thresh = 15,
wolf_reprod_thresh = 30
)
bushes = Matrix{Bush}(undef, WIDTH, HEIGHT)
for x in 1:WIDTH, y in 1:HEIGHT
bushes[x,y] = Bush(x, y, false)
end
all_positions = [(x, y) for x in 1:WIDTH, y in 1:HEIGHT]
bush_positions = sample(all_positions, n_bushes, replace=false)
for (x, y) in bush_positions
bushes[x,y].active = true
end
sheep = Sheep[]
for _ in 1:n_sheep
x, y = rand(1:WIDTH), rand(1:HEIGHT)
push!(sheep, Sheep(x, y, sheep_energy))
end
wolves = Wolf[]
for _ in 1:n_wolves
x, y = rand(1:WIDTH), rand(1:HEIGHT)
push!(wolves, Wolf(x, y, wolf_energy))
end
params = Dict(
:bush_regrowth => bush_regrowth,
:sheep_reprod => sheep_reprod,
:wolf_reprod => wolf_reprod,
:sheep_hunger => sheep_hunger,
:wolf_hunger => wolf_hunger,
:sheep_eat_gain => sheep_eat_gain,
:wolf_eat_gain => wolf_eat_gain,
:sheep_reprod_thresh => sheep_reprod_thresh,
:wolf_reprod_thresh => wolf_reprod_thresh
)
Model(sheep, wolves, bushes, 0, params)
end
功能 **move_agent!**在地图上随机移动代理(羊或狼)。 它产生一个随机偏移 **dx**及 **dy**取值-1、0或1(任何方向或位置的一个步骤)并计算新坐标, **mod1**提供边界的"包裹"-如果代理超出地图的边缘,则会出现在对面。
function move_agent!(agent::Agent, model)
dx, dy = rand(-1:1, 2)
new_x = mod1(agent.x + dx, WIDTH)
new_y = mod1(agent.y + dy, HEIGHT)
agent.x, agent.y = new_x, new_y
end
功能 eat!(sheep::Sheep, model) 允许绵羊在当前的笼子里吃植物。 她检查羊下的灌木丛(model.bushes[sheep.x, sheep.y]),如果灌木是活动的(active=true),使灌木不活跃(吃它),并通过以下方式增加绵羊的能量 sheep_eat_gain 从参数中,返回 true (喂食成功),如果灌木不活动,返回 false
功能 reproduce!(agent::Sheep, model),在满足条件时进行绵羊育种。 它检查两个条件:随机数不太可能重现(sheep_reprod)和羊的能量高于阈值(sheep_reprod_thresh),如果满足条件:将羊的能量分成两半,创建一个具有相同坐标和一半能量的新羊,将其添加到模型中,返回 true (复制成功),如果不满足条件,返回 false
function eat!(sheep::Sheep, model)
bush = model.bushes[sheep.x, sheep.y]
if bush.active
bush.active = false
sheep.energy += model.params[:sheep_eat_gain]
return true
end
false
end
function reproduce!(agent::Sheep, model)
if rand() < model.params[:sheep_reprod] && agent.energy > model.params[:sheep_reprod_thresh]
agent.energy ÷= 2
new_sheep = Sheep(agent.x, agent.y, agent.energy)
push!(model.sheep, new_sheep)
return true
end
false
end
然后对于狼也有类似的功能,与羊的关键区别:
*狼猎羊(不是植物)
*使用自己的参数(wolf_eat_gain, **wolf_reprod**等。)
*复制的机制相似,但数值不同
function eat!(wolf::Wolf, model)
sheep_idx = findfirst(s -> s.x == wolf.x && s.y == wolf.y, model.sheep)
if !isnothing(sheep_idx)
splice!(model.sheep, sheep_idx)
wolf.energy += model.params[:wolf_eat_gain]
return true
end
false
end
function reproduce!(agent::Wolf, model)
if rand() < model.params[:wolf_reprod] && agent.energy > model.params[:wolf_reprod_thresh]
agent.energy ÷= 2
new_wolf = Wolf(agent.x, agent.y, agent.energy)
push!(model.wolves, new_wolf)
return true
end
false
end
功能 regenerate_bushes!(model),以一定的概率在地图上恢复被吃掉的植物(灌木丛),该函数贯穿比赛场地的所有单元格(宽度×高度),对于每个不活动的灌木丛(bush.active == false)与概率 bush_regrowth (从模型的参数)使灌木活跃,通过将随机数与 model.params[:bush_regrowth]
function regenerate_bushes!(model)
for x in 1:WIDTH, y in 1:HEIGHT
bush = model.bushes[x,y]
if !bush.active && rand() < model.params[:bush_regrowth]
bush.active = true
end
end
end
功能 step!(model) 执行生态系统模拟的一个步骤,更新所有代理的状态和验证完成条件.
主要工作阶段:
-
步进计数器的增量
model.step += 1 -
绵羊处理(循环):
-移动(
move_agent!)
-营养(如果你不能吃,减少能量sheep_hunger)
-复制的尝试(reproduce!) -
狼治疗(在一个周期):
-移动(
move_agent!)
-狩猎(如果失败,减少能量wolf_hunger)
-复制的尝试(reproduce!) -
过滤已故代理人:
-清除能量小于0的绵羊
-清除能量小于0的狼 -
植物修复:
regenerate_bushes!-食用灌木的更新
-
检查完成条件:
-所有羊或所有狼的灭绝
-达到最大步数(MAX_STEPS)
-相关消息的输出 -
进度记录:每个
SAVE_EVERY步骤显示当前统计信息 -
返回值:
false-如果模拟要结束true-如果模拟继续
function step!(model)
model.step += 1
for sheep in model.sheep
move_agent!(sheep, model)
if !eat!(sheep, model)
sheep.energy -= model.params[:sheep_hunger]
end
reproduce!(sheep, model)
end
for wolf in model.wolves
move_agent!(wolf, model)
if !eat!(wolf, model)
wolf.energy -= model.params[:wolf_hunger]
end
reproduce!(wolf, model)
end
filter!(s -> s.energy > 0, model.sheep)
filter!(w -> w.energy > 0, model.wolves)
regenerate_bushes!(model)
if isempty(model.sheep) || isempty(model.wolves)
if isempty(model.sheep)
println("Симуляция остановлена на шаге $(model.step): все овцы вымерли.")
else
println("Симуляция остановлена на шаге $(model.step): все волки вымерли.")
end
return false
end
if model.step >= MAX_STEPS
println("Симуляция завершена: достигнуто максимальное количество шагов ($MAX_STEPS).")
return false
end
if model.step % SAVE_EVERY == 0
println("Прогресс: завершен шаг $(model.step). Овец: $(length(model.sheep)), волков: $(length(model.wolves))")
end
true
end
功能 plot_model(model) в它以彩色地图的形式可视化生态系统的当前状态,显示所有药剂和植物的位置。
-每个代理在地图上正好占据一个正方形
-显示优先级:狼>羊>植物(如果它们在同一个笼子里)
-颜色选择直观的解释:
-红色-危险(掠食者)
-白色-中性(猎物)
-绿色-植物
function plot_model(model)
grid = zeros(Int, WIDTH, HEIGHT)
for x in 1:WIDTH, y in 1:HEIGHT
if model.bushes[x,y].active
grid[x,y] = 3
end
end
for sheep in model.sheep
grid[sheep.x, sheep.y] = 2
end
for wolf in model.wolves
grid[wolf.x, wolf.y] = 1
end
colors = [colorant"black", colorant"red", colorant"white", colorant"green"]
heatmap(grid,
c=colors,
clim=(0,3),
title="Шаг: $(model.step) | Овцы: $(length(model.sheep)) | Волки: $(length(model.wolves))",
axis=false,
legend=false
)
end
功能 run_simulation 运行和管理整个生态系统模拟的主要功能。
它包括以下步骤::
-
初始化:
-
主仿真周期包括当前状态的逐步可视化(
plot_model),执行仿真步骤(step!),保存当前人口数据,并在满足停止条件时中断。 -
创建动画并将模拟过程保存到GIF文件"wolf_sheep_sim。gif"
-
结果的输出。
function run_simulation(;
n_sheep = 50,
n_wolves = 10,
n_bushes = 500,
sheep_energy = 10,
wolf_energy = 50,
bush_regrowth = 0.01,
sheep_reprod = 0.04,
wolf_reprod = 0.05,
sheep_hunger = 1,
wolf_hunger = 2,
sheep_eat_gain = 5,
wolf_eat_gain = 20,
sheep_reprod_thresh = 15,
wolf_reprod_thresh = 30
)
model = init_model(
n_sheep = n_sheep,
n_wolves = n_wolves,
n_bushes = n_bushes,
sheep_energy = sheep_energy,
wolf_energy = wolf_energy,
bush_regrowth = bush_regrowth,
sheep_reprod = sheep_reprod,
wolf_reprod = wolf_reprod,
sheep_hunger = sheep_hunger,
wolf_hunger = wolf_hunger,
sheep_eat_gain = sheep_eat_gain,
wolf_eat_gain = wolf_eat_gain,
sheep_reprod_thresh = sheep_reprod_thresh,
wolf_reprod_thresh = wolf_reprod_thresh
)
sheep_history = Int[]
wolf_history = Int[]
bush_history = Int[]
step_history = Int[]
anim = @animate for _ in 1:MAX_STEPS
plot_model(model)
should_continue = step!(model)
push!(sheep_history, length(model.sheep))
push!(wolf_history, length(model.wolves))
push!(bush_history, sum(b.active for b in model.bushes))
push!(step_history, model.step)
should_continue || break
end
println("\nРезультаты симуляции:")
println("Финальный шаг: $(model.step)")
println("Количество овец: $(length(model.sheep))")
println("Количество волков: $(length(model.wolves))")
println("Количество растений: $(sum(b.active for b in model.bushes))")
plt = plot(step_history, [sheep_history, wolf_history, bush_history],
label = ["Овцы" "Волки" "Растения"],
xlabel = "Шаги симуляции",
ylabel = "Количество",
title = "Динамика популяций",
linewidth = 2)
display(plt)
display(gif(anim, "wolf_sheep_sim.gif", fps=10))
end
接下来,我们运行它,为了您的方便,已经应用了代码单元格的掩码,按照下面的示例,您可以使用滑块控制整个模型。
run_simulation(
#基本人口
参数n_sheep=100,#羊的初始个数
n_wolves=5,#初始狼数
n_bushes=70,#初始草量
#能量参数
sheep_energy=100,#羊的初始能量
wolf_energy=1000,#狼的初始能量
#资源恢复选项
bush_regrowth=0.005,#每步复草概率
#养殖参数
sheep_reprod=0.02,#羊每步繁殖概率
wolf_reprod=0.1,#每步一只狼的繁殖概率
#禁食参数
sheep_hunger=1,#羊在没有食物的情况下每步的能量损失
wolf_hunger=3,#没有食物的情况下每步损失狼的能量
#功率参数
sheep_eat_gain=8,#羊吃草时能量增益
wolf_eat_gain=25,#狼吃羊时的能量增益
#繁殖门槛
sheep_reprod_thresh=20,#绵羊繁殖的最小能量
wolf_reprod_thresh=35#狼繁殖的最小能量
)
run_simulation(
n_sheep = 100 # @param {type:"slider",min:0,max:1000,step:1}
,
n_wolves = 24 # @param {type:"slider",min:0,max:1000,step:1}
,
n_bushes = 70 # @param {type:"slider",min:0,max:1000,step:1}
,
sheep_energy = 100 # @param {type:"slider",min:0,max:1000,step:1}
,
wolf_energy = 79 # @param {type:"slider",min:0,max:1000,step:1}
,
bush_regrowth = 0.005 # @param {type:"slider",min:0,max:1,step:0.001}
,
sheep_reprod = 0.02 # @param {type:"slider",min:0,max:1,step:0.01}
,
wolf_reprod = 0.01 # @param {type:"slider",min:0,max:1,step:0.01}
,
sheep_hunger = 1 # @param {type:"slider",min:0,max:1000,step:1}
,
wolf_hunger = 3 # @param {type:"slider",min:0,max:1000,step:1}
,
sheep_eat_gain = 8 # @param {type:"slider",min:0,max:1000,step:1}
,
wolf_eat_gain = 25 # @param {type:"slider",min:0,max:1000,step:1}
,
sheep_reprod_thresh = 20 # @param {type:"slider",min:0,max:1000,step:1}
,
wolf_reprod_thresh = 35 # @param {type:"slider",min:0,max:1000,step:1}
)
结论
总之,我想考虑这种模式对社区的积极影响。:
-
这个模型对学习很有用–它完美地展示了基础知识:
-生态系统(食物链,人口动态)
-基于代理的建模(自主对象的行为)
-模拟中的平衡参数 -
研究–让你学习:
-生态系统适应变化的能力
-物种灭绝的影响
-初始条件对系统发展的影响 -
对于发展,建设的一个例子:
-离散模拟
-实时数据可视化
-过程动画