sign_crn.conditions¶
Conditions for CBE¶
We consider conditions for existence and uniqueness of positive complex-balanced equilibria (CBE) of (chemical) reaction networks. These conditions also describe injectivity and bijectivity of polynomial and exponential maps as seen in [MHR19].
In both cases, we apply the conditions to a pair of matrices.
Robustness of existence and uniqueness¶
We consider the following matrices:
sage: from sign_crn.conditions import *
sage: P = matrix([[1, 0, 1, 0], [0, 0, 0, 1]])
sage: P
[1 0 1 0]
[0 0 0 1]
sage: Pt = matrix([[1, 0, 1, 1], [0, 1, 0, -1]])
sage: Pt
[ 1 0 1 1]
[ 0 1 0 -1]
To study robustness, we consider a condition involving maximal minors:
sage: closure_condition(P, Pt)
True
There is also an equivalent condition using sign vectors:
sage: from sign_crn.conditions import closure_condition_sign_vectors
sage: closure_condition_sign_vectors(P, Pt)
True
Now, we consider an example involving parameters:
sage: var("a, b, c")
(a, b, c)
sage: P = matrix([[c, 1, c]])
sage: P
[c 1 c]
sage: Pt = matrix([[a, b, -1]])
sage: Pt
[ a b -1]
We obtain the following condition on the variables:
sage: closure_condition(P, Pt) # random
[{-b > 0, c == 0},
{-b < 0, c == 0},
{-b > 0, c > 0, -a*c > 0},
{-b < 0, c < 0, -a*c < 0}]
Thus, there are four possibilities to set the variables: From the first two sets of conditions, we see that the closure condition is satisfied if \(c\) is zero and \(b\) is nonzero. The closure condition is also satisfied if \(a\) and \(b\) are negative and \(c\) is positive or if \(a\) and \(b\) are positive and \(c\) is negative.
Uniqueness¶
We define the following matrices:
sage: P = matrix([[1, 1, 1]])
sage: Pt = matrix([[1, 0, 1]])
The package uses maximal minors to study uniqueness:
sage: uniqueness_condition(P, Pt)
True
Instead, we can consider the oriented matroids determined by these matrices:
sage: from sign_crn.conditions import uniqueness_condition_sign_vectors
sage: uniqueness_condition_sign_vectors(P, Pt)
True
Now, we consider another example:
sage: P = matrix([[1, 1, 1]])
sage: Pt = matrix([[1, -1, 1]])
The condition is violated:
sage: uniqueness_condition(P, Pt)
False
Finally, we consider an example with parameters \(a, b \in \mathbb{R}\):
sage: var("a, b")
(a, b)
sage: P = matrix([[1, 1, 1]])
sage: P
[1 1 1]
sage: Pt = matrix([[a, b, -1]])
sage: Pt
[ a b -1]
Here, the function returns a system of inequalities:
sage: uniqueness_condition(P, Pt) # random order
[{-a >= 0, -b >= 0}]
Hence, the condition holds if and only if \(a, b \leq 0\).
Note that we cannot apply uniqueness_condition_sign_vectors() because of the parameters.
Existence and uniqueness¶
We consider the following matrices:
sage: P = matrix([[1, 0, 1, 0], [0, 1, 0, 1]])
sage: P
[1 0 1 0]
[0 1 0 1]
sage: Pt = matrix([[1, 0, 0, -1], [0, 1, 1, 1]])
sage: Pt
[ 1 0 0 -1]
[ 0 1 1 1]
The uniqueness condition is satisfied:
sage: uniqueness_condition(P, Pt)
True
We check the face condition:
sage: face_condition(P, Pt)
True
Finally, the nondegeneracy condition delivers:
sage: nondegeneracy_condition(P, Pt)
True
Let us consider another example by swapping the matrices. The uniqueness condition is symmetric in the two matrices and thus holds again:
sage: uniqueness_condition(Pt, P)
True
However, the face condition is violated:
sage: face_condition(Pt, P)
False
Now, we consider a map involving a parameter. (Compare with Example 20 of [MHR19]):
sage: var("a")
a
sage: assume(a > 0)
sage: P = matrix([[0, 0, 1, 1, -1, 0], [1, -1, 0, 0, 0, -1], [0, 0, 1, -1, 0, 0]])
sage: P
[ 0 0 1 1 -1 0]
[ 1 -1 0 0 0 -1]
[ 0 0 1 -1 0 0]
sage: Pt = matrix([[1, 1, 0, 0, -1, a], [1, -1, 0, 0, 0, 0], [0, 0, 1, -1, 0, 0]])
sage: Pt
[ 1 1 0 0 -1 a]
[ 1 -1 0 0 0 0]
[ 0 0 1 -1 0 0]
The first two conditions depend on the sign vectors corresponding to the rows of these matrices which are independent of the specific value for \(a\):
sage: uniqueness_condition(P, Pt)
True
sage: face_condition(P, Pt)
True
The nondegeneracy condition is satisfied for \(a \in (0, 1) \cup (1, 2)\). We demonstrate this for some values:
sage: nondegeneracy_condition(P, Pt(a=1/2))
True
sage: nondegeneracy_condition(P, Pt(a=3/2))
True
On the other hand, this condition does not hold if \(a \in \{1\} \cup [2, \infty)\):
sage: nondegeneracy_condition(P, Pt(a=1))
False
sage: nondegeneracy_condition(P, Pt(a=2))
False
sage: nondegeneracy_condition(P, Pt(a=3))
False
To certify the result, we call:
sage: nondegeneracy_condition(P, Pt(a=1), certify=True)
(False, (1, 1, 0, 0, -1, 1))
Hence, the positive support of the vector v = (1, 1, 0, 0, -1, 1) in row(Pt)
can be covered by a sign vector (++000+) corresponding to ker(P).
Functions
|
Closure condition using maximal minors. |
|
Closure condition using sign vectors. |
|
Face condition using nonnegative cocircuits. |
|
Nondegeneracy condition. |
|
Uniqueness condition using maximal minors. |
|
Uniqueness condition using sign vectors. |
Classes
Class for conditions for chemical reaction networks. |
- class sign_crn.conditions.ConditionsCRN¶
Class for conditions for chemical reaction networks.
- are_kernel_matrices_defined() bool¶
Return whether the kernel matrices are defined.
- are_reduced_matrices_defined() bool¶
Return whether the reduced matrices are defined.
- closure_condition() bool | list[set]¶
Closure condition using maximal minors.
OUTPUT: If the result depends on variables, a list of sets is returned. The condition holds if the inequalities in (at least) one of these sets are satisfied.
- face_condition() bool¶
Face condition using nonnegative cocircuits.
This condition is about nonnegative cocircuits covering other nonnegative cocircuits.
- static from_kernel_matrices(stoichiometric_kernel_matrix: matrix, kinetic_order_kernel_matrix: matrix) ConditionsCRN¶
Construct the object from kernel matrices.
The kernel matrices are the right kernel matrices of the stoichiometric matrix and the kinetic order matrix.
- static from_reduced_matrices(reduced_stoichiometric_matrix: matrix, reduced_kinetic_order_matrix: matrix) ConditionsCRN¶
Construct the object from the stoichiometric matrix and the kinetic order matrix.
- property kinetic_order_kernel_matrix: matrix¶
Return the kernel matrix of the kinetic order matrix.
- nondegeneracy_condition(certify: bool = False) bool¶
Nondegeneracy condition.
This condition is about whether all positive equal components of a vector can be covered by nonnegative cocircuits.
If
certifyis true, a list is returned to certify the result. (See the examples.)
- property reduced_kinetic_order_matrix: matrix¶
Return the reduced kinetic order matrix.
- property reduced_stoichiometric_matrix: matrix¶
Return the reduced stoichiometric matrix.
- property stoichiometric_kernel_matrix: matrix¶
Return the kernel matrix of the stoichiometric matrix.
- uniqueness_condition() bool | list[set]¶
Uniqueness condition using maximal minors.
OUTPUT: If the result depends on variables, a list of sets is returned. The condition holds if the inequalities in exactly one of these sets are satisfied.
- sign_crn.conditions.closure_condition(matrix1: matrix, matrix2: matrix) bool | list[set]¶
Closure condition using maximal minors.
OUTPUT: If the result depends on variables, a list of sets is returned. The condition holds if the inequalities in (at least) one of these sets are satisfied.
See also
Note
The matrices need to have maximal rank and the same dimensions. Otherwise, a
ValueErroris raised.
- sign_crn.conditions.closure_condition_sign_vectors(matrix1: matrix, matrix2: matrix) bool¶
Closure condition using sign vectors.
This condition is about whether a set of sign vectors is contained in the closure of another set of sign vectors, or equivalently, whether covectors are covered by topes.
See also
Note
This implementation is inefficient and should not be used for large examples. Instead, use
closure_condition().
- sign_crn.conditions.face_condition(kernel_matrix1: matrix, kernel_matrix2: matrix) bool¶
Face condition using nonnegative cocircuits.
This condition is about nonnegative cocircuits covering other nonnegative cocircuits.
- sign_crn.conditions.nondegeneracy_condition(kernel_matrix1: matrix, kernel_matrix2: matrix, certify: bool = False) bool¶
Nondegeneracy condition.
This condition is about whether all positive equal components of a vector can be covered by nonnegative cocircuits.
If
certifyis true, a list is returned to certify the result. (See the examples.)EXAMPLES:
We consider the following matrices:
sage: from sign_crn import * sage: P = matrix([[1, 0, 1, 0], [0, 1, 0, 1]]) sage: Pt = matrix([[1, 0, 0, -1], [0, 1, 0, -1]]) sage: nondegeneracy_condition(P, Pt) True
Next, we certify the result. The corresponding subspaces are trivially nondegenerate since there are no nonnegative covectors in the kernel of
P:sage: nondegeneracy_condition(P, Pt, certify=True) (True, 'no nonnegative covectors')
Now, we consider an example of degenerate subspaces:
sage: P = matrix([[0, 0, 1]]) sage: Pt = matrix([[1, 1, 0]]) sage: nondegeneracy_condition(P, Pt, certify=True) (False, (1, 1, 0))
The resulting vector lies in the row space of
Pt. The nonnegative covector(++0)in the kernel ofPcovers the first two equal components.In the next example, there exists a partial cover:
sage: P = matrix([[1, 1, 0, 0], [0, 0, 1, -1]]) sage: Pt = matrix([[1, 1, 0, -1], [0, 0, 1, 0]]) sage: nondegeneracy_condition(P, Pt, certify=True) (True, ([], [[[2, 3]]], [[[[2, 3]], [(--++)]]]))
In fact, a vector in the row space of
Ptwith equal positive components on[2, 3]corresponding to(--++)can be fully covered by covectors. However, this vector would not satisfy the condition on the support.
- sign_crn.conditions.uniqueness_condition(matrix1: matrix, matrix2: matrix) bool | list[set]¶
Uniqueness condition using maximal minors.
OUTPUT: Return whether there exists at most one equilibrium. If the result depends on variables, a list of sets is returned. The condition holds if the inequalities in exactly one of these sets are satisfied.
See also
Note
The matrices need to have maximal rank and the same dimensions. Otherwise, a
ValueErroris raised.TESTS:
sage: from sign_crn import * sage: var("a, b") (a, b) sage: P = matrix([[1, 0, -1], [0, 1, -1]]) sage: P [ 1 0 -1] [ 0 1 -1] sage: Pt = matrix([[1, 0, a], [0, 1, b]]) sage: Pt [1 0 a] [0 1 b] sage: uniqueness_condition(P, Pt) # random order [{-a >= 0, -b >= 0}] sage: conditions = uniqueness_condition(P, Pt)[0] sage: conditions # random order sage: (-a >= 0) in conditions and (-b >= 0) in conditions True sage: P = matrix([[a, 0, 1, 0], [0, 1, -1, 0], [0, 0, 0, 1]]) sage: Pt = matrix([[1, 0, 0, -1], [0, b, 1, 1], [0, 0, a, 1]]) sage: uniqueness_condition(P, Pt) # random order [{(a - 1)*a >= 0, a*b >= 0}, {(a - 1)*a <= 0, a*b <= 0}] sage: len(_), len(_[0]) (2, 2)
- sign_crn.conditions.uniqueness_condition_sign_vectors(matrix1: matrix, matrix2: matrix) bool¶
Uniqueness condition using sign vectors.
See also
Note
This implementation is inefficient and should not be used for large examples. Instead, use
uniqueness_condition().EXAMPLES:
sage: from sign_crn.conditions import uniqueness_condition_sign_vectors sage: P = matrix([[1, 1, 1]]) sage: P [1 1 1] sage: Pt = matrix([[1, 0, 1]]) sage: Pt [1 0 1] sage: uniqueness_condition_sign_vectors(P, Pt) True sage: P = matrix([[1, 0, -1], [0, 1, -1]]) sage: P [ 1 0 -1] [ 0 1 -1] sage: Pt = matrix([[1, 0, -1], [0, 1, 1]]) sage: Pt [ 1 0 -1] [ 0 1 1] sage: uniqueness_condition_sign_vectors(P, Pt) False
TESTS:
sage: from sign_crn.conditions import uniqueness_condition_sign_vectors sage: A = identity_matrix(3) sage: uniqueness_condition_sign_vectors(A, A) True