如何使用多代理将代理合并到不同类型的代理中?

问题描述 投票:0回答:1

从示例连续空间社交距离开始,我尝试创建一个模型,该模型涉及将每对附近的代理合并为具有其他属性的不同类型的代理。

using Agents

@agent struct Single(ContinuousAgent{2, Float64})
  mass :: Float64
  propertyA :: Integer
end

@agent struct Double(ContinuousAgent{2, Float64})
  mass :: Float64
  propertyB :: Float64
  propertyC :: Integer
end

using Random

agent_step!(agent, model) = move_agent!(agent, model, model.dt)

function merge_agents!(a1, a2, model)
    new_mass = a1.mass + a2.mass
    new_pos = ((a1.pos[1]+a2.pos[1])/2.0, (a1.pos[2]+a2.pos[2])/2.0)
    new_vel = sincos(2π * rand(abmrng(model))) .* 0.0
    add_agent!(Double, model; pos = new_pos, vel = new_vel, mass = new_mass, propertyB = 20.0, propertyC = 5)
    remove_agent!(a1, model)
    remove_agent!(a2, model)
end

function model_step!(model)
    for (a1, a2) in interacting_pairs(model, 0.01, :nearest)
        if isa(a1, Single) && isa(a2, Single)
            merge_agents!(a1, a2, model)
        end
    end
end

function ball_model(; speed = 0.002)
    space2d = ContinuousSpace((1, 1); spacing = 0.02)
    model = StandardABM(Union{Single, Double}, space2d; agent_step!, model_step!, properties = Dict(:dt => 1.0),rng = MersenneTwister(42))
    for ind in 1:100
        new_pos = Tuple(rand(abmrng(model), 2))
        new_vel = sincos(2π * rand(abmrng(model))) .* speed
        add_agent!(Single, model; pos = new_pos, vel = new_vel, mass = 1.0, propertyA = 10)
    end
    return model   
end

model = ball_model()

using CairoMakie

abmvideo(
    "mergingAgents-Union.mp4",
    model;
    title = "Merging agents (Union)",
    frames = 500,
    dt = 1,
    framerate = 25,
    agent_size = agent -> isa(agent, Double) ? 20 : 10,
    agent_color = agent -> isa(agent, Double) ? :blue : :green
)

上面的代码可以按预期工作。

Agents of the types Single (smaller blue disks) and Double (larger green disks).

但是,我看到Agents.jl文档建议使用

@multiagent
而不是
Union
,所以我尝试相应地调整代码:

using Agents

@agent struct Single(ContinuousAgent{2, Float64})
  mass :: Float64
  propertyA :: Integer
end

@agent struct Double(ContinuousAgent{2, Float64})
  mass :: Float64
  propertyB :: Float64
  propertyC :: Integer
end

@multiagent Nucleus(Single, Double) <: AbstractAgent

using Random

agent_step!(agent, model) = move_agent!(agent, model, model.dt)

function merge_agents!(a1, a2, model)
    new_mass = a1.mass + a2.mass
    new_pos = ((a1.pos[1]+a2.pos[1])/2.0, (a1.pos[2]+a2.pos[2])/2.0)
    new_vel = sincos(2π * rand(abmrng(model))) .* 0.0
    new_agent = Nucleus(Double(model, new_pos, new_vel, new_mass, 20.0, 5))
    add_agent!(new_agent, model)
    remove_agent!(a1, model)
    remove_agent!(a2, model)
end

function model_step!(model)
    for (a1, a2) in interacting_pairs(model, 0.01, :nearest)
        if isa(a1, Single) && isa(a2, Single)
            merge_agents!(a1, a2, model)
        end
    end
end

function ball_model(; speed = 0.002)
    space2d = ContinuousSpace((1, 1); spacing = 0.02)
    model = StandardABM(Nucleus, space2d; agent_step!, model_step!, properties = Dict(:dt => 1.0),rng = MersenneTwister(42))
    for ind in 1:100
        new_pos = Tuple(rand(abmrng(model), 2))
        new_vel = sincos(2π * rand(abmrng(model))) .* speed
        new_agent = Nucleus(Single(model, new_pos, new_vel, 1.0, 10))
        add_agent_own_pos!(new_agent, model)
    end
    return model
end

model = ball_model()

using CairoMakie

abmvideo(
    "mergingAgents-multiagent.mp4",
    model;
    title = "Merging agents (multiagent)",
    frames = 500,
    dt = 1,
    framerate = 25,
    agent_size = agent -> isa(agent, Double) ? 20 : 10,
    agent_color = agent -> isa(agent, Double) ? :blue : :green
)

现在,代理不再合并了。

Agents of the type Single (smaller blue disks) that don't merge into agents of the type anymore.

我做错了什么?

julia simulation modeling agents.jl
1个回答
0
投票

Agents.@multiagent
(当前为 v6.1)文档说

@multiagent YourAgentType(AgentTypesToMerge...) [<: OptionalSupertype]

定义多个代理“子类型”,它们是唯一类型 YourAgentType 的变体。这意味着所有“子类型”都包含在总体类型中。那么,你就无法根据

typeof
来区分它们,而需要使用
variantof
函数来代替。 [...]

检索代理变量的方法是通过函数

variantof
。 [...]

您还可以使用

variant
函数访问随附的变体实例。 [...]

使用用

Nucleus
包裹
Single
Double
构建的代理,问题在于像
isa(anAgent, Single)
isa(anAgent, Double)
这样的表达式是错误的。

anAgent = Nucleus(Single(id=-1; pos=[-2.0,-3.0], vel=[-0.2,-0.3], mass=-4.0, propertyA=-5))

typeof(anAgent) # Nucleus

isa(anAgent, Nucleus) # true

isa(anAgent, Single) # false

解决方案是用

Nucleus
variant(anAgent)
打开
variantof(anAgent)

isa(variant(anAgent), Single) # true

variantof(anAgent) == Single  # true

例如

function model_step!(model)
    for (a1, a2) in interacting_pairs(model, 0.01, :nearest)
        if isa(variant(a1), Single) && isa(variant(a2), Single)          # modified
            merge_agents!(a1, a2, model)
        end
    end
end

abmvideo(
    "mergingAgents-multiagent.mp4",
    model;
    title = "Merging agents (multiagent)",
    frames = 500,
    dt = 1,
    framerate = 25,
    agent_size = agent -> isa(variant(agent), Double) ? 20 : 10,         # modified
    agent_color = agent -> isa(variant(agent), Double) ? :blue : :green  # modified
)
© www.soinside.com 2019 - 2024. All rights reserved.