@@ -206,9 +206,6 @@ function laplacianmat(rn::ReactionSystem, pmap::Dict = Dict(); sparse = false)
206
206
D * K
207
207
end
208
208
209
- Base. zero (:: Type{Union{R, Symbolics.BasicSymbolic{Real}}} ) where R <: Real = zero (R)
210
- Base. one (:: Type{Union{R, Symbolics.BasicSymbolic{Real}}} ) where R <: Real = one (R)
211
-
212
209
@doc raw """
213
210
fluxmat(rn::ReactionSystem, pmap = Dict(); sparse=false)
214
211
@@ -225,8 +222,6 @@ function fluxmat(rn::ReactionSystem, pmap::Dict = Dict(); sparse=false)
225
222
end
226
223
227
224
rcmap = reactioncomplexmap (rn)
228
- nc = length (rcmap)
229
- nr = length (rates)
230
225
mtype = eltype (rates) <: Symbolics.BasicSymbolic ? Num : eltype (rates)
231
226
if sparse
232
227
return fluxmat (SparseMatrixCSC{mtype, Int}, rcmap, rates)
@@ -936,7 +931,7 @@ function isdetailedbalanced(rs::ReactionSystem, parametermap::Dict; abstol=0, re
936
931
complexes, D = reactioncomplexes (rs)
937
932
img = incidencematgraph (rs)
938
933
undir_img = SimpleGraph (incidencematgraph (rs))
939
- K = ratematrix (rs, pmap)
934
+ K = adjacencymat (rs, pmap)
940
935
941
936
spanning_forest = Graphs. kruskal_mst (undir_img)
942
937
outofforest_edges = setdiff (collect (edges (undir_img)), spanning_forest)
@@ -993,52 +988,26 @@ function isdetailedbalanced(rs::ReactionSystem, parametermap)
993
988
end
994
989
995
990
"""
996
- iscomplexbalanced(rs::ReactionSystem, parametermap)
991
+ iscomplexbalanced(rs::ReactionSystem, parametermap; sparse = false )
997
992
998
993
Constructively compute whether a network will have complex-balanced equilibrium
999
994
solutions, following the method in van der Schaft et al., [2015](https://link.springer.com/article/10.1007/s10910-015-0498-2#Sec3).
1000
- Accepts a dictionary, vector, or tuple of variable-to-value mappings, e.g. [k1 => 1.0, k2 => 2.0,...].
1001
- """
1002
- function iscomplexbalanced (rs:: ReactionSystem , parametermap:: Dict )
1003
- if length (parametermap) != numparams (rs)
1004
- error (" Incorrect number of parameters specified." )
1005
- end
1006
995
1007
- pmap = symmap_to_varmap (rs, parametermap)
1008
- pmap = Dict (ModelingToolkit. value (k) => v for (k, v) in pmap)
1009
-
1010
- sm = speciesmap (rs)
1011
- cm = reactioncomplexmap (rs)
1012
- complexes, D = reactioncomplexes (rs)
996
+ Requires the specification of values for the parameters/rate constants. Accepts a dictionary, vector, or tuple of parameter-to-value mappings, e.g. [k1 => 1.0, k2 => 2.0,...].
997
+ """
998
+ function iscomplexbalanced (rs:: ReactionSystem , parametermap:: Dict ; sparse = false )
1013
999
rxns = reactions (rs)
1014
- nc = length (complexes)
1015
- nr = numreactions (rs)
1016
- nm = numspecies (rs)
1017
-
1018
1000
if ! all (r -> ismassaction (r, rs), rxns)
1019
1001
error (" The supplied ReactionSystem has reactions that are not ismassaction. Testing for being complex balanced is currently only supported for pure mass action networks." )
1020
1002
end
1021
1003
1022
- rates = [substitute (rate, pmap) for rate in reactionrates (rs)]
1023
-
1024
- # Construct kinetic matrix, K
1025
- K = zeros (nr, nc)
1026
- for c in 1 : nc
1027
- complex = complexes[c]
1028
- for (r, dir) in cm[complex]
1029
- rxn = rxns[r]
1030
- if dir == - 1
1031
- K[r, c] = rates[r]
1032
- end
1033
- end
1034
- end
1035
-
1036
- L = - D * K
1037
- S = netstoichmat (rs)
1004
+ L = laplacianmat (rs, parametermap; sparse)
1005
+ D = incidencemat (rs; sparse)
1006
+ S = netstoichmat (rs; sparse)
1038
1007
1039
1008
# Compute ρ using the matrix-tree theorem
1040
1009
g = incidencematgraph (rs)
1041
- R = ratematrix (rs, rates )
1010
+ R = adjacencymat (rs, parametermap; sparse )
1042
1011
ρ = matrixtree (g, R)
1043
1012
1044
1013
# Determine if 1) ρ is positive and 2) D^T Ln ρ lies in the image of S^T
@@ -1069,50 +1038,74 @@ function iscomplexbalanced(rs::ReactionSystem, parametermap)
1069
1038
end
1070
1039
1071
1040
"""
1072
- ratematrix (rs::ReactionSystem, parametermap )
1041
+ adjacencymat (rs::ReactionSystem, pmap = Dict(); sparse = false )
1073
1042
1074
1043
Given a reaction system with n complexes, outputs an n-by-n matrix where R_{ij} is the rate
1075
1044
constant of the reaction between complex i and complex j. Accepts a dictionary, vector, or tuple
1076
1045
of variable-to-value mappings, e.g. [k1 => 1.0, k2 => 2.0,...].
1046
+
1047
+ Equivalent to the adjacency matrix of the weighted graph whose weights are the
1048
+ reaction rates.
1049
+ Returns a symbolic matrix by default, but will return a numerical matrix if parameter values are specified via pmap.
1050
+
1051
+ The difference between this matrix and [`fluxmat`](@ref) is quite subtle. The non-zero entries to both matrices are the rate constants. However:
1052
+ - In `fluxmat`, the rows represent complexes and columns represent reactions, and an entry (c, r) is non-zero if reaction r's source complex is c.
1053
+ - In `adjacencymat`, the rows and columns both represent complexes, and an entry (c1, c2) is non-zero if there is a reaction c1 --> c2.
1077
1054
"""
1078
- function ratematrix (rs:: ReactionSystem , rates:: Vector{Float64} )
1079
- complexes, D = reactioncomplexes (rs)
1080
- n = length (complexes)
1081
- rxns = reactions (rs)
1082
- ratematrix = zeros (n, n)
1055
+ function adjacencymat (rn:: ReactionSystem , pmap:: Dict = Dict (); sparse = false )
1056
+ rates = if isempty (pmap)
1057
+ reactionrates (rn)
1058
+ else
1059
+ substitutevals (rn, pmap, parameters (rn), reactionrates (rn))
1060
+ end
1061
+ mtype = eltype (rates) <: Symbolics.BasicSymbolic ? Num : eltype (rates)
1083
1062
1084
- for r in 1 : length (rxns)
1085
- rxn = rxns[r]
1086
- s = findfirst (== (- 1 ), @view D[:, r])
1087
- p = findfirst (== (1 ), @view D[:, r])
1088
- ratematrix[s, p] = rates[r]
1063
+ if sparse
1064
+ return adjacencymat (SparseMatrixCSC{mtype, Int}, incidencemat (rn), rates)
1065
+ else
1066
+ return adjacencymat (Matrix{mtype}, incidencemat (rn), rates)
1089
1067
end
1090
- ratematrix
1091
1068
end
1092
1069
1093
- function ratematrix (rs:: ReactionSystem , parametermap:: Dict )
1094
- if length (parametermap) != numparams (rs)
1095
- error (" Incorrect number of parameters specified." )
1070
+ function adjacencymat (:: Type{SparseMatrixCSC{T, Int}} , D, rates) where T
1071
+ Is = Int[]
1072
+ Js = Int[]
1073
+ Vs = T[]
1074
+ nc = size (D, 1 )
1075
+
1076
+ for r in 1 : length (rates)
1077
+ s = findfirst (== (- 1 ), @view D[:, r])
1078
+ p = findfirst (== (1 ), @view D[:, r])
1079
+ push! (Is, s)
1080
+ push! (Js, p)
1081
+ push! (Vs, rates[r])
1096
1082
end
1083
+ A = sparse (Is, Js, Vs, nc, nc)
1084
+ end
1097
1085
1098
- pmap = symmap_to_varmap (rs, parametermap)
1099
- pmap = Dict (ModelingToolkit. value (k) => v for (k, v) in pmap)
1086
+ function adjacencymat (:: Type{Matrix{T}} , D, rates) where T
1087
+ nc = size (D, 1 )
1088
+ A = zeros (T, nc, nc)
1100
1089
1101
- rates = [substitute (rate, pmap) for rate in reactionrates (rs)]
1102
- ratematrix (rs, rates)
1090
+ for r in 1 : length (rates)
1091
+ s = findfirst (== (- 1 ), @view D[:, r])
1092
+ p = findfirst (== (1 ), @view D[:, r])
1093
+ A[s, p] = rates[r]
1094
+ end
1095
+ A
1103
1096
end
1104
1097
1105
- function ratematrix (rs :: ReactionSystem , parametermap :: Vector{<:Pair} )
1106
- pdict = Dict (parametermap )
1107
- ratematrix (rs , pdict)
1098
+ function adjacencymat (rn :: ReactionSystem , pmap :: Vector{<:Pair} ; sparse = false )
1099
+ pdict = Dict (pmap )
1100
+ adjacencymat (rn , pdict; sparse )
1108
1101
end
1109
1102
1110
- function ratematrix (rs :: ReactionSystem , parametermap :: Tuple )
1111
- pdict = Dict (parametermap )
1112
- ratematrix (rs , pdict)
1103
+ function adjacencymat (rn :: ReactionSystem , pmap :: Tuple ; sparse = false )
1104
+ pdict = Dict (pmap )
1105
+ adjacencymat (rn , pdict; sparse )
1113
1106
end
1114
1107
1115
- function ratematrix (rs :: ReactionSystem , parametermap )
1108
+ function adjacencymat (rn :: ReactionSystem , pmap )
1116
1109
error (" Parameter map must be a dictionary, tuple, or vector of symbol/value pairs." )
1117
1110
end
1118
1111
0 commit comments