Skip to content

Commit

Permalink
🚧 Nutrients.Concentration upgraded + feature expansion into dense mat…
Browse files Browse the repository at this point in the history
…rix.
  • Loading branch information
iago-lito committed Nov 8, 2024
1 parent 58b647f commit 34420f3
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 127 deletions.
28 changes: 27 additions & 1 deletion src/GraphDataInputs/check.jl
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ function check_list_refs(
# If edges space for source and target are the same, allow elision.
if list isa UAdjacency
(space isa Int64 || space isa Index) && (space = (space, space))
allow_missing || argerr("Dense adjacency lists checking is unimplemented yet.")
end

# Possibly infer the (integer) space from a template if none is given.
Expand Down Expand Up @@ -339,20 +338,47 @@ end
#-------------------------------------------------------------------------------------------
# Checking missing refs, either against a template or against the whole space if none.

# (ASSUMING all refs are valid)
miss_refs(map::UMap, n::Int64, ::Nothing) = length(map) < n
miss_refs(map::UMap, x::Index, ::Nothing) = length(map) < length(x)
function miss_refs(map::UMap, _, template::AbstractSparseVector)
nz, _ = findnz(template)
length(map) < length(nz)
end

function miss_refs(adj::UAdjacency, (m, n)::Tuple{Int64,Int64}, ::Nothing)
length(adj) < m && return true
for (_, sub) in adj
length(sub) < n && return true
end
false
end
function miss_refs(adj::UAdjacency, (x, y)::Tuple{Index,Index}, ::Nothing)
(m, n) = length.((x, y))
miss_refs(adj, (m, n), nothing)
end
function miss_refs(adj::UAdjacency, _, template::AbstractSparseMatrix)
nz, _ = findnz(template)
sum(length(sub) for (_, sub) in adj) < length(nz)
end

needles(n::Int64, ::Nothing) = ((i,) for i in 1:n)
needles(x::Index, ::Nothing) = ((k,) for k in keys(x))
needles((m, n)::Tuple{Int64,Int64}, ::Nothing) = ((i, j) for i in 1:m, j in 1:n)
needles((x, y)::Tuple{Index,Index}, ::Nothing) = ((p, q) for p in keys(x), q in keys(y))
needles(::Int64, template::AbstractSparseVector) = ((i,) for i in findnz(template)[1])
needles(::Tuple{Int64,Int64}, template::AbstractSparseMatrix) =
(access for access in zip(findnz(template)[1:2]...))
function needles(x::Index, template::AbstractSparseVector)
revmap = Dict(i => n for (n, i) in x)
sort!(collect((revmap[i],) for i in findnz(template)[1]))
end
function needles((x, y)::Tuple{Index,Index}, template::AbstractSparseMatrix)
xrev = Dict(i => m for (m, i) in x)
yrev = Dict(j => n for (n, j) in y)
res = collect((xrev[i], yrev[j]) for (i, j) in zip(findnz(template)[1:2]...))
sort!(res)
end

check_missing_refs(list, space, template, name, item) =
if miss_refs(list, space, template)
Expand Down
58 changes: 57 additions & 1 deletion src/GraphDataInputs/expand.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ function to_dense_vector(map::AbstractMap{Int64,T}) where {T}
end
res
end

function to_dense_vector(map::AbstractMap{Symbol,T}, index) where {T}
res = Vector{T}(undef, length(map))
for (key, value) in map
Expand All @@ -155,6 +156,7 @@ function to_dense_vector(map::AbstractMap{Symbol,T}, index) where {T}
end
res
end

export to_dense_vector

# Assuming all indices are valid.
Expand All @@ -165,6 +167,7 @@ function to_sparse_vector(map::AbstractMap{Int64,T}, n::Int64) where {T}
end
res
end

function to_sparse_vector(map::AbstractMap{Symbol,T}, index) where {T}
res = spzeros(T, length(index))
for (key, value) in map
Expand All @@ -173,13 +176,15 @@ function to_sparse_vector(map::AbstractMap{Symbol,T}, index) where {T}
end
res
end

function to_sparse_vector(map::AbstractBinMap{Int64}, n::Int64)
res = spzeros(Bool, n)
for i in map
res[i] = true
end
res
end

function to_sparse_vector(map::AbstractBinMap{Symbol}, index)
res = spzeros(Bool, length(index))
for key in map
Expand All @@ -188,6 +193,7 @@ function to_sparse_vector(map::AbstractBinMap{Symbol}, index)
end
res
end

export to_sparse_vector

# Accommodate slight signature variations in case an index is always used.
Expand All @@ -202,9 +208,34 @@ to_sparse_vector(map::AbstractBinMap{Int64}, index) = to_sparse_vector(map, leng

#-------------------------------------------------------------------------------------------
# Assuming the input is a correctly checked adjacency list,
# expand to a sparse matrix.
# expand to a dense or sparse matrix.
# This may require a label-to-indices mapping referred to as "index" (yup, confusing).

# Assuming all indices have been given.
function to_dense_matrix(adj::AbstractAdjacency{Int64,T}) where {T}
res = Matrix{T}(undef, (length(adj), length(last(first(adj)))))
for (i, list) in adj
for (j, value) in list
res[i, j] = value
end
end
res
end

function to_dense_matrix(adj::AbstractAdjacency{Symbol,T}, i_index, j_index) where {T}
res = Matrix{T}(undef, (length(adj), length(last(first(adj)))))
for (ikey, list) in adj
for (jkey, value) in list
i = i_index[ikey]
j = j_index[jkey]
res[i, j] = value
end
end
res
end

export to_dense_matrix

function to_sparse_matrix(adj::AbstractAdjacency{Int64,T}, n::Int64, m::Int64) where {T}
res = spzeros(T, (n, m))
for (i, list) in adj
Expand All @@ -214,6 +245,7 @@ function to_sparse_matrix(adj::AbstractAdjacency{Int64,T}, n::Int64, m::Int64) w
end
res
end

function to_sparse_matrix(adj::AbstractAdjacency{Symbol,T}, i_index, j_index) where {T}
res = spzeros(T, (length(i_index), length(j_index)))
for (ikey, list) in adj
Expand All @@ -225,6 +257,7 @@ function to_sparse_matrix(adj::AbstractAdjacency{Symbol,T}, i_index, j_index) wh
end
res
end

function to_sparse_matrix(adj::AbstractBinAdjacency{Int64}, n::Int64, m::Int64)
res = spzeros(Bool, (n, m))
for (i, list) in adj
Expand All @@ -234,6 +267,7 @@ function to_sparse_matrix(adj::AbstractBinAdjacency{Int64}, n::Int64, m::Int64)
end
res
end

function to_sparse_matrix(adj::AbstractBinAdjacency{Symbol}, i_index, j_index)
res = spzeros(Bool, (length(i_index), length(j_index)))
for (ikey, list) in adj
Expand All @@ -245,9 +279,21 @@ function to_sparse_matrix(adj::AbstractBinAdjacency{Symbol}, i_index, j_index)
end
res
end

export to_sparse_matrix

# Accommodate slight signature variations in case an index is always used.
function to_dense_matrix(adj::AbstractAdjacency{Int64,T}, i_index, j_index) where {T}
m, i = length.((adj, i_index))
n, j = length.((last(first(adj)), j_index))
m == i || argerr(
"Cannot produce a dense matrix with $m outer values and $i outer references.",
)
n == j || argerr(
"Cannot produce a dense matrix with $n inner values and $j inner references.",
)
to_dense_matrix(adj)
end
to_sparse_matrix(map::AbstractAdjacency{Int64,T}, i_index, j_index) where {T} =
to_sparse_matrix(map, length(i_index), length(j_index))
to_sparse_matrix(map::AbstractBinAdjacency{Int64}, i_index, j_index) =
Expand Down Expand Up @@ -335,6 +381,16 @@ macro to_sparse_vector_if_map(var::Symbol, index)
end
export @to_sparse_vector_if_map

macro to_dense_matrix_if_adjacency(var::Symbol, i_index, j_index)
var, i_index, j_index = esc.((var, i_index, j_index))
quote
$var isa
Union{AbstractDict{<:Any,<:AbstractDict},AbstractDict{<:Any,<:AbstractSet}} &&
($var = to_dense_matrix($var, $i_index, $j_index))
end
end
export @to_dense_matrix_if_adjacency

macro to_sparse_matrix_if_adjacency(var::Symbol, i_index, j_index)
var, i_index, j_index = esc.((var, i_index, j_index))
quote
Expand Down
21 changes: 13 additions & 8 deletions src/components/display.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# Display matrix nonzero values ranges.
function showrange(io::IO, m::SparseMatrix)
# Display values ranges.
function showrange(io::IO, values)
min, max = extrema(values)
if min == max
print(io, "$min")
else
print(io, "$min to $max")
end
end

# Restrict to nonzero values.
function showrange(io::IO, m::AbstractSparseArray)
nz = findnz(m)[3]
if isempty(nz)
print(io, "·")
else
min, max = extrema(nz)
if min == max
print(io, "$min")
else
print(io, "$min to $max")
end
showrange(io, nz)
end
end
42 changes: 21 additions & 21 deletions src/components/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,29 +82,29 @@ include("./foodweb.jl")
# Biorates and other values parametrizing the ODE.
# (typical example 'nodes' data)
include("./body_mass.jl")
# include("./metabolic_class.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")
Expand Down
Loading

0 comments on commit 34420f3

Please sign in to comment.