desr Reference¶
Submodules¶
desr.ode_system module¶
-
class
desr.ode_system.
ODESystem
(variables, derivatives, indep_var=None, initial_conditions=None)[source]¶ Bases:
object
A system of differential equations.
The main attributes are
variables
andderivatives
.variables
is an ordered tuple of variables, which includes the independent variable.derivatives
is an ordered tuple of the same length that contains the derivatives with respect toindep_var
.Parameters: - variables (tuple of sympy.Symbol) – Ordered tuple of variables.
- derivatives (tuple of sympy.Expression) – Ordered tuple of derivatives.
- indep_var (sympy.Symbol, optional) – Independent variable we are differentiating with respect to.
- initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
-
add_constraints
(lhs, rhs)[source]¶ Add constraints that must be obeyed by the system. :param lhs: The left hand side of the constraint. :type lhs: sympy.Expr :param rhs: The right hand side of the constraint. :type rhs: sympy.Expr
Todo
- Finish docstring and tests, here and for: finding scaling symmetries and also translation
- Check for 0 case
>>> eqns = ['dx/dt = c_0*x*y', 'dy/dt = c_1*(1-x)*(1-y)']
>>> system = ODESystem.from_equations(eqns) >>> system dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(-x + 1)*(-y + 1) dc_0/dt = 0 dc_1/dt = 0
>>> system.add_constraints('c_2', 'c_0 + c_1') >>> system dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(-x + 1)*(-y + 1) dc_0/dt = 0 dc_1/dt = 0 dc_2/dt = 0 c_2 == c_0 + c_1
>>> system.add_constraints('c_2', 'c_0 + x') Traceback (most recent call last): ... ValueError: Cannot add constraints on non-constant parameters set([x]). This would make an interesting project though...
>>> system.add_constraints('c_0', 0) Traceback (most recent call last): ... ValueError: Cannot express equality with 0.
-
constant_variables
¶ Return the constant variables - specifically those which have a None derivative.
Returns: The constant variables. Return type: tuple
-
constraints
¶ - Finish docstring
Returns:
Type: Todo
-
default_order_variables
()[source]¶ Reorder the variables into (independent variable, dependent variables, constant variables), which generally gives the simplest reductions. Variables of the same type are sorted by their string representations.
>>> eqns = ['dz_1/dt = z_1*z_3', 'dz_2/dt = z_1*z_2 / (z_3 ** 2)'] >>> system = ODESystem.from_equations('\n'.join(eqns)) >>> system.variables (t, z_1, z_2, z_3)
>>> system.reorder_variables(['z_2', 'z_3', 't', 'z_1']) >>> system.variables (z_2, z_3, t, z_1)
>>> system.default_order_variables() >>> system.variables (t, z_1, z_2, z_3)
-
derivative_dict
¶ expr mapping, filtering out the
None
’s in expr.Returns: Keys are non-constant variables, value is the derivative with respect to the independent variable. Return type: dict Type: Return a variable
-
derivatives
¶ Getter for an ordered tuple of expressions representing the derivatives of self.variables.
Returns: Ordered tuple of sympy.Expressions. Return type: tuple
-
diff_subs
(to_sub, expand_before=False, expand_after=True, factor_after=False, subs_constraints=False)[source]¶ Make substitutions into the derivatives, returning a new system. :param to_sub: Dictionary of substitutions to make. :type to_sub: dict :param expand_before: Expand the sympy expression for each derivative before substitution. :type expand_before: bool :param expand_after: Expand the sympy expression for each derivative after substitution. :type expand_after: bool :param factor_after: Factorise the sympy expression for each derivative after substitution. :type factor_after: bool :param subs_constraints: Perform the substitutions into the initial constraints. :type subs_constraints: bool
Returns: System with substitutions carried out. Return type: ODESystem >>> eqns = ['dx/dt = c_0*x*y', 'dy/dt = c_1*(1-x)*(1-y)'] >>> system = ODESystem.from_equations(eqns) >>> system.diff_subs({'1-x': 'z'}, expand_before=False, expand_after=False, factor_after=False) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*z*(-y + 1) dc_0/dt = 0 dc_1/dt = 0 >>> system.diff_subs({'1-x': 'z'}, expand_before=True, expand_after=False, factor_after=False) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*x*y - c_1*x - c_1*y + c_1 dc_0/dt = 0 dc_1/dt = 0
>>> system.diff_subs({'x': '1-z'}, expand_before=True, expand_after=True, factor_after=False) dt/dt = 1 dx/dt = -c_0*y*z + c_0*y dy/dt = -c_1*y*z + c_1*z dc_0/dt = 0 dc_1/dt = 0
>>> system.add_constraints('c_0', 'c_1**2') >>> system.diff_subs({'c_0': '1'}, subs_constraints=False) dt/dt = 1 dx/dt = x*y dy/dt = c_1*x*y - c_1*x - c_1*y + c_1 dc_0/dt = 0 dc_1/dt = 0 c_0 == c_1**2 >>> system.diff_subs({'c_0': '1'}, subs_constraints=True) dt/dt = 1 dx/dt = x*y dy/dt = c_1*x*y - c_1*x - c_1*y + c_1 dc_0/dt = 0 dc_1/dt = 0 1 == c_1**2
-
classmethod
from_dict
(deriv_dict, indep_var=t, initial_conditions=None)[source]¶ Instantiate from a text of equations.
Parameters: - deriv_dict (dict) – {variable: derivative} mapping.
- indep_var (sympy.Symbol) – Independent variable, that the derivatives are with respect to.
- initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
Returns: System of ODEs.
Return type: >>> _input = {'x': 'c_0*x*y', 'y': 'c_1*(1-x)*(1-y)'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.iteritems()} >>> ODESystem.from_dict(_input) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(-x + 1)*(-y + 1) dc_0/dt = 0 dc_1/dt = 0
>>> _input = {'y': 'c_0*x*y', 'z': 'c_1*(1-y)*z**2'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.iteritems()} >>> ODESystem.from_dict(_input, indep_var=sympy.Symbol('x')) dx/dx = 1 dy/dx = c_0*x*y dz/dx = c_1*z**2*(-y + 1) dc_0/dx = 0 dc_1/dx = 0
-
classmethod
from_equations
(equations, indep_var=t, initial_conditions=None)[source]¶ Instantiate from multiple equations.
Parameters: - equations (str, iter of str) – Equations of the form “dx/dt = expr”, optionally seperated by
\n
. - indep_var (sympy.Symbol) – The independent variable, usually
t
. - initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
Returns: System of equations.
Return type: >>> eqns = ['dx/dt = c_0*x*y', 'dy/dt = c_1*(1-x)*(1-y)'] >>> ODESystem.from_equations(eqns) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(-x + 1)*(-y + 1) dc_0/dt = 0 dc_1/dt = 0 >>> eqns = '\n'.join(['dy/dx = c_0*x*y', 'dz/dx = c_1*(1-y)*z**2']) >>> ODESystem.from_equations(eqns, indep_var=sympy.Symbol('x')) dx/dx = 1 dy/dx = c_0*x*y dz/dx = c_1*z**2*(-y + 1) dc_0/dx = 0 dc_1/dx = 0
- equations (str, iter of str) – Equations of the form “dx/dt = expr”, optionally seperated by
-
classmethod
from_tex
(tex)[source]¶ Given the LaTeX of a system of differential equations, return a ODESystem of it.
Parameters: tex (str) – LaTeX Returns: System of ODEs. Return type: ODESystem >>> eqns = ['\frac{dE}{dt} &= - k_1 E S + k_{-1} C + k_2 C \\', ... '\frac{dS}{dt} &= - k_1 E S + k_{-1} C \\', ... '\frac{dC}{dt} &= k_1 E S - k_{-1} C - k_2 C \\', ... '\frac{dP}{dt} &= k_2 C'] >>> ODESystem.from_tex('\n'.join(eqns)) dt/dt = 1 dC/dt = -C*k_2 - C*k_m1 + E*S*k_1 dE/dt = C*k_2 + C*k_m1 - E*S*k_1 dP/dt = C*k_2 dS/dt = C*k_m1 - E*S*k_1 dk_1/dt = 0 dk_2/dt = 0 dk_m1/dt = 0
Todo
- Allow initial conditions to be set from tex.
-
indep_var
¶ Return the independent variable.
Returns: The independent variable, which we are differentiating with respect to. Return type: sympy.Symbol
-
indep_var_index
¶ Return the independent variable index.
Returns: The index of indep_var
invariables
.Return type: int
-
initial_conditions
¶ initial-value mapping.
Returns: Keys are non-constant variables, value is the constant representing their initial condition. Return type: dict Type: Return a variable
-
maximal_scaling_matrix
()[source]¶ Determine the maximal scaling matrix leaving this system invariant.
Returns: Maximal scaling matrix. Return type: sympy.Matrix >>> eqns = '\n'.join(['ds/dt = -k_1*e_0*s + (k_1*s + k_m1)*c', ... 'dc/dt = k_1*e_0*s - (k_1*s + k_m1 + k_2)*c']) >>> system = ODESystem.from_equations(eqns) >>> system.maximal_scaling_matrix() Matrix([ [1, 0, 0, 0, -1, -1, -1], [0, 1, 1, 1, -1, 0, 0]])
-
non_constant_variables
¶ Return the non-constant variables - specifically those which have a derivative that isn’t None or 1.
Returns: The constant variables. Return type: tuple >>> _input = {'x': 'c_0*x*y', 'y': 'c_1*(1-x)*(1-y)*t'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.iteritems()} >>> system = ODESystem.from_dict(_input) >>> system.non_constant_variables (x, y)
-
num_constants
¶ Return the number of constant variables - specifically those which have a
None
derivativeReturns: Number of non-constant variables. Return type: int
-
power_matrix
()[source]¶ Determine the ‘exponent’ or ‘power’ matrix of the system, denoted by \(K\) in the literature, by gluing together the power matrices of each derivative.
In particular, it concatenates \(K_{\left(\frac{t}{x} \cdot \frac{dx}{dt}\right)}\) for \(x\) in
variables
, where \(t\) is the independent variable.>>> eqns = '\n'.join(['ds/dt = -k_1*e_0*s + (k_1*s + k_m1)*c', ... 'dc/dt = k_1*e_0*s - (k_1*s + k_m1 + k_2)*c']) >>> system = ODESystem.from_equations(eqns) >>> system.variables (t, c, s, e_0, k_1, k_2, k_m1) >>> system.power_matrix() Matrix([ [1, 1, 1, 1, 1, 1, 1], [0, 0, 0, -1, 0, 1, 1], [1, 0, 0, 1, 0, 0, -1], [0, 0, 0, 1, 1, 0, 0], [1, 0, 0, 1, 1, 1, 0], [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1]])
While we get a different answer to the example in the paper, this is just due to choosing our reference exponent in a different way.
Todo
- Change the code to agree with the paper.
>>> system.update_initial_conditions({'s': 's_0'}) >>> system.power_matrix() Matrix([ [1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, -1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, -1, 1], [0, 0, 0, 1, 1, 0, 0, 0], [1, 0, 0, 1, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, -1]])
-
reorder_variables
(variables)[source]¶ Reorder the equation according to the new order of variables.
Parameters: variables (str, iter) – Another ordering of the variables. >>> eqns = ['dz_1/dt = z_1*z_3', 'dz_2/dt = z_1*z_2 / (z_3 ** 2)'] >>> system = ODESystem.from_equations('\n'.join(eqns)) >>> system.variables (t, z_1, z_2, z_3) >>> system.derivatives [1, z_1*z_3, z_1*z_2/z_3**2, 0]
>>> system.reorder_variables(['z_2', 'z_3', 't', 'z_1']) >>> system.variables (z_2, z_3, t, z_1) >>> system.derivatives [z_1*z_2/z_3**2, 0, 1, z_1*z_3]
-
to_tex
()[source]¶ Returns: TeX representation. Return type: str >>> eqns = ['dC/dt = -C*k_2 - C*k_m1 + E*S*k_1', ... 'dE/dt = C*k_2 + C*k_m1 - E*S*k_1', ... 'dP/dt = C*k_2', ... 'dS/dt = C*k_m1 - E*S*k_1'] >>> system = ODESystem.from_equations('\n'.join(eqns)) >>> print system.to_tex() \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0
>>> system.update_initial_conditions({'C': 'C_0'}) >>> print system.to_tex() \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0 \\ \frac{dC_{0}}{dt} &= 0 \\ C\left(0\right) &= C_{0}
>>> system.add_constraints('K_m', '(k_m1 + k_2) / k_1') >>> print system.to_tex() \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0 \\ \frac{dC_{0}}{dt} &= 0 \\ \frac{dK_{m}}{dt} &= 0 \\ C\left(0\right) &= C_{0} \\ K_{m} &= \frac{1}{k_{1}} \left(k_{2} + k_{-1}\right)
-
update_initial_conditions
(initial_conditions)[source]¶ Update the internal record of initial conditions.
Parameters: initial_conditions (dict) – non-constant variable: initial value constant. >>> _input = {'x': 'c_0*x*y', 'y': 'c_1*(1-x)*(1-y)*t'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.iteritems()} >>> system = ODESystem.from_dict(_input) >>> system.update_initial_conditions({'x': 'x_0'}) >>> system.initial_conditions {x: x_0}
>>> system.update_initial_conditions({'c_0': 'k'}) Traceback (most recent call last): ... ValueError: Cannot set initial condition k for variable c_0 with derivative None.
>>> system dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*t*(-x + 1)*(-y + 1) dc_0/dt = 0 dc_1/dt = 0 dx_0/dt = 0 x(0) = x_0
-
variables
¶ Return the variables appearing in the system.
Returns: Ordered tuple of variables appearing in the system. Return type: tuple
-
desr.ode_system.
maximal_scaling_matrix
(exprs, variables=None)[source]¶ Determine the maximal scaling matrix leaving this system invariant, in row Hermite normal form.
Parameters: - exprs (iter) – Iterable of sympy.Expressions.
- variables – An ordering on the variables. If None, sort according to the string representation.
Returns: sympy.Matrix
>>> exprs = ['z_1*z_3', 'z_1*z_2 / (z_3 ** 2)'] >>> exprs = map(sympy.sympify, exprs) >>> maximal_scaling_matrix(exprs) Matrix([[1, -3, -1]])
>>> exprs = ['(z_1 + z_2**2) / z_3'] >>> exprs = map(sympy.sympify, exprs) >>> maximal_scaling_matrix(exprs) Matrix([[2, 1, 2]])
-
desr.ode_system.
parse_de
(diff_eq, indep_var='t')[source]¶ Parse a first order ordinary differential equation and return (variable of derivative, rational function
>>> parse_de('dn/dt = n( r(1 - n/K) - kp/(n+d) )') (n, n(-kp/(d + n) + r(1 - n/K)))
>>> parse_de('dp/dt==sp(1 - hp / n)') (p, sp(-hp/n + 1))
-
desr.ode_system.
rational_expr_to_power_matrix
(expr, variables)[source]¶ Take a rational expression and determine the power matrix wrt an ordering on the variables, as on page 497 of Hubert-Labahn.
>>> exprs = map(sympy.sympify, "n*( r*(1 - n/K) - k*p/(n+d) );s*p*(1 - h*p / n)".split(';')) >>> variables = sorted(expressions_to_variables(exprs), key=str) >>> variables [K, d, h, k, n, p, r, s] >>> rational_expr_to_power_matrix(exprs[0], variables) Matrix([ [0, -1, -1, 0, 0, 0], [0, 1, 0, 1, 0, 1], [0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0], [0, 1, 2, 0, 1, -1], [1, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0]])
>>> rational_expr_to_power_matrix(exprs[1], variables) Matrix([ [ 0, 0], [ 0, 0], [ 1, 0], [ 0, 0], [-1, 0], [ 2, 1], [ 0, 0], [ 1, 1]])
desr.ode_translation module¶
-
class
desr.ode_translation.
ODETranslation
(scaling_matrix, variables_domain=None, hermite_multiplier=None)[source]¶ Bases:
object
An object used for translating between systems of ODEs according to a scaling matrix. The key data are
scaling_matrix
andherm_mult
, which together contain all the information needed (along with a variable order) to reduce anODESystem
.Parameters: - scaling_matrix (sympy.Matrix) – Matrix that defines the torus action on the system.
- variables_domain (iter of sympy.Symbol, optional) – An ordering of the variables we expect to act upon.
If this is not given, we will act on a system according to the position of the variables in
variables
, as long as there is the correct number of variables. - hermite_multiplier (sympy.Matrix, optional) – User-defined Hermite multiplier, that puts
scaling_matrix
into column Hermite normal form. If not given, the normal Hermite multiplier will be calculated.
-
auxiliaries
(variables=None)[source]¶ The auxiliary variables of the system, as determined by
herm_mult_i
.Returns: - The auxiliary variables of the system,
- in terms of
variables_domain
if notNone
. Otherwise, usevariables
and failing that use \(x_i\).
Return type: tuple >>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.auxiliaries() Matrix([[1/s, d, d*s/k]])
-
dep_var_herm_mult
(indep_var_index=0)[source]¶ Parameters: indep_var_index (int) – The index of the independent variable. Returns: The Hermite multiplier \(V\), ignoring the independent variable. Return type: sympy.Matrix >>> translation = ODETranslation(sympy.Matrix(range(12)).reshape(3, 4)) >>> translation.herm_mult Matrix([ [ 0, 0, 1, 0], [ 0, 0, 0, 1], [-1, 3, -3, -2], [ 1, -2, 2, 1]]) >>> translation.dep_var_herm_mult(1) Matrix([ [ 0, 0, 1], [-1, 3, -3], [ 1, -2, 2]])
-
dep_var_inv_herm_mult
(indep_var_index=0)[source]¶ Parameters: indep_var_index (int) – The index of the independent variable. Returns: The inverse Hermite multiplier \(W\), ignoring the independent variable. Return type: sympy.Matrix >>> translation = ODETranslation(sympy.Matrix(range(12)).reshape(3, 4)) >>> translation.inv_herm_mult Matrix([ [0, 1, 2, 3], [1, 1, 1, 1], [1, 0, 0, 0], [0, 1, 0, 0]]) >>> translation.dep_var_inv_herm_mult(1) Matrix([ [0, 2, 3], [1, 1, 1], [1, 0, 0]])
-
extend_from_invariants
(invariant_choice)[source]¶ Extend a given set of invariants, expressed as a matrix of exponents, to find a Hermite multiplier that will rewrite the system in terms of invariant_choice.
Parameters: invariant_choice (sympy.Matrix) – The \(n \times k\) matrix representing the invariants, where \(n\) is the number of variables and \(k\) is the number of given invariants. Returns: An ODETranslation representing the rewrite rules in terms of the given invariants. Return type: ODETranslation >>> variables = sympy.symbols(' '.join(['y{}'.format(i) for i in xrange(6)])) >>> ode_translation = ODETranslation(sympy.Matrix([[1, 0, 3, 0, 2, 2], ... [0, 2, 0, 1, 0, 1], ... [2, 0, 0, 3, 0, 0]])) >>> ode_translation.invariants(variables=variables) Matrix([[y0**3*y2*y5**2/(y3**2*y4**5), y1*y4**2/y5**2, y2**2/y4**3]])
Now we can express two new invariants, which we think are more interesting, as a matrix. We pick the product of the first two invariants, and the product of the last two invariants:
y0**3 * y1 * y2/(y3**2 * y4**3)
andy1 * y2**2/(y4 * y5**2)
>>> new_inv = sympy.Matrix([[3, 1, 1, -2, -3, 0], ... [0, 1, 2, 0, -1, -2]]).T
>>> new_translation = ode_translation.extend_from_invariants(new_inv) >>> new_translation.invariants(variables=variables) Matrix([[y0**3*y1*y2/(y3**2*y4**3), y1*y2**2/(y4*y5**2), y1*y4**2/y5**2]])
-
classmethod
from_ode_system
(ode_system)[source]¶ Create a
ODETranslation
given anode_system.ODESystem
instance, by taking the maximal scaling matrix.Parameters: ode_system (ODESystem) – Return type: ODETranslation
-
herm_form
¶ The Hermite normal form of the scaling matrix: \(H = AV\).
Type: Returns Type: sympy.Matrix
-
herm_mult
¶ - A column Hermite multiplier \(V\) that puts the
scaling_matrix
in column Hermite normal form. That is: \(AV = H\) is in column Hermite normal form.Type: Returns Type: sympy.Matrix
-
herm_mult_i
¶ \(V_{\mathfrak{i}}\): the first \(r\) columns of \(V\).
The columns represent the auxiliary variables of the reduction.Type: Returns Type: sympy.Matrix
-
herm_mult_n
¶ - \(V_{\mathfrak{n}}\): the last \(n-r\) columns of the Hermite multiplier \(V\). The columns represent the invariants of the scaling action.
Type: Returns Type: sympy.Matrix
-
inv_herm_mult
¶ - The inverse of the Hermite multiplier \(W=V^{-1}\).
Type: Returns Type: sympy.Matrix
-
inv_herm_mult_d
¶ - \(W_{\mathfrak{d}}\): the last \(n-r\) rows of \(W\).
Type: Returns Type: sympy.Matrix
-
inv_herm_mult_u
¶ - \(W_{\mathfrak{u}}\): the first \(r\) rows of \(W\).
Type: Returns Type: sympy.Matrix
-
invariants
(variables=None)[source]¶ The invariants of the system, as determined by
herm_mult_n
.Returns: - The invariants of the system, in terms of
variables_domain
if notNone
. - Otherwise, use
variables
and failing that use \(y_i\).
Return type: tuple >>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.invariants() Matrix([[s*t, n/d, k*p/(d*s), K/d, h*s/k, r/s]])
- The invariants of the system, in terms of
-
is_invariant_expr
(expr, variable_order=None)[source]¶ Determine whether an expression is an invariant or not
Parameters: - expr (sympy.Expr) – A symbolic expression which may or may not be an invariant under the scaling action.
- variable_order (list, tuple) – An ordered list that determines how the matrix acts on the variables.
Returns: True if the expression is an invariant.
Return type: bool
-
moving_frame
(variables=None)[source]¶ Given a finite-dimensional Lie group \(G\) acting on a manifold \(M\), a moving frame is defined as a \(G\)-equivariant map \(\rho : M \rightarrow G\).
We can construct a moving frame given a rational section, by sending a point \(x \in M\) to the Lie group element \(\rho ( x )\) such that \(\rho ( x ) \cdot x\) lies on \(K\).
>>> equations = 'dz1/dt = z1*(1+z1*z2);dz2/dt = z2*(1/t - z1*z2)'.split(';') >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> moving_frame = translation.moving_frame() >>> moving_frame (z2,)
Now we can check that the moving frame moves a point to the cross-section.
>>> translation.rational_section() Matrix([[1 - 1/z2]]) >>> scale_action(moving_frame, translation.scaling_matrix) # \rho(x) Matrix([[1, z2, 1/z2]]) >>> # :math:`\rho(x).x` should satisfy the equations of the rational section. >>> scale_action(moving_frame, translation.scaling_matrix).multiply_elementwise(sympy.Matrix(system.variables).T) Matrix([[t, z1*z2, 1]])
Another example:
>>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> moving_frame = translation.moving_frame() >>> moving_frame (s, 1/d, k/(d*s))
Now we can check that the moving frame moves a point to the cross-section.
>>> translation.rational_section() Matrix([[1 - 1/s, d - 1, d*s - 1/k]]) >>> scale_action(moving_frame, translation.scaling_matrix) # \rho(x) Matrix([[s, 1/d, k/(d*s), 1/d, 1/d, s/k, 1/k, 1/s, 1/s]]) >>> # :math:`\rho(x).x` should satisfy the equations of the rational section. >>> scale_action(moving_frame, translation.scaling_matrix).multiply_elementwise(sympy.Matrix(system.variables).T) Matrix([[s*t, n/d, k*p/(d*s), K/d, 1, h*s/k, 1, r/s, 1]])
See [Fels1999] for more details.
-
multiplier_add_columns
(i, j, alpha)[source]¶ Add column j alpha times to the ith column of the Hermite multiplier: C_i <- C_i + alpha * C_j Check that we are only operating with 0 columns of the scaling matrix.
Parameters: - i (int) – Column index
- j (int) – Column index
- alpha (int) – Coefficient for addition
>>> translation = ODETranslation(sympy.Matrix([[1, 0, 1, 1, -1], ... [0, 1, 0, -1, 1]])) >>> translation.herm_form Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) >>> translation.herm_mult Matrix([ [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [1, 1, -1, -1, 0], [0, 0, 0, 0, 1], [0, 1, 0, -1, 1]]) >>> translation.inv_herm_mult Matrix([ [1, 0, 1, 1, -1], [0, 1, 0, -1, 1], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 0]]) >>> translation.multiplier_add_columns(2, 3, 1)
>>> translation.herm_mult Matrix([ [0, 0, 1, 0, 0], [0, 0, 1, 1, 0], [1, 1, -2, -1, 0], [0, 0, 0, 0, 1], [0, 1, -1, -1, 1]])
Check we have recalculated the inverse after a column operation.
>>> translation.inv_herm_mult Matrix([ [ 1, 0, 1, 1, -1], [ 0, 1, 0, -1, 1], [ 1, 0, 0, 0, 0], [-1, 1, 0, 0, 0], [ 0, 0, 0, 1, 0]])
>>> translation.multiplier_add_columns(1, 3, 1) Traceback (most recent call last): ... ValueError: Cannot swap non-zero column 1
>>> translation.multiplier_add_columns(3, 3, 1) Traceback (most recent call last): ... ValueError: Cannot add column 3 to itself
Sympy’s natural column accessing is unhappy with negative indices, so make sure we don’t pick up any bad habits
>>> translation = ODETranslation(sympy.Matrix([[1, 0, 1, 0], [0, 1, 0, 1]])) >>> translation.herm_mult Matrix([ [0, 0, 1, 0], [0, 0, 0, 1], [1, 0, -1, 0], [0, 1, 0, -1]]) >>> translation.multiplier_add_columns(2, -1, 1) >>> translation.herm_mult Matrix([ [0, 0, 1, 0], [0, 0, 1, 1], [1, 0, -1, 0], [0, 1, -1, -1]])
-
multiplier_negate_column
(i)[source]¶ Negate column i: C_i <- -C_i Check that we are only operating with 0 columns of the scaling matrix.
Parameters: i (int) – Column index >>> translation = ODETranslation(sympy.Matrix([[1, 0, 1, 1, -1], ... [0, 1, 0, -1, 1]])) >>> translation.herm_form Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) >>> translation.herm_mult Matrix([ [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [1, 1, -1, -1, 0], [0, 0, 0, 0, 1], [0, 1, 0, -1, 1]]) >>> translation.inv_herm_mult Matrix([ [1, 0, 1, 1, -1], [0, 1, 0, -1, 1], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 0]]) >>> translation.multiplier_negate_column(3)
>>> translation.herm_mult Matrix([ [0, 0, 1, 0, 0], [0, 0, 0, -1, 0], [1, 1, -1, 1, 0], [0, 0, 0, 0, 1], [0, 1, 0, 1, 1]])
Check we have recalculated the inverse after a column operation.
>>> translation.inv_herm_mult Matrix([ [1, 0, 1, 1, -1], [0, 1, 0, -1, 1], [1, 0, 0, 0, 0], [0, -1, 0, 0, 0], [0, 0, 0, 1, 0]])
>>> translation.multiplier_negate_column(1) Traceback (most recent call last): ... ValueError: Cannot negate non-zero column 1
Sympy’s natural column accessing is unhappy with negative indices, so make sure we don’t pick up any bad habits
>>> translation = ODETranslation(sympy.Matrix([[1, 0, 1], [0, 1, 0]])) >>> translation.herm_mult Matrix([ [0, 0, 1], [0, 1, 0], [1, 0, -1]]) >>> translation.multiplier_negate_column(-1) >>> translation.herm_mult Matrix([ [0, 0, -1], [0, 1, 0], [1, 0, 1]])
-
multiplier_swap_columns
(i, j)[source]¶ Swap columns i and j of the Hermite multiplier, checking that we are only swapping 0 columns of the scaling matrix.
Parameters: - i (int) – Column index
- j (int) – Column index
>>> translation = ODETranslation(sympy.Matrix([[1, 0, 1, 1, -1], ... [0, 1, 0, -1, 1]])) >>> translation.herm_form Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) >>> translation.herm_mult Matrix([ [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [1, 1, -1, -1, 0], [0, 0, 0, 0, 1], [0, 1, 0, -1, 1]]) >>> translation.inv_herm_mult Matrix([ [1, 0, 1, 1, -1], [0, 1, 0, -1, 1], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 0]])
>>> translation.multiplier_swap_columns(2, 3)
>>> translation.herm_mult Matrix([ [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [1, 1, -1, -1, 0], [0, 0, 0, 0, 1], [0, 1, -1, 0, 1]])
Check we have recalculated the inverse after a column operation.
>>> translation.inv_herm_mult Matrix([ [1, 0, 1, 1, -1], [0, 1, 0, -1, 1], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0]])
>>> translation.multiplier_swap_columns(1, 3) Traceback (most recent call last): ... ValueError: Cannot swap non-zero column 1
>>> translation.multiplier_swap_columns(2, 6) Traceback (most recent call last): ... IndexError: Index out of range: a[6]
Sympy’s natural column accessing is unhappy with negative indices, so make sure we don’t pick up any bad habits
>>> translation = ODETranslation(sympy.Matrix([[1, 0, 1, 0], [0, 1, 0, 1]])) >>> translation.herm_mult Matrix([ [0, 0, 1, 0], [0, 0, 0, 1], [1, 0, -1, 0], [0, 1, 0, -1]]) >>> translation.multiplier_swap_columns(2, -1) >>> translation.herm_mult Matrix([ [0, 0, 0, 1], [0, 0, 1, 0], [1, 0, 0, -1], [0, 1, -1, 0]])
-
n
¶ - The number of original variables that the scaling action is acting on: \(n\).
- In particular, it is the number of columns of
scaling_matrix
.
Type: Returns Type: int
-
r
¶ - The dimension of the scaling action: \(r\).
- In particular it is the number of rows of
scaling_matrix
.
Type: Returns Type: int
-
rational_section
(variables=None)[source]¶ Given a finite-dimensional Lie group \(G\) acting on a manifold \(M\), a cross-section \(K \subset M\) is a subset that intersects each orbit of \(M\) in exactly one place.
Parameters: variables (iter of sympy.Symbol, optional) – Variables of the system. Returns: A set of equations defining a variety that is a cross-section. Return type: sympy.Matrix >>> equations = 'dz1/dt = z1*(1+z1*z2);dz2/dt = z2*(1/t - z1*z2)'.split(';') >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.rational_section() Matrix([[1 - 1/z2]])
>>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.rational_section() Matrix([[1 - 1/s, d - 1, d*s - 1/k]])
See [Fels1999] for more details.
-
reverse_translate
(variables)[source]¶ Given the solutions of a reduced system, reverse translate them into solutions of the original system.
Note
This doesn’t reverse translate the parameter reduction scheme.
It only guesses between
reverse_translate_general()
andreverse_translate_dep_var()
Parameters: - variables (iter of sympy.Expression) – The solution auxiliary variables \(x(t)\) and solution invariants \(y(t)\) of the reduced system. Variables should be ordered auxiliary variables followed by invariants.
- indep_var_index (int) – The location of the independent variable.
Return type: tuple
-
reverse_translate_dep_var
(variables, indep_var_index)[source]¶ Given the solutions of a (dep_var) reduced system, reverse translate them into solutions of the original system.
Parameters: - variables (iter of sympy.Expression) – The solution auxiliary variables \(x(t)\) and solution invariants \(y(t)\) of the reduced system. Variables should be ordered auxiliary variables followed by invariants.
- indep_var_index (int) – The location of the independent variable.
Return type: tuple
Example 6.4 from [Hubert2013c]. We will just take the matrices from the paper, rather than use our own (which are constructed using different conventions).
\[ \begin{align}\begin{aligned}\frac{dz_1}{dt} = z_1 \left( 1+ z_1 z_2 \right)\\\frac{dz_2}{dt} = z_2 \left(\frac{1}{t} - z_1 z_2 \right)\end{aligned}\end{align} \]>>> equations = 'dz1/dt = z1*(1+z1*z2);dz2/dt = z2*(1/t - z1*z2)'.split(';') >>> system = ODESystem.from_equations(equations) >>> var_order = ['t', 'z1', 'z2'] >>> system.reorder_variables(var_order) >>> scaling_matrix = sympy.Matrix([[0, 1, -1]]) >>> hermite_multiplier = sympy.Matrix([[0, 1, 0], ... [1, 0, 1], ... [0, 0, 1]]) >>> translation = ODETranslation(scaling_matrix=scaling_matrix, ... hermite_multiplier=hermite_multiplier) >>> reduced = translation.translate_dep_var(system) >>> # Check reduction >>> answer = ODESystem.from_equations('dx0/dt = x0*(y0 + 1);dy0/dt = y0*(1 + 1/t)'.split(';')) >>> reduced == answer True >>> reduced dt/dt = 1 dx0/dt = x0*(y0 + 1) dy0/dt = y0*(1 + 1/t) >>> t_var, c1_var, c2_var = sympy.var('t c1 c2') >>> reduced_soln = (c2_var*sympy.exp(t_var+c1_var*(1-t_var)*sympy.exp(t_var)), ... c1_var * t_var * sympy.exp(t_var)) >>> original_soln = translation.reverse_translate_dep_var(reduced_soln, system.indep_var_index) >>> original_soln == (reduced_soln[0], reduced_soln[1] / reduced_soln[0]) True >>> original_soln (c2*exp(c1*(-t + 1)*exp(t) + t), c1*t*exp(t)*exp(-c1*(-t + 1)*exp(t) - t)/c2)
-
reverse_translate_general
(variables, system_indep_var_index=0)[source]¶ Given an iterable of variables, or exprs, reverse translate into the original variables. Here we expect t as the first variable, since we need to divide by it and substitute
Given the solutions of a (general) reduced system, reverse translate them into solutions of the original system.
Parameters: - variables (iter of sympy.Expression) – The independent variable \(t\), the solution auxiliary variables \(x(t)\) and the solution invariants \(y(t)\) of the reduced system. Variables should be ordered: independent variable, auxiliary variables then invariants.
- indep_var_index (int) – The location of the independent variable.
Return type: tuple
Example 6.6 from [Hubert2013c]. We will just take the matrices from the paper, rather than use our own (which are constructed using different conventions).
\[ \begin{align}\begin{aligned}\frac{dz_1}{dt} = \frac{z_1 \left(z_1^5 z_2 - 2 \right)}{3t}\\\frac{dz_2}{dt} = \frac{z_2 \left(10 - 2 z_1^5 z_2 + \frac{3 z_1^2 z_2}{t} \right)}{3t}\end{aligned}\end{align} \]>>> equations = ['dz1/dt = z1*(z1**5*z2 - 2)/(3*t)', ... 'dz2/dt = z2*(10 - 2*z1**5*z2 + 3*z1**2*z2/t )/(3*t)'] >>> system = ODESystem.from_equations(equations) >>> var_order = ['t', 'z1', 'z2'] >>> system.reorder_variables(var_order) >>> scaling_matrix = sympy.Matrix([[3, -1, 5]]) >>> hermite_multiplier = sympy.Matrix([[1, 1, -1], ... [2, 3, 2], ... [0, 0, 1]]) >>> translation = ODETranslation(scaling_matrix=scaling_matrix, ... hermite_multiplier=hermite_multiplier) >>> reduced = translation.translate_general(system) >>> # Quickly check the reduction >>> answer = ODESystem.from_equations(['dx0/dt = x0*(2*y0*y1/3 - 1/3)/t', ... 'dy0/dt = y0*(y0*y1 - 1)/t', ... 'dy1/dt = y1*(y1 + 1)/t']) >>> reduced == answer True >>> reduced dt/dt = 1 dx0/dt = x0*(2*y0*y1/3 - 1/3)/t dy0/dt = y0*(y0*y1 - 1)/t dy1/dt = y1*(y1 + 1)/t
Check reverse translation:
>>> reduced_soln = (sympy.var('t'), ... sympy.sympify('c3/(t**(1/3)*(ln(t-c1)-ln(t)+c2)**(2/3))'), # x ... sympy.sympify('c1/(t*(ln(t-c1)-ln(t)+c2))'), # y1 ... sympy.sympify('t/(c1 - t)')) # y2 >>> original_soln = translation.reverse_translate_general(reduced_soln, system.indep_var_index) >>> original_soln_answer = [#reduced_soln[1] ** 3 / (reduced_soln[2] ** 2) # x^3 / y1^2 ... reduced_soln[2] / reduced_soln[1], # y1 / x ... reduced_soln[1] ** 5 * reduced_soln[3] / reduced_soln[2] ** 4] # x^5 y2 / y1^4 >>> original_soln_answer = tuple([soln.subs({sympy.var('t'): sympy.sympify('t / (c3**3 / c1**2)')}) ... for soln in original_soln_answer]) >>> original_soln == original_soln_answer True >>> original_soln[0] c1/(c3*(c1**2*t/c3**3)**(2/3)*(c2 - log(c1**2*t/c3**3) + log(c1**2*t/c3**3 - c1))**(1/3)) >>> original_soln[1] c3**5*(c1**2*t/c3**3)**(10/3)*(c2 - log(c1**2*t/c3**3) + log(c1**2*t/c3**3 - c1))**(2/3)/(c1**4*(-c1**2*t/c3**3 + c1))
-
reverse_translate_parameter
(variables)[source]¶ Given the solutions of a reduced system, reverse translate them into solutions of the original system.
Parameters: variables (iter of sympy.Expression) – \(r\) constants (auxiliary variables) followed by the independent, dependent and invariant constants. Example 7.5 (Prey-predator model) from [Hubert2013c].
Use the matrices from the paper, which differ to ours as different conventions are used.
\[ \begin{align}\begin{aligned}\frac{dn}{dt} = n \left( r \left(1 - \frac{n}{K} \right) - \frac{k p}{n + d} \right)\\\frac{dp}{dt} = s p \left(1 - \frac{h p}{n} \right)\end{aligned}\end{align} \]>>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> system.variables (t, n, p, K, d, h, k, r, s) >>> maximal_scaling_matrix = system.maximal_scaling_matrix() >>> # Hand craft a Hermite multiplier given the invariants from the paper. >>> # This is done by placing the auxiliaries first, then rearranging the invariants and reading them off >>> # individually from the Hermite multiplier given in the paper >>> herm_mult = sympy.Matrix([[ 0, 0, 0, 1, 0, 0, 0, 0, 0], # t ... [ 0, 0, 0, 0, 1, 0, 0, 0, 0], # n ... [ 0, 0, 0, 0, 0, 1, 0, 0, 0], # p ... [ 0, 1, 1, 0, -1, -1, -1, 0, 0], # K ... [ 0, 0, 0, 0, 0, 0, 1, 0, 0], # d ... [ 0, 0, -1, 0, 0, 1, 0, -1, 0], # h ... [ 0, 0, 0, 0, 0, 0, 0, 1, 0], # k ... [-1, 0, 0, 1, 0, 0, 0, -1, -1], # r ... [ 0, 0, 0, 0, 0, 0, 0, 0, 1]]) # s >>> translation = ODETranslation(maximal_scaling_matrix, ... variables_domain=system.variables, ... hermite_multiplier=herm_mult) >>> translation.translate_parameter(system) dt/dt = 1 dn/dt = -c1*n*p/(c0 + n) - n**2 + n dp/dt = c2*p - c2*p**2/n dc0/dt = 0 dc1/dt = 0 dc2/dt = 0 >>> translation.translate_parameter_substitutions(system) {k: c1, n: n, r: 1, d: c0, K: 1, h: 1, s: c2, p: p, t: t} >>> soln_reduced = sympy.var('x1, x2, x3, t, n, p, c0, c1, c2') >>> translation.reverse_translate_parameter(soln_reduced) Matrix([[t*x1, n*x2, p*x3, x2, c0*x2, x2/x3, c1*x2/(x1*x3), 1/x1, c2/x1]])
-
rewrite_rules
(variables=None)[source]¶ Given a set of variables, print the rewrite rules. These are the rules that allow you to write any rational invariant in terms of the
invariants
.Parameters: variables (iter of sympy.Symbol) – The names of the variables appearing in the rational invariant. Returns: A dict
whose keys are the given variables and whose values are the values to be substituted.Return type: dict >>> equations = ['dn/dt = n*( r*(1 - n/K) - k*p/(n+d) )','dp/dt = s*p*(1 - h*p / n)'] >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.rewrite_rules() {k: 1, n: n/d, r: r/s, d: 1, K: K/d, h: h*s/k, s: 1, p: k*p/(d*s), t: s*t}
For example, \(r t\) is an invariant. Substituting in the above mapping gives us a way to write it in terms of our generating set of invariants:
\[r t \mapsto \left( \frac{r}{s} \right) \left( s t \right) = r t\]
-
scaling_matrix
¶ The scaling matrix that this translation corresponds to, often denoted \(A\).
Type: Returns Type: sympy.Matrix
-
to_tex
()[source]¶ Returns: The scaling matrix \(A\), the Hermite multiplier \(V\) and \(W = V^{-1}\), in beautiful LaTeX. Return type: str >>> print ODETranslation(sympy.Matrix(range(12)).reshape(3, 4)).to_tex() A= 0 & 1 & 2 & 3 \\ 4 & 5 & 6 & 7 \\ 8 & 9 & 10 & 11 \\ V= 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ -1 & 3 & -3 & -2 \\ 1 & -2 & 2 & 1 \\ W= 0 & 1 & 2 & 3 \\ 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\
-
translate
(system)[source]¶ Translate an
ode_system.ODESystem
into a reduced system.First, try the simplest parameter reduction method, then the dependent variable translation (where the scaling action ignores the independent variable) and finally the general reduction scheme.
Parameters: system (ODESystem) – System to reduce. Return type: ODESystem
-
translate_dep_var
(system)[source]¶ Given a system of ODEs, translate the system into a simplified version. Assume we are only working on dependent variables, not the independent variable.
Parameters: system (ODESystem) – System to reduce. Return type: ODESystem >>> equations = 'dz1/dt = z1*(1+z1*z2);dz2/dt = z2*(1/t - z1*z2)'.split(';') >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.translate_dep_var(system=system) dt/dt = 1 dx0/dt = x0*(y0 - 1/t) dy0/dt = y0*(1 + 1/t)
-
translate_general
(system)[source]¶ The most general reduction scheme. If there are \(n\) variables (including the independent variable) then there will be a system of \(n-r+1\) invariants and \(r\) auxiliary variables.
Parameters: system (ODESystem) – System to reduce. Return type: ODESystem >>> equations = 'dn/dt = n*( r*(1 - n/K) - k*p/(n+d) );dp/dt = s*p*(1 - h*p / n)'.split(';') >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.translate_general(system=system) dt/dt = 1 dx0/dt = 0 dx1/dt = 0 dx2/dt = 0 dy0/dt = y0/t dy1/dt = y1*(-y0*y1*y5/y3 - y0*y2/(y1 + 1) + y0*y5)/t dy2/dt = y2*(y0 - y0*y2*y4/y1)/t dy3/dt = 0 dy4/dt = 0 dy5/dt = 0
-
translate_parameter_substitutions
(system)[source]¶ Given a system, determine the substitutions made in the parameter reduction.
Parameters: system (ODESystem) – The system in question. Return type: dict >>> equations = 'dn/dt = n*( r*(1 - n/K) - k*p/(n+d) );dp/dt = s*p*(1 - h*p / n)'.split(';') >>> system = ODESystem.from_equations(equations) >>> translation = ODETranslation.from_ode_system(system) >>> translation.translate_parameter_substitutions(system=system) {k: 1, n: n, r: c2, d: 1, K: c0, h: c1, s: 1, p: p, t: t}
-
variables_domain
¶ - The variables that the scaling action acts on.
Type: Returns Type: tuple, None
-
desr.ode_translation.
extend_rectangular_matrix
(matrix_, check_unimodular=True)[source]¶ Given a rectangular \(n \times m\) integer matrix, extend it to a unimodular one by appending columns.
Parameters: matrix (sympy.Matrix) – The rectangular matrix to be extended. Returns: Square matrix of determinant 1. Return type: sympy.Matrix >>> matrix_ = sympy.Matrix([[1, 0], ... [0, 1], ... [0, 0],]) >>> extend_rectangular_matrix(matrix_) Matrix([ [1, 0, 0], [0, 1, 0], [0, 0, 1]])
By default, we will throw if we cannot extend a matrix to a unimodular matrix.
>>> matrix_[0, 0] = 2 >>> extend_rectangular_matrix(matrix_=matrix_) Traceback (most recent call last): ... ValueError: Unable to extend the matrix Matrix([[2, 0], [0, 1], [0, 0]]) to a unimodular matrix.
We can extend some more interesting matrices.
>>> matrix_ = sympy.Matrix([[3, 2], ... [-2, 1], ... [5, 6],]) >>> extend_rectangular_matrix(matrix_) Matrix([ [ 3, 2, 0], [-2, 1, 1], [ 5, 6, 1]])
-
desr.ode_translation.
scale_action
(vect, scaling_matrix)[source]¶ Given a vector of sympy expressions, determine the action defined by scaling_matrix I.e. Given vect, calculate vect^scaling_matrix (in notation of Hubert Labahn).
Parameters: - vect (iter of sympy.Expression) – Element of the algebraic torus that is going to act on the system.
- scaling_matrix (sympy.Matrix) – Matrix that defines the action on the system.
Returns: Matrix that, when multiplied element-wise with an element of the manifold, gives the result of the action.
Return type: sympy.Matrix
Example 3.3
>>> x = sympy.var('x') >>> A = sympy.Matrix([[2, 3]]) >>> scale_action([x], A) Matrix([[x**2, x**3]])
Example 3.4
>>> v = sympy.var('m v') >>> A = sympy.Matrix([[6, 0, -4, 1, 3], [0, 3, 1, -4, 3]]) >>> scale_action(v, A) Matrix([[m**6, v**3, v/m**4, m/v**4, m**3*v**3]])
desr.matrix_normal_forms module¶
-
desr.matrix_normal_forms.
element_wise_lt
(matrix_, other)[source]¶ Given a rectangular \(n \times m\) integer matrix, return a matrix of bools with (i, j)th entry equal to matrix_[i,j] < other or other[i,j], depending on the type of other.
Parameters: - matrix (sympy.Matrix) – The input matrix
- other (sympy.Matrix, int) – Value(s) to compare it to.
Returns: \(n \times m\) Boolean matrix
Return type: sympy.Matrix
>>> x = sympy.eye(2) * 3 >>> element_wise_lt(x, 2) Matrix([ [False, True], [ True, False]]) >>> element_wise_lt(x, sympy.Matrix([[4, -1], [1, 1]])) Matrix([ [True, False], [True, False]])
-
desr.matrix_normal_forms.
expand_matrix
(matrix_)[source]¶ Given a rectangular \(n \times m\) integer matrix, return an \((n+1) \times (m+1)\) matrix where the extra row and column are 0 except on the first entry which is 1.
Parameters: matrix (sympy.Matrix) – The rectangular matrix to be expanded Returns: An \((n+1) \times (m+1)\) matrix Return type: sympy.Matrix >>> matrix_ = sympy.diag(*[1, 1, 2]) >>> expand_matrix(matrix_) Matrix([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 2]])
>>> matrix_ = sympy.Matrix([1]) >>> expand_matrix(matrix_) Matrix([ [1, 0], [0, 1]])
>>> matrix_ = sympy.Matrix([[0]]) >>> expand_matrix(matrix_) Matrix([ [1, 0], [0, 0]])
>>> matrix_ = sympy.Matrix([[]]) >>> expand_matrix(matrix_) Matrix([[1]])
>>> matrix_ = sympy.Matrix([[1, 2, 3]]) >>> expand_matrix(matrix_) Matrix([ [1, 0, 0, 0], [0, 1, 2, 3]]) >>> expand_matrix(matrix_.T) Matrix([ [1, 0], [0, 1], [0, 2], [0, 3]])
-
desr.matrix_normal_forms.
get_pivot_row_indices
(matrix_)[source]¶ Return the pivot indices of the matrix
Parameters: matrix (sympy.Matrix) – The matrix in question. Returns: A list of indices, where the pivot entry of row i is [i, indices[i]] Return type: indices (list) >>> matrix_ = sympy.eye(3) >>> get_pivot_row_indices(matrix_) [0, 1, 2]
>>> matrix_ = sympy.Matrix([[1, 0, 0],[0, 0, 1]]) >>> get_pivot_row_indices(matrix_) [0, 2]
-
desr.matrix_normal_forms.
hnf_col
(matrix_)¶ Default function for calculating column Hermite normal forms.
Parameters: matrix (sympy.Matrix) – Input matrix. Returns: - Tuple containing:
- hermite_normal_form (sympy.Matrix): The column Hermite normal form of matrix_.
normal_multiplier (sympy.Matrix): The normal Hermite multiplier.
Return type: tuple Return type: (sympy.Matrix, sympy.Matrix)
-
desr.matrix_normal_forms.
hnf_col_lll
(matrix_)[source]¶ Compute the Hermite normal form, acts on the COLUMNS of a matrix. The Havas, Majewski, Matthews LLL method is used. We usually take \(\alpha = \frac{m_1}{n_1}\), with \((m_1,n_1)=(1,1)\) to get best results.
Parameters: matrix (sympy.Matrix) – Integer mxn matrix, nonzero, at least two rows Returns: hnf (sympy.Matrix): The column Hermite normal form of matrix_. unimod (sympy.Matrix): Unimodular matrix representing the column actions. Return type: tuple Return type: (sympy.Matrix, sympy.Matrix) >>> A = sympy.Matrix([[8, 2, 15, 9, 11], ... [6, 0, 6, 2, 3]]) >>> h, v = hnf_col(A) >>> h Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) >>> v Matrix([ [-1, 0, 0, -1, -1], [-3, -1, 6, -1, 0], [ 1, 0, 1, 1, 2], [ 0, -1, -3, -3, 0], [ 0, 1, 0, 2, -2]]) >>> A * v == h True
-
desr.matrix_normal_forms.
hnf_row
(matrix_)¶ Default function for calculating row Hermite normal forms.
Parameters: matrix (sympy.Matrix) – Input matrix. Returns: hermite_normal_form (sympy.Matrix): The column Hermite normal form of matrix_. normal_multiplier (sympy.Matrix): The normal Hermite multiplier.
Return type: tuple Return type: (sympy.Matrix, sympy.Matrix)
-
desr.matrix_normal_forms.
hnf_row_lll
(matrix_)[source]¶ Compute the Hermite normal form, acts on the ROWS of a matrix. The Havas, Majewski, Matthews LLL method is used. We usually take \(\alpha = \frac{m_1}{n_1}\), with \((m_1,n_1)=(1,1)\) to get best results.
Parameters: matrix (sympy.Matrix) – Integer mxn matrix, nonzero, at least two rows Returns: hnf (sympy.Matrix): The row Hermite normal form of matrix_. unimod (sympy.Matrix): Unimodular matrix representing the row actions.
Return type: tuple Return type: (sympy.Matrix, sympy.Matrix) >>> matrix_ = sympy.Matrix([[2, 0], ... [3, 3], ... [0, 0]]) >>> result = hnf_row_lll(matrix_) >>> result[0] Matrix([ [1, 3], [0, 6], [0, 0]]) >>> result[1] Matrix([ [-1, 1, 0], [-3, 2, 0], [ 0, 0, 1]]) >>> result[1] * matrix_ == result[0] True
>>> hnf_row_lll(sympy.Matrix([[0, -2, 0]])) (Matrix([[0, 2, 0]]), Matrix([[-1]]))
>>> matrix_ = sympy.Matrix([[0, 1, 0, 1], [-1, 0, 1, 0]]) >>> hnf_row_lll(matrix_)[0] Matrix([ [1, 0, -1, 0], [0, 1, 0, 1]])
-
desr.matrix_normal_forms.
is_hnf_col
(matrix_)[source]¶ Decide whether a matrix is in row Hermite normal form, when acting on rows.
Parameters: matrix (sympy.Matrix) – The matrix in question. Returns: bool
-
desr.matrix_normal_forms.
is_hnf_row
(matrix_)[source]¶ Decide whether a matrix is in Hermite normal form, when acting on rows. This is according to the Havas Majewski Matthews definition.
Parameters: matrix (sympy.Matrix) – The matrix in question. Returns: bool >>> is_hnf_row(sympy.eye(4)) True >>> is_hnf_row(sympy.ones(2)) False >>> is_hnf_row(sympy.Matrix([[1, 2, 0], [0, 1, 0]])) False >>> is_hnf_row(sympy.Matrix([[1, 0, 0], [0, 2, 1]])) True >>> is_hnf_row(sympy.Matrix([[1, 0, 0], [0, -2, 1]])) False
-
desr.matrix_normal_forms.
is_normal_hermite_multiplier
(hermite_multiplier, matrix_)[source]¶ Determine whether hermite_multiplier is the normal Hermite multiplier of matrix. This is the COLUMN version.
Parameters: - hermite_multiplier (sympy.Matrix) – Candidate column normal Hermite multiplier
- matrix (sympy.Matrix) – Matrix
Returns: matrix_ * hermite_multiplier is in Hermite normal form and hermite_multiplier is in normal form.
Return type: bool
-
desr.matrix_normal_forms.
is_smf
(matrix_)[source]¶ Given a rectangular \(n \times m\) integer matrix, determine whether it is in Smith normal form or not.
Parameters: matrix (sympy.Matrix) – The rectangular matrix to be decomposed Returns: True if in Smith normal form, False otherwise. Return type: bool >>> matrix_ = sympy.diag(1, 1, 2) >>> is_smf(matrix_) True >>> matrix_ = sympy.diag(-1, 1, 2) >>> is_smf(matrix_) False >>> matrix_ = sympy.diag(2, 1, 1) >>> is_smf(matrix_) False >>> matrix_ = sympy.diag(1, 2, 0) >>> is_smf(matrix_) True >>> matrix_ = sympy.diag(2, 6, 0) >>> is_smf(matrix_) True >>> matrix_ = sympy.diag(2, 5, 0) >>> is_smf(matrix_) False >>> matrix_ = sympy.diag(0, 1, 1) >>> is_smf(matrix_) False >>> matrix_ = sympy.diag(0) >>> is_smf(sympy.diag(0)), is_smf(sympy.diag(1)), is_smf(sympy.Matrix()), (True, True, True)
Check a real example:
>>> matrix_ = sympy.Matrix([[2, 4, 4], ... [-6, 6, 12], ... [10, -4, -16]]) >>> is_smf(matrix_) False
>>> matrix_ = sympy.diag(2, 6, 12) >>> is_smf(matrix_) True
Check it works for non-square matrices:
>>> matrix_ = sympy.Matrix(4, 5, range(20)) >>> is_smf(matrix_) False
>>> matrix_ = sympy.Matrix([[1, 0], [1, 2]]) >>> is_smf(matrix_) False
-
desr.matrix_normal_forms.
normal_hnf_col
(matrix_)[source]¶ Return the column HNF and the unique normal Hermite multiplier.
Parameters: matrix (sympy.Matrix) – Input matrix. Returns: - Tuple containing:
- hermite_normal_form (sympy.Matrix): The column Hermite normal form of matrix_. normal_multiplier (sympy.Matrix): The normal Hermite multiplier.
Return type: tuple >>> A = sympy.Matrix([[8, 2, 15, 9, 11], ... [6, 0, 6, 2, 3]]) >>> h, v = normal_hnf_col(A) >>> h Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0]]) >>> v Matrix([ [ 0, 0, 1, 0, 0], [ 0, 0, 0, 1, 0], [ 2, 1, 3, 1, 5], [ 9, 2, 21, 3, 21], [-10, -3, -22, -4, -24]]) >>> (A * v) == h True
-
desr.matrix_normal_forms.
normal_hnf_row
(matrix_)[source]¶ Return the row HNF and the unique normal Hermite multiplier.
Parameters: matrix (sympy.Matrix) – Input matrix. Returns: Tuple containing: hermite_normal_form (sympy.Matrix): The row Hermite normal form of matrix_. normal_multiplier (sympy.Matrix): The normal Hermite multiplier.Return type: tuple
-
desr.matrix_normal_forms.
smf
(matrix_)[source]¶ Given a rectangular \(n \times m\) integer matrix, calculate the Smith Normal Form \(S\) and multipliers \(U\), \(V\) such that \(U \textrm{matrix_} V = S\).
Parameters: matrix (sympy.Matrix) – The rectangular matrix to be decomposed. Returns: - S (sympy.Matrix) – The Smith normal form of matrix_.
- U (sympy.Matrix) – \(U\) (the matrix representing the row operations of the decomposition).
- V (sympy.Matrix) – \(V\) (the matrix representing the column operations of the decomposition).
Return type: (sympy.Matrix, sympy.Matrix, sympy.Matrix) >>> matrix_ = sympy.Matrix([[2, 4, 4], ... [-6, 6, 12], ... [10, -4, -16]]) >>> smf(matrix_)[0] Matrix([ [2, 0, 0], [0, 6, 0], [0, 0, 12]])
>>> matrix_ = sympy.diag(2, 1, 0) >>> smf(matrix_)[0] Matrix([ [1, 0, 0], [0, 2, 0], [0, 0, 0]])
>>> matrix_ = sympy.diag(5, 2, 0) >>> smf(matrix_)[0] Matrix([ [1, 0, 0], [0, 10, 0], [0, 0, 0]])
desr.diophantine module¶
Diophantine is a python package for finding small solutions of systems of diophantine equations (see https://en.wikipedia.org/wiki/Diophantine_equation). It is based on PHP code by Keith Matthews (see www.number-theory.org) that implements the algorithm described in the included ‘algorithm.pdf’ (see http://www.numbertheory.org/lll.html for a list of associated publications).
There are two branches of this code in the GitHub repository (see https://github.com/tclose/Diophantine.git), ‘master’, which uses the sympy library and therefore uses arbitrarily long integer representations, and ‘numpy’, which uses the numpy library, which is faster but can suffer from integer overflow errors despite using int64 representations.
Diophantine is released under the MIT Licence (see Licence for details)
Author: Thomas G. Close (tom.g.close@gmail.com)
-
desr.diophantine.
comparer
(a, b, c, d)[source]¶ Assumes b>0 and d>0. Returns -1, 0 or 1 according as a/b <,=,> c/d+
-
desr.diophantine.
first_nonzero_is_negative
(A)[source]¶ returns 0 if the first nonzero column j of A contains more than one nonzero entry, or contains only one nonzero entry and which is positive+ returns 1 if the first nonzero column j of A contains only one nonzero entry, which is negative+ This assumes A is a nonzero matrix with at least two rows+
-
desr.diophantine.
initialise_working_matrices
(G)[source]¶ G is a nonzero matrix with at least two rows.
-
desr.diophantine.
introot
(a, b, c, d)[source]¶ With Z=a/b, U=c/d, returns [sqrt(a/b)+c/d]. First ANSWER = [sqrt(Z)] + [U]. One then tests if Z < ([sqrt(Z)] + 1 -U)^2. If this does not hold, ANSWER += 1+ For use in fincke_pohst()+
-
desr.diophantine.
lllhermite
(G, m1=1, n1=1)[source]¶ Input: integer mxn matrix A, nonzero, at least two rows+ Output: small unimodular matrix B and HNF(A), such that BA=HNF(A)+ The Havas, Majewski, Matthews LLL method is used+ We usually take alpha=m1/n1, with (m1,n1)=(1,1) to get best results+
-
desr.diophantine.
lnearint
(a, b)[source]¶ left nearest integer returns y+1/2 if a/b=y+1/2, y integral+
-
desr.diophantine.
solve
(A, b)[source]¶ Finds small solutions to systems of diophantine equations, A x = b, where A is a M x N matrix of coefficents, b is a M x 1 vector and x is the N x 1 solution vector, e.g.
>>> A = sympy.Matrix([[1, 0, 0, 2], [0, 2, 3, 5], [2, 0, 3, 1], [-6, -1, 0, 2], ... [0, 1, 1, 1], [-1, 2, 0,1], [-1, -2, 1, 0]]).T >>> b = sympy.Matrix([1, 1, 1, 1]) >>> solve(A, b) [Matrix([ [-1], [ 1], [ 0], [ 0], [-1], [-1], [-1]])]
The returned solution vector will tend to be one with the smallest norms. If multiple solutions with the same norm are found they will all be returned. If there are no solutions the empty list will be returned.
desr.chemical_reaction_network module¶
-
class
desr.chemical_reaction_network.
ChemicalReactionNetwork
(chemical_species, complexes, reactions)[source]¶ Bases:
object
Chemical reaction network, made up of Species, Complexes and Reactions.
-
classmethod
from_diagram
(diagram)[source]¶ Given a text diagram, return an interpreted chemical reaction network.
>>> ChemicalReactionNetwork.from_diagram('x + y -> z \n y + z -> 2*z') 1.y + 1.x -> 1.z 1.y + 1.z -> 2.z
We can add reversible reactions like so:
>>> ChemicalReactionNetwork.from_diagram('x + y -> z \n z -> x + y') 1.y + 1.x -> 1.z 1.z -> 1.y + 1.x
-
n
¶ The number of chemical species in the network.
Returns: int
-
ode_equations
()[source]¶ Return a tuple of differential equations for each species.
Returns: A differential equation, represented by a sympy.Expression, for the dynamics of each species. Return type: tuple
-
p
¶ The number of complexes in the network.
Returns: int
-
r
¶ The number of different chemical reactions in the network.
Returns: int
-
classmethod
-
class
desr.chemical_reaction_network.
ChemicalSpecies
(id_)[source]¶ Bases:
object
Chemical species, A_i from Harrington paper. Typically represents a single chemical element.
-
class
desr.chemical_reaction_network.
Complex
(*args, **kwargs)[source]¶ Bases:
_abcoll.MutableMapping
A complex of ChemicalSpecies. Represented as a dictionary where the keys are chemical species and the value represents its coefficient in the complex.
-
as_vector
(variable_order)[source]¶ Represent the complex as a vector with respect to a given variable order.
Parameters: variable_order (iter) – Iterable of ChemicalSpecies
’s.Return type: tuple
-
desr.sympy_helper module¶
Created on Fri Dec 26 12:35:16 2014
Helper functions to deal with sympy expressions and equations
Author: Richard Tanburn (richard.tanburn@gmail.com)
-
desr.sympy_helper.
degree
(expr)[source]¶ Return the degree of a sympy expression. I.e. the largest number of variables multiplied together. NOTE DOES take into account idempotency of binary variables
>>> str_eqns = ['x + y', ... 'x*y*z - 1', ... 'x ** 2 + a*b*c', ... 'x**2 + y', ... 'x', ... 'x*y',] >>> eqns = str_exprs_to_sympy_eqns(str_eqns) >>> for e in eqns: print degree(e.lhs - e.rhs) 1 3 3 1 1 2
Check we deal with constants correctly >>> (degree(0), degree(1), degree(4), … degree(sympy.S.Zero), degree(sympy.S.One), degree(sympy.sympify(4))) (0, 0, 0, 0, 0, 0)
-
desr.sympy_helper.
dict_as_eqns
(dict_)[source]¶ Given a dictionary of lhs: rhs, return the sympy Equations in a list
>>> x, y, z = sympy.symbols('x y z') >>> dict_as_eqns({x: 1, y: z, x*y: 1 - z}) [Eq(x*y, -z + 1), Eq(x, 1), Eq(y, z)]
-
desr.sympy_helper.
eqns_with_variables
(eqns, variables, strict=False)[source]¶ Given a set of atoms, return only equations that have something in common
>>> x, y, z1, z2 = sympy.symbols('x y z1 z2') >>> eqns = ['x + y == 1', '2*z1 + 1 == z2', 'x*z1 == 0'] >>> eqns = str_eqns_to_sympy_eqns(eqns) >>> eqns_with_variables(eqns, [x]) [Eq(x + y - 1, 0), Eq(x*z1, 0)] >>> eqns_with_variables(eqns, [z1]) [Eq(2*z1 - z2 + 1, 0), Eq(x*z1, 0)] >>> eqns_with_variables(eqns, [y]) [Eq(x + y - 1, 0)]
>>> eqns_with_variables(eqns, [x], strict=True) [] >>> eqns_with_variables(eqns, [x, z1], strict=True) [Eq(x*z1, 0)] >>> eqns_with_variables(eqns, [x, y, z1], strict=True) [Eq(x + y - 1, 0), Eq(x*z1, 0)]
-
desr.sympy_helper.
expressions_to_variables
(exprs)[source]¶ Take a list of equations or expressions and return a set of variables
>>> eqn = sympy.Eq(sympy.sympify('x*a + 1')) >>> expr = sympy.sympify('x + y*z + 2*a^b') >>> to_test = [expr, eqn] >>> expressions_to_variables(to_test) set([x, z, a, b, y])
-
desr.sympy_helper.
is_constant
(expr)[source]¶ Determine whether an expression is constant >>> expr = ‘x + 2*y’ >>> is_constant(sympy.sympify(expr)) False >>> expr = ‘x + 5’ >>> is_constant(sympy.sympify(expr)) False >>> expr = ‘3’ >>> is_constant(sympy.sympify(expr)) True >>> expr = ‘2*x - 4’ >>> is_constant(sympy.sympify(expr)) False
-
desr.sympy_helper.
is_equation
(eqn, check_true=True)[source]¶ Return True if it is an equation rather than a boolean value. If it is False, raise a ContradictionException. We never want anything that might be False.
Optionally, we can turn the check off, but THE DEFAULT VALUE SHOULD ALWAYS BE TRUE. Otherwise bad things will happen.
>>> x, y = sympy.symbols('x y') >>> eq1 = sympy.Eq(x, y) >>> eq2 = sympy.Eq(x, x) >>> eq3 = sympy.Eq(x, y).subs(y, x) >>> eq4 = sympy.Eq(2*x*y, 2)
>>> is_equation(eq1) True >>> is_equation(eq2) False >>> is_equation(eq3) False >>> is_equation(eq4) True
Now check that it raises exceptions for the right things
>>> is_equation(0) False
-
desr.sympy_helper.
is_monomial
(expr)[source]¶ Determine whether expr is a monomial
>>> is_monomial(sympy.sympify('a*b**2/c')) True >>> is_monomial(sympy.sympify('a*b**2/c + d/e')) False >>> is_monomial(sympy.sympify('a*b**2/c + 1')) False >>> is_monomial(sympy.sympify('a*(b**2/c + 1)')) False
-
desr.sympy_helper.
monomial_to_powers
(monomial, variables)[source]¶ Given a monomial, return powers wrt some variables
>>> variables = sympy.var('a b c d e') >>> monomial_to_powers(sympy.sympify('a*b'), variables) [1, 1, 0, 0, 0]
>>> monomial_to_powers(sympy.sympify('a*b**2/c'), variables) [1, 2, -1, 0, 0]
>>> monomial_to_powers(sympy.sympify('a*b**2/c + d/e'), variables) Traceback (most recent call last): ... ValueError: a*b**2/c + d/e is not a monomial
>>> monomial_to_powers(sympy.sympify('a*b**2/c + 1'), variables) Traceback (most recent call last): ... ValueError: a*b**2/c + 1 is not a monomial
-
desr.sympy_helper.
str_eqns_to_sympy_eqns
(str_eqns)[source]¶ Take string equations and sympify
>>> str_eqns = ['x + y == 1', 'x*y*z - 3*a == -3'] >>> eqns = str_eqns_to_sympy_eqns(str_eqns) >>> for e in eqns: print e Eq(x + y - 1, 0) Eq(-3*a + x*y*z + 3, 0)
-
desr.sympy_helper.
str_exprs_to_sympy_eqns
(str_exprs)[source]¶ Take some strings and return the sympy expressions
>>> str_eqns = ['x + y - 1', 'x*y*z - 3*a + 3', '2*a - 4*b'] >>> eqns = str_exprs_to_sympy_eqns(str_eqns) >>> for e in eqns: print e Eq(x + y - 1, 0) Eq(-3*a + x*y*z + 3, 0) Eq(2*a - 4*b, 0)
desr.tex_tools module¶
Created on Wed Aug 12 01:37:16 2015
Author: Richard Tanburn (richard.tanburn@gmail.com)
-
desr.tex_tools.
eqns_to_tex
(eqns)[source]¶ To convert to array environment, copy the output into a lyx LaTeX cell, then copy this entire cell into an eqnarray of sufficient size
-
desr.tex_tools.
expr_to_tex
(expr)[source]¶ Given a sympy expression, write out the TeX.
Parameters: expr (sympy.Expression) – Expression to turn into TeX Returns: str >>> print map(expr_to_tex, map(sympy.sympify, ['(x + y - 1.5)**2', '(x + y_m1)**1', 'k_m1*t'])) ['\\left(x + y - 1.5\\right)^{2}', 'x + y_{-1}', 'k_{-1} t']
-
desr.tex_tools.
matrix_to_tex
(matrix_)[source]¶ Given a matrix, write out the TeX.
Parameters: matrix (sympy.Matrix) – Matrix to turn into TeX Returns: str Printing is the correct way to use this function, but the docstring looks a bit odd. >>> print matrix_to_tex(sympy.eye(2)) 1 & 0 \ 0 & 1 \
-
desr.tex_tools.
tex_to_sympy
(tex)[source]¶ Given some TeX, turn it into sympy expressions and equations. Each line is parsed seperately.
Parameters: tex (str) – LaTeX Returns: list >>> lines = [r'\frac{dE}{dt} &= - k_1 E S + k_{-1} C + k_2 C \\', ... r'\frac{dS}{dt} &= - k_1 E S + k_{-1} C \\', ... r'\frac{dC}{dt} &= k_1 E S - k_{-1} C - k_2 C \\', ... r'\frac{dP}{dt} &= k_2 C'] >>> sym = tex_to_sympy('\n'.join(lines)) >>> for s in sym: print s Eq(Derivative(E, t), C*k_2 + C*k_m1 - E*S*k_1) Eq(Derivative(S, t), C*k_m1 - E*S*k_1) Eq(Derivative(C, t), -C*k_2 - C*k_m1 + E*S*k_1) Eq(Derivative(P, t), C*k_2)
>>> print tex_to_sympy('k_2 &= V_2d ( APCT - APCs ) + V_2dd APCs') Eq(k_2, APCs*V_2dd + V_2d*(APCT - APCs))
desr.unittests module¶
-
class
desr.unittests.
TestChemicalReactionNetwork
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test cases for the ChemicalReactionNetwork class
-
class
desr.unittests.
TestHermiteMethods
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
-
test_example1
()[source]¶ Example from Extended gcd and Hermite nomal form via lattice basis reduction
-
test_example_sage
()[source]¶ Example from the Sage website See: http://doc.sagemath.org/html/en/reference/matrices/sage/matrix/matrix_integer_dense.html
-
test_wiki_example
()[source]¶ Test the examples from wikipedia https://en.wikipedia.org/wiki/Hermite_normal_form
-
-
class
desr.unittests.
TestInitialConditions
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test methods relating to initial conditions
-
class
desr.unittests.
TestODESystemScaling
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test ode_system.py scaling methods
-
test_example_6_4_hub_lab
()[source]¶ Predator prey model from [Hubert2013c], example 6.4 dz1/dt = z1*(1+z1*z2) dz2/dt = z2*(1/t - z1*z2)
-
test_example_6_6_hub_lab
()[source]¶ Example 6.6 from [Hubert2013c], where we act on time dz1/dt = z1*(z1**5*z2 - 2)/(3*t) dz2/dt = z2*(10 - 2*z1**5*z2 + 3*z1**2*z2/t )/(3*t)
-
test_example_pred_prey_choosing_invariants
()[source]¶ Predator prey model from [Hubert2013c] dn/dt = n( r(1 - n/K) - kp/(n+d) ) dp/dt = sp(1 - hp / n)
Rather than using the invariants suggested by the algorithm, we pick our own and extend it.
-
test_example_pred_prey_hub_lab
()[source]¶ Predator prey model from [Hubert2013c] dn/dt = n( r(1 - n/K) - kp/(n+d) ) dp/dt = sp(1 - hp / n)
-
test_verhulst_log_growth
()[source]¶ Verhult logistic growth model from [Hubert2013c] dn/dt = r*n*(1-n/k)
-