Space.jl 5.58 KB
Newer Older
Victor's avatar
Victor committed
1

Victor's avatar
Victor committed
2
3
4

abstract type IsFinite{T} end

Victor's avatar
Victor committed
5
6
7
8
# `Dim` is the dimension of the space,
# `T` is the element type,
# `I` to indicate finiteness

Victor's avatar
Victor committed
9
10
abstract type AbstractSpace{Dim,T,I} end
AbstractSpacesTuple = Tuple{Vararg{AbstractSpace}}
11
import Base:ndims,isfinite,eltype
Victor's avatar
Victor committed
12
Base.ndims(x::AbstractSpace{Dim,T,I}) where {Dim,T,I} = Dim
Victor's avatar
Victor committed
13
Base.isfinite(x::AbstractSpace{Dim,T,IsFinite{t}}) where {Dim,T,t} = t #not sure we need this
14
Base.eltype(::AbstractSpace{Dim,T,I}) where {Dim,T,I} = T
15
16
Base.ndims(ss::AbstractSpacesTuple) = length(ss)
Base.eltype(ss::AbstractSpacesTuple) where {Dim,T,I} = Tuple{eltype.(ss)...}
Victor's avatar
Victor committed
17
18
19

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

Victor's avatar
Victor committed
20
21
22
# Static spaces
abstract type AbstractStatSpace{Dim,T,I} <: AbstractSpace{Dim,T,I} end

23
24
"""
$(TYPEDEF)
Victor's avatar
Victor committed
25
26
27
28
29
30
31
32
33

Creates a Graph Space.

# Example
```julia
using LightGraphs
g = star_graph(7)
GraphSpace(g)
```
Victor's avatar
Victor committed
34

35
"""
Victor's avatar
Victor committed
36
struct GraphSpace{T} <: AbstractStatSpace{1,T,IsFinite{true}}
Victor's avatar
Victor committed
37
38
39
    g::AbstractGraph{T}
end

Victor's avatar
Victor committed
40
abstract type AbstractSegment{T<:Number}  <: AbstractStatSpace{1,T,IsFinite{true}} end
41
42
43

"""
$(TYPEDEF)
Victor's avatar
Victor committed
44
45
46
47
48
49
50
51
52
53

Creates a segment space, where individuals are reflected at both ends.

# Arguments
* `s` start of the segment
* `e` end of the segment
# Example
```julia
ContinuousSegment(1., 2.)
```
54
"""
55
struct ContinuousSegment{T<:AbstractFloat} <:  AbstractSegment{T}
Victor's avatar
Victor committed
56
57
58
59
    s::T
    e::T
end

60
61
"""
$(TYPEDEF)
Victor's avatar
Victor committed
62
63
64
65
66
67
68
69
70
71
72
73

Creates a discrete segement space, where individuals are reflected at both ends.

# Arguments
* `s` start of the segment
* `e` end of the segment

# Example

```julia
    DiscreteSegment(1, 2)
```
74
"""
75
struct DiscreteSegment{T<:Integer} <: AbstractSegment{T}
Victor's avatar
Victor committed
76
77
78
    s::T
    e::T
end
Victor's avatar
Victor committed
79

80
81
"""
$(TYPEDEF)
Victor's avatar
Victor committed
82
83
84
85
86
87

Creates a real space.

# Arguments
* `N` dimension of the space 
* `T` type of the underlying traits.
88
"""
Victor's avatar
Victor committed
89
struct RealSpace{N,T} <: AbstractStatSpace{N,T,IsFinite{false}} end
Victor's avatar
Victor committed
90
RealSpace(N) = RealSpace{N,Float64}()
Victor's avatar
Victor committed
91
92
93
94
95
"""
$(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
96

Victor's avatar
Victor committed
97
## Increments - specialised function
Victor's avatar
Victor committed
98
# TODO: find a way to put a type on D in get_inc
99

Victor's avatar
Victor committed
100
101
"""
$(SIGNATURES)
Victor's avatar
Victor committed
102

Victor's avatar
Victor committed
103
104
105
106
107
108
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
109
    if Dim > 1
110
        return D .* randn(T,Dim)
Victor's avatar
Victor committed
111
    else
112
        return D * randn(T)
Victor's avatar
Victor committed
113
    end
Victor's avatar
Victor committed
114
end
115

Victor's avatar
Victor committed
116
function get_inc(D,s::AbstractSpace{Dim,T,I}) where {Dim,T<:Integer,I<:IsFinite{false}}
Victor's avatar
Victor committed
117
    if Dim > 1
118
        return round.(T,D .*randn(Float32,Dim))
Victor's avatar
Victor committed
119
120
121
122
123
    else
        return round(D * randn(Float32))
    end
end

124
#TODO: there is probably a better way of dealing with those two functions
Victor's avatar
Victor committed
125
function get_inc(x,D,s::ContinuousSegment{T}) where {T}
126
    inc = D * randn(T)
Victor's avatar
Victor committed
127
    return _reflect1D(x,inc,s)
Victor's avatar
Victor committed
128
129
130
end

function get_inc(x,D,s::DiscreteSegment{T}) where {T}
Victor's avatar
Victor committed
131
    inc = D * randn(Float32)
Victor's avatar
Victor committed
132
    return round(T,_reflect1D(x,inc,s))
Victor's avatar
Victor committed
133
134
end

135
136
137
138
139
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

140
# normal dispersal kernel that gets truncated
141
function get_inc(x,D::Number,s::GraphSpace{T}) where {T}
Victor's avatar
Victor committed
142
    niter = round(T,abs(D*randn(Float32))) + 1
143
    # here we add +1 since randomwalk(s.g,x,niter) returns x
Victor's avatar
Victor committed
144
145
146
147
148
    if niter > 0
        return last(randomwalk(s.g,x,niter)) - x
    else
        return 0
    end
Victor's avatar
Victor committed
149
end
150
# short range dispersal kernel, jump to neighbour node
151
function get_inc(x,D::Nothing,s::GraphSpace{T}) where {T}
152
153
    return last(randomwalk(s.g,x,2)) - x
end
Victor's avatar
Victor committed
154

Victor's avatar
Victor committed
155
156
157
158
## Dynamic spaces
abstract type AbstractDynSpace{Dim,T<:Number} <: AbstractSpace{Dim,T,IsFinite{true}} end
"""
$(TYPEDEF)
Victor's avatar
Victor committed
159

Victor's avatar
Victor committed
160
161
162
163
164
165
166
167
168
A dynamic graph space.

# Arguments
* `g` the underlying graph
* `f` a function that takes as argument time,
and returns the index of the graph to pick at time `t` from array `g`

# Example
`DynGraphSpace(g,f)`
Victor's avatar
Victor committed
169
170
171
172
173
174
175
176
177
178
179
180
"""
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
Victor's avatar
Victor committed
181

Victor's avatar
Victor committed
182
183
184
185
186
Returns the graph correseponding to `d::DynGraphSpace` at time `t`
"""
get_graph(d::DynGraphSpace,t) = d.g[d.f(t)]


187
188
189
## 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
190
191
192
193
194
195
196
197
198
    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

199
200
201
202
203
# 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
204
205
#increment the trajectory of trait 1 
# such that it follows a reflected brownian motion (1D)
Victor's avatar
Victor committed
206
207
function _reflect1D(x::Number,inc::Number,s::AbstractSegment)
    if x + inc < s.s
Victor's avatar
Victor committed
208
        inc = 2 * ( s.s - x ) - inc
Victor's avatar
Victor committed
209
    elseif  x + inc > s.e
Victor's avatar
Victor committed
210
        inc = 2 * ( s.e - x ) - inc
Victor's avatar
Victor committed
211
212
213
    else
        return inc
    end
Victor's avatar
Victor committed
214
    _reflect1D(x,inc,s)
Victor's avatar
Victor committed
215
end
Victor's avatar
Victor committed
216
217
218
219
220
221
222
223
224
225
226
227

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