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
+ odesys = convert(ODESystem, rs)
27
+
28
+ # dependency of each ODE on state variables
29
+ equation_dependencies(odesys)
30
+
31
+ # dependency of each ODE on parameters
32
+ equation_dependencies(odesys, variables=parameters(odesys))
33
+
34
+ # Jumps
35
+ jumpsys = convert(JumpSystem, rs)
36
+
37
+ # dependency of each jump rate function on state variables
38
+ equation_dependencies(jumpsys)
39
+
40
+ # dependency of each jump rate function on parameters
41
+ equation_dependencies(jumpsys, variables=parameters(jumpsys))
42
+ ```
43
+ """
3
44
function equation_dependencies (sys:: AbstractSystem ; variables= states (sys))
4
45
eqs = equations (sys)
5
46
deps = Set {Operation} ()
@@ -14,14 +55,74 @@ function equation_dependencies(sys::AbstractSystem; variables=states(sys))
14
55
depeqs_to_vars
15
56
end
16
57
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
+ """
18
85
mutable struct BipartiteGraph{T <: Integer }
86
+ """ Number of edges from source vertices to vertices they depend on."""
19
87
ne:: Int
88
+ """ Forward adjacency list mapping index of source vertices to the vertices they depend on."""
20
89
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."""
21
91
badjlist:: Vector{Vector{T}} # badjlist[dst] = [src1,src2,...]
22
92
end
23
93
24
- # convert equation-variable dependencies to a bipartite graph
94
+ """
95
+ ```julia
96
+ Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer}
97
+ ```
98
+
99
+ Test whether two [`BipartiteGraph`](@ref)s are equal.
100
+ """
101
+ function Base. isequal (bg1:: BipartiteGraph{T} , bg2:: BipartiteGraph{T} ) where {T<: Integer }
102
+ iseq = (bg1. ne == bg2. ne)
103
+ iseq &= (bg1. fadjlist == bg2. fadjlist)
104
+ iseq &= (bg1. badjlist == bg2. badjlist)
105
+ iseq
106
+ end
107
+
108
+ """
109
+ ```julia
110
+ asgraph(eqdeps, vtois)
111
+ ```
112
+
113
+ Convert a collection of equation dependencies, for example as returned by
114
+ `equation_dependencies`, to a [`BipartiteGraph`](@ref).
115
+
116
+ Notes:
117
+ - `vtois` should provide `Dict` like mapping from variable dependency in `eqdeps`
118
+ to the integer idx of the variable to use in the graph.
119
+
120
+ Example:
121
+ Continuing the example started in [`equation_dependencies`](@ref)
122
+ ```julia
123
+ digr = asgraph(equation_dependencies(odesys), Dict(s => i for (i,s) in enumerate(states(odesys))))
124
+ ```
125
+ """
25
126
function asgraph (eqdeps, vtois)
26
127
fadjlist = Vector {Vector{Int}} (undef, length (eqdeps))
27
128
for (i,dep) in enumerate (eqdeps)
@@ -38,22 +139,55 @@ function asgraph(eqdeps, vtois)
38
139
BipartiteGraph (ne, fadjlist, badjlist)
39
140
end
40
141
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
47
142
48
143
# 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)
144
+ """
145
+ ```julia
146
+ asgraph(sys::AbstractSystem; variables=states(sys),
147
+ variablestoids=Dict(convert(Variable, v) => i for (i,v) in enumerate(variables)))
148
+ ```
149
+
150
+ Convert an `AbstractSystem` to a [`BipartiteGraph`](@ref) mapping equations
151
+ to variables they depend on.
152
+
153
+ Notes:
154
+ - Defaults for kwargs creating a mapping from `equations(sys)` to `states(sys)`
155
+ they depend on.
156
+ - `variables` should provide the list of variables to use for generating
157
+ the dependency graph.
158
+ - `variablestoids` should provide `Dict` like mapping from a `Variable` to its
159
+ `Int` index within `variables`.
160
+
161
+ Example:
162
+ Continuing the example started in [`equation_dependencies`](@ref)
163
+ ```julia
164
+ digr = asgraph(odesys)
165
+ ```
166
+ """
167
+ function asgraph (sys:: AbstractSystem ; variables= states (sys),
168
+ variablestoids= Dict (convert (Variable, v) => i for (i,v) in enumerate (variables)))
169
+ asgraph (equation_dependencies (sys, variables= variables), variablestoids)
54
170
end
55
171
56
- # for each variable determine the equations that modify it
172
+ """
173
+ ```julia
174
+ variable_dependencies(sys::AbstractSystem; variables=states(sys), variablestoids=nothing)
175
+ ```
176
+
177
+ For each variable determine the equations that modify it and return as a [`BipartiteGraph`](@ref).
178
+
179
+ Notes:
180
+ - Dependencies are returned as a [`BipartiteGraph`](@ref) mapping variable
181
+ indices to the indices of equations that map to them.
182
+ - `variables` denotes the list of variables to determine dependencies for.
183
+ - `variablestoids` denotes a `Dict` mapping `Variable`s to `Int`s.
184
+
185
+ Example:
186
+ Continuing the example of [`equation_dependencies`](@ref)
187
+ ```julia
188
+ variable_dependencies(odesys)
189
+ ```
190
+ """
57
191
function variable_dependencies (sys:: AbstractSystem ; variables= states (sys), variablestoids= nothing )
58
192
eqs = equations (sys)
59
193
vtois = isnothing (variablestoids) ? Dict (convert (Variable, v) => i for (i,v) in enumerate (variables)) : variablestoids
@@ -76,7 +210,31 @@ function variable_dependencies(sys::AbstractSystem; variables=states(sys), varia
76
210
BipartiteGraph (ne, fadjlist, badjlist)
77
211
end
78
212
79
- # convert BipartiteGraph to LightGraph.SimpleDiGraph
213
+ """
214
+ ```julia
215
+ asdigraph(g::BipartiteGraph, sys::AbstractSystem; variables = states(sys), equationsfirst = true)
216
+ ```
217
+
218
+ Convert a [`BipartiteGraph`](@ref) to a `LightGraph.SimpleDiGraph`.
219
+
220
+ Notes:
221
+ - The resulting `SimpleDiGraph` unifies the two sets of vertices (equations
222
+ and then states in the case it comes from [`asgraph`](@ref)), producing one
223
+ ordered set of integer vertices (`SimpleDiGraph` does not support two distinct
224
+ collections of vertices so they must be merged).
225
+ - `variables` gives the variables that `g` is associated with (usually the
226
+ `states` of a system).
227
+ - `equationsfirst` (default is `true`) gives whether the [`BipartiteGraph`](@ref)
228
+ gives a mapping from equations to variables they depend on (`true`), as calculated
229
+ by [`asgraph`](@ref), or whether it gives a mapping from variables to the equations
230
+ that modify them, as calculated by [`variable_dependencies`](@ref).
231
+
232
+ Example:
233
+ Continuing the example in [`asgraph`](@ref)
234
+ ```julia
235
+ dg = asdigraph(digr)
236
+ ```
237
+ """
80
238
function asdigraph (g:: BipartiteGraph , sys:: AbstractSystem ; variables = states (sys), equationsfirst = true )
81
239
neqs = length (equations (sys))
82
240
nvars = length (variables)
@@ -96,7 +254,25 @@ function asdigraph(g::BipartiteGraph, sys::AbstractSystem; variables = states(sy
96
254
SimpleDiGraph (g. ne, fadjlist, badjlist)
97
255
end
98
256
99
- # maps the i'th eq to equations that depend on it
257
+ """
258
+ ```julia
259
+ eqeq_dependencies(eqdeps::BipartiteGraph{T}, vardeps::BipartiteGraph{T}) where {T <: Integer}
260
+ ```
261
+
262
+ Calculate a `LightGraph.SimpleDiGraph` that maps each equation to equations they depend on.
263
+
264
+ Notes:
265
+ - The `fadjlist` of the `SimpleDiGraph` maps from an equation to the equations that
266
+ modify variables it depends on.
267
+ - The `badjlist` of the `SimpleDiGraph` maps from an equation to equations that
268
+ depend on variables it modifies.
269
+
270
+ Example:
271
+ Continuing the example of `equation_dependencies`
272
+ ```julia
273
+ eqeqdep = eqeq_dependencies(asgraph(odesys), variable_dependencies(odesys))
274
+ ```
275
+ """
100
276
function eqeq_dependencies (eqdeps:: BipartiteGraph{T} , vardeps:: BipartiteGraph{T} ) where {T <: Integer }
101
277
g = SimpleDiGraph {T} (length (eqdeps. fadjlist))
102
278
@@ -111,5 +287,23 @@ function eqeq_dependencies(eqdeps::BipartiteGraph{T}, vardeps::BipartiteGraph{T}
111
287
g
112
288
end
113
289
114
- # maps the i'th variable to variables that depend on it
290
+ """
291
+ ```julia
292
+ varvar_dependencies(eqdeps::BipartiteGraph{T}, vardeps::BipartiteGraph{T}) where {T <: Integer} = eqeq_dependencies(vardeps, eqdeps)
293
+ ```
294
+
295
+ Calculate a `LightGraph.SimpleDiGraph` that maps each variable to variables they depend on.
296
+
297
+ Notes:
298
+ - The `fadjlist` of the `SimpleDiGraph` maps from a variable to the variables that
299
+ depend on it.
300
+ - The `badjlist` of the `SimpleDiGraph` maps from a variable to variables on which
301
+ it depends.
302
+
303
+ Example:
304
+ Continuing the example of `equation_dependencies`
305
+ ```julia
306
+ varvardep = varvar_dependencies(asgraph(odesys), variable_dependencies(odesys))
307
+ ```
308
+ """
115
309
varvar_dependencies (eqdeps:: BipartiteGraph{T} , vardeps:: BipartiteGraph{T} ) where {T <: Integer } = eqeq_dependencies (vardeps, eqdeps)
0 commit comments