StockFlow

StockFlow.TheoryStockAndFlow0Constant

define the sub-schema of c0, which includes the three objects: stocks(S), sum-auxiliary-variables(SV), and the linkages between them (LS) to be composed

source
StockFlow.CausalLoopMethod

Create a CausalLoop (Graph with named vertices) with a vector of vertices, and a vector of pairs of vertices.

CausalLoop([:A, :B], [:A => :B, :B => :B]) will create a CausalLoop with vertices A and B, an edge A => B and an edge B => B.

source
StockFlow.StockAndFlow0Method
StockAndFlow0(s,sv,ssv)

for an instance of the sub-schema, the program supports only have stocks, or only have sum auxiliary variables, or both stocks and sum auxiliary variables, or have both

source
StockFlow.StockAndFlowFMethod
StockAndFlowF(s,p,v,f,sv)

EXAMPLE: when define the dynamical variables, need to define with the correct order

sir_StockAndFlow=StockAndFlowF((:S=>(:F_NONE,:inf,:N), :I=>(:inf,:F_NONE,:N)),
 (:c, :beta),
 (:v_prevalence=>(:I,:N,:/),:v_meanInfectiousContactsPerS=>(:c,:v_prevalence,:*),:v_perSIncidenceRate=>(:beta,:v_meanInfectiousContactsPerS,:*),:v_newInfetions=>(:S,:v_perSIncidenceRate,:*)),
 (:inf=>:v_newInfetions),
 (:N))
source
StockFlow.OpenMethod

Construct an OpenCausalLoopPM with a CausalLoopPM, and any number of additional CausalLoopPM to act as feet.

source
StockFlow.add_prefix!Method
add_prefix!(sf::AbstractStockAndFlowStructureF, prefix)

Modify a AbstractStockAndFlowStructureF so named elements begin with prefix Prefix can be anything which can be cast to a Symbol.For feet.

source
StockFlow.add_prefix!Method
add_prefix!(sf::AbstractStockAndFlowStructureF, prefix)

Modify a AbstractStockAndFlowStructureF so named elements begin with prefix Prefix can be anything which can be cast to a Symbol.

source
StockFlow.add_suffix!Method
add_suffix!(sf::AbstractStockAndFlow0, suffix)

Modify a AbstractStockAndFlow0 so named elements end with suffix. Suffix can be anything which can be cast to a Symbol. For feet.

source
StockFlow.add_suffix!Method
add_suffix!(sf::AbstractStockAndFlow0, suffix)

Modify a AbstractStockAndFlow0 so named elements end with suffix. Suffix can be anything which can be cast to a Symbol.

source
StockFlow.all_shortest_pathsMethod

Return Matrix{Vector{Vector{Int}}} of all shortest paths. First index is src, second is tgt, and it points to a vector of all shortest paths, represented as a sequence of edge indices.

Shortest path to self is empty. [Vector{Int}()]

An empty Vector at i, j represents there being no path i -> j.

source
StockFlow.all_shortest_pathsMethod

Return Matrix{Vector{Vector{Int}}} of all shortest paths. First index is src, second is tgt, and it points to a vector of all shortest paths, represented as a sequence of edge indices.

Shortest path to self is empty. [Vector{Int}()]

An empty Vector at i, j represents there being no path i -> j.

source
StockFlow.argsMethod
args(p::AbstractStockAndFlowF,v)

Return a Vector of Symbols of flattened stocks, sums, parameters and source dynamic variables a dynamic variable at index v links to.

source
StockFlow.argsMethod
args(p::AbstractStockAndFlowStructureF,v)

Return a Vector of Symbols of flattened stocks, sums, parameters and source dynamic variables a dynamic variable at index v links to.

source
StockFlow.args_vnameMethod

Return a Tuple of Vectors of Symbols of flattened stocks, sums, parameters and source dynamic variables a dynamic variable at index v links to.

source
StockFlow.cl_cyclesMethod

CausalLoopPM, return all cycles of a causal loop as a vector of vectors of int, where positive edges come before negative.

Each cycle will include each edge at most once.

Don't count empty vector as a cycle.

source
StockFlow.cl_cyclesMethod

CausalLoopPol, return all cycles of a causal loop as a vector of vectors of int.

Each cycle will include each edge at most once.

Don't count empty vector as a cycle.

source
StockFlow.convertSystemStructureToStockFlowMethod

Return a new stock flow with flattened names, operators and positions from an AbstractStockAndFlowStructureF. Need to provide dynamic variable definitions, eg

convertSystemStructureToStockFlow(MyStockFlowStructure, (:v_prevalence=>(:I,:N,:/),:v_meanInfectiousContactsPerS=>(:c,:v_prevalence,:*)))
source
StockFlow.convertToCausalLoopMethod

Convert StockFlow to CausalLoop. Nodes: stocks, flows, sum variables, parameters, nonflow dynamic variables Edges: morphisms in stock flow

source
StockFlow.funcFlowsMethod

return the LVector of pairs: fname => function (with function of sum variables substitue in)

source
StockFlow.funcFlowsRawMethod

return the LVector of pairs: fname => function (raw: not substitutes the function of sum variables yet)

source
StockFlow.funcSVMethod

generate the function of a sum auxiliary variable (index sv) with the sum of all stocks links to it

source
StockFlow.is_circuitMethod

Return true if a given list of edges is a walk, and the target of the final edge is the source of the first.

Empty list of edges does not count as a circuit.

source
StockFlow.is_walkMethod

Return true if a given list of edges is a walk; that the target for each edge is the source of the next. Empty list of edges counts as a walk.

Note, negative edges come after positive edges:

julia> using StockFlow; using StockFlow.Syntax;
julia> cl = (@cl A => +B, B => -C, C => +D, D => -E);
julia> is_walk(cl, [1,3,2,4])
true
source
StockFlow.lsnamesMethod

return the pair of names of (stock, sum-auxiliary-variable) for all linkages between them

source
StockFlow.make_v_expr_nonrecursiveMethod

Generates the expression of an auxiliary variable, only going one layer deep If other dynamic variables make up its definition, they will not be substituted.

source
StockFlow.num_indep_loops_var_onMethod

Count how many loops a variable is on, ignoring when two vertices have more than one edge between them.

A => +B, B => +C, C => +A, C => -A will be treated as 1 loop.

Takes a CausalLoopPM or a CausalLoopPol, and a Symbol. Throws an error if that Symbol is the name for more than one variable.

source
StockFlow.num_loops_var_onMethod

Count how many loops a variable is on.

A => +B, B => +C, C => +A, C => -A will be treated as 2 loops: [1,2,3] and [1,2,4]. Each variable will be treated as being on 2 loops.

Takes a CausalLoopPM or a CausalLoopPol, and a Symbol. Throws an error if that Symbol is the name for more than one variable.

source
StockFlow.pnameMethod

CausalLoopPM, name a positive edge by its source and target. For composition.

source
StockFlow.pnamesMethod

CausalLoopPM, pairs of source, target for positive edges. Used for composition.

source
StockFlow.sedgeMethod

Return source vertex index of an edge of CausalLoopPM by index. Negative edges come after positive edges.

julia-repl julia> using StockFlow; StockFlow.Syntax; julia> cl = (@cl A => +B, B => -C, C => +D); julia> sedge(cl, 3) 2` The nodes are ordered A, B, C. The edges are ordered A => +B, C => +D, B => -C; so, the source index of the third edge is B, which has index 2.

source
StockFlow.tedgeMethod

Return target vertex index of an edge of CausalLoopPM by index. Negative edges come after positive edges. See sedge.

source
StockFlow.to_clpMethod

Create a CausalLoopPol from a vector of node names, and two vectors indicating which indices for vertices will act as edges.

to_clp([:A, :B], [1 => 2], Vector{Pair{Int, Int}}()) will create a CausalLoopPol with a positive polarity edge from A to B.

source
StockFlow.vtgtMethod

return auxiliary variable's source auxiliary variables that it links to

source
StockFlow.SyntaxModule

Alternative syntax for use in the definition of stock and flow models.

Examples

# An S-I-R model of infection
SIR = @stock_and_flow begin
    :stocks
    S
    I
    R

    :parameters
    c
    beta
    tRec

    :dynamic_variables
    v_prevalence = I / N
    v_meanInfectiousContactsPerS = c * v_prevalence
    v_perSIncidenceRate = beta * v_meanInfectiousContactsPerS
    v_newInfections = S * v_perSIncidenceRate
    v_newRecovery = I / tRec

    :flows
    S => inf(v_newInfections) => I
    I => rec(v_newRecovery) => R

    :sums
    N = [S, I, R]
end

# Generates:
# SIR = StockAndFlowF(
#     # stocks
#     (:S => (:F_NONE, :inf, :N), :I => (:inf, :rec, :N), :R => (:rec, :F_NONE, :N)),
#     # parameters
#     (:c, :beta, :tRec),
#     # dynamical variables
#     (   :v_prevalence => ((:I, :N) => :/),
#         :v_meanInfectiousContactsPerS => ((:c, :v_prevalence) => :*),
#         :v_perSIncidenceRate => ((:beta, :v_meanInfectiousContactsPerS) => :*),
#         :v_newInfections => ((:S, :v_perSIncidenceRate) => :*),
#         :v_newRecovery => ((:I, :tRec) => :/),
#     ),
#     # flows
#     (:inf => :v_newInfections, :rec => :v_newRecovery),
#     # sum dynamical variables
#     (:N),
# )

# The same model as before, but with the dynamic variables inferred
SIR_2 = @stock_and_flow begin
    :stocks
    S
    I
    R

    :parameters
    c
    beta
    tRec

    # We can leave out dynamic variables and let them be inferred from flows entirely!

    :flows
    S => inf(S * beta * (c * (I / N))) => I
    I => rec(I / tRec) => R

    :sums
    N = [S, I, R]
end

# Another possible S-I-R model definition
SIR_3 = @stock_and_flow begin
    :stocks
    S
    I
    R

    :parameters
    c
    beta
    tRec
    omega
    alpha

    :dynamic_variables
    v_prevalence = I / totalPopulation
    v_forceOfInfection = c * v_prevalence * beta

    :flows
    S => inf(S * v_forceOfInfection) => I
    ☁ => births(totalPopulation * alpha) => S
    S => deathsS(S * omega) => ☁
    I => rec(I / tRec) => R
    I => deathsI(I * omega) => ☁
    R => deathsR(R * omega) => ☁


    :sums
    totalPopulation = [S, I, R]
end
source
StockFlow.Syntax.cl_macroFunction

Create a causal loop with polarities with a block of statements in a tuple, consisting of A => +B, A => -B and A.

Will create a causal loop without polarities if you use A => B without a + or -.

source
StockFlow.Syntax.create_footMethod
create_foot(block :: Expr)

Create foot (StockAndFlow0) using format A => B, where A is a stock and B is a sum variable. Use () to represent no stock or sum variable. To have multiple stocks or sum variables, chain together multiple pairs with commas. Repeated occurences of the same symbol will be treated as the same stock or sum variable. You cannot create distinct stocks or sum variables with the same name using this format.

standard_foot = @foot A => N
emptyfoot = @foot () => ()
all_seir_links = @foot S => N, E => N, I => N, R => N
no_stocks = @foot () => N, () => NI, () => NS
no_sum = @foot A => ()
multiple_links = @foot A => B, A => B # will have two links from A to B.
source
StockFlow.Syntax.infer_linksMethod
infer_links(sfsrc :: StockAndFlowF, sftgt :: StockAndFlowF, NecMaps :: Dict{Symbol, Vector{Int64}})

Infer LS, I, O, LV, LSV, LVV, LPV mappings for an ACSetTransformation. Returns dictionary of Symbols to lists of indices, corresponding to an ACSetTransformation argument. If there exist no such mappings (eg, no LVV), that pairing will not be included in the returned dictionary.

If A <- C -> B, and we have A -> A' and B -> B' and a unique C' such that A' <- C' -> B', we can assume C -> C'.

:S => [2,4,1,3], :F => [1,2,4,3], ...

NecMaps must contain keys S, F, SV, P, V, each pointing to a (possibly empty) array of indices

source
StockFlow.Syntax.@causal_loopMacro

Create a causal loop diagram, with or without Polarities. X => +Y creates a positive edge, X => -Y a negative, and X => Y creates a causal loop without polarities. Defaults to creating with polarities, if there are no edges.


julia> (@causal_loop begin
       :nodes
       A
       B

       :edges
       A => +B

       end) == CausalLoopPM([:A,:B], [:A => :B], [POL_POSITIVE])
true

julia> ((@causal_loop begin
       :nodes
       λ
       β
       :edges
       λ => β
       β => -λ
       end) ==
       (@causal_loop begin
       :nodes
       λ
       β
       :edges
       λ => β
       β => λ
       end) ==
       CausalLoop([:λ, :β], [:λ => :β, :β => :λ]))
true

julia> (@causal_loop begin end) == CausalLoopPM()
true
source
StockFlow.Syntax.@clMacro

Compressed notation to create causal loop. Using A => B without a + or - creates a CausalLoop without polarities.

julia> (@cl A => +B, C => -D) == CausalLoopPM([:A, :B, :C, :D], [:A => :B, :C => :D], [POL_POSITIVE, POL_NEGATIVE])
true

julia> (@cl A, B, C => -A, C => +B, D) == CausalLoopPM([:A, :B, :C, :D], [:C => :A, :C => :B], [POL_NEGATIVE, POL_POSITIVE])
true
source
StockFlow.Syntax.@clMacro

Compressed notation to create causal loop with polarities.

No argument function for empty causal loop.

julia> @cl
CausalLoopPM {V:0, P:0, M:0, Name:0}
source
StockFlow.Syntax.@feetMacro
feet(block :: Expr)

Create Vector of feet using same notation for foot macro. Separated by newlines. First argument is stock, second is sum variable.

feetses = @feet begin
    A => B
    () => N
    C => ()
    D => E
    () => ()
    P => NI, R => NI, () => N
end
source
StockFlow.Syntax.@footMacro
foot(block :: Expr)

Create a foot with S => N syntax, where S is stock, N is sum variable.

@foot P => Q
@foot S1 => ()
@foot () => N
@foot () => ()
@foot A => N, () => NI
source
StockFlow.Syntax.@stock_and_flowMacro
stock_and_flow(block :: Expr)

Compiles stock and flow syntax of the line-based block form

  :stocks
    symbol_1
    symbol_2
    ...
    symbol_n

  :parameters
    param_1
    param_2
    ...
    param_n

  :dynamic_variables
    dyvar_1 = symbol_h * param_g ... - symbol_x / param_y
    ...
    dyvar_n = symbol_k * param_j - dyvar_a ... - symbol_p / param_q

  :flows
    symbol_r => flow_name_1(dyvar_k) => symbol_q
    symbol_z => flow_name_2(dyvar_g * param_v) => symbol_p
    ☁       => flow_name_3(symbol_c + dyvar_b) => symbol_r
    symbol_j => flow_name_4(param_l + symbol_m) => CLOUD
    ...
    symbol_y => flow_name_n(dyvar_f) => ☁

into a StockAndFlowF data type for use with the StockFlow.jl modelling system.

source