jataware / COVID-19_Projections

Implementations of COVID19 Models
0 stars 0 forks source link

AlgebraicDynamics version of the compartmental model #2

Closed jpfairbanks closed 1 year ago

jpfairbanks commented 2 years ago

Hi @fivegrant, I looked at the catlab version of the model and saw that you are using ContinuousMachine for your implementation.

When I look at the following DirectedWiringDiagram with all of the feedback arrows that point up, I see that Machine syntax is not a good fit for this problem. Machines are often used in engineered systems where there is a clear flow of information from input to output with some limited feedback interaction. For example in controls theory, the information flows sensor -> controller -> plant -> sensor. In this case all but one arrow points forward.

image

Naturally occuring systems like disease dynamics are typically undirected, where all the variables flow back to influence other variables. In this setting you want to use ResourceSharers to model your system.

The documentation shows this in the Lotka-Volterra three ways page: https://algebraicjulia.github.io/AlgebraicDynamics.jl/dev/examples/Lotka-Volterra/#Undirected-composition

You end up with the same ODE, but the syntactic composition rule is much more concise.

jpfairbanks commented 2 years ago

BTW, the OpenPetriNet category from AlgebraicPetri embed into the ResourceSharer as implemented by this PR https://github.com/AlgebraicJulia/AlgebraicDynamics.jl/pull/105/files

fivegrant commented 2 years ago

Really appreciate you taking a look at this!

So if I use a resource sharer this:

compartments = WiringDiagram([], [:susceptible, :exposed, :presymptomatic,
        :symptomatic, :asymptomatic, :quarantined, :isolated, :recovered, :death ])

susceptible_box  = add_box!(compartments, Box(
        :susceptible, [:E₂, :A, :I, :Q, :L], [:S]
))
exposed_box  = add_box!(compartments, Box(
        :exposed, [:S, :E₂, :A, :I, :Q, :L], [:E₁]
))
presymptomatic_box  = add_box!(compartments, Box(
        :presymptomatic, [:E₁], [:E₂]
))
symptomatic_box  = add_box!(compartments, Box(
        :symptomatic, [:E₂], [:I]
))
asymptomatic_box  = add_box!(compartments, Box(
        :asymptomatic, [:E₂], [:A]
))
quarantined_box  = add_box!(compartments, Box(
        :quarantined, [:E₂], [:Q]
))
isolated_box  = add_box!(compartments, Box(
        :isolated, [:I, :A], [:L]
))
recovered_box  = add_box!(compartments, Box(
        :recovered, [:I, :A, :Q, :L], [:R]
))
death_box  = add_box!(compartments, Box(
        :death, [:I, :L, :Q], [:D]
))

# Why is this step necessary/ Is it necessary?
add_wires!(compartments, Pair[     
    (susceptible_box, 1)  => (exposed_box, 1),
    (exposed_box, 1)  => (presymptomatic_box, 1),

    (presymptomatic_box, 1)  => (symptomatic_box, 1),
    (presymptomatic_box, 1)  => (asymptomatic_box, 1),
    (presymptomatic_box, 1)  => (quarantined_box, 1),

    (asymptomatic_box, 1)  => (isolated_box, 1),
    (asymptomatic_box, 1)  => (recovered_box, 1),

    (symptomatic_box, 1)  => (isolated_box, 1),
    (symptomatic_box, 1)  => (recovered_box, 1),
    (symptomatic_box, 1)  => (death_box, 1),

    (quarantined_box, 1)  => (recovered_box, 1),
    (quarantined_box, 1)  => (death_box, 1),

    (isolated_box, 1)  => (recovered_box, 1),
    (isolated_box, 1)  => (death_box, 1),

    # Loop back to Susceptible [IS THIS NECESSARY?]
    (presymptomatic_box,1) => (susceptible_box,1),
    (asymptomatic_box,1) => (susceptible_box,1),
    (symptomatic_box,1) => (susceptible_box,1), 
    (quarantined_box,1) => (susceptible_box,1), 
    (isolated_box,1) => (susceptible_box,1), 

    # Loop back to Exposed [IS THIS NECESSARY?]
    (presymptomatic_box,1) => (exposed_box,1),
    (asymptomatic_box,1) => (exposed_box,1),
    (symptomatic_box,1) => (exposed_box,1), 
    (quarantined_box,1) => (exposed_box,1), 
    (isolated_box,1) => (exposed_box,1),
    ]
)

should become this:

compartments = @relation (S, E₁, E₂,
                          I, A,  Q,
                          L, R,  D,) begin
    expose(E₂, A, I, Q, L, S)
    infect(S, E₂, A, I, Q, L, E₁)
    neutralize(E₁, E₂)
    worsen(E₂, I)
    quarantine(E₂, Q)
    isolate(E₂, Q, L)
    recover(I, A, Q, L, R)
    die(I, L, Q, D)

end

Will include the updated model soon

fivegrant commented 1 year ago

stale