ABMEv_Agent.jl 5.17 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
13
14
15
16
17
18
19
20
21
    # history of traits for geotraits
    x_history::Array{T,1}
    # 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
29
30
31
# infers position type and zeros
function initpos(s::S) where {S<:AbstractSpacesTuple}
    Eltype = eltype.(s)
    Dims = ndims.(s)
    pos = tuple()
    for i in 1:length(Eltype)
        if Dims[i] > 1
32
            pos = (pos...,Eltype[i](ones(Dims[i])))
Victor's avatar
Victor committed
33
        else
34
            pos = (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
"""
Victor's avatar
Victor committed
60
function Agent(s::S, pos::P;ancestors=false,rates=false) where {P,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
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))
81

82
Base.copy(m::Missing) = missing
Victor's avatar
Victor committed
83

84
Base.copy(n::Nothing) = nothing
85

Victor's avatar
Victor committed
86
87
88
89
90
91
92
93
94
95
function Base.show(io::IO, a::AbstractAgent)
     print(io,"pos: ")
     show(io, a.x_history)
     println(io)
     print(io,"t: ")
     show(io, a.t_history)
 end

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
96
97
98
99
#####################
###Agent accessors###
#####################

100
"""
Victor's avatar
Victor committed
101
102
    get_x(a::Agent)
Returns trait i of the agent
103
"""
Victor's avatar
Victor committed
104

105
Base.getindex(a::Agent,i) = a.x_history[end][i]
Victor's avatar
Victor committed
106
107
108

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

"""
Victor's avatar
Victor committed
111
$(SIGNATURES)
Victor's avatar
Victor committed
112
113
Returns geotrait of agent `a` at time `t`
"""
Victor's avatar
Victor committed
114
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
115
    tarray = vcat(a.t_history[2:end],convert(U,t))
116
117
118
    tarray .-= a.t_history
    return sum(get_xhist(a,1) .* tarray)
end
Victor's avatar
Victor committed
119

120
# This method can acces geotrait, while the second not
Victor's avatar
Victor committed
121
"""
Victor's avatar
Victor committed
122
$(SIGNATURES)
Victor's avatar
Victor committed
123
124
125
Returns trait `i` of the agent.
Geotrait corresponds to dimension `i=0`.
"""
Victor's avatar
Victor committed
126
get_x(a::Agent,t::Number,i::Integer) = i > 0 ? a.x_history[end][Int(i)] : get_geo(a,t)
Victor's avatar
Victor committed
127
128

"""
Victor's avatar
Victor committed
129
$(SIGNATURES)
Victor's avatar
Victor committed
130
131
Get time when agent born.
"""
Victor's avatar
Victor committed
132
133
134
get_t(a::Agent) = a.t_history[end]

# TODO: change this with getindex
135
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
136

137
get_xhist(a::AbstractAgent) = a.x_history
Victor's avatar
Victor committed
138

139
get_thist(a::AbstractAgent) = a.t_history
140

Victor's avatar
Victor committed
141
get_d(a::AbstractAgent) = a.d
142

Victor's avatar
Victor committed
143
144
145
146
get_b(a::AbstractAgent) = a.b

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

147
148
149
# 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
150
151

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

153
import Base.zero
Victor's avatar
Victor committed
154

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

157
158
159
160
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
161
162
    @unpack D,mu = p
    _x = get_x(a)
163
164
    inc = zero(_x)
    for (i,ss) in enumerate(s)
Victor's avatar
Victor committed
165
        if rand() < mu[i]
166
            inc[i] = get_inc(_x[i],D[i],ss)
Victor's avatar
Victor committed
167
        end
168
    end
169
170
171
172
173
174
175
176
177
178
    tuple((_x .+ inc)...)
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
179
    push!(a.t_history,t)
180
181
    a.x_history = push!(a.x_history,_get_xinc(a,s,p,t))
    return a
182
183
end

184
function increment_x!(a::AbstractAgent{A,R},s::AbstractSpacesTuple,p::Dict,t::T) where {A<:Ancestors{false},R,T}
Victor's avatar
Victor committed
185
186
    a.t_history[1] = t
    a.x_history[1] = _get_xinc(a,s,p,t)
187
    return a
188
189
end

190
"""
191
    function tin(t::Number,a::Number,b::Number)
192
193
194
if t in [a,b) returns 1. else returns 0
"""

195
function tin(t::Number,a::Number,b::Number)
196
197
198
199
200
201
202
203
204
205
    return t>=a && t<b ? 1. : 0.
end

function split_move(t)
    return .0 + 1/100*(t-20.)*tin(t,20.,120.) + tin(t,120.,Inf64)
end

function split_merge_move(t)
    return .0 + 1/30*(t-10.)*tin(t,10.,40.) + tin(t,40.,70.) + (1- 1/30*(t-70.))*tin(t,70.,100.)
end