Problems with Agent constructors

I’m probably not seeing something obvious but for some reason I have one Agent for which the constructor works and another one for which I get an error when I try to call the constructor and I have no clue why.

Here is the code:

@agent struct Actor(NoSpaceAgent) <: AbstractActor
    types::Set{Symbol} = Set{Symbol}()
    behaviors::Vector{Function} = Vector{Function}()
    properties::D where {D <: Dict{Symbol, <:Any}} = Dict{Symbol, Any}()
end

abstract type BalanceActor{C <: FixedDecimal} <: AbstractActor end

# This one works
@agent struct SuMSyActor{C}(Actor) <: BalanceActor{C}
    model::ABM
    balance::SuMSyBalance
    contribution_settings::Union{SuMSy, Nothing}
    contribution::C = CUR_0
end

# This one does not
@agent struct MonetaryActor{C}(Actor) <: BalanceActor{C}
    model::ABM
    balance::AbstractBalance = Balance()
end

This is how I call the constructors:

# I initialised the necessary variables beforehand

SuMSyActor(model, model = model, balance = balance, contribution_settings = contribution_settings)

MonetaryActor(model, model = model)

#I also tried
MonetaryActor(model, model = model, balance = Balance())

The error I get with MonetaryActor is:

ERROR: MethodError: no method matching MonetaryActor(::Int64, ::Set{…}, ::Vector{…}, ::Dict{…}, ::StandardABM{…}, ::Balance{…})

Closest candidates are:
  MonetaryActor(::AgentBasedModel, ::Any...)
   @ EconoSim ~/.julia/packages/Agents/8JW8b/src/core/agents.jl:217

Stacktrace:
 [1] MonetaryActor(; id::Int64, types::Set{…}, behaviors::Vector{…}, properties::Dict{…}, model::StandardABM{…}, balance::Balance{…})
   @ EconoSim ~/.julia/packages/Agents/8JW8b/src/core/agents.jl:216
 [2] MonetaryActor(m::StandardABM{…}; kwargs::@Kwargs{…})
   @ EconoSim ~/.julia/packages/Agents/8JW8b/src/core/agents.jl:219
 [3] top-level scope
   @ REPL[12]:1
Some type information was truncated. Use `show(err)` to see complete types.

What am I missing here?

Can you provide a runnable example? Because it seems strange that SuMSyActor works but MonetaryActor doesn’t

Here is compilable code. I really don’t see why the MonetaryActor constructor doesn’t work.

using Agents
using FixedPointDecimals

Fixed(digits::Integer) = FixedDecimal{Int128, digits}
Currency = Fixed(4)

abstract type AbstractActor <: AbstractAgent end

@agent struct Actor(NoSpaceAgent) <: AbstractActor
    types::Set{Symbol} = Set{Symbol}()
    behaviors::Vector{Function} = Vector{Function}()
    properties::D where {D <: Dict{Symbol, <:Any}} = Dict{Symbol, Any}()
end

abstract type BalanceActor{C <: FixedDecimal} <: AbstractActor end

# This one works
@agent struct SuMSyActor{C}(Actor) <: BalanceActor{C}
    model::ABM
    balance::Integer
    contribution_settings::Union{Integer, Nothing}
    contribution::C = Currency(0)
end

# This one does not
@agent struct MonetaryActor{C}(Actor) <: BalanceActor{C}
    model::ABM
    balance::Integer = 1
end

model1 = ABM(Actor, agent_step! = step!)

SuMSyActor(model1, model = model1, balance = 1, contribution_settings = 2)

model2 = ABM(Actor, agent_step! = step!)

MonetaryActor(model2, model = model2)

As a quick fix, you can specify the parameter

julia> MonetaryActor{FixedDecimal}(model2, model = model2)
MonetaryActor{FixedDecimal}(1, Set{Symbol}(), Function[], Dict{Symbol, Any}(), StandardABM with 0 agents of type Actor
 agents container: Dict
 space: nothing (no spatial structure)
 scheduler: fastest, 1)

I’m still a little confused on why it doesn’t work but I don’t have time today to investigate it further

Ah, sure, it is because you didn’t use any C parameter in MonetaryActor fields, so there is no constructor which can infer its type by the field values. That’s why you can only construct MonetaryActor{FixedDecimal}. So everything is fine.

1 Like

It makes sense it shouldn’t work, as the type C is not used anywhere in the type body. The macro doesn’t know how to create “instantiators” for this type.

2 Likes

If you did

struct A{C}
a::Float64
end

you can’t instantiate x = A(0.1). Which is what the macro tries to create. You’d need to make the explicit x = A{whatever}(0.1). There is no way to deduce whatever from inputs as you can see.

1 Like

We happen to respond exactly at the same time the same thing :laughing:

great minds think alike HAH

1 Like