ABMEv_Agent.jl 5.69 KB
Newer Older
Victor's avatar
Victor committed
1
2
abstract type Ancestors{T} end
abstract type Rates{T} end
3

Victor's avatar
Victor committed
4
5
abstract type AbstractAgent{A<:Ancestors,R<:Rates} end # tc for time contingency, fit for fitness coeff
AbstractAgentM = Union{Missing,AbstractAgent}
6
export AbstractAgentM
7
8
9
10

"""
$(TYPEDEF)
"""
Victor's avatar
Victor committed
11
mutable struct Agent{A<:Ancestors,R<:Rates,T<:Tuple,U,V} <: AbstractAgent{A,R}
12
    # history of traits for geotraits
13
    x_history::Array{Any,1}
14
15
16
17
18
19
20
21
    # birth time of ancestors
    t_history::Array{U,1}
    # death rate
    d::V
    #birth rate
    b::V
end

22

23
24
eltype(a::Agent{A,R,T,U,V}) where {A,R,T,U,V} = T

Victor's avatar
Victor committed
25
26
27
28
# infers position type and zeros
function initpos(s::S) where {S<:AbstractSpacesTuple}
    Eltype = eltype.(s)
    Dims = ndims.(s)
29
    pos = []
Victor's avatar
Victor committed
30
31
    for i in 1:length(Eltype)
        if Dims[i] > 1
32
            push!(pos,ones(eltype(Eltype[i]),Dims[i]))
Victor's avatar
Victor committed
33
        else
34
            pos = push!(pos,one(Eltype[i]))
Victor's avatar
Victor committed
35
36
37
38
39
        end
    end
    Tuple{Eltype...},pos
end

40
41
42
43
44
# default initialiser
"""
$(SIGNATURES)
    Initialises agent with 0 values everywhere
"""
Victor's avatar
Victor committed
45
46
function Agent(s::S;ancestors=false,rates=false) where {S  <: AbstractSpacesTuple}
    T,pos = initpos(s)
Victor's avatar
Victor committed
47
    t = 0.
48
    U =  Float64
Victor's avatar
Victor committed
49
50
51
    d = rates ?  Float64(.0) : nothing
    b = d
    V = rates ?  Float64 : Nothing
Victor's avatar
Victor committed
52
    Agent{Ancestors{ancestors},Rates{rates},T,U,V}([pos],[t],d,b)
Victor's avatar
Victor committed
53
54
55
end

# here pos is provided
56
57
58
59
"""
$(SIGNATURES)
    Initialises agent with `pos` provided
"""
60
function Agent(s::S, pos::P;ancestors=false,rates=false) where {P<:Vector,S  <: AbstractSpacesTuple}
61
62
63
64
65
66
67
68
69
    T = eltype.(s)
    for (i,p) in enumerate(pos)
        if typeof(p) !== T[i]
            try
                p = convert(T[i],p)
            catch e
                throw(ArgumentError("Position provided does not match with underlying space"))
            end
        end
Victor's avatar
Victor committed
70
    end
Victor's avatar
Victor committed
71
    t = 0.
72
    U =  Float64
Victor's avatar
Victor committed
73
74
75
    d = rates ?  Float64(.0) : nothing
    b = d
    V = rates ?  Float64 : Nothing
Victor's avatar
Victor committed
76
    Agent{Ancestors{ancestors},Rates{rates},Tuple{T...},U,V}([pos],[t],d,b)
Victor's avatar
Victor committed
77
end
78

Victor's avatar
Victor committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# TODO : to be modified
function Agent(s::S,pos::Vector,t::Vector{U};ancestors=false,rates=false) where {S  <: AbstractSpacesTuple,U}
    T = eltype.(s)
    for (i,p) in enumerate(pos[1])
        if typeof(p) !== T[i]
            try
                p = convert(T[i],p)
            catch e
                throw(ArgumentError("Position provided does not match with underlying space"))
            end
        end
    end
    d = rates ?  Float64(.0) : nothing
    b = d
    V = rates ?  Float64 : Nothing
    Agent{Ancestors{ancestors},Rates{rates},Tuple{T...},U,V}(pos,t,d,b)
end

Victor's avatar
Victor committed
97
98
import Base:copy,show
Base.copy(a::A) where {A<:AbstractAgent} = A(copy(a.x_history),copy(a.t_history),copy(a.d),copy(a.b))
Victor's avatar
Victor committed
99
100
101
102
# this function only copies the trait history and time (x,t), and set birth and death rates to 0.
copyxt(a::Agent{A,R,T,U,V}) where {A,R,T,U,V<:Number} = Agent{A,R,T,U,V}(copy(a.x_history),copy(a.t_history),zero(V),zero(V))
copyxt(a::Agent{A,R,T,U,Nothing}) where {A,R,T,U} = Agent{A,R,T,U,Nothing}(copy(a.x_history),copy(a.t_history),nothing,nothing)
# this has to be overloaded for Base.copy(a::Agent) to work properly
103
104
Base.copy(m::Missing) = missing
Base.copy(n::Nothing) = nothing
105

Victor's avatar
Victor committed
106
107
108
function Base.show(io::IO, a::Agent{A,R,T,U,V}) where {A,R,T,U,V}
     println(io, "Agent with indices of type", T)
end
Victor's avatar
Victor committed
109
110
111

Base.summary(A::AbstractAgent) = string(TYPE_COLOR,nameof(typeof(a)),NO_COLOR," with uType ",TYPE_COLOR,eltype(a.x_history))

Victor's avatar
Victor committed
112
113
114
115
#####################
###Agent accessors###
#####################

116
"""
Victor's avatar
Victor committed
117
118
    get_x(a::Agent)
Returns trait i of the agent
119
"""
Victor's avatar
Victor committed
120

121
Base.getindex(a::Agent,i) = a.x_history[end][i]
Victor's avatar
Victor committed
122
123
124

get_x(a::Agent) = a.x_history[end]
@deprecate get_x(a) a[:]
Victor's avatar
Victor committed
125
126

"""
Victor's avatar
Victor committed
127
$(SIGNATURES)
Victor's avatar
Victor committed
128
129
Returns geotrait of agent `a` at time `t`
"""
Victor's avatar
Victor committed
130
function get_geo(a::Agent{A,R,T,U,V},t::Number) where {A<:Ancestors{true},R,T,U,V}
Victor's avatar
Victor committed
131
    tarray = vcat(a.t_history[2:end],convert(U,t))
132
133
134
    tarray .-= a.t_history
    return sum(get_xhist(a,1) .* tarray)
end
Victor's avatar
Victor committed
135

136
# This method can acces geotrait, while the second not
Victor's avatar
Victor committed
137
"""
Victor's avatar
Victor committed
138
$(SIGNATURES)
Victor's avatar
Victor committed
139
140
141
Returns trait `i` of the agent.
Geotrait corresponds to dimension `i=0`.
"""
142
get_x(a::AbstractAgent,t::Number,i::Integer) = i > 0 ? a.x_history[end][Int(i)] : get_geo(a,t)
Victor's avatar
Victor committed
143
144

"""
Victor's avatar
Victor committed
145
$(SIGNATURES)
Victor's avatar
Victor committed
146
147
Get time when agent born.
"""
Victor's avatar
Victor committed
148
149
150
get_t(a::Agent) = a.t_history[end]

# TODO: change this with getindex
151
get_xhist(a::AbstractAgent,i::Number) = [a.x_history[t][Int(i)] for t in 1:length(a.x_history)]
Victor's avatar
Victor committed
152

153
get_xhist(a::AbstractAgent) = a.x_history
Victor's avatar
Victor committed
154

155
get_thist(a::AbstractAgent) = a.t_history
156

Victor's avatar
Victor committed
157
get_d(a::AbstractAgent) = a.d
158

Victor's avatar
Victor committed
159
160
161
162
get_b(a::AbstractAgent) = a.b

get_fitness(a::AbstractAgent) = a.b - a.d

163
164
165
# TODO : we can surely extract N in Agent{A,R,Tuple{Vararg{S,N}},U,V}
# Inspiration : where U <: Union{Missing,Agent{T}} where T
Base.length(a::AbstractAgent) = length(a.x_history[end])
Victor's avatar
Victor committed
166
167

nancestors(a::Agent) = length(a.x_history)
168

169
import Base.zero
Victor's avatar
Victor committed
170

171
Base.zero(t::Tuple{Vararg{Union{Number,Tuple{Vararg{Number}}}}}) = [zero.(e) for e in t]
Victor's avatar
Victor committed
172

173
174
175
176
import Base.(+)
(+)(t1::Tuple{Vararg{T,N}},t2::Tuple{Vararg{T,N}}) where {T<:Number,N}= tuple([t1[i] + t2[i] for i in 1:length(t1)]...)

function _get_xinc(a::AbstractAgent,s::AbstractSpacesTuple,p::Dict,t::Number)
Victor's avatar
Victor committed
177
    @unpack D,mu = p
178
    _x = copy(get_x(a))
179
    for (i,ss) in enumerate(s)
Victor's avatar
Victor committed
180
        if rand() < mu[i]
181
            _x[i] += get_inc(_x[i],D[i],ss,t)
Victor's avatar
Victor committed
182
        end
183
    end
184
    _x
185
186
187
188
189
190
191
192
193
end

## Modifiers
"""
    $(SIGNATURES)
This function increments agent by random numbers specified in p
ONLY FOR CONTINUOUS DOMAINS
"""
function increment_x!(a::AbstractAgent{A,R},s::AbstractSpacesTuple,p::Dict,t::T) where {A<:Ancestors{true},R,T}
Victor's avatar
Victor committed
194
    push!(a.t_history,t)
195
196
    a.x_history = push!(a.x_history,_get_xinc(a,s,p,t))
    return a
197
198
end

199
function increment_x!(a::AbstractAgent{A,R},s::AbstractSpacesTuple,p::Dict,t::T) where {A<:Ancestors{false},R,T}
Victor's avatar
Victor committed
200
201
    a.t_history[1] = t
    a.x_history[1] = _get_xinc(a,s,p,t)
202
    return a
203
end