Browse Source

Added native visualizations to algebraicpetri (#23)

* Added native visualizations to algebraicpetri

* Added missing test

* Version bump
pull/24/head
Micah Halter 4 months ago
committed by GitHub
parent
commit
621db9028d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 68 additions and 22 deletions
  1. +2
    -1
      Project.toml
  2. +2
    -3
      examples/covid/_covid.jl
  3. +1
    -2
      examples/covid/chime/chime-cset.jl
  4. +1
    -2
      examples/covid/chime/chime.jl
  5. +1
    -1
      examples/covid/coexist/coexist.jl
  6. +3
    -4
      examples/covid/epidemiology.jl
  7. +5
    -6
      examples/predation/lotka-volterra.jl
  8. +7
    -2
      src/AlgebraicPetri.jl
  9. +38
    -0
      src/visualization.jl
  10. +8
    -1
      test/types.jl

+ 2
- 1
Project.toml View File

@ -2,7 +2,7 @@ name = "AlgebraicPetri"
uuid = "4f99eebe-17bf-4e98-b6a1-2c4f205a959b"
license = "MIT"
authors = ["Micah Halter <micah@mehalter.com>"]
version = "0.5.0"
version = "0.5.1"
[deps]
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"
@ -10,6 +10,7 @@ Catlab = "134e5e36-593f-5add-ad60-77f754baafbe"
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Petri = "4259d249-1051-49fa-8328-3f8ab9391c33"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
[compat]
AutoHashEquals = "^0.2.0"


+ 2
- 3
examples/covid/_covid.jl View File

@ -5,7 +5,6 @@
using AlgebraicPetri
using AlgebraicPetri.Epidemiology
using Petri: Model, Graph
using OrdinaryDiffEq
using Plots
@ -62,7 +61,7 @@ seird_city = to_hom_expr(FreeBiproductCategory, seird_city)
display_wd(seird_city)
# -
Graph(Model(decoration(F(seird_city))))
Graph(decoration(F(seird_city)))
# create a multi-city SEIRD models
@ -73,7 +72,7 @@ pc_seird_3 = F(seird_3)
p_seird_3 = decoration(pc_seird_3)
display_wd(seird_3)
# -
Graph(Model(p_seird_3))
Graph(p_seird_3)
# Define time frame and initial parameters


+ 1
- 2
examples/covid/chime/chime-cset.jl View File

@ -1,5 +1,4 @@
using AlgebraicPetri
using Petri: Model, Graph
using OrdinaryDiffEq
using Plots
using Catlab.Meta
@ -27,7 +26,7 @@ end
sir_cset= LabelledReactionNet{Function, Float64}((:S=>990, :I=>10, :R=>0), (:inf, β)=>((:S, :I)=>(:I,:I)), (:rec, t->γ)=>(:I=>:R))
Graph(Model(sir_cset))
Graph(sir_cset)
prob = ODEProblem(sir_cset, (17.0, 120.0))
sol = OrdinaryDiffEq.solve(prob,Tsit5())


+ 1
- 2
examples/covid/chime/chime.jl View File

@ -1,6 +1,5 @@
using AlgebraicPetri
using AlgebraicPetri.Epidemiology
using Petri: Model, Graph
using OrdinaryDiffEq
using LabelledArrays
using Plots
@ -15,7 +14,7 @@ sir = transmission ⋅ recovery
p_sir = apex(F_epi(sir));
display_wd(sir)
#-
Graph(Model(p_sir))
Graph(p_sir)
u0 = LVector(S=990, I=10, R=0);
t_span = (17.0,120.0)


+ 1
- 1
examples/covid/coexist/coexist.jl View File

@ -250,7 +250,7 @@ display_wd(threeNCoexist)
threeNCoexist_algpetri = apex(F_tcx(threeNCoexist))
threeNCoexist_petri = Petri.Model(threeNCoexist_algpetri)
Graph(threeNCoexist_petri)
Graph(threeNCoexist_algpetri)
# We can JSON to convert this Petri net into an
# easily shareable format


+ 3
- 4
examples/covid/epidemiology.jl View File

@ -5,7 +5,6 @@
using AlgebraicPetri
using AlgebraicPetri.Epidemiology
using Petri: Model, Graph
using LabelledArrays
using OrdinaryDiffEq
using Plots
@ -33,7 +32,7 @@ display_wd(sir)
# Use Petri.jl to visualize the C-Set
Graph(Model(cset_sir))
Graph(cset_sir)
# define initial states and transition rates, then
# create, solve, and visualize ODE problem
@ -65,7 +64,7 @@ p_seir = apex(F_epi(seir));
display_wd(seir)
#-
Graph(Model(p_seir))
Graph(p_seir)
# define initial states and transition rates, then
# create, solve, and visualize ODE problem
@ -94,7 +93,7 @@ p_seird = apex(F_epi(seird));
display_wd(seird)
#-
Graph(Model(p_seird))
Graph(p_seird)
# define initial states and transition rates, then
# create, solve, and visualize ODE problem


+ 5
- 6
examples/predation/lotka-volterra.jl View File

@ -4,7 +4,6 @@
using AlgebraicPetri
using Petri: Model, Graph
using OrdinaryDiffEq
using Plots
@ -21,13 +20,13 @@ display_wd(ex) = to_graphviz(ex, orientation=LeftToRight, labels=true);
petriOb = codom(Open([1], PetriNet(1), [1]))
birth_petri = Open([1], PetriNet(1, (1, (1,1))), [1]);
Graph(Model(apex(birth_petri)))
Graph(birth_petri)
#-
predation_petri = Open([1,2], PetriNet(2, ((1,2), (2,2))), [2]);
Graph(Model(apex(predation_petri)))
Graph(predation_petri)
#-
death_petri = Open([1], PetriNet(1, (1, ())), [1]);
Graph(Model(apex(death_petri)))
Graph(death_petri)
# #### Step 2: Define a presentation of the free biproduct category
# that encodes the domain specific information
@ -52,7 +51,7 @@ lotka_volterra = (birth ⊗ id(wolves)) ⋅ predation ⋅ death
lotka_petri = apex(F(lotka_volterra))
display_wd(lotka_volterra)
#-
Graph(Model(lotka_petri))
Graph(lotka_petri)
# Generate appropriate vector fields, define parameters, and visualize solution
@ -102,7 +101,7 @@ end
display_wd(dual_lv)
#-
dual_lv_petri = apex(F(to_hom_expr(FreeBiproductCategory, dual_lv)))
Graph(Model(dual_lv_petri))
Graph(dual_lv_petri)
# Generate a new solver, provide parameters, and analyze results


+ 7
- 2
src/AlgebraicPetri.jl View File

@ -20,7 +20,7 @@ using Catlab.Theories
using Petri
using LabelledArrays
using LinearAlgebra: mul!
import Petri: Model, vectorfield
import Petri: Model, Graph, vectorfield
vectorify(n::Vector) = n
vectorify(n::Tuple) = length(n) == 1 ? [n] : n
@ -81,6 +81,9 @@ add_inputs!(p::AbstractPetriNet,n,t,s;kw...) = add_parts!(p,:I,n;it=t,is=s,kw...
add_output!(p::AbstractPetriNet,t,s;kw...) = add_part!(p,:O;ot=t,os=s,kw...)
add_outputs!(p::AbstractPetriNet,n,t,s;kw...) = add_parts!(p,:O,n;ot=t,os=s,kw...)
sname(p::AbstractPetriNet,s) = (1:ns(p))[s]
tname(p::AbstractPetriNet,t) = (1:nt(p))[t]
# Note: although indexing makes this pretty fast, it is often faster to bulk-convert
# the PetriNet net into a transition matrix, if you are working with all of the transitions
inputs(p::AbstractPetriNet,t) = subpart(p,incident(p,t,:it),:is)
@ -288,6 +291,8 @@ rates(p::AbstractLabelledReactionNet) = begin
LVector(;[(tnames[t]=>rate(p, t)) for t in 1:nt(p)]...)
end
include("visualization.jl")
include("Epidemiology.jl")
end
end

+ 38
- 0
src/visualization.jl View File

@ -0,0 +1,38 @@
using Catlab.Graphics.Graphviz
import Catlab.Graphics.Graphviz: Graph, Edge
import Base.Iterators: flatten
using StatsBase
export Graph
function edgify(δ, transition, reverse::Bool)
return [Edge(reverse ? ["T_$transition", "S_$k"] :
["S_$k", "T_$transition"],
Attributes(:label=>"$(δ[k])", :labelfontsize=>"6"))
for k in collect(keys(δ)) if δ[k] != 0]
end
function Graph(p::AbstractPetriNet)
statenodes = [Node(string("S_$(sname(p, s))"), Attributes(:shape=>"circle", :color=>"#6C9AC3")) for s in 1:ns(p)]
transnodes = [Node(string("T_$(tname(p, k))"), Attributes(:shape=>"square", :color=>"#E28F41")) for k in 1:nt(p)]
graph_attrs = Attributes(:rankdir=>"LR")
node_attrs = Attributes(:shape=>"plain", :style=>"filled", :color=>"white")
edge_attrs = Attributes(:splines=>"splines")
stmts = vcat(statenodes, transnodes)
edges = map(1:nt(p)) do k
k_name = tname(p, k)
vcat(edgify(countmap(map(x->sname(p,x), inputs(p, k))), k_name, false),
edgify(countmap(map(x->sname(p, x), outputs(p, k))), k_name, true))
end |> flatten |> collect
stmts = vcat(stmts, edges)
g = Graphviz.Digraph("G", stmts; graph_attrs=graph_attrs, node_attrs=node_attrs, edge_attrs=edge_attrs)
return g
end
function Graph(op::Union{OpenPetriNet, OpenLabelledPetriNetUntyped, OpenReactionNet, OpenLabelledReactionNetUntyped})
Graph(apex(op))
end

+ 8
- 1
test/types.jl View File

@ -13,6 +13,13 @@ sir_tpetri= PetriNet(TransitionMatrices(sir_petri))
@test Petri.Model(sir_petri) == Petri.Model(sir_rxn)
@test Petri.Model(sir_lpetri) == Petri.Model(sir_lrxn)
@test typeof(Graph(sir_petri)) == Graph
@test typeof(Graph(sir_lpetri)) == Graph
@test typeof(Graph(sir_rxn)) == Graph
@test typeof(Graph(open_sir_rxn)) == Graph
@test typeof(Graph(sir_lrxn)) == Graph
@test typeof(Graph(open_sir_lrxn)) == Graph
@test inputs(sir_petri, 1) == [1,2]
@test outputs(sir_petri, 1) == [2,2]
@test concentration(sir_rxn, 1) == 990
@ -54,4 +61,4 @@ add_input!(sir_petri, 4, 4)
add_output!(sir_petri, 4, 3)
@test ni(sir_petri) == 5
@test no(sir_petri) == 5
@test sir_petri == PetriNet(4, ((1, 2), (2, 2)), (2, 3), (1, 4), (4, 3))
@test sir_petri == PetriNet(4, ((1, 2), (2, 2)), (2, 3), (1, 4), (4, 3))

Loading…
Cancel
Save