Skip to content

Commit

Permalink
Merge pull request #128 from neonWhiteout/SemanticDomainsNoZero
Browse files Browse the repository at this point in the history
Causal Loop with Polarities
  • Loading branch information
neonWhiteout authored Aug 19, 2024
2 parents ee5ab0f + 19ee94f commit b4043b8
Show file tree
Hide file tree
Showing 17 changed files with 2,513 additions and 515 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "StockFlow"
uuid = "58c4a0e8-2944-4d18-9fa2-e17726aee9e5"
license = "MIT"
authors = ["Xiaoyan Li <[email protected]>"]
version = "0.2.2"
version = "0.2.3"

[deps]
AlgebraicRewriting = "725a01d3-f174-5bbd-84e1-b9417bad95d9"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# # Causal Loop Operations

using StockFlow
using StockFlow.Syntax
using StockFlow.PremadeModels

GraphCL(convertToCausalLoop(seir()))

C2 = CausalLoopPM([:C2], [:C2 => :C2 for _ in 1:5], [POL_NEGATIVE, POL_POSITIVE, POL_NEGATIVE, POL_POSITIVE, POL_NEGATIVE])

C2′ = @causal_loop begin
:nodes
C2
:edges
C2 => -C2
C2 => +C2
C2 => -C2
C2 => +C2
C2 => -C2
end;

C2′′ = (@cl C2 => -C2, C2 => +C2, C2 => -C2, C2 => +C2, C2 => -C2);

C2 == C2′ == C2′′

GraphCL(C2)

GraphRB(C2)

CL_ABC = @cl A => +B, B => +C, C => -A, D

GraphCL(CL_ABC)

GraphRB(CL_ABC)

nvert(CL_ABC)

nedges(CL_ABC)

np(CL_ABC)

nm(CL_ABC)

sedge(CL_ABC, 3) # Source node for edge 3, which is C => A, is C, which is index 3

tedge(CL_ABC, 3) # C => A, target is A, with index 1

vnames(CL_ABC)

epol(CL_ABC, 1) # Polarity of edge 1, A => B, is positive

epols(CL_ABC)

outgoing_edges(CL_ABC, 1) # indices of all edges with src 1 (in this case, A)

outgoing_edges(CL_ABC, 4) # D

incoming_edges(CL_ABC, 1) # indices of all edges with src 1

cl_cycles(CL_ABC)

extract_loops(CL_ABC)

is_walk(CL_ABC, [1,2,3,1,2])

is_walk(CL_ABC, [3,2])

is_walk(CL_ABC, Vector{Int}())

is_circuit(CL_ABC, [1,2,3])

is_circuit(CL_ABC, [1,2])

walk_polarity(CL_ABC, [1,2,3,1,2,3])

extract_all_nonduplicate_paths(CL_ABC)

num_loops_var_on(CL_ABC, :D)

num_loops_var_on(CL_ABC, :A)

num_loops_var_on(C2, :C2)

num_indep_loops_var_on(C2, :C2) # Treating each pair of nodes as if there is at most one edge between them

to_graphs_graph(CL_ABC)

betweenness(CL_ABC)

to_graphs_graph(C2) # eliminates duplicate edges!

betweenness(C2)

num_inputs_outputs(C2) # in, out

num_inputs_outputs_pols(C2) # pos in, pos out, neg in, neg out

all_shortest_paths(C2)

all_shortest_paths(@cl((A => B, B => C, C => D, A => B′, B′ => C′, C′ => D)))

shortest_paths( (@cl A => B, B => C, C => D, A => B′, B′ => C′, C′ => D), :A, :D )

betweenness(@cl((A => B, B => C, C => D, A => B′, B′ => C′, C′ => D)))

all_shortest_paths(convertToCausalLoop(seir()))

all_shortest_paths(CL_ABC)

GraphCL(CL_ABC)

shortest_paths(CL_ABC, :A, :C)

cl = @causal_loop begin
:nodes
A
B
C
D
E
:edges
A => B
B => C
B => C
B => D
D => C
end;

cl2 = @causal_loop begin
:nodes
A
B
C
D
E
:edges
A => B
B => C
B => D
D => C
end;

GraphCL(cl)

betweenness(cl)

betweenness(cl2)

# ### Note, negative polarities always come after positive!

cl_small = @cl A => -B, B => +C

epols(cl_small)

to_simple_cl(cl_small) == (@cl A, B => C, A => B) # Note the order!

to_simple_cl(cl_small)

using StockFlow.Syntax.Composition

ABC = (@cl A => B, B => C)
BCD = (@cl B => C, C => D)
@compose ABC BCD begin
(ABC, BCD)
(ABC, BCD) ^ B => C
end

ABC_pol = (@cl A => +B, B => -C)
BCD_pol = (@cl B => -C, C => +D)
@compose ABC_pol BCD_pol begin
(ABC, BCD)
(ABC, BCD) ^ B => -C
end

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ GraphF(seir)

seir_causalLoop = convertToCausalLoop(seir)

Graph(seir_causalLoop)
GraphCL(seir_causalLoop)


1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ makedocs(
"Example" => Any[
"generated/Covid19_composition_model_in_paper.md",
"generated/full_fledged_schema_examples_new/CasualLoopDiagrams/convert_from_SEIR_stockFlowDiagram.md",
"generated/full_fledged_schema_examples_new/CasualLoopDiagrams/Causal_Loop_Operations.md",
"generated/full_fledged_schema_examples_new/composition/composed_open_population_SIRV_model.md",
"generated/full_fledged_schema_examples_new/composition/COVID_full_model.md",
"generated/full_fledged_schema_examples_new/composition/curable_sexually_transmitted_diseases_model.md",
Expand Down
142 changes: 109 additions & 33 deletions docs/src/DSLs.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,100 @@ end) == ([StockAndFlow0([:A, :AA],[:B],[:A => :B, :AA => :B]),
StockAndFlow0([:X, :Z],[:Y, :B],[:X => :Y, :X => :B])])
```

---

---

## @causal_loop

Create a causal loop, with or without polarities. X => +Y indicates a positive
polarity, X => -Y indicates a negative polarity, and if there are any edges
X => Y without polarities, the ultimate causal loop diagram will be without
polarities.

Use :nodes to indicate nodes, and :edges to indicate edges.

If there are no edges, will default to a causal loop with polarities.

Note, for functions which return indices for edges, negative edges come
after positive edges.

Avoid using nodes with the same name.

```julia

# Triangle, without polarities.
@causal_loop begin
:nodes
A
B
C

:edges
A => B
B => C
C => A
end

# Triangle, with polarities, creating a balancing loop.
@causal_loop begin
:nodes
A
B
C

:edges
A => -B
B => +C
C => +A
end

# Causal loop with two nodes and three edges;
# A has a positive self edge, and A has two edges to B, one positive, one negative.
@causal_loop begin
:nodes
A
B

:edges
A => +A
A => +B
A => -B
end

# Empty causal loop, treated with polarities.
@causal_loop begin end

```

---

## @cl

Compressed syntax for creating a causal loop diagram. Similar to above.

Separate statements with commas, and use a symbol on its own to indicate a
node without an edge. Nodes will be ordered in the order they're encountered.

```julia
# Triangle, without polarities.
(@cl A => B, B => C, C => A)
# Triangle, with polarities, creating a balancing loop.
(@cl A => -B, B => +C C => +A)

# No edges between nodes, treated as a causal loop with polarities.
(@cl A, B, C)

# Same as first, but now C is node 1, B is node 2, and A is node 3.
(@cl C, B, A => B, B => C, C => A)

# Empty causal loop, treated as with polarities.
(@cl)

```



---

# Stratification
Expand Down Expand Up @@ -261,6 +355,10 @@ and sums which are in the corresponding foot.

Composition with no stockflows given as argument returns an empty stockflow.

Composition also works with causal loop diagrams. If using causal loop with
polarities, the edges you compose on must have the same polarities; you
cannot compose A => +B with A => -B.

```julia
(@compose begin
()
Expand All @@ -287,6 +385,15 @@ Diabetes_Model = @compose Model_Normoglycemic Model_Hyperglycemic Model_Norm_Hyp
(Hyper, NH) ^ Prediabetic_U => N
(Hyper, NH) ^ Prediabetic_D => N
end

ABC = (@cl A => B, B => C)
BCD = (@cl B => C, C => D)

ABCD = @compose ABC BCD begin
(ABC, BCD)
(ABC, BCD) ^ B => C
end

```

---
Expand All @@ -306,10 +413,10 @@ Rewrite has 8 headers, :stocks, :flows, :sums, :dynamic\_variables, :redefs, :re
and :dyvar\_swaps

The first five are used to indicate if an instance of that type is being
added. Use the same definition syntax as in @stock_and_flow.
added. Use the same definition syntax as in @stock\_and\_flow.

:redefs is used to change the definition of a dynamic variable, flow or
sum. Again, use the same syntax as in @stock_and_flow.
sum. Again, use the same syntax as in @stock\_and\_flow.

:removes indicates that an object should be deleted. You just need the name of it in the original.

Expand Down Expand Up @@ -370,39 +477,8 @@ end

---

# Homomorphism

## @hom

Using two stockflows and a block with the same headers as @stratify, define an ACSetTransformation from the first stockflow to another.

Half of a stratify. Rather than creating two homomorphisms and taking the pullback, creates one homomorphism.

```julia
@hom WeightModel l_type begin
:stocks
NormalWeight => pop
OverWeight => pop
Obese => pop

:parameters
μ => μ
~δ => δ
rage => rage
_ => rFstOrder

:dynamic_variables
v_NewBorn => v_birth
~Becoming => v_fstOrder
~Death => v_death
_ => v_aging

:flows
f_NewBorn => f_birth
~Becoming => f_fstOrder
~Death => f_death
~id => f_aging
_ => f_death

end
```
Loading

0 comments on commit b4043b8

Please sign in to comment.