ABMEv_Space.jl 5.07 KB
Newer Older
Victor's avatar
Victor committed
1

Victor's avatar
Victor committed
2
3
4
5

abstract type IsFinite{T} end

#ife stands for is finite
Victor's avatar
Victor committed
6
7
"""
$(TYPEDEF)
Victor's avatar
Victor committed
8
9
`Dim` is the dimension of the space,
`T` is the element type,
Victor's avatar
Victor committed
10
11
`I` to indicate finiteness
"""
Victor's avatar
Victor committed
12
13
abstract type AbstractSpace{Dim,T,I} end
AbstractSpacesTuple = Tuple{Vararg{AbstractSpace}}
14
import Base:ndims,isfinite,eltype
Victor's avatar
Victor committed
15
Base.ndims(x::AbstractSpace{Dim,T,I}) where {Dim,T,I} = Dim
Victor's avatar
Victor committed
16
Base.isfinite(x::AbstractSpace{Dim,T,IsFinite{t}}) where {Dim,T,t} = t #not sure we need this
17
Base.eltype(::AbstractSpace{Dim,T,I}) where {Dim,T,I} = T
18
19
Base.ndims(ss::AbstractSpacesTuple) = length(ss)
Base.eltype(ss::AbstractSpacesTuple) where {Dim,T,I} = Tuple{eltype.(ss)...}
Victor's avatar
Victor committed
20
21
22

SpaceType=Union{Nothing, AbstractSpace} # not sure what is this used for

Victor's avatar
Victor committed
23
24
25
# Static spaces
abstract type AbstractStatSpace{Dim,T,I} <: AbstractSpace{Dim,T,I} end

26
27
28
"""
$(TYPEDEF)
"""
Victor's avatar
Victor committed
29
struct GraphSpace{T} <: AbstractStatSpace{1,T,IsFinite{true}}
Victor's avatar
Victor committed
30
31
32
    g::AbstractGraph{T}
end

Victor's avatar
Victor committed
33
abstract type AbstractSegment{T<:Number}  <: AbstractStatSpace{1,T,IsFinite{true}} end
34
35
36
37

"""
$(TYPEDEF)
"""
38
struct ContinuousSegment{T<:AbstractFloat} <:  AbstractSegment{T}
Victor's avatar
Victor committed
39
40
41
42
    s::T
    e::T
end

43
44
45
"""
$(TYPEDEF)
"""
46
struct DiscreteSegment{T<:Integer} <: AbstractSegment{T}
Victor's avatar
Victor committed
47
48
49
    s::T
    e::T
end
Victor's avatar
Victor committed
50

51
52
"""
$(TYPEDEF)
Victor's avatar
Victor committed
53
A real space with dimension N and type T
54
"""
Victor's avatar
Victor committed
55
struct RealSpace{N,T} <: AbstractStatSpace{N,T,IsFinite{false}} end
Victor's avatar
Victor committed
56
RealSpace(N) = RealSpace{N,Float64}()
Victor's avatar
Victor committed
57
58
59
60
61
"""
$(TYPEDEF)
A natural space with dimension N and type T
"""
struct NaturalSpace{N,T} <: AbstractStatSpace{N,T,IsFinite{false}} end
Victor's avatar
Victor committed
62

Victor's avatar
Victor committed
63
## Increments - specialised function
Victor's avatar
Victor committed
64
# TODO: find a way to put a type on D in get_inc
65

Victor's avatar
Victor committed
66
67
68
69
70
71
72
73
"""
$(SIGNATURES)
Returns increment corresponding to space `s`
"""
get_inc(x,D,s::AbstractStatSpace,t) = get_inc(x,D,s) # this is defined to skip representation of t for following specialised methods
get_inc(x,D,s::AbstractSpace{Dim,T,I}) where {Dim,T,I<:IsFinite{false}} = get_inc(D,s) # This is defined to skip representation of x for spaces which do not use reflections.

function get_inc(D,s::AbstractSpace{Dim,T,I}) where {Dim,T<:AbstractFloat,I<:IsFinite{false}}
Victor's avatar
Victor committed
74
    if Dim > 1
75
        return D .* randn(T,Dim)
Victor's avatar
Victor committed
76
    else
77
        return D * randn(T)
Victor's avatar
Victor committed
78
    end
Victor's avatar
Victor committed
79
end
80

Victor's avatar
Victor committed
81
function get_inc(D,s::AbstractSpace{Dim,T,I}) where {Dim,T<:Integer,I<:IsFinite{false}}
Victor's avatar
Victor committed
82
    if Dim > 1
83
        return round.(T,D .*randn(Float32,Dim))
Victor's avatar
Victor committed
84
85
86
87
88
    else
        return round(D * randn(Float32))
    end
end

89
#TODO: there is probably a better way of dealing with those two functions
Victor's avatar
Victor committed
90
function get_inc(x,D,s::ContinuousSegment{T}) where {T}
91
    inc = D * randn(T)
Victor's avatar
Victor committed
92
    return _reflect1D(x,inc,s)
Victor's avatar
Victor committed
93
94
95
end

function get_inc(x,D,s::DiscreteSegment{T}) where {T}
Victor's avatar
Victor committed
96
    inc = D * randn(Float32)
Victor's avatar
Victor committed
97
    return round(T,_reflect1D(x,inc,s))
Victor's avatar
Victor committed
98
99
end

100
101
102
103
104
function get_inc(x,D::Nothing,s::DiscreteSegment{T}) where {T}
    inc = rand([one(T),-one(T)])
    return round(T,_reflect1D(x,inc,s))
end

105
# normal dispersal kernel that gets truncated
106
function get_inc(x,D::Number,s::GraphSpace{T}) where {T}
Victor's avatar
Victor committed
107
    niter = round(T,abs(D*randn(Float32))) + 1
108
    # here we add +1 since randomwalk(s.g,x,niter) returns x
Victor's avatar
Victor committed
109
110
111
112
113
    if niter > 0
        return last(randomwalk(s.g,x,niter)) - x
    else
        return 0
    end
Victor's avatar
Victor committed
114
end
115
# short range dispersal kernel, jump to neighbour node
116
function get_inc(x,D::Nothing,s::GraphSpace{T}) where {T}
117
118
    return last(randomwalk(s.g,x,2)) - x
end
Victor's avatar
Victor committed
119

Victor's avatar
Victor committed
120
121
122
123
124
## Dynamic spaces
abstract type AbstractDynSpace{Dim,T<:Number} <: AbstractSpace{Dim,T,IsFinite{true}} end
"""
$(TYPEDEF)
A dynamic graph space.
Victor's avatar
Victor committed
125
126
127

# Example
`DynGraphSpace(g,f)`
Victor's avatar
Victor committed
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
Function `f(t)` takes as argument time, and returns the index of the graph to pick at time `t` from array `g`
"""
struct DynGraphSpace{T<:Number} <: AbstractDynSpace{1,T}
    g::Vector{AbstractGraph{T}}
    f #update function
end
# This is surely not elegant, but we have not found an other way to do it yet
function DynGraphSpace(g::Array{A},f) where A <: AbstractGraph
     DynGraphSpace{eltype(g[1])}(g,f)
 end

"""
$SIGNATURES
Returns the graph correseponding to `d::DynGraphSpace` at time `t`
"""
get_graph(d::DynGraphSpace,t) = d.g[d.f(t)]


146
147
148
## Increments - specialised functions for dynamic graphs
# normal dispersal kernel that gets truncated
function get_inc(x,D::Number,d::DynGraphSpace{T},t) where {T}
Victor's avatar
Victor committed
149
150
151
152
153
154
155
156
157
    niter = round(Int,abs(D*randn())) + 1
    # here we add +1 since randomwalk(s.g,x,niter) returns x
    if niter > 0
        return last(randomwalk(get_graph(d,t),x,niter)) - x
    else
        return 0
    end
end

158
159
160
161
162
# short range dispersal kernel, jump to neighbour node
function get_inc(x,D::Nothing,d::DynGraphSpace{T},t) where {T}
    return last(randomwalk(get_graph(d,t),x,2)) - x
end

Victor's avatar
Victor committed
163
"""
Victor's avatar
Victor committed
164
165
$(SIGNATURES)
Here we increment the trajectory of trait 1 such that it follows a reflected brownian motion (1D)
Victor's avatar
Victor committed
166
"""
Victor's avatar
Victor committed
167
168
function _reflect1D(x::Number,inc::Number,s::AbstractSegment)
    if x + inc < s.s
Victor's avatar
Victor committed
169
        inc = 2 * ( s.s - x ) - inc
Victor's avatar
Victor committed
170
    elseif  x + inc > s.e
Victor's avatar
Victor committed
171
        inc = 2 * ( s.e - x ) - inc
Victor's avatar
Victor committed
172
173
174
    else
        return inc
    end
Victor's avatar
Victor committed
175
    _reflect1D(x,inc,s)
Victor's avatar
Victor committed
176
end
Victor's avatar
Victor committed
177
178
179
180
181
182
183
184
185
186
187
188

function _get_types_dim(s::S) where S<:AbstractSpacesTuple
    T = eltype.(s)
    TT = collect(T)
    _nd = ndims.(s)
    for (i,n) in enumerate(_nd)
        if n > 1
            TT[i] = Vector{TT[i]}
        end
    end
    return TT
end