Skip to content

Commit

Permalink
🔧 Bugs with int-indexed map / adjacency inputs.
Browse files Browse the repository at this point in the history
  • Loading branch information
iago-lito committed Nov 18, 2024
1 parent 0d88dca commit f5591a0
Show file tree
Hide file tree
Showing 48 changed files with 373 additions and 185 deletions.
22 changes: 20 additions & 2 deletions src/GraphDataInputs/check.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,24 @@ export @check_template
# Int64, (Int64, Int64), Index or (Index, Index).
# So the space is *also* an index to convert labels to integers.

#-------------------------------------------------------------------------------------------
# Check that the given value is a valid (dense) {ref -> indice} index.
function check_index(index::AbstractDict{Symbol,Int})
n = length(index)
notfound = OrderedSet(1:n)
for (ref, i) in index
1 <= i <= n || argerr("Invalid index: received $n reference$(n > 1 ? "s" : "") \
but one of them is [$i] ($(repr(ref))).")
if i in notfound
pop!(notfound, i)
end
end
for i in notfound
argerr("Invalid index: no reference given for index [$i].")
end
end
export check_index

#-------------------------------------------------------------------------------------------
# Check references against a general reference space.

Expand Down Expand Up @@ -218,8 +236,8 @@ function check_list_refs(
end
if !(isnothing(template) || isnothing(space))
a, b = size(template), space
(a == b || a == (b,)) ||
argerr("Inconsistent template size ($a) vs. references space ($b).")
(a == b || a == (b,) || a == (b, b)) ||
argerr("Inconsistent template size vs. references space: $a vs. $b.")
end
end

Expand Down
10 changes: 10 additions & 0 deletions src/GraphDataInputs/expand.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ end

export to_dense_vector

# Assuming input is a dense index.
function to_dense_refs(index::AbstractDict{Symbol,Int})
refs = Vector{Symbol}(undef, length(index))
for (ref, i) in index
refs[i] = ref
end
refs
end
export to_dense_refs

# Assuming all indices are valid.
function to_sparse_vector(map::AbstractMap{Int64,T}, n::Int64) where {T}
res = spzeros(T, n)
Expand Down
2 changes: 1 addition & 1 deletion src/components/body_mass.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mutable struct Map <: Blueprint
species::Brought(Species)
Map(M, sp = _Species) = new(@tographdata(M, Map{Float64}), sp)
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.M))
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refspace(bp.M))
@blueprint Map "[species => mass] map"
export Map

Expand Down
4 changes: 1 addition & 3 deletions src/components/carrying_capacity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.K, @ref raw.producers.mas
#-------------------------------------------------------------------------------------------
mutable struct Map <: Blueprint
K::@GraphData Map{Float64}
species::Brought(Species)
Map(K, sp = _Species) = new(@tographdata(K, Map{Float64}), sp)
Map(K) = new(@tographdata(K, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.K))
@blueprint Map "[species => carrying capacity] map"
export Map

Expand Down
4 changes: 1 addition & 3 deletions src/components/consumption_rate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.alpha, @ref raw.consumers
#-------------------------------------------------------------------------------------------
mutable struct Map <: Blueprint
alpha::@GraphData Map{Float64}
species::Brought(Species)
Map(alpha, sp = _Species) = new(@tographdata(alpha, Map{Float64}), sp)
Map(alpha) = new(@tographdata(alpha, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.alpha))
@blueprint Map "[species => consumption rate] map"
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/efficiency.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,5 @@ end
# Just display range.
function F.shortline(io::IO, model::Model, ::_Efficiency)
print(io, "Efficiency: ")
showrange(model._e)
showrange(io, model._e)
end
26 changes: 9 additions & 17 deletions src/components/foodweb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,7 @@ mutable struct Adjacency <: Blueprint
end

# Infer number or names of species from the lists.
function F.implied_blueprint_for(bp::Adjacency, ::_Species)
(; A) = bp
if A isa BinAdjacency{Int64}
S = refspace(A)
Species(S)
elseif A isa BinAdjacency{Symbol}
names = refs(A)
Species(names)
else
throw("unreachable: invalid adjacency list type")
end
end
F.implied_blueprint_for(bp::Adjacency, ::_Species) = Species(refspace(bp.A))

@blueprint Adjacency "adjacency list of trophic links"
export Adjacency
Expand Down Expand Up @@ -330,11 +319,14 @@ function F.shortline(io::IO, model::Model, ::_Foodweb)
t = model.tops.number
n(n) = n > 0 ? "$n" : "no"
s(n) = n > 1 ? "s" : ""
print(io, "Foodweb: $(n(l)) link$(s(l)), \
$(n(p)) producer$(s(p)), \
$(n(c)) consumer$(s(c)), \
$(n(r)) prey$(s(r)), \
$(n(t)) top$(s(t)).")
print(
io,
"Foodweb: $(n(l)) link$(s(l)), \
$(n(p)) producer$(s(p)), \
$(n(c)) consumer$(s(c)), \
$(n(r)) prey$(s(r)), \
$(n(t)) top$(s(t)).",
)
end

# ==========================================================================================
Expand Down
4 changes: 1 addition & 3 deletions src/components/growth_rate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.r, @ref raw.producers.mas

mutable struct Map <: Blueprint
r::@GraphData Map{Float64}
species::Brought(Species)
Map(r, sp = _Species) = new(@tographdata(r, Map{Float64}), sp)
Map(r) = new(@tographdata(r, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.r))
@blueprint Map "[species => growth rate] map"
export Map

Expand Down
4 changes: 1 addition & 3 deletions src/components/half_saturation_density.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.B0, @ref raw.consumers.ma
#-------------------------------------------------------------------------------------------
mutable struct Map <: Blueprint
B0::@GraphData Map{Float64}
species::Brought(Species)
Map(B0, sp = _Species) = new(@tographdata(B0, Map{Float64}), sp)
Map(B0) = new(@tographdata(B0, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.B0))
@blueprint Map "[species => half-saturation density] map"
export Map

Expand Down
4 changes: 1 addition & 3 deletions src/components/intraspecific_interference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.c, @ref raw.consumers.mas
#-------------------------------------------------------------------------------------------
mutable struct Map <: Blueprint
c::@GraphData Map{Float64}
species::Brought(Species)
Map(c, sp = _Species) = new(@tographdata(c, Map{Float64}), sp)
Map(c) = new(@tographdata(c, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.c))
@blueprint Map "[species => intra-specific interference] map"
export Map

Expand Down
50 changes: 25 additions & 25 deletions src/components/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,34 +81,34 @@ include("./foodweb.jl")

# # Biorates and other values parametrizing the ODE.
# # (typical example 'nodes' data)
# include("./body_mass.jl")
# include("./metabolic_class.jl")
include("./body_mass.jl")
include("./metabolic_class.jl")

# # Useful global values to calculate other biorates.
# # (typical example 'graph' data)
# include("./temperature.jl")
# Useful global values to calculate other biorates.
# (typical example 'graph' data)
include("./temperature.jl")

# # Replicated/adapted from the above.
# # TODO: factorize subsequent repetitions there.
# # Easier once the Internals become more consistent?
# include("./hill_exponent.jl") # <- First, good example of 'graph' component. Read first.
# include("./growth_rate.jl") # <- First, good example of 'node' component. Read first.
# include("./efficiency.jl") # <- First, good example of 'edges' component. Read first.
# include("./carrying_capacity.jl")
# include("./mortality.jl")
# include("./metabolism.jl")
# include("./maximum_consumption.jl")
# include("./producers_competition.jl")
# include("./consumers_preferences.jl")
# include("./handling_time.jl")
# include("./attack_rate.jl")
# include("./half_saturation_density.jl")
# include("./intraspecific_interference.jl")
# include("./consumption_rate.jl")
# Replicated/adapted from the above.
# TODO: factorize subsequent repetitions there.
# Easier once the Internals become more consistent?
include("./hill_exponent.jl") # <- First, good example of 'graph' component. Read first.
include("./growth_rate.jl") # <- First, good example of 'node' component. Read first.
include("./efficiency.jl") # <- First, good example of 'edges' component. Read first.
include("./carrying_capacity.jl")
include("./mortality.jl")
include("./metabolism.jl")
include("./maximum_consumption.jl")
include("./producers_competition.jl")
include("./consumers_preferences.jl")
include("./handling_time.jl")
include("./attack_rate.jl")
include("./half_saturation_density.jl")
include("./intraspecific_interference.jl")
include("./consumption_rate.jl")

# # Namespace nutrients data.
# include("./nutrients/main.jl")
# export Nutrients
# Namespace nutrients data.
include("./nutrients/main.jl")
export Nutrients

include("./nontrophic_layers/main.jl")
# using .NontrophicInteractions
Expand Down
4 changes: 1 addition & 3 deletions src/components/maximum_consumption.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ F.expand!(raw, bp::Flat) = expand!(raw, to_template(bp.y, @ref raw.consumers.mas
#-------------------------------------------------------------------------------------------
mutable struct Map <: Blueprint
y::@GraphData Map{Float64}
species::Brought(Species)
Map(y, sp = _Species) = new(@tographdata(y, Map{Float64}), sp)
Map(y) = new(@tographdata(y, Map{Float64}))
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.y))
@blueprint Map "[species => maximum consumption] map"
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/metabolic_class.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ mutable struct Map <: Blueprint
species::Brought(Species)
Map(M, sp = _Species) = new(@tographdata(M, Map{Symbol}), sp)
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.classes))
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refspace(bp.classes))
@blueprint Map "[species => class] map" depends(Foodweb)
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/metabolism.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mutable struct Map <: Blueprint
species::Brought(Species)
Map(x, sp = _Species) = new(@tographdata(x, Map{Float64}), sp)
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.x))
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refspace(bp.x))
@blueprint Map "[species => metabolism] map"
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/mortality.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mutable struct Map <: Blueprint
species::Brought(Species)
Map(d, sp = _Species) = new(@tographdata(d, Map{Float64}), sp)
end
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refs(bp.d))
F.implied_blueprint_for(bp::Map, ::_Species) = Species(refspace(bp.d))
@blueprint Map "[species => mortality] map"
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/nontrophic_layers/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ multiplex_defaults = MultiplexParametersDict(;
),
)

include("./competition.jl")
# include("./competition.jl")
# include("./facilitation.jl")
# include("./interference.jl")
# include("./refuge.jl")
Expand Down
2 changes: 1 addition & 1 deletion src/components/nontrophic_layers/nti_modules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ if (false)
using .KwargsHelpers
using .MultiplexApi: MultiplexParametersDict, InteractionDict, interactions_names
using .AliasingDicts: expand
local (competition,)
local ( competition, )
end

11 changes: 2 additions & 9 deletions src/components/nutrients/concentration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,8 @@ mutable struct Adjacency <: Blueprint
nutrients::Brought(Nutrients.Nodes)
Adjacency(c, nt = Nutrients._Nodes) = new(@tographdata(c, Adjacency{Float64}), nt)
end
function F.implied_blueprint_for(bp::Adjacency, ::Nutrients._Nodes)
# HERE: this should've been done for every such adjacency implication, right?
space = refspace_inner(bp.c)
if space isa Integer
Nutrients.Nodes(space)
else
Nutrients.Nodes(keys(space))
end
end
F.implied_blueprint_for(bp::Adjacency, ::Nutrients._Nodes) =
Nutrients.Nodes(refspace_inner(bp.c))
@blueprint Adjacency "[producer => [nutrient => concentration]] map"
export Adjacency

Expand Down
11 changes: 2 additions & 9 deletions src/components/nutrients/half_saturation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,8 @@ mutable struct Adjacency <: Blueprint
nutrients::Brought(Nutrients.Nodes)
Adjacency(h, nt = Nutrients._Nodes) = new(@tographdata(h, Adjacency{Float64}), nt)
end
function F.implied_blueprint_for(bp::Adjacency, ::Nutrients._Nodes)
# HERE: this should've been done for every such adjacency implication, right?
space = refspace_inner(bp.h)
if space isa Integer
Nutrients.Nodes(space)
else
Nutrients.Nodes(keys(space))
end
end
F.implied_blueprint_for(bp::Adjacency, ::Nutrients._Nodes) =
Nutrients.Nodes(refspace_inner(bp.h))
@blueprint Adjacency "[producer => [nutrient => half-saturation]] map"
export Adjacency

Expand Down
6 changes: 6 additions & 0 deletions src/components/nutrients/nodes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ mutable struct Names <: Blueprint
Names(names) = new(Symbol.(names))
Names(names...) = new(Symbol.(collect(names)))

# From an index (useful when implied).
function Names(index::AbstractDict{Symbol,Int})
check_index(index)
new(to_dense_refs(index))
end

# Don't own data if useful to user.
Names(names::Vector{Symbol}) = new(names)
end
Expand Down
2 changes: 1 addition & 1 deletion src/components/nutrients/supply.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mutable struct Map <: Blueprint
nutrients::Brought(Nutrients.Nodes)
Map(s, nt = Nutrients._Nodes) = new(@tographdata(s, Map{Float64}), nt)
end
F.implied_blueprint_for(bp::Map, ::Nutrients._Nodes) = Nutrients.Nodes(refs(bp.s))
F.implied_blueprint_for(bp::Map, ::Nutrients._Nodes) = Nutrients.Nodes(refspace(bp.s))
@blueprint Map "[nutrient => supply] map"
export Map

Expand Down
2 changes: 1 addition & 1 deletion src/components/nutrients/turnover.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mutable struct Map <: Blueprint
nutrients::Brought(Nutrients.Nodes)
Map(t, nt = Nutrients._Nodes) = new(@tographdata(t, Map{Float64}), nt)
end
F.implied_blueprint_for(bp::Map, ::Nutrients._Nodes) = Nutrients.Nodes(refs(bp.t))
F.implied_blueprint_for(bp::Map, ::Nutrients._Nodes) = Nutrients.Nodes(refspace(bp.t))
@blueprint Map "[nutrient => turnover] map"
export Map

Expand Down
7 changes: 7 additions & 0 deletions src/components/species.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# Name + '_'-suffix is the module defining blueprints for this component.
module Species_
include("blueprint_modules.jl")
include("blueprint_modules_identifiers.jl")

#-------------------------------------------------------------------------------------------
# Construct from a given set of names.
Expand All @@ -23,6 +24,12 @@ mutable struct Names <: Blueprint
Names(names) = new(Symbol.(names))
Names(names...) = new(Symbol.(collect(names)))

# From an index (useful when implied).
function Names(index::AbstractDict{Symbol,Int})
check_index(index)
new(to_dense_refs(index))
end

# Don't own data if useful to user.
Names(names::Vector{Symbol}) = new(names)
end
Expand Down
12 changes: 12 additions & 0 deletions test/graph_data_inputs/check.jl
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,18 @@
v = gc((@GraphData K{Float64}), [1 => 5, 2 => 8])
@test @check_list_refs v :item part_index

# Check index.
check_index(Dict([:a => 1, :b => 2, :c => 3]))
@argfails(
check_index(Dict([:a => 1, :c => 3])),
"Invalid index: received 2 references but one of them is [3] (:c)."
)
@argfails(
check_index(Dict([:a => 1, :c => 1])),
"Invalid index: no reference given for index [2]."
)


#---------------------------------------------------------------------------------------
# Adjacency lists.

Expand Down
Loading

0 comments on commit f5591a0

Please sign in to comment.