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 eea8f623 authored by Victor's avatar Victor
Browse files

many modifications provided

parent e9e7d0a5
......@@ -3,6 +3,7 @@ __precompile__()
module ABMEv
using Distributions,LinearAlgebra,Reexport,StatsBase
using LightGraphs
using UnPack
include("ABMEv_Agent.jl")
include("ABMEv_Space.jl")
......
abstract type StdAgent end
abstract type MixedAgent end
mutable struct Agent{T,U}
abstract type Ancestors{T} end
abstract type Rates{T} end
hasancestors(::Type{Ancestors{T}}) where {T} = T #not sure we need it
hasrates(::Type{Rates{T}}) where {T} = T # not sure we need it
abstract type AbstractAgent{A<:Ancestors,R<:Rates} end # tc for time contingency, fit for fitness coeff
AbstractAgentM = Union{Missing,AbstractAgent}
mutable struct Agent{A<:Ancestors,R<:Rates,T,U,V} <: AbstractAgent{A,R}
# history of traits for geotraits
x_history::Array{U}
pos::Array{T,1}
# birth time of ancestors
t_history::Array{Float64,1}
t_history::Array{U,1}
# death rate
d::Float64
d::V
#birth rate
b::Float64
b::V
end
# 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
pos = (pos...,tuple(zeros(Eltype[i],Dims[i])...))
else
pos = (pos...,zero(Eltype[i]))
end
end
Tuple{Eltype...},pos
end
function Agent(s::S;ancestors=false,rates=false) where {S <: AbstractSpacesTuple}
T,pos = initpos(s)
t = ancestors ? [Float64(.0)] : [nothing]
U = ancestors ? Float64 : Nothing
d = rates ? Float64(.0) : nothing
b = d
V = rates ? Float64 : Nothing
Agent{Ancestors{ancestors},Rates{rates},T,U,V}([pos],t,d,b)
end
# Constructors
# This constructor should be used when one wants to impose the type of the agent (e.g. Mixed)
Agent{T}(xhist::Array{U}) where {T,U} = Agent{T,U}(reshape(xhist,:,1),[0.],0.,1.)
# here pos is provided
function Agent(s::S, pos::P;ancestors=false,rates=false) where {P,S <: AbstractSpacesTuple}
T = Tuple{eltype.(s)...}
if !(T <: P)
throw(ArgumentError("Position provided does not match with underlying space"))
end
t = ancestors ? Float64(.0) : [nothing]
U = ancestors ? Float64 : Nothing
d = rates ? Float64(.0) : nothing
b = d
V = rates ? Float64 : Nothing
Agent{Ancestors{ancestors},Rates{rates},T,U,V}([pos],t,d,b)
end
# This constructor is used by default
Agent(xhist::Array{U}) where {U <: Number} = Agent{StdAgent}(xhist)
# TODO : implement pretty print
Agent() = Agent(Float64[],0.,0.,1.)
import Base.copy
copy(a::Agent{T,U}) where {T,U} = Agent{T,U}(copy(a.x_history),copy(a.t_history),copy(a.d),copy(a.b))
copy(a::Agent{A,R,T,U,V}) where {A,R,T,U,V} = Agent{A,R,T,U,V}(copy(a.pos),copy(a.t_history),copy(a.d),copy(a.b))
copy(m::Missing) = missing
copy(n::Nothing) = nothing
#####################
###Agent accessors###
......@@ -32,14 +70,14 @@ copy(m::Missing) = missing
get_x(a::Agent)
Returns trait i of the agent
"""
get_x(a::Agent) = a.x_history[:,end]
get_x(a::AbstractAgent) = a.x_history[end]
"""
function get_geo(a::Agent{U,T},t::Number) where {U,T}
Returns geotrait of agent `a` at time `t`
"""
function get_geo(a::Agent{U,T},t::Number) where {U,T}
tarray = vcat(a.t_history[2:end],convert(T,t))
function get_geo(a::Agent{Ancestors{true},R,T,U,V},t::Number) where {R,T,U,V}
tarray = vcat(a.t_history[2:end],convert(U,t))
tarray .-= a.t_history
return sum(get_xhist(a,1) .* tarray)
end
......@@ -50,13 +88,13 @@ Returns trait `i` of the agent.
Geotrait corresponds to dimension `i=0`.
"""
get_x(a::Agent,t::Number,i::Integer) = i > 0 ? a.x_history[Int(i),end] : get_geo(a,t)
get_x(a::Agent,i::Integer) = a.x_history[Int(i),end]
get_x(a::AbstractAgent,t::Number,i::Integer) = i > 0 ? a.x_history[end][Int(i)] : get_geo(a,t)
get_x(a::AbstractAgent,i::Integer) = a.x_history[end][Int(i)]
"""
get_t(a::Agent) = a.t_history[end]
Get time when agent born.
"""
get_t(a::Agent) = a.t_history[end]
get_t(a::AbstractAgent) = a.t_history[end]
get_xhist(a::Agent,i::Number) = a.x_history[Int(i),:]
get_xhist(a::Agent) = a.x_history
get_thist(a::Agent) = a.t_history
......@@ -102,42 +140,6 @@ function get_xarray(world::Array{T,1},t::Number,geotrait::Bool=false) where {T <
return xarray
end
# """
# get_xhist(world::Vector{Agent},geotrait = false)
# Returns the trait history of every agents of world in the form of an 3 dimensional array,
# with
# - first dimension as the agent index
# - second as time index
# - third as trait index
# If geotrait = true, then a last trait dimension is added, corresponding to geotrait.
# Note that because number of ancestors are different between agents, we return an array which size corresponds to the minimum of agents ancestors,
# and return the last generations, dropping the youngest ones
# """
# function get_xhist(world::Vector{T}) where {T <: Agent}
# hist = minimum(get_nancestors.(world))
# ntraits = get_dim(first(world));
# xhist = zeros(length(world), hist, ntraits + geotrait);
# for (i,a) in enumerate(world)
# xhist[i,:,1:end-geotrait] = get_xhist(a)[:,end-hist+1:end]';
# end
# return xhist
# end
# TODO: This method broken, when one ask for the geotraits
# function get_xhist(world::Vector{T},t::Number,geotrait = false) where {T <: Agent}
# hist = minimum(get_nancestors.(world))
# ntraits = get_dim(first(world));
# xhist = zeros(length(world), hist, ntraits + geotrait);
# for (i,a) in enumerate(world)
# xhist[i,:,1:end-geotrait] = get_xhist(a)[:,end-hist+1:end]';
# if geotrait
# xhist[i,:,ntraits+geotrait] = cumsum(get_xhist(a,1))[end-hist+1:end]
# end
# end
# return xhist
# end
function world2df(world::Array{T,1},geotrait=false) where {T <: Agent}
xx = get_xarray(world)
dfw = DataFrame(:f => get_fitness.(world))
......
......@@ -13,21 +13,21 @@ end
function update_afterbirth_std!(world,idx_offspring,p::Dict) where T
# updating competition only the two columns corresponding to agent idx
α = p["alpha"];K=p["K"];
@unpack d,b = p
x_offspring = get_x(world[idx_offspring])
for a in skipmissing(world)
a.d += α(get_x(a),x_offspring)
a.d += d(get_x(a),x_offspring)
end
# Now updating new agent
world[idx_offspring].d = sum(α.(get_x.(skipmissing(world)),Ref(x_offspring))) - α(x_offspring,x_offspring)
world[idx_offspring].b = K(x_offspring)
world[idx_offspring].d = sum(d.(get_x.(skipmissing(world)),Ref(x_offspring))) - d(x_offspring,x_offspring)
world[idx_offspring].b = b(x_offspring)
end
function update_afterdeath_std!(world,x_death,p::Dict) where T
α = p["alpha"]
@unpack d
# updating death rate only the two columns corresponding to agent idx
for a in skipmissing(world)
a.d -= α(get_x(a),x_death)
a.d -= d(get_x(a),x_death)
end
end
......
using LightGraphs
"""
abstract type AbstractSpace{Dim,T,F} end
`Dim` is the dimension of the space, `T` is the element type, `ife` is a bool which is `true`
when space is finite
"""
abstract type IsFinite{T} end
Base.isfinite(::Type{IsFinite{T}}) where {T} = T
#ife stands for is finite
abstract type AbstractSpace{Dim,T,I} end
AbstractSpacesTuple = Tuple{Vararg{AbstractSpace}}
Base.ndims(x::AbstractSpace{Dim,T,I}) where {Dim,T,I} = Dim
Base.isfinite(x::AbstractSpace{Dim,T,I}) where {Dim,T,F,I} = isfinite(I) #not sure we need this
Base.eltype(::AbstractSpace{Dim,T,I}) where {Dim,T,I} = T
SpaceType=Union{Nothing, AbstractSpace} # not sure what is this used for
abstract type AbstractDiscreteSpace{Dim,T,I} <: AbstractSpace{Dim,T,I} end
abstract type AbstractGraphSpace{T} <: AbstractDiscreteSpace{1,T,IsFinite{true}} end
struct GraphSpace{T} <: AbstractGraphSpace{T}
g::AbstractGraph{T}
end
struct DiscreteSegment{T} <: AbstractDiscreteSpace{1,T,IsFinite{true}}
s::T
e::T
end
struct Real1DSpace{T} <: AbstractSpace{1,T,IsFinite{false}} end
"""
function increment_x!(a::Agent{StdAgent,U},t::U,p::Dict) where U
......
struct AgentBasedModel{A, S, F, P}
agents::A
space::S
scheduler::F
properties::P
end
function AgentBasedModel(a::Vector{A},s::S) where {A<:AbstractAgentM, S<:AbstractSpacesTuple}
AgentBasedModel(a,s,nothing, nothing)
end
function AgentBasedModel(N <:Int, Max <: Int ,s::S) where {A<:AbstractAgentM, S<:AbstractSpacesTuple}
# To be implemented
end
......@@ -47,11 +47,10 @@ It should correspond to an integer, as it indexes the column to plot
xarray = get_x.(world_sm,tspan_ar[:],trait)
seriestype := :scatter
markercolor := eth_grad_small[d_i ./ maximum(d_i)]
# markercolor := :blue
markerstrokewidth := 0
seriesalpha :=1.
xlabel := "time"
ylabel := "trait value"
# xlabel := "time"
# ylabel := "trait value"
label := ""
grid := false
# markersize := 2.3/1000*size(world_sm,1)
......@@ -88,7 +87,7 @@ It should correspond to an integer, as it indexes the column to plot
yaxis := "trait value"
label := ""
grid := false
marker := (:rect,20,1.)
# marker := (:rect,20,1.)
x1_array[:],xt_array[:]
end
end
......
using LightGraphs
mysegment = DiscreteSegment(1,10)
mygraph = GraphSpace(SimpleGraph(10,10))
myline = Real1DSpace{Float64}()
myspace = (mysegment,mygraph,myline)
@test isfinite(mysegment) true
@test isfinite(mygraph) true
@test isfinite(myline) false
a1 = Agent(myspace)
a2 = Agent(myspace,ancestors = true)
a3 = Agent(myspace,(1,1,1.))
a4 = Agent(myspace,(1,1,1.),rates=true)
typeof(a1) <: AbstractAgent
agents = [a1,a2,a3,a4]
agentsm = [a1,a2,a3,a4,missing]
AgentBasedModel(agents,myspace)
AgentBasedModel(agentsm,myspace)
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