# Issue updating agent properties - all values are the same! - Agents.jl

**URL:** <https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255>\
**Category:** General Usage\
**Tags:** agents\
**Created:** [October 5, 2021, 9:04pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255 "2021-10-05T21:04:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bfried1](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@bfried1](https://discourse.julialang.org/u/bfried1)\
**Post date:** [October 5, 2021, 9:04pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/1 "2021-10-05T21:04:45Z")

</div>

I apologize in advance if the issue is trivial. I’m still learning how to use Agents.jl and I cannot figure out what this issue is.

I will post my code and comment around it. The issue is stated below.

The packages in use:

```nohighlight
using LightGraphs
using SparseArrays: findnz                       
using Plots  
using Statistics

```

Defining my agent:

```julia
mutable struct AgentZ <: AbstractAgent
    id::Int
    cond::Array{Float64,1}
    delta::Float64
    lambda::Float64
    learning_rate::Float64
    extinction_rate::Float64 
    signal::Array{Float64,1}
end

```

Function to create model:

```julia
function create_model(; num_agents,num_signals,p)

space = nothing
properties = Dict(
:network => erdos_renyi(num_agents, p),
)
    

model = AgentBasedModel(
        AgentZ,
        space,
        scheduler = Schedulers.randomly,
        properties = properties,
    )

    
for i=1:num_agents
add_agent!(
            model,
            cond,
            delta,
            lambda,
            learning_rate,
            extinction_rate,
            signal,
            )
end

        
return model
end

```

This is a function that assigns to each agent’s signal the value 0 or 1. This part works.

```julia
function update_sig!(model)
    
    for i in allagents(model)
       i.signal=rand(0:1,num_signals)
    end

end

```

This function, conditioned on the random signal, changes an agent’s cond by plus/minus 1. The issue lies here. When I step the model forward agent.cond, for all agents, takes the same value, where some should go down and some up.

```julia
function update_cond!(agent)
    
    if agent.signal[1] == 1
        agent.cond[1] += 1
    else
        agent.cond[1] -= 1 
    end

end

```

Defining the agent\_step!

```julia
function agent_step!(agent,model)
update_sig!(model)
update_cond!(agent)
end

```

Setting the parameters and creating the model:

```julia
num_signals = 1
num_agents = 10
p=0.3
cond = zeros(num_signals).+.001
delta = 0
lambda = 1
learning_rate = .05
extinction_rate = 1
signal = zeros(num_signals)
model= create_model(;num_agents,num_signals,p)

```

You can check the issue here by stepping the model and printing the value of the two properties for all agents, signal and cond. Notice signal works well, but cond takes the same value across all the agents. Where is the mistake, how do I get cond to take the proper values?

```julia
step!(model, agent_step!)

```

```julia
for i =1:num_agents
print(model[i].cond)
end

```

```julia
for i =1:num_agents
print(model[i].signal)
end

```

Thank you,  
Bfried1

---

<div class="post-metadata">

**Author:** ![mikkoku](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikkoku/32/16274_2.png) [@mikkoku](https://discourse.julialang.org/u/mikkoku)\
**Post date:** [October 6, 2021, 5:28am UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/2 "2021-10-06T05:28:48Z")

</div>

I think you are using the same array `cond` for every agent. You could replace it with `copy(cond)` in the `add_agent!` call.

---

<div class="post-metadata">

**Author:** ![Libbum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/libbum/32/3935_2.png) [@Libbum](https://discourse.julialang.org/u/Libbum)\
**Post date:** [October 6, 2021, 7:16am UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/3 "2021-10-06T07:16:15Z")

</div>

Yep, the underlying issue as @mikkoku has already stated is that `cond` is a global variable in your setup, which is then referenced by each agent in your model.

Agents.jl handles this for you on the data collection side when you [provide the appropriate `obtainer` value to `run!`](https://juliadynamics.github.io/Agents.jl/stable/tutorial/#Agents.run!):

> `obtainer = identity` : method to transfer collected data to the `DataFrame` . Typically only change this to [`copy`](https://docs.julialang.org/en/v1/base/base/#Base.copy) if some data are mutable containers (e.g. `Vector` ) which change during evolution, or [`deepcopy`](https://docs.julialang.org/en/v1/base/base/#Base.deepcopy) if some data are nested mutable containers.

Since its more feasible for users to generate their own initialization functions, this property of containers in Julia is one aspect of the language that can catch people out.

Using `copy` when adding your `cond` and `signal` Arrays to each agent will be the solution here.

I’d also recommend an alternate solution: don’t set all of the agent properties in the global scope—add them as keyword arguments to `create_model` like you do with `num_agents` etc.

Something like

```julia
function create_model(; num_agents = 10,
                        num_signals = 1,
                        p = 0.3,
                        delta = 0,
                        lambda = 1,
                        learning_rate = 0.05,
                        extinction_rate = 1)

space = nothing
properties = Dict(
:network => erdos_renyi(num_agents, p),
)
    

model = AgentBasedModel(
        AgentZ,
        space,
        scheduler = Schedulers.randomly,
        properties,
    )

    
for i=1:num_agents
add_agent!(
            model,
            zeros(num_signals).+.001, # Since this is not assigned anywhere,
            delta, # a new Array will be created each step of the for loop
            lambda,
            learning_rate,
            extinction_rate,
            zeros(num_signals),
            )
end
       
return model
end

```

---

<div class="post-metadata">

**Author:** ![bfried1](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@bfried1](https://discourse.julialang.org/u/bfried1)\
**Post date:** [October 6, 2021, 1:56pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/4 "2021-10-06T13:56:14Z")

</div>

Thank you! @mikkoku

---

<div class="post-metadata">

**Author:** ![bfried1](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@bfried1](https://discourse.julialang.org/u/bfried1)\
**Post date:** [October 6, 2021, 1:59pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/5 "2021-10-06T13:59:37Z")

</div>

@Libbum, thank you for the information and great suggestion! Answers like this are what keeps the Julia community growing.

---

<div class="post-metadata">

**Author:** ![bfried1](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@bfried1](https://discourse.julialang.org/u/bfried1)\
**Post date:** [October 6, 2021, 5:36pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/6 "2021-10-06T17:36:30Z")

</div>

@mikkoku @Libbum,  
Both your solutions worked, but now a new issue has arisen. The changes in `cond` do not correctly correspond to the `signal`.

Updated code:

```julia
function create_model(; num_agents,num_signals,p)

space = nothing
properties = Dict(
:network => SimpleWeightedGraph(num_agents),
)
    

model = AgentBasedModel(
        Agent_Zero,
        space,
        scheduler = Schedulers.randomly,
        properties = properties,
    )

    
for i=1:num_agents
add_agent!(
            model,
            copy(cond), # noted change 
            delta,
            lambda,
            learning_rate,
            extinction_rate,
            copy(signal), # noted change 
            )
end
        
return model
end

```

After using `step!(model, agent_step!)` once I check the parameters to find:

```julia
for i =1:num_agents
print(model[i].cond)
end

```

Output:`[-0.999][1.001][-0.999][-0.999][-0.999][1.001][-0.999][-0.999][1.001][1.001]`

```julia
for i =1:num_agents
print(model[i].signal)
end

```

Output:`[0.0][0.0][1.0][0.0][0.0][1.0][0.0][1.0][1.0][0.0]`

As you can see there is something off. Just looking at the first two values for each output, the `signal` for the first two agents is 0, yet one’s `cond` went up and the other’s down. I’ve also noticed that this issue does not happen when `num_agents=1`.

Thank you,  
bfried1

---

<div class="post-metadata">

**Author:** ![bfried1](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@bfried1](https://discourse.julialang.org/u/bfried1)\
**Post date:** [October 6, 2021, 6:00pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/7 "2021-10-06T18:00:37Z")

</div>

I found the issue:

```julia
function update_sig!(model)
    
    for i in allagents(model)
       i.signal=rand(0:1,num_signals)
    end

end

```

Is called for each agent, when it should be called only once.

---

<div class="post-metadata">

**Author:** ![Libbum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/libbum/32/3935_2.png) [@Libbum](https://discourse.julialang.org/u/Libbum)\
**Post date:** [October 6, 2021, 8:04pm UTC](https://discourse.julialang.org/t/issue-updating-agent-properties-all-values-are-the-same-agents-jl/69255/8 "2021-10-06T20:04:54Z")

</div>

I wasn’t sure if this was your intention or not initially.

What’s the logic you need here?

_Do you need a random set of signals for each agent, then based on a change in the signal you would like to modify the `cond` property?_  
For that, you could do

```julia
function agent_step!(agent, model)
    agent.signal = rand(0:1, length(agent.signal))
    update_cond!(agent)
end

```

_Do you need a random set of signals (but only one set), that change each step, then based on a change in the signal you would like to modify the `cond` property of each agent?_

Better to then add `signal` as a model property and have a model step. Note: by default agent properties are calculated first, but we can change that with the [`agents_first` boolean passed to `step!`](https://juliadynamics.github.io/Agents.jl/stable/tutorial/#Agents.step!)

```julia
# Remove `signal` as a property from `Agent_Zero`

function create_model(; num_agents,num_signals,p)

space = nothing
properties = Dict(
:network => SimpleWeightedGraph(num_agents),
:signal => signal, # Note: you can do this here if you want, since it's never a copy
)
    

model = AgentBasedModel(
        Agent_Zero,
        space,
        scheduler = Schedulers.randomly,
        properties = properties,
    )

    
for i=1:num_agents
add_agent!(
            model,
            copy(cond), # noted change 
            delta,
            lambda,
            learning_rate,
            extinction_rate,
            )
end
        
return model
end

function model_step!(model)
    model.signal = rand(0:1, length(model.signal))
end

function agent_step!(agent, model)
# Essentially `update_cond!`
    if model.signal[1] == 1
        agent.cond[1] += 1
    else
        agent.cond[1] -= 1 
    end
end

# Step with
step!(model, agent_step!, model_step!, 1; agents_first = false)

```

* * *

I also notice that your `update_cond!` function only ever cares about the first value in `signal` and `cond`. Is this intentional? Or should all of the values be updated?

There are a number of ways to do this. An example:

```julia
agent.cond[model.signal .== 1] .+= 1
agent.cond[model.signal .== 0] .-= 1

```

You can also simplify this to

```julia
agent.cond[model.signal] .+= 1
agent.cond[.!model.signal] .-= 1

```

if you changed `signal` to `rand(Bool, num_signals)`.
