To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit ce88d252 authored by Victor's avatar Victor
Browse files

update with tuple fixes

parent fcb3d958
Pipeline #93088 failed with stage
in 18 minutes and 2 seconds
......@@ -24,28 +24,38 @@ import Base:eltype
eltype(a::Agent{A,R,T,U,V}) where {A,R,T,U,V} = T
# infers position type and zeros
function initpos(s::S) where {S<:AbstractSpacesTuple}
Eltype = eltype.(s)
Dims = ndims.(s)
pos = []
for i in 1:length(Eltype)
if Dims[i] > 1
push!(pos,ones(Eltype[i],Dims[i]))
function _initpos(s::S) where {S<:AbstractSpacesTuple}
T = collect(eltype.(s))
TT = collect(T)
_nd = ndims.(s)
for (i,n) in enumerate(_nd)
if n > 1
TT[i] = Vector{TT[i]}
end
end
pos = Union{TT...}[]
for i in 1:length(TT)
if _nd[i] > 1
push!(pos,ones(T[i],_nd[i]))
else
pos = push!(pos,one(Eltype[i]))
pos = push!(pos,one(T[i]))
end
end
_Type = eltype.(pos)
Tuple{_Type...},pos
Tuple{T...},pos
end
# default initialiser
"""
$(SIGNATURES)
Initialises agent with 0 values everywhere
"""
function Agent(s::S;ancestors=false,rates=false) where {S <: AbstractSpacesTuple}
T,pos = initpos(s)
# args
- `s` is the underlying space
- `ancestors=true` when agents fitness needs to be updated at each time step.
This is needed for the Gillepsie algorithm, but not for CFM algorithm
- `ancestors=true` when one wants to store ancestors traits.
"""
function Agent(s::S;ancestors=false,rates=true) where {S <: AbstractSpacesTuple}
T,pos = _initpos(s)
t = 0.
U = Float64
d = rates ? Float64(.0) : nothing
......@@ -54,59 +64,66 @@ function Agent(s::S;ancestors=false,rates=false) where {S <: AbstractSpacesTupl
Agent{Ancestors{ancestors},Rates{rates},T,U,V}([pos],[t],d,b)
end
# here pos is provided
"""
$(SIGNATURES)
Initialises agent with `pos` provided
"""
function Agent(s::S, pos::P;ancestors=false,rates=false) where {P<:Vector,S <: AbstractSpacesTuple}
# here pos t should be provided
# this allows to initilise agents from any time steps knowing ancestors traits
function Agent(s::S,pos_t::Vector,t::Vector{U};ancestors=false,rates=true) where {S <: AbstractSpacesTuple, U <: AbstractFloat}
T = eltype.(s)
for (i,p) in enumerate(pos)
if eltype(p) !== T[i]
try
p = convert.(T[i],p)
catch e
throw(ArgumentError("Position provided does not match with underlying space"))
end
TT = collect(T) # we need an array to convert thereafter position
_nd = ndims.(s)
for (i,n) in enumerate(_nd)
if n > 1
TT[i] = Vector{T[i]}
end
end
t = 0.
U = Float64
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
# 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]
length(pos_t) == length(t) ? nothing : ArgumentError("length of `pos` should match length of `t`")
# we convert all
pos2_t = Vector{Union{TT...}}[]
for pos in pos_t
pos2 = Union{TT...}[]
for (i,p) in enumerate(pos)
try
p = convert(T[i],p)
push!(pos2,convert(TT[i],p))
catch e
throw(ArgumentError("Position provided does not match with underlying space"))
end
end
push!(pos2_t,pos2)
end
# U = Float64
d = rates ? Float64(.0) : nothing
b = d
V = rates ? Float64 : Nothing
Agent{Ancestors{ancestors},Rates{rates},Tuple{T...},U,V}(pos,t,d,b)
Agent{Ancestors{ancestors},Rates{rates},Tuple{T...},U,V}(pos2_t,t,d,b)
end
"""
Agent(s, pos;ancestors=false,rates=true)
Initialises agent with initial position `pos` provided
# args
- `s` is the underlying space
- `ancestors=true` when agents fitness needs to be updated at each time step.
This is needed for the Gillepsie algorithm, but not for CFM algorithm
- `ancestors=true` when one wants to store ancestors traits.
"""
Agent(s, pos; ancestors=false, rates=true) = Agent(s, [pos], [0.],ancestors=ancestors, rates=rates)
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))
# 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
Base.copy(m::Missing) = missing
Base.copy(n::Nothing) = nothing
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)
println(io, "Agent with indices of type ", T)
end
Base.summary(A::AbstractAgent) = string(TYPE_COLOR,nameof(typeof(a)),NO_COLOR," with uType ",TYPE_COLOR,eltype(a.x_history))
......@@ -179,12 +196,16 @@ function _get_xinc(a::AbstractAgent,s::AbstractSpacesTuple,p::Dict,t::Number)
@unpack D,mu = p
_x = deepcopy(get_x(a))
for (i,ss) in enumerate(s)
E = eltype(mu[i])
S = eltype(ss)
if length(mu[i]) > 1
mut = rand(eltype(mu[i]),ndims(ss)) .< mu[i]
mut = (rand(E,ndims(ss)) .< mu[i]) .|> S
_x[i] .+= mut .* get_inc(_x[i],D[i],ss,t)
else
mut = rand(eltype(mu[i])) < mu[i]
_x[i] += mut * get_inc(_x[i],D[i],ss,t)
mut = rand(E) < mu[i]
if mut
_x[i] += get_inc(_x[i],D[i],ss,t)
end
end
end
_x
......
......@@ -93,13 +93,13 @@ function get_inc(x,D,s::ContinuousSegment{T}) where {T}
end
function get_inc(x,D,s::DiscreteSegment{T}) where {T}
inc = D * randn()
inc = D * randn(Float32)
return round(T,_reflect1D(x,inc,s))
end
# normal dispersal kernel that gets truncated
function get_inc(x,D::Number,s::GraphSpace{T}) where {T}
niter = round(Int,abs(D*randn())) + 1
niter = round(T,abs(D*randn(Float32))) + 1
# here we add +1 since randomwalk(s.g,x,niter) returns x
if niter > 0
return last(randomwalk(s.g,x,niter)) - x
......
......@@ -73,8 +73,8 @@ w4 = World(a4,myspace4,p4)
@test abs(β) < Inf
end
@testset "Isolation by history - hamming distance" begin
a1 = Agent((DiscreteSegment(1,10),),[(1,),(2,),(3,)],[0,1,4],ancestors=true)
a2 = Agent((DiscreteSegment(1,10),),[(1,),(10,),(3,),(10,)],[0,3,4,5],ancestors=true)
a1 = Agent((DiscreteSegment(1,10),),[1,2,3],[0.,1.,4.],ancestors=true)
a2 = Agent((DiscreteSegment(1,10),),[1,10,3,10],[0.,3.,4.,5.],ancestors=true)
@test get_dist_hist(a1,a2,(x,y)->y!=x,1) 3.0
end
end
......
......@@ -12,8 +12,8 @@ sigma_a = .7;
K0 = 1000;
b(X,t) = gaussian(X[1],0.,sigma_K)
d(X,Y,t) = gaussian(X[1],Y[1],sigma_a)/K0
D = (1e-2,)
mu = [.1]
D = [1e-2]
mu = [1.]
NMax = 10000
tend = 1.5
p = Dict{String,Any}();@pack! p = D,mu,NMax
......@@ -25,6 +25,6 @@ w0 = World(myagents,myspace,p,0.)
@testset "Hamming distances" begin
@test typeof(get_xhist_mat(agents(w0))[1] )<: Array
@test get_pairwise_average_isolation(w0) >0
@test get_pairwise_average_isolation(w0) > 0
@test get_local_pairwise_average_isolation(w0) > 0
end
......@@ -63,7 +63,7 @@ end
a4 = Agent(myspace2,[1,1.,[1.,1]],rates=true)
a5 = Agent(myspace2,ancestors=true)
# increment test
p_myspace = Dict("D"=>[1e-10,1e-10,1e-10],"mu" =>[1,1,1] )
p_myspace = Dict("D"=>Union{Float64,Float16}[1e-10,1e-10,Float16(1e-10)],"mu" =>Union{Float64,Float16}[1.,1.,Float16(1)] )
p_myspace2 = Dict("D"=>[1,1,[1,1]],"mu" =>[1,1,[1,1]])
# basic test
......@@ -75,7 +75,7 @@ end
old_a1 = deepcopy(a1)
@test prod((get_x(old_a1) . get_x(increment_x!(a1,myspace,p_myspace,0.))))
@test !prod((get_x(old_a1) .== get_x(increment_x!(a1,myspace,p_myspace,0.))))
# @test !prod((get_x(old_a1) .== get_x(increment_x!(a1,myspace,p_myspace,0.))))
@test nancestors(increment_x!(a2,myspace,p_myspace,2.)) > 1
@test !isnothing(increment_x!(a4,myspace2,p_myspace2,2.))
@test !isnothing(increment_x!(a5,myspace2,p_myspace2,2.))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment