From 597d32a078a343fa8074e71ea35cd7bd9aa64b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20W=C3=BCrfel?= Date: Wed, 23 Oct 2024 16:23:53 +0200 Subject: [PATCH] improve constructor for single edges/vertices given --- src/NetworkDynamics.jl | 2 +- src/construction.jl | 66 ++++++++++++++++++++++++++-------------- src/network_structure.jl | 13 +++++--- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/NetworkDynamics.jl b/src/NetworkDynamics.jl index bc52cf56..d5e2df16 100644 --- a/src/NetworkDynamics.jl +++ b/src/NetworkDynamics.jl @@ -1,7 +1,7 @@ module NetworkDynamics using Graphs: Graphs, AbstractGraph, SimpleEdge, edges, vertices, ne, nv, SimpleGraph, SimpleDiGraph, add_edge!, has_edge -using TimerOutputs: @timeit_debug, reset_timer! +using TimerOutputs: TimerOutputs, @timeit_debug, @timeit using ArgCheck: @argcheck using PreallocationTools: PreallocationTools, DiffCache, get_tmp diff --git a/src/construction.jl b/src/construction.jl index 9fcc7425..4b36a608 100644 --- a/src/construction.jl +++ b/src/construction.jl @@ -8,12 +8,14 @@ function Network(g::AbstractGraph, check_graphelement=true, dealias=false, verbose=false) - reset_timer!() + # TimerOutputs.reset_timer!() @timeit_debug "Construct Network" begin # collect all vertex/edgf to vector + all_same_v = vertexf isa VertexFunction + all_same_e = edgef isa EdgeFunction maybecopy = dealias ? copy : identity - _vertexf = vertexf isa Vector ? vertexf : [maybecopy(vertexf) for _ in vertices(g)] - _edgef = edgef isa Vector ? edgef : [maybecopy(edgef) for _ in edges(g)] + _vertexf = all_same_v ? [maybecopy(vertexf) for _ in vertices(g)] : vertexf + _edgef = all_same_e ? [maybecopy(edgef) for _ in edges(g)] : edgef @argcheck _vertexf isa Vector{<:VertexFunction} "Expected VertexFuncions, got $(eltype(_vertexf))" @argcheck _edgef isa Vector{<:EdgeFunction} "Expected EdgeFuncions, got $(eltype(_vertexf))" @@ -22,10 +24,10 @@ function Network(g::AbstractGraph, # check if components alias eachother copy if necessary # allready dealiase if provided as single functions - if dealias && vertexf isa Vector + if dealias && !all_same_v dealias!(_vertexf) end - if dealias && edgef isa Vector + if dealias && !all_same_e dealias!(_edgef) end @@ -52,27 +54,45 @@ function Network(g::AbstractGraph, end # create index manager - im = IndexManager(g, dynstates, edepth, vdepth, _vertexf, _edgef; mightalias=!dealias) + @timeit_debug "Construct Index manager" begin + valias = dealias ? :none : (all_same_v ? :all : :some) + ealias = dealias ? :none : (all_same_e ? :all : :some) + im = IndexManager(g, dynstates, edepth, vdepth, _vertexf, _edgef; valias, ealias) + end # check graph_element metadata and attach if necessary - for (i, vf) in pairs(_vertexf) - if check_graphelement && has_graphelement(vf) - if get_graphelement(vf) != i - @warn "Vertex function $(vf.name) is placed at node index $i bus has \ - `graphelement` $(get_graphelement(vf)) stored in metadata. \ - The wrong data will be ignored! Use `check_graphelement=false` tu supress this warning." + if check_graphelement + @timeit_debug "Check graph element" begin + if !all_same_v + for (i, vf) in pairs(_vertexf) + if has_graphelement(vf) + if get_graphelement(vf) != i + @warn "Vertex function $(vf.name) is placed at node index $i bus has \ + `graphelement` $(get_graphelement(vf)) stored in metadata. \ + The wrong data will be ignored! Use `check_graphelement=false` tu supress this warning." + end + end + end + elseif has_graphelement(vertexf) + @warn "Provided vertex function has assigned `graphelement` metadata. \ + but is used at every vertex. The `graphelement` will be ignored." end - end - end - for (iteredge, ef) in zip(im.edgevec, _edgef) - if check_graphelement && has_graphelement(ef) - ge = get_graphelement(ef) - src = get(im.unique_vnames, ge.src, ge.src) - dst = get(im.unique_vnames, ge.dst, ge.dst) - if iteredge.src != src || iteredge.dst != dst - @warn "Edge function $(ef.name) at $(iteredge.src) => $(iteredge.dst) has wrong `:graphelement` $src => $dst). \ - The wrong data will be ignored! Use `check_graphelement=false` tu supress this warning." + if !all_same_e + for (iteredge, ef) in zip(im.edgevec, _edgef) + if has_graphelement(ef) + ge = get_graphelement(ef) + src = get(im.unique_vnames, ge.src, ge.src) + dst = get(im.unique_vnames, ge.dst, ge.dst) + if iteredge.src != src || iteredge.dst != dst + @warn "Edge function $(ef.name) at $(iteredge.src) => $(iteredge.dst) has wrong `:graphelement` $src => $dst). \ + The wrong data will be ignored! Use `check_graphelement=false` tu supress this warning." + end + end + end + elseif has_graphelement(edgef) + @warn "Provided edge function has assigned `graphelement` metadata. \ + but is used for all edges. The `graphelement` will be ignored." end end end @@ -140,7 +160,7 @@ function Network(g::AbstractGraph, ) end - # print_timer() + # TimerOutputs.print_timer() return nw end diff --git a/src/network_structure.jl b/src/network_structure.jl index 2db7e5dd..f5e310d1 100644 --- a/src/network_structure.jl +++ b/src/network_structure.jl @@ -26,9 +26,9 @@ mutable struct IndexManager{G} aliased_edgefs::IdDict{EdgeFunction, @NamedTuple{idxs::Vector{Int}, hash::UInt}} unique_vnames::Dict{Symbol,Int} unique_enames::Dict{Symbol,Int} - function IndexManager(g, dyn_states, edepth, vdepth, vertexf, edgef; mightalias) - aliased_vertexf_hashes = _aliased_hashes(VertexFunction, vertexf, mightalias) - aliased_edgef_hashes = _aliased_hashes(EdgeFunction, edgef, mightalias) + function IndexManager(g, dyn_states, edepth, vdepth, vertexf, edgef; valias, ealias) + aliased_vertexf_hashes = _aliased_hashes(VertexFunction, vertexf, valias) + aliased_edgef_hashes = _aliased_hashes(EdgeFunction, edgef, ealias) unique_vnames = unique_mappings(getproperty.(vertexf, :name), 1:nv(g)) unique_enames = unique_mappings(getproperty.(edgef, :name), 1:ne(g)) new{typeof(g)}(g, collect(edges(g)), @@ -43,14 +43,17 @@ mutable struct IndexManager{G} unique_enames) end end -function _aliased_hashes(T, cfs, mightalias) +function _aliased_hashes(T, cfs, aliastype) hashdict = IdDict{T, @NamedTuple{idxs::Vector{Int}, hash::UInt}}() - if mightalias + if aliastype == :some ag = aliasgroups(cfs) for (c, idxs) in ag h = hash(c) hashdict[c] = (; idxs=idxs, hash=h) end + elseif aliastype == :all + c = first(cfs) + hashdict[c] =(; idxs=collect(eachindex(cfs)), hash=hash(c)) end hashdict end