Skip to content

Commit c44a35f

Browse files
committed
start dg docs
1 parent 2c62ae2 commit c44a35f

File tree

3 files changed

+150
-16
lines changed

3 files changed

+150
-16
lines changed

docs/make.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ makedocs(
1919
"systems/NonlinearSystem.md",
2020
"systems/OptimizationSystem.md",
2121
"systems/ReactionSystem.md",
22-
"systems/PDESystem.md"
22+
"systems/PDESystem.md",
23+
"systems/DependencyGraphs.md"
2324
],
2425
"IR.md"
2526
]

docs/src/systems/DependencyGraphs.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Dependency Graphs
2+
3+
# Types
4+
```@docs
5+
BipartiteGraph
6+
```
7+
8+
# Functions for calculating dependency graphs
9+
```@docs
10+
equation_dependencies
11+
asgraph
12+
```

src/systems/dependency_graphs.jl

+136-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,46 @@
1-
# variables equations depend on as a vector of vectors of variables
2-
# each system type should define extract_variables! for a single equation
1+
"""
2+
```julia
3+
equation_dependencies(sys::AbstractSystem; variables=states(sys))
4+
```
5+
6+
Given an `AbstractSystem` calculate for each equation the variables it depends on.
7+
8+
Notes:
9+
- Variables that are not in `variables` are filtered out.
10+
- `get_variables!` is used to determine the variables within a given equation.
11+
- returns a `Vector{Vector{Variable}}()` mapping the index of an equation to the `variables` it depends on.
12+
13+
Example:
14+
```julia
15+
using ModelingToolkit
16+
@parameters β γ κ η t
17+
@variables S(t) I(t) R(t)
18+
19+
# use a reaction system to easily generate ODE and jump systems
20+
rxs = [Reaction(β, [S,I], [I], [1,1], [2]),
21+
Reaction(γ, [I], [R]),
22+
Reaction(κ+η, [R], [S])]
23+
rs = ReactionSystem(rxs, t, [S,I,R], [β,γ,κ,η])
24+
25+
# ODEs:
26+
os = convert(ODESystem, rs)
27+
28+
# dependency of each ODE on state variables
29+
equation_dependencies(os)
30+
31+
# dependency of each ODE on parameters
32+
equation_dependencies(os, variables=parameters(os))
33+
34+
# Jumps
35+
js = convert(JumpSystem, rs)
36+
37+
# dependency of each jump rate function on state variables
38+
equation_dependencies(js)
39+
40+
# dependency of each jump rate function on parameters
41+
equation_dependencies(js, variables=parameters(js))
42+
```
43+
"""
344
function equation_dependencies(sys::AbstractSystem; variables=states(sys))
445
eqs = equations(sys)
546
deps = Set{Operation}()
@@ -14,14 +55,67 @@ function equation_dependencies(sys::AbstractSystem; variables=states(sys))
1455
depeqs_to_vars
1556
end
1657

17-
# modeled on LightGraphs SimpleGraph
58+
"""
59+
$(TYPEDEF)
60+
61+
A bipartite graph representation between two, possibly distinct, sets of vertices
62+
(source and dependencies). Maps source vertices, labelled `1:N₁`, to vertices
63+
on which they depend (labelled `1:N₂`).
64+
65+
# Fields
66+
$(FIELDS)
67+
68+
# Example
69+
```julia
70+
using ModelingToolkit
71+
72+
ne = 4
73+
srcverts = 1:4
74+
depverts = 1:2
75+
76+
# six source vertices
77+
fadjlist = [[1],[1],[2],[2],[1],[1,2]]
78+
79+
# two vertices they depend on
80+
badjlist = [[1,2,5,6],[3,4,6]]
81+
82+
bg = BipartiteGraph(7, fadjlist, badjlist)
83+
```
84+
"""
1885
mutable struct BipartiteGraph{T <: Integer}
86+
"""Number of edges from source vertices to vertices they depend on."""
1987
ne::Int
88+
"""Forward adjacency list mapping index of source vertices to the vertices they depend on."""
2089
fadjlist::Vector{Vector{T}} # fadjlist[src] = [dest1,dest2,...]
90+
"""Backwrad adjacency list mapping index of vertices that are dependencies to the source vertices that depend on them."""
2191
badjlist::Vector{Vector{T}} # badjlist[dst] = [src1,src2,...]
2292
end
2393

24-
# convert equation-variable dependencies to a bipartite graph
94+
function Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer}
95+
iseq = (bg1.ne == bg2.ne)
96+
iseq &= (bg1.fadjlist == bg2.fadjlist)
97+
iseq &= (bg1.badjlist == bg2.badjlist)
98+
iseq
99+
end
100+
101+
"""
102+
```julia
103+
asgraph(eqdeps, vtois)
104+
```
105+
106+
Convert a collection of equation dependencies, for example as returned by
107+
`equation_dependencies`, to a `BipartiteGraph`.
108+
109+
Notes:
110+
- `vtois` should provide `Dict` like mapping from variable dependency in `eqdeps`
111+
to the integer idx of the variable to use in the graph.
112+
113+
Example:
114+
Continuing the example started in [`equation_dependencies`](@ref)
115+
```julia
116+
digr = asgraph(equation_dependencies(os), Dict(s => i for (i,s) in enumerate(states(os))))
117+
```
118+
"""
25119
function asgraph(eqdeps, vtois)
26120
fadjlist = Vector{Vector{Int}}(undef, length(eqdeps))
27121
for (i,dep) in enumerate(eqdeps)
@@ -38,20 +132,41 @@ function asgraph(eqdeps, vtois)
38132
BipartiteGraph(ne, fadjlist, badjlist)
39133
end
40134

41-
function Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer}
42-
iseq = (bg1.ne == bg2.ne)
43-
iseq &= (bg1.fadjlist == bg2.fadjlist)
44-
iseq &= (bg1.badjlist == bg2.badjlist)
45-
iseq
46-
end
47135

48136
# could be made to directly generate graph and save memory
49-
function asgraph(sys::AbstractSystem; variables=nothing, variablestoids=nothing)
50-
vs = isnothing(variables) ? states(sys) : variables
51-
eqdeps = equation_dependencies(sys, variables=vs)
52-
vtois = isnothing(variablestoids) ? Dict(convert(Variable, v) => i for (i,v) in enumerate(vs)) : variablestoids
53-
asgraph(eqdeps, vtois)
137+
"""
138+
```julia
139+
asgraph(sys::AbstractSystem; variables=states(sys),
140+
variablestoids=Dict(convert(Variable, v) => i for (i,v) in enumerate(variables)))
141+
```
142+
143+
Convert an `AbstractSystem` to a `BipartiteGraph` mapping equations
144+
to variables they depend on.
145+
146+
Notes:
147+
- Defaults for kwargs creating a mapping from `equations(sys)` to `states(sys)`
148+
they depend on.
149+
- `variables` should provide the list of variables to use for generating
150+
the dependency graph.
151+
- `variablestoids` should provide `Dict` like mapping from a variable to its
152+
integer index within `variables`.
153+
154+
Example:
155+
Continuing the example started in [`equation_dependencies`](@ref)
156+
```julia
157+
digr = asgraph(os)
158+
```
159+
"""
160+
function asgraph(sys::AbstractSystem; variables=states(sys),
161+
variablestoids=Dict(convert(Variable, v) => i for (i,v) in enumerate(variables)))
162+
asgraph(equation_dependencies(sys, variables=variables), variablestoids)
54163
end
164+
# function asgraph(sys::AbstractSystem; variables=nothing, variablestoids=nothing)
165+
# vs = isnothing(variables) ? states(sys) : variables
166+
# eqdeps = equation_dependencies(sys, variables=vs)
167+
# vtois = isnothing(variablestoids) ? Dict(convert(Variable, v) => i for (i,v) in enumerate(vs)) : variablestoids
168+
# asgraph(eqdeps, vtois)
169+
# end
55170

56171
# for each variable determine the equations that modify it
57172
function variable_dependencies(sys::AbstractSystem; variables=states(sys), variablestoids=nothing)
@@ -76,6 +191,12 @@ function variable_dependencies(sys::AbstractSystem; variables=states(sys), varia
76191
BipartiteGraph(ne, fadjlist, badjlist)
77192
end
78193

194+
"""
195+
- The resulting `SimpleDiGraph` unifies the two sets of vertices (equations
196+
and then states in the case `eqdeps` comes from `equation_dependencies`), producing
197+
one ordered set of integer vertices (as `SimpleDiGraph` does not support two distinct
198+
collections of nodes.
199+
"""
79200
# convert BipartiteGraph to LightGraph.SimpleDiGraph
80201
function asdigraph(g::BipartiteGraph, sys::AbstractSystem; variables = states(sys), equationsfirst = true)
81202
neqs = length(equations(sys))

0 commit comments

Comments
 (0)