@@ -769,3 +769,110 @@ function iscomplexbalanced(rs::ReactionSystem, parametermap::Dict)
769
769
# Determine if 1) ρ is positive and 2) D^T Ln ρ lies in the image of S^T
770
770
if all (> (0 ), ρ)
771
771
img = D' * log .(ρ)
772
+ if rank (S' ) == rank (hcat (S' , img)) return true else return false end
773
+ else
774
+ return false
775
+ end
776
+ end
777
+
778
+ function iscomplexbalanced (rs:: ReactionSystem , parametermap:: Vector{Pair{Symbol, Float64}} )
779
+ pdict = Dict (parametermap)
780
+ iscomplexbalanced (rs, pdict)
781
+ end
782
+
783
+ function iscomplexbalanced (rs:: ReactionSystem , parametermap:: Tuple{Pair{Symbol, Float64}} )
784
+ pdict = Dict (parametermap)
785
+ iscomplexbalanced (rs, pdict)
786
+ end
787
+
788
+ iscomplexbalanced (rs:: ReactionSystem , parametermap) = error (" Parameter map must be a dictionary, tuple, or vector of symbol/value pairs." )
789
+
790
+
791
+ """
792
+ ratematrix(rs::ReactionSystem, parametermap)
793
+
794
+ Given a reaction system with n complexes, outputs an n-by-n matrix where R_{ij} is the rate constant of the reaction between complex i and complex j.
795
+ """
796
+
797
+ function ratematrix (rs:: ReactionSystem , rates:: Vector{Float64} )
798
+ complexes, D = reactioncomplexes (rs)
799
+ n = length (complexes)
800
+ rxns = reactions (rs)
801
+ ratematrix = zeros (n, n)
802
+
803
+ for r in 1 : length (rxns)
804
+ rxn = rxns[r]
805
+ s = findfirst (== (- 1 ), @view D[:,r])
806
+ p = findfirst (== (1 ), @view D[:,r])
807
+ ratematrix[s, p] = rates[r]
808
+ end
809
+ ratematrix
810
+ end
811
+
812
+ function ratematrix (rs:: ReactionSystem , parametermap:: Dict{Symbol, Float64} )
813
+ if length (parametermap) != numparams (rs)
814
+ error (" The number of reaction rates must be equal to the number of parameters" )
815
+ end
816
+ pmap = symmap_to_varmap (rs, parametermap)
817
+ rates = [substitute (rate, pmap) for rate in reactionrates (rs)]
818
+ ratematrix (rs, rates)
819
+ end
820
+
821
+ function ratematrix (rs:: ReactionSystem , parametermap:: Vector{Pair{Symbol, Float64}} )
822
+ pdict = Dict (parametermap)
823
+ ratematrix (rs, pdict)
824
+ end
825
+
826
+ function ratematrix (rs:: ReactionSystem , parametermap:: Tuple{Pair{Symbol, Float64}} )
827
+ pdict = Dict (parametermap)
828
+ ratematrix (rs, pdict)
829
+ end
830
+
831
+ ratematrix (rs:: ReactionSystem , parametermap) = error (" Parameter map must be a dictionary, tuple, or vector of symbol/value pairs." )
832
+
833
+ # ## BELOW: Helper functions for iscomplexbalanced
834
+
835
+ function matrixtree (g:: SimpleDiGraph , distmx:: Matrix )
836
+ n = nv (g)
837
+ if size (distmx) != (n, n)
838
+ error (" Size of distance matrix is incorrect" )
839
+ end
840
+
841
+ π = zeros (n)
842
+
843
+ if ! Graphs. is_connected (g)
844
+ ccs = Graphs. connected_components (g)
845
+ for cc in ccs
846
+ sg, vmap = Graphs. induced_subgraph (g, cc)
847
+ distmx_s = distmx[cc, cc]
848
+ π_j = matrixtree (sg, distmx_s)
849
+ π[cc] = π_j
850
+ end
851
+ return π
852
+ end
853
+
854
+ # generate all spanning trees
855
+ ug = SimpleGraph (SimpleDiGraph (g))
856
+ trees = collect (Combinatorics. combinations (collect (edges (ug)), n- 1 ))
857
+ trees = SimpleGraph .(trees)
858
+ trees = filter! (t-> isempty (Graphs. cycle_basis (t)), trees)
859
+
860
+ # constructed rooted trees for every vertex, compute sum
861
+ for v in 1 : n
862
+ rootedTrees = [reverse (Graphs. bfs_tree (t, v, dir= :in )) for t in trees]
863
+ π[v] = sum ([treeweight (t, g, distmx) for t in rootedTrees])
864
+ end
865
+
866
+ # sum the contributions
867
+ return π
868
+ end
869
+
870
+ function treeweight (t:: SimpleDiGraph , g:: SimpleDiGraph , distmx:: Matrix )
871
+ prod = 1
872
+ for e in edges (t)
873
+ s = Graphs. src (e); t = Graphs. dst (e)
874
+ prod *= distmx[s, t]
875
+ end
876
+ prod
877
+ end
878
+
0 commit comments