From 625c442dcc975f9fdf71dca79b1b60c6b592bca4 Mon Sep 17 00:00:00 2001 From: hhhults Date: Fri, 23 Jun 2023 11:21:34 -0700 Subject: [PATCH 1/4] added labelled petri/reaction net compatibility --- ext/AlgebraicDynamicsAlgebraicPetriExt.jl | 31 ++++++++---- test/ext/AlgebraicPetri.jl | 62 +++++++++++++++-------- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/ext/AlgebraicDynamicsAlgebraicPetriExt.jl b/ext/AlgebraicDynamicsAlgebraicPetriExt.jl index 86e03e4..f2be5e8 100644 --- a/ext/AlgebraicDynamicsAlgebraicPetriExt.jl +++ b/ext/AlgebraicDynamicsAlgebraicPetriExt.jl @@ -3,17 +3,28 @@ module AlgebraicDynamicsAlgebraicPetriExt using AlgebraicPetri using AlgebraicDynamics using Catlab +using LabelledArrays import AlgebraicDynamics.UWDDynam: ContinuousResourceSharer -function ContinuousResourceSharer{T}(pn::Union{OpenPetriNet, OpenLabelledPetriNet}) where T - nstates = nparts(apex(pn), :S) - portmap = vcat(map(legs(pn)) do f - f[:S](parts(dom(f), :S)) - end...) - nports = length(portmap) - vf(u, p, t) = vectorfield(apex(pn))(zeros(nstates), u, p, t) - - ContinuousResourceSharer{T}(nports, nstates, vf, portmap) - end +# vecfields need to be initialized differently depending on type of net +function vf(pn::OpenPetriNet,T::Type,ns::Int64) + vf(u, p, t) = vectorfield(apex(pn))(zeros(T,ns), u, p, t) +end +function vf(pn::OpenLabelledPetriNet,T::Type,ns::Int64) + vf(u, p, t) = vectorfield(apex(pn))(LVector(NamedTuple{tuple(snames(apex(pn))...)}(zeros(T,ns))), u, p, t) +end + +function vf(pn::OpenLabelledReactionNet,T::Type,ns::Int64) + vf(u, p, t) = vectorfield(apex(pn))(LVector(NamedTuple{tuple(snames(apex(pn))...)}(zeros(T,ns))), u, rates(apex(pn)), t) +end + +function ContinuousResourceSharer{T}(pn::Union{OpenPetriNet,OpenLabelledPetriNet,OpenLabelledReactionNet}) where T + nstates = nparts(apex(pn), :S) + portmap = vcat(map(legs(pn)) do f + f[:S](parts(dom(f), :S)) + end...) + nports = length(portmap) + ContinuousResourceSharer{T}(nports, nstates, vf(pn,T,nstates), portmap) +end end \ No newline at end of file diff --git a/test/ext/AlgebraicPetri.jl b/test/ext/AlgebraicPetri.jl index 07522c8..51a8667 100644 --- a/test/ext/AlgebraicPetri.jl +++ b/test/ext/AlgebraicPetri.jl @@ -2,26 +2,46 @@ using AlgebraicDynamics using AlgebraicPetri using Catlab using Test +using AlgebraicDynamics.UWDDynam +using LabelledArrays + @testset "AlgebraicPetri" begin - birth_petri = Open(PetriNet(1, 1=>(1,1))); - rs = ContinuousResourceSharer{Float64}(birth_petri) - @test nstates(rs) == 1 - @test nports(rs) == 1 - @test portmap(rs) == [1] - u = [1.0]; p = [2.0]; - @test eval_dynamics(rs, u, p, 0) == [2.0] - - Brusselator= LabelledPetriNet([:A, :B, :D, :E, :X, :Y], - :t1 => (:A => (:X, :A)), - :t2 => ((:X, :X, :Y) => (:X, :X, :X)), - :t3 => ((:B, :X) => (:Y, :D, :B)), - :t4 => (:X => :E) - ) - - open_bruss = Open([:A, :D], Brusselator, [:A, :B]) - rs = ContinuousResourceSharer{Float64}(open_bruss) - @test nstates(rs) == 6 - @test nports(rs) == 4 - @test portmap(rs) == [1,3, 1,2] - end \ No newline at end of file + birth_petri = Open(PetriNet(1, 1=>(1,1))); + rs = ContinuousResourceSharer{Float64}(birth_petri) + @test nstates(rs) == 1 + @test nports(rs) == 1 + @test portmap(rs) == [1] + u = [1.0]; p = [2.0]; + @test eval_dynamics(rs, u, p, 0) == [2.0] + + labelled_birth_petri = Open(LabelledPetriNet([:foo], (:bar,(:foo=>(:foo,:foo))))); + rs = ContinuousResourceSharer{Float64}(labelled_birth_petri) + @test nstates(rs) == 1 + @test nports(rs) == 1 + @test portmap(rs) == [1] + u = LVector(foo=1.0); p = LVector(bar=2.0); + @test eval_dynamics(rs, u, p, 0) == [2.0] + + labelled_birth_react = Open(LabelledReactionNet{Float64}{Float64}([:foo=>1.0], ((:bar=>2.0),(:foo=>(:foo,:foo))))); + rs = ContinuousResourceSharer{Float64}(labelled_birth_react) + @test nstates(rs) == 1 + @test nports(rs) == 1 + @test portmap(rs) == [1] + u = LVector(NamedTuple(zip(snames(apex(labelled_birth_react)),Vector(subpart(apex(labelled_birth_react),:concentration))))) + p = LVector(bar=2.0) + @test eval_dynamics(rs, u, p, 0) == [2.0] + + Brusselator= LabelledPetriNet([:A, :B, :D, :E, :X, :Y], + :t1 => (:A => (:X, :A)), + :t2 => ((:X, :X, :Y) => (:X, :X, :X)), + :t3 => ((:B, :X) => (:Y, :D, :B)), + :t4 => (:X => :E) + ) + + open_bruss = Open([:A, :D], Brusselator, [:A, :B]) + rs = ContinuousResourceSharer{Float64}(open_bruss) + @test nstates(rs) == 6 + @test nports(rs) == 4 + @test portmap(rs) == [1,3, 1,2] +end \ No newline at end of file From 712c575d38fcc01ea125c315f7eba1140b19b52a Mon Sep 17 00:00:00 2001 From: "James P. Fairbanks" Date: Fri, 7 Jun 2024 21:02:59 -0400 Subject: [PATCH 2/4] TST: fix AlgebraicPetri whitespace --- test/ext/AlgebraicPetri.jl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/ext/AlgebraicPetri.jl b/test/ext/AlgebraicPetri.jl index 51a8667..67ba60a 100644 --- a/test/ext/AlgebraicPetri.jl +++ b/test/ext/AlgebraicPetri.jl @@ -6,33 +6,35 @@ using AlgebraicDynamics.UWDDynam using LabelledArrays -@testset "AlgebraicPetri" begin - birth_petri = Open(PetriNet(1, 1=>(1,1))); +@testset "AlgebraicPetri" begin + birth_petri = Open(PetriNet(1, 1 => (1, 1))) rs = ContinuousResourceSharer{Float64}(birth_petri) @test nstates(rs) == 1 @test nports(rs) == 1 @test portmap(rs) == [1] - u = [1.0]; p = [2.0]; + u = [1.0] + p = [2.0] @test eval_dynamics(rs, u, p, 0) == [2.0] - labelled_birth_petri = Open(LabelledPetriNet([:foo], (:bar,(:foo=>(:foo,:foo))))); + labelled_birth_petri = Open(LabelledPetriNet([:foo], (:bar, (:foo => (:foo, :foo))))) rs = ContinuousResourceSharer{Float64}(labelled_birth_petri) @test nstates(rs) == 1 @test nports(rs) == 1 @test portmap(rs) == [1] - u = LVector(foo=1.0); p = LVector(bar=2.0); + u = LVector(foo=1.0) + p = LVector(bar=2.0) @test eval_dynamics(rs, u, p, 0) == [2.0] - labelled_birth_react = Open(LabelledReactionNet{Float64}{Float64}([:foo=>1.0], ((:bar=>2.0),(:foo=>(:foo,:foo))))); + labelled_birth_react = Open(LabelledReactionNet{Float64}{Float64}([:foo => 1.0], ((:bar => 2.0), (:foo => (:foo, :foo))))) rs = ContinuousResourceSharer{Float64}(labelled_birth_react) @test nstates(rs) == 1 @test nports(rs) == 1 @test portmap(rs) == [1] - u = LVector(NamedTuple(zip(snames(apex(labelled_birth_react)),Vector(subpart(apex(labelled_birth_react),:concentration))))) + u = LVector(NamedTuple(zip(snames(apex(labelled_birth_react)), Vector(subpart(apex(labelled_birth_react), :concentration))))) p = LVector(bar=2.0) @test eval_dynamics(rs, u, p, 0) == [2.0] - Brusselator= LabelledPetriNet([:A, :B, :D, :E, :X, :Y], + Brusselator = LabelledPetriNet([:A, :B, :D, :E, :X, :Y], :t1 => (:A => (:X, :A)), :t2 => ((:X, :X, :Y) => (:X, :X, :X)), :t3 => ((:B, :X) => (:Y, :D, :B)), @@ -43,5 +45,5 @@ using LabelledArrays rs = ContinuousResourceSharer{Float64}(open_bruss) @test nstates(rs) == 6 @test nports(rs) == 4 - @test portmap(rs) == [1,3, 1,2] + @test portmap(rs) == [1, 3, 1, 2] end \ No newline at end of file From e5bf2bf53d3e9dbd4f1f192722dcc7aa1ac4e43a Mon Sep 17 00:00:00 2001 From: "James P. Fairbanks" Date: Fri, 7 Jun 2024 22:11:30 -0400 Subject: [PATCH 3/4] ENH: add documentation for AlgebraicPetri Integration --- docs/make.jl | 1 + docs/src/AlgebraicPetri.md | 19 +++++++++++++++++++ ext/AlgebraicDynamicsAlgebraicPetriExt.jl | 18 +++++++++++++----- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 docs/src/AlgebraicPetri.md diff --git a/docs/make.jl b/docs/make.jl index 4adf94b..e15b351 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -67,6 +67,7 @@ makedocs( "examples/Ross-Macdonald.md" ], "Threshold Linear Networks" => "TLN.md", + "AlgebraicPetri Integration" => "AlgebraicPetri.md", "Library Reference" => "api.md" ] ) diff --git a/docs/src/AlgebraicPetri.md b/docs/src/AlgebraicPetri.md new file mode 100644 index 0000000..3b69a7f --- /dev/null +++ b/docs/src/AlgebraicPetri.md @@ -0,0 +1,19 @@ +# AlgebraicPetri.jl Integration + +You can construct a [`ContinuousResourceSharer`](@ref) from an Open Petri Net for any kind of network supported by AlgebraicPetri.jl including: + +1. OpenPetriNet +2. OpenLabelledPetriNet +3. OpenLabelledReactionNet + +````@example +Brusselator = LabelledPetriNet([:A, :B, :D, :E, :X, :Y], + :t1 => (:A => (:X, :A)), + :t2 => ((:X, :X, :Y) => (:X, :X, :X)), + :t3 => ((:B, :X) => (:Y, :D, :B)), + :t4 => (:X => :E) +) + +open_bruss = Open([:A, :D], Brusselator, [:A, :B]) +rs = ContinuousResourceSharer{Float64}(open_bruss) +```` \ No newline at end of file diff --git a/ext/AlgebraicDynamicsAlgebraicPetriExt.jl b/ext/AlgebraicDynamicsAlgebraicPetriExt.jl index f2be5e8..b83e978 100644 --- a/ext/AlgebraicDynamicsAlgebraicPetriExt.jl +++ b/ext/AlgebraicDynamicsAlgebraicPetriExt.jl @@ -6,25 +6,33 @@ using Catlab using LabelledArrays import AlgebraicDynamics.UWDDynam: ContinuousResourceSharer +export OpenNet + +""" OpenNet=Union{OpenPetriNet,OpenLabelledPetriNet,OpenLabelledReactionNet} + +A type alias for any kind of open network from AlgebraicPetri. +""" +const OpenNet = Union{OpenPetriNet,OpenLabelledPetriNet,OpenLabelledReactionNet} + # vecfields need to be initialized differently depending on type of net -function vf(pn::OpenPetriNet,T::Type,ns::Int64) +function dynamics(pn::OpenPetriNet,T::Type,ns::Int64) vf(u, p, t) = vectorfield(apex(pn))(zeros(T,ns), u, p, t) end -function vf(pn::OpenLabelledPetriNet,T::Type,ns::Int64) +function dynamics(pn::OpenLabelledPetriNet,T::Type,ns::Int64) vf(u, p, t) = vectorfield(apex(pn))(LVector(NamedTuple{tuple(snames(apex(pn))...)}(zeros(T,ns))), u, p, t) end -function vf(pn::OpenLabelledReactionNet,T::Type,ns::Int64) +function dynamics(pn::OpenLabelledReactionNet,T::Type,ns::Int64) vf(u, p, t) = vectorfield(apex(pn))(LVector(NamedTuple{tuple(snames(apex(pn))...)}(zeros(T,ns))), u, rates(apex(pn)), t) end -function ContinuousResourceSharer{T}(pn::Union{OpenPetriNet,OpenLabelledPetriNet,OpenLabelledReactionNet}) where T +function ContinuousResourceSharer{T}(pn::OpenNet) where T nstates = nparts(apex(pn), :S) portmap = vcat(map(legs(pn)) do f f[:S](parts(dom(f), :S)) end...) nports = length(portmap) - ContinuousResourceSharer{T}(nports, nstates, vf(pn,T,nstates), portmap) + ContinuousResourceSharer{T}(nports, nstates, dynamics(pn,T,nstates), portmap) end end \ No newline at end of file From ebdd9a73bf35da5da9e5f80d83b0cce01584747f Mon Sep 17 00:00:00 2001 From: "James P. Fairbanks" Date: Sat, 8 Jun 2024 09:50:13 -0400 Subject: [PATCH 4/4] DOC: fix imports in doc page --- docs/src/AlgebraicPetri.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/src/AlgebraicPetri.md b/docs/src/AlgebraicPetri.md index 3b69a7f..1619e86 100644 --- a/docs/src/AlgebraicPetri.md +++ b/docs/src/AlgebraicPetri.md @@ -6,14 +6,22 @@ You can construct a [`ContinuousResourceSharer`](@ref) from an Open Petri Net fo 2. OpenLabelledPetriNet 3. OpenLabelledReactionNet -````@example +````@example AlgPetri +using AlgebraicPetri +using AlgebraicDynamics Brusselator = LabelledPetriNet([:A, :B, :D, :E, :X, :Y], :t1 => (:A => (:X, :A)), :t2 => ((:X, :X, :Y) => (:X, :X, :X)), :t3 => ((:B, :X) => (:Y, :D, :B)), :t4 => (:X => :E) ) +```` +You just call the constructor for ContinuousResourceSharer on an Open Petri Net. +The constructor knows where to use labels or integers for the state variables. +It also knows to get parameters from the ReactionNet and enclose them into the dynamics. + +````@example AlgPetri open_bruss = Open([:A, :D], Brusselator, [:A, :B]) rs = ContinuousResourceSharer{Float64}(open_bruss) ```` \ No newline at end of file