Serializing Stock and Flow Models

using StockFlow
using Catlab
using Catlab.CategoricalAlgebra
using JSON3
import StockFlow: StockAndFlowpUntyped, vectorify, state_dict, add_stocks!, add_flow!, add_links!

In order to serialize our models to JSON, we need to encode our functions as strings instead of julia functions. You can always recover the original model with Base.Meta.parse and eval.

StockAndFlowSymbolic = StockAndFlowpUntyped{Symbol,String}

# This is our constructor specialized to String formulas.
NewStockAndFlowSymbolic(s,f) = begin
	d = StockAndFlowSymbolic()

    s = vectorify(s)
    add_stocks!(d,length(s),sname=s)

    s_idx = state_dict(s)
    f = vectorify(f)
    for (i, ((fattr,uds),ls)) in enumerate(f)
      fn = first(fattr)
      ff = last(fattr)
    	sui = s_idx[first(uds)]
    	sdi = s_idx[last(uds)]
    	ls = vectorify(ls)
    	add_flow!(d,sui,sdi,fname=fn,ϕf=ff)
    	add_links!(d,map(x->s_idx[x],ls),repeat([i], length(ls)), length(ls))
    end
    d
end
NewStockAndFlowSymbolic (generic function with 1 method)

Examples

Our first example model is SIR.

# define functions ϕ of flows in the SIR model
fNewIncidence = "p.cβ*u.S*u.I/p.N"
fNewRecovery = "u.I/p.tr"

# StockAndFlowp(stocks,
#               (flow=>function, upstream=>downstream) => stocks linked)
sir = NewStockAndFlowSymbolic((:S, :I, :R),
   ((:NewIncidence=>fNewIncidence, :S=>:I)=>(:S,:I),
    (:NewRecovery=>fNewRecovery, :I=>:R)=>:I))
StockFlow.StockAndFlowpUntyped{Symbol, String} {Flow:2, Stock:3, Link:3, Name:0, FuncFlow:0}
Flow u d fname ϕf
1 1 2 NewIncidence p.cβ*u.S*u.I/p.N
2 2 3 NewRecovery u.I/p.tr
Stock sname
1 S
2 I
3 R
Link s t
1 1 1
2 2 1
3 2 2

@example JSON JSON3.pretty(generatejsonacset(sir))


We can include some of the premade models, which are found in the `PremadeModels` module. They are all full-bore Stock and Flows.

@example JSON m = StockFlow.PremadeModels.seir_model

@example JSON JSON3.pretty(generatejsonacset(m))


## Schemas

The restricted class of primitive models.

@example JSON JSON3.pretty(generatejsonacset_schema(TheoryStockAndFlowp))


And for the generic schema

@example JSON JSON3.pretty(generatejsonacset_schema(TheoryStockAndFlow)) ```