Commit eea8f623 by Victor

### 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 # 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.) # 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 # This constructor is used by default Agent(xhist::Array{U}) where {U <: Number} = Agent{StdAgent}(xhist) 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 # 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 # 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)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!