@@ -206,9 +206,6 @@ function laplacianmat(rn::ReactionSystem, pmap::Dict = Dict(); sparse = false)
206206 D * K
207207end
208208
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-
212209@doc raw """
213210 fluxmat(rn::ReactionSystem, pmap = Dict(); sparse=false)
214211
@@ -225,8 +222,6 @@ function fluxmat(rn::ReactionSystem, pmap::Dict = Dict(); sparse=false)
225222 end
226223
227224 rcmap = reactioncomplexmap (rn)
228- nc = length (rcmap)
229- nr = length (rates)
230225 mtype = eltype (rates) <: Symbolics.BasicSymbolic ? Num : eltype (rates)
231226 if sparse
232227 return fluxmat (SparseMatrixCSC{mtype, Int}, rcmap, rates)
@@ -936,7 +931,7 @@ function isdetailedbalanced(rs::ReactionSystem, parametermap::Dict; abstol=0, re
936931 complexes, D = reactioncomplexes (rs)
937932 img = incidencematgraph (rs)
938933 undir_img = SimpleGraph (incidencematgraph (rs))
939- K = ratematrix (rs, pmap)
934+ K = adjacencymat (rs, pmap)
940935
941936 spanning_forest = Graphs. kruskal_mst (undir_img)
942937 outofforest_edges = setdiff (collect (edges (undir_img)), spanning_forest)
@@ -993,52 +988,26 @@ function isdetailedbalanced(rs::ReactionSystem, parametermap)
993988end
994989
995990"""
996- iscomplexbalanced(rs::ReactionSystem, parametermap)
991+ iscomplexbalanced(rs::ReactionSystem, parametermap; sparse = false )
997992
998993Constructively compute whether a network will have complex-balanced equilibrium
999994solutions, 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
1006995
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 )
1013999 rxns = reactions (rs)
1014- nc = length (complexes)
1015- nr = numreactions (rs)
1016- nm = numspecies (rs)
1017-
10181000 if ! all (r -> ismassaction (r, rs), rxns)
10191001 error (" The supplied ReactionSystem has reactions that are not ismassaction. Testing for being complex balanced is currently only supported for pure mass action networks." )
10201002 end
10211003
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)
10381007
10391008 # Compute ρ using the matrix-tree theorem
10401009 g = incidencematgraph (rs)
1041- R = ratematrix (rs, rates )
1010+ R = adjacencymat (rs, parametermap; sparse )
10421011 ρ = matrixtree (g, R)
10431012
10441013 # 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)
10691038end
10701039
10711040"""
1072- ratematrix (rs::ReactionSystem, parametermap )
1041+ adjacencymat (rs::ReactionSystem, pmap = Dict(); sparse = false )
10731042
10741043 Given a reaction system with n complexes, outputs an n-by-n matrix where R_{ij} is the rate
10751044 constant of the reaction between complex i and complex j. Accepts a dictionary, vector, or tuple
10761045 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.
10771054"""
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)
10831062
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)
10891067 end
1090- ratematrix
10911068end
10921069
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])
10961082 end
1083+ A = sparse (Is, Js, Vs, nc, nc)
1084+ end
10971085
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)
11001089
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
11031096end
11041097
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 )
11081101end
11091102
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 )
11131106end
11141107
1115- function ratematrix (rs :: ReactionSystem , parametermap )
1108+ function adjacencymat (rn :: ReactionSystem , pmap )
11161109 error (" Parameter map must be a dictionary, tuple, or vector of symbol/value pairs." )
11171110end
11181111
0 commit comments