GithubHelp home page GithubHelp logo

algebraicjulia / structured-epidemic-modeling Goto Github PK

View Code? Open in Web Editor NEW
12.0 4.0 5.0 6.04 MB

Results and software for our paper on structured epidemic modeling

License: BSD 2-Clause "Simplified" License

Jupyter Notebook 99.65% Julia 0.35%
epidemic-model epidemiology simulation modeling modeling-and-simulation dynamical-systems category-theory algebra categorical-logic scientific-computing

structured-epidemic-modeling's Introduction

Structured Epidemic Modeling

In our preprint An Algebraic Framework for Structured Epidemic Modeling, we present an approach to scientific modeling, grounded in applied category theory, in which the high-level structure of a model is visible and manipulable in its software implementation. Here we reproduce and expand on the presented examples.

structured-epidemic-modeling's People

Contributors

epatters avatar jpfairbanks avatar p-stokes avatar slibkind avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

structured-epidemic-modeling's Issues

Problems porting a related epidemiological model

I'm trying to use the examples here to port an existing high/low risk model to use AlgebraicPetri.jl. I get an error ERROR: Pullbacks of TypeSets that are not products are not supported when I try to compose the model. Can anyone spot where I'm going wrong?

using AlgebraicPetri
using Catlab
using Catlab.Graphics
using Catlab.Graphics.Graphviz
using Catlab.Graphics.Graphviz: Html
using Catlab.WiringDiagrams
using Catlab.CategoricalAlgebra
using Catlab.Programs.RelationalPrograms
using GraphViz
using LabelledArrays
using OrdinaryDiffEq
using Plots

# Functions for graphing typed Petri nets
colors = ["#a08eae","#ffeec6", "#a8dcd9", "#ffeec6", "#a8dcd9"]

function def_trans(typed_petri::ACSetTransformation, colors; labels = true)
  (p, t; pos = "") -> ("t$t", Attributes(
             :label => labels ? Html(flatten(tname(p,t))) : "" ,
             :shape=>"square",
             :color=>colors[typed_petri[:T](t)],
             :pos=>pos))
end

function def_trans(colors = colors; labels = true)
  (p, t; pos = "") -> ("t$t", Attributes(
             :label => labels ? "$(tname(p, t))" : "" ,
             :shape=>"square",
             :color=>colors[t],
             :pos=>pos))
end

flatten(tname::Symbol) = "$tname"

function flatten(tname::Tuple)
    names = split(replace(string(tname), "("=>"", ")"=>"", ":"=>""), ",")
    for i in 1:length(names)
        name = strip(names[i])
        if name[1:2] == "id"
            continue
        end
        return name
    end
    return "id"
end

def_states(p, s; pos="") = ("s$s", Attributes(
        :label => sname(p,s) isa Tuple where T ? Html(replace(string(sname(p,s)), ":"=>"", "," => "", "("=>"", ")"=>"")) : "$(sname(p,s))",
        :shape=>"circle",
        :color=>"#6C9AC3",
        :pos=>pos
))

Graph_typed(typed_petri::ACSetTransformation, colors = colors; labels = true) = Graph(dom(typed_petri),
    make_trans = def_trans(typed_petri, colors; labels = labels),
    make_states = def_states
)

### Define models

SIR = LabelledPetriNet([:S, :I, :R],
   => ((:S, :I)=>(:I, :I)),
   => (:I=>:R),
  :∅ => (:S => :S),
  :∅ => (:I => :I),
  :∅ => (:R => :R)
)

infectious_type = LabelledPetriNet([:Pop],
  :interact=>((:Pop, :Pop)=>(:Pop, :Pop)), 
  :t_disease=>(:Pop=>:Pop),
  :t_strata=>(:Pop=>:Pop)
)

## Pull out indexing from model

s, = parts(infectious_type, :S)
t_interact, t_disease, t_strata = parts(infectious_type, :T)
i_interact1, i_interact2, i_disease, i_strata = parts(infectious_type, :I)
o_interact1, o_interact2, o_disease, o_strata = parts(infectious_type, :O)

typed_SIR = ACSetTransformation(SIR, infectious_type,
  S = [s, s, s],
  T = [t_interact, t_disease, t_strata, t_strata, t_strata],
  I = [i_interact1, i_interact2, i_disease, i_strata, i_strata, i_strata],
  O = [o_interact1, o_interact2, o_disease, o_strata, o_strata, o_strata],
  Name = name -> nothing # specify the mapping for the loose ACSet transform
)

Graph_typed(typed_SIR)

risk = LabelledPetriNet([:H, :L],
    :∅ => (:H => :H),
    :∅ => (:L => :L),
    :interact => ((:H, :H) => (:H, :H)),
    :interact => ((:L, :L) => (:L, :L)),
    :interact => ((:H, :L) => (:H, :L)),
    :interact => ((:L, :H) => (:L, :H)),
)

typed_risk = ACSetTransformation(risk, infectious_type,
  S = [s, s],
  T = [t_disease, t_disease, t_interact, t_interact, t_interact, t_interact],
  I = [i_disease, i_disease, i_interact1, i_interact2, i_interact1, i_interact2, i_interact2, i_interact1, i_interact2, i_interact1],
  O = [o_disease, o_disease, o_interact1, o_interact2, o_interact1, o_interact2, o_interact2, o_interact1, o_interact2, o_interact1],
  Name = name -> nothing # specify the mapping for the loose ACSet transform
)
[i_disease, i_disease, i_interact1, i_interact2, i_interact1, i_interact2, i_interact2, i_interact1, i_interact2, i_interact1]

Graph_typed(typed_risk)

typed_stratify(typed_model1, typed_model2) =
  compose(proj1(pullback(typed_model1, typed_model2)), typed_model1)

SIR_risk = typed_stratify(typed_SIR, typed_risk)

using Catlab fails in Julia 1.7.2

WE36383:Structured-Epidemic-Modeling zuck016$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.2 (2022-02-06)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

(@v1.7) pkg> activate
  Activating project at `~/.julia/environments/v1.7`

(@v1.7) pkg> add Catlab
    Updating registry at `~/.julia/registries/General.toml`
   Resolving package versions...
  No Changes to `~/.julia/environments/v1.7/Project.toml`
  No Changes to `~/.julia/environments/v1.7/Manifest.toml`

julia> using Catlab
[ Info: Precompiling Catlab [134e5e36-593f-5add-ad60-77f754baafbe]
ERROR: LoadError: MethodError: no method matching names(::Base.Broadcast.BroadcastFunction{Module})
Closest candidates are:
  names(::Module; all, imported) at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/reflection.jl:102
Stacktrace:
  [1] top-level scope
    @ ~/.julia/packages/Catlab/2P2DD/src/categorical_algebra/CSetDataStructures.jl:14
  [2] include(mod::Module, _path::String)
    @ Base ./Base.jl:418
  [3] include(x::String)
    @ Catlab ~/.julia/packages/Catlab/2P2DD/src/Catlab.jl:1
  [4] top-level scope
    @ ~/.julia/packages/Catlab/2P2DD/src/Catlab.jl:8
  [5] include
    @ ./Base.jl:418 [inlined]
  [6] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
    @ Base ./loading.jl:1318
  [7] top-level scope
    @ none:1
  [8] eval
    @ ./boot.jl:373 [inlined]
  [9] eval(x::Expr)
    @ Base.MainInclude ./client.jl:453
 [10] top-level scope
    @ none:1
in expression starting at /Users/zuck016/.julia/packages/Catlab/2P2DD/src/categorical_algebra/CSetDataStructures.jl:1
in expression starting at /Users/zuck016/.julia/packages/Catlab/2P2DD/src/Catlab.jl:1
ERROR: Failed to precompile Catlab [134e5e36-593f-5add-ad60-77f754baafbe] to /Users/zuck016/.julia/compiled/v1.7/Catlab/jl_9e64Ab.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:33
 [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, ignore_loaded_modules::Bool)
   @ Base ./loading.jl:1466
 [3] compilecache(pkg::Base.PkgId, path::String)
   @ Base ./loading.jl:1410
 [4] _require(pkg::Base.PkgId)
   @ Base ./loading.jl:1120
 [5] require(uuidkey::Base.PkgId)
   @ Base ./loading.jl:1013
 [6] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:997

Problem wiring a simple SEIR model

For some reason, the following code for an SEIR model wires E to R, rather than I to R. Can anyone spot where I'm going wrong?

using AlgebraicPetri,AlgebraicPetri.TypedPetri
using Catlab, Catlab.CategoricalAlgebra, Catlab.Programs
using Catlab.WiringDiagrams, Catlab.Graphics
using AlgebraicDynamics.UWDDynam


epi_transitions = LabelledPetriNet(
  [:Pop],
  :infection=>((:Pop, :Pop)=>(:Pop, :Pop)),
  :progression=>(:Pop=>:Pop),
  :recovery=>(:Pop=>:Pop)
)

seir_uwd = @relation () where (S::Pop, E::Pop, I::Pop, R::Pop) begin
    infection(S, I, E, I)
    progression(E, I)
    recovery(I, R)
end
seir_acst = oapply_typed(epi_transitions, seir_uwd, [, , ])
seir_lpn = dom(seir_acst)
Graph(seir_lpn)

Issues trying to get simple composition working

I'm trying to get the worlds simplest composition working (basically SI \cdot IR -> SIR), but oapply doesn't seem to work here (using composition.ipynb as a template). I like to add suffixes to my variable names so I know their types.

using AlgebraicPetri,AlgebraicPetri.TypedPetri
using Catlab, Catlab.CategoricalAlgebra, Catlab.Programs
using Catlab.WiringDiagrams
using AlgebraicDynamics.UWDDynam

epi_transitions = LabelledPetriNet(
  [:Pop],
  :infection=>((:Pop, :Pop)=>(:Pop, :Pop)),
  :recovery=>(:Pop=>:Pop),
  :strata=>(:Pop=>:Pop)
)

si_uwd = @relation () where (S::Pop, I::Pop) begin
    infection(S, I, I, I)
end
si_acs = oapply_typed(epi_transitions, si_uwd, [])
si_lpn = dom(si_acs)

ir_uwd = @relation () where (I::Pop, R::Pop) begin
    recovery(I, R)
end
ir_acs = oapply_typed(epi_transitions, ir_uwd, [])
ir_lpn = dom(ir_acs)

sir_uwd = @relation () where (S::Pop, I::Pop, R::Pop) begin
    si(S, I)
    ir(I, R)
end

oapply(sir_uwd, Dict(
    :si => si_lpn,
    :ir => ir_lpn,
))

The error:

ERROR: MethodError: no method matching oapply(::Catlab.Programs.RelationalPrograms.TypedUnnamedRelationDiagram{Symbol, Symbol, Symbol}, ::Vector{LabelledPetriNet}, ::Nothing)

Closest candidates are:
  oapply(::AbstractUWD, ::AbstractDict, ::Union{Nothing, AbstractDict}; hom_attr, ob_attr, kwargs...)
   @ Catlab ~/.julia/packages/Catlab/NhhmR/src/wiring_diagrams/Algebras.jl:21
  oapply(::AbstractUWD, ::AbstractVector{<:StructuredMulticospan{L}}, ::Union{Nothing, AbstractVector}; return_colimit) where L
   @ Catlab ~/.julia/packages/Catlab/NhhmR/src/wiring_diagrams/Algebras.jl:77
  oapply(::AbstractUWD, ::AbstractDict{S, R}) where {S, R<:AbstractResourceSharer}
   @ AlgebraicDynamics ~/.julia/packages/AlgebraicDynamics/s3uNa/src/uwd_dynam.jl:298
  ...

Stacktrace:
 [1] oapply(composite::Catlab.Programs.RelationalPrograms.TypedUnnamedRelationDiagram{Symbol, Symbol, Symbol}, hom_map::Dict{Symbol, LabelledPetriNet}, ob_map::Nothing; hom_attr::Symbol, ob_attr::Symbol, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Catlab.WiringDiagrams.WiringDiagramAlgebras ~/.julia/packages/Catlab/NhhmR/src/wiring_diagrams/Algebras.jl:28
 [2] oapply(composite::Catlab.Programs.RelationalPrograms.TypedUnnamedRelationDiagram{Symbol, Symbol, Symbol}, hom_map::Dict{Symbol, LabelledPetriNet}, ob_map::Nothing)
   @ Catlab.WiringDiagrams.WiringDiagramAlgebras ~/.julia/packages/Catlab/NhhmR/src/wiring_diagrams/Algebras.jl:21
 [3] oapply(composite::Catlab.Programs.RelationalPrograms.TypedUnnamedRelationDiagram{Symbol, Symbol, Symbol}, hom_map::Dict{Symbol, LabelledPetriNet})
   @ Catlab.WiringDiagrams.WiringDiagramAlgebras ~/.julia/packages/Catlab/NhhmR/src/wiring_diagrams/Algebras.jl:21
 [4] top-level scope
   @ REPL[112]:1

Any pointers on how I'm going wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.