Structures for systems of equation over rings with operators¶
File for the structures concerning differential systems
This file contains the structures and main algorithms to manipulate and study the solutions of differential systems expressed in terms of differential polynomials.
AUTHORS:
Antonio Jimenez-Pastor (2022-02-04): initial version
- class dalgebra.rwo_polynomial.rwo_polynomial_system.RWOSystem(equations, parent=None, variables=None)¶
Bases:
object
Class for representing a system over a ring with an operator.
This class allows the user to represent a system of equations over a ring with operators (see the category
RingsWithOperators
) as a list of infinite polynomials in one or several variables.This class will offer a set of methods and properties to extract the main information of the system and also the main algorithms and methods to study or manipulate these systems such as elimination procedures, etc.
INPUT:
equations
: list or tuple of operator polynomials (seeRWOPolynomial
). The system will be the one defined by \(eq = 0\) for all \(eq\) in the inputequations
.parent
: the common parent to transform the input. The final parent of all the elements will a common structure (if possible) that will be the pushout of all the parents ofelements
and this structure.variables
: list of names or infinite variables that will fix the variables of the system. If it is not given, we will consider all the differential variables as main variables.
- algebraic_equations()¶
Method to get the equivalent algebraic equations.
Considering a differential polynomial algebraically means to separate semantically the relation of different derivatives of a differential variable. This is mainly useful once all differential operations are completed.
OUTPUT:
A tuple of polynomials in a common parent that represent the equations of
self
in a purely algebraic context.EXAMPLES:
sage: from dalgebra import * sage: R.<u> = DifferentialPolynomialRing(QQ) sage: system = DifferentialSystem([u[1]-u[0]]) sage: system.algebraic_equations() (-u_0 + u_1,) sage: system.extend_by_operation([1]).algebraic_equations() (-u_0 + u_1, -u_1 + u_2)
We can check that the parent of all the equations is the same:
sage: parents = [el.parent() for el in system.extend_by_operation([1]).algebraic_equations()] sage: all(el == parents[0] for el in parents[1:]) True sage: parents[0] Multivariate Polynomial Ring in u_0, u_1, u_2 over Differential Ring [[Rational Field], (0,)]
The same can be checked for a multivariate differential polynomial:
sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base().gens()[0] sage: system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]]) sage: system.algebraic_equations() ((x - 1)*v_0 + x*u_0 + x^2*u_2, v_1 - v_2 + u_1) sage: system.extend_by_operation([1,2]).algebraic_equations() ((x - 1)*v_0 + x*u_0 + x^2*u_2, v_0 + (x - 1)*v_1 + u_0 + x*u_1 + 2*x*u_2 + x^2*u_3, v_1 - v_2 + u_1, v_2 - v_3 + u_2, v_3 - v_4 + u_3)
And the parents are again the same for all those equations:
sage: parents = [el.parent() for el in system.extend_by_operation([1,2]).algebraic_equations()] sage: all(el == parents[0] for el in parents[1:]) True sage: parents[0] Multivariate Polynomial Ring in v_0, v_1, v_2, v_3, v_4, u_0, u_1, u_2, u_3 over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]
The output of this method depends actively in the set of active variables that defines the system:
sage: system_with_u = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]], variables=[u]) sage: system_with_u.algebraic_equations() (x*u_0 + x^2*u_2 + (x - 1)*v_0, u_1 + v_1 - v_2) sage: system_with_u.extend_by_operation([1,2]).algebraic_equations() (x*u_0 + x^2*u_2 + (x - 1)*v_0, u_0 + x*u_1 + 2*x*u_2 + x^2*u_3 + v_0 + (x - 1)*v_1, u_1 + v_1 - v_2, u_2 + v_2 - v_3, u_3 + v_3 - v_4)
In this case, the parent prioritize the variables related with \(u_*\):
sage: system_with_u.algebraic_equations()[0].parent() Multivariate Polynomial Ring in u_0, u_1, u_2 over Multivariate Polynomial Ring in v_0, v_1, v_2 over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)] sage: parents = [el.parent() for el in system_with_u.extend_by_operation([1,2]).algebraic_equations()] sage: all(el == parents[0] for el in parents[1:]) True sage: parents[0] Multivariate Polynomial Ring in u_0, u_1, u_2, u_3 over Multivariate Polynomial Ring in v_0, v_1, v_2, v_3, v_4 over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]
- algebraic_variables()¶
Method to retrieve the algebraic variables in the system.
This method computes the number of algebraic variables that appear on the system. This means, gathering each appearance of the differential variables and filter them by the variables of the system.
OUTPUT:
A tuple containing the algebraic variables appearing in the system (as differential polynomials)
EXAMPLES:
sage: from dalgebra import * sage: R.<u> = DifferentialPolynomialRing(QQ) sage: system = DifferentialSystem([u[1]-u[0]]) sage: system.algebraic_variables() (u_0, u_1) sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base().gens()[0] sage: system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]]) sage: system.algebraic_variables() (v_0, v_1, v_2, u_0, u_1, u_2) sage: system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]], variables = [u]) sage: system.algebraic_variables() (u_0, u_1, u_2)
- build_sp1 = <function RWOSystem.extend_by_operation>¶
alias for method
extend_by_operation()
- change_variables(variables)¶
Method that creates a new system with new set of main variables.
This method returns an equivalent system as
self
, i.e., with the same equations and with the same parent. Bu now we fix a different set of variables as main variables of the system.INPUT:
variables
: set of new variables for the system. SeeRWOSystem
to see the format for this input.
OUTPUT:
A
RWOSystem
with the same equations but main variables given byvariables
.EXAMPLES:
sage: from dalgebra import * sage: bR = QQ[x]; x = bR('x') sage: R.<u,v> = DifferentialPolynomialRing(bR) sage: eq1 = u[0]*x - v[1] sage: eq2 = u[1] - (x-1)*v[0] sage: system = DifferentialSystem([eq1,eq2], variables=[u,v]) sage: system.change_variables(u) System over [Ring of operator polynomials in (u, v) over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]] with variables [(u_*,)]: { x*u_0 - v_1 == 0 u_1 + (-x + 1)*v_0 == 0 } sage: system.change_variables([v]) System over [Ring of operator polynomials in (u, v) over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]] with variables [(v_*,)]: { x*u_0 - v_1 == 0 u_1 + (-x + 1)*v_0 == 0 }
- diff_resultant(verbose, *args, **kwds)¶
Method to compute the operator resultant of this system.
TODO: add explanation of resultant.
This method has the optional argument
verbose
which, when given, will print the logging output in the console (sys.stdout
)INPUT:
bound_L
: bound for the values ofLs
for methodextend_by_operation()
.operation
: index for the operation for which we want to compute the resultant.alg_res
: ("auto"
by default) method to compute the algebraic resultant once we extended a system to a valid system (seeis_sp2()
). The valid values are, currently,"dixon"
,"macaulay"
and"iterative"
.
OUTPUT:
The resultant for this system.
TODO: add examples
- equation(index, *apply)¶
Method to get an equation from the system.
This method allows to obtain one equation from this system. This means, obtain a polynomial that is equal to zero, assuming the polynomials in
self._equations
are all equal to zero.This method allow to obtain the equations in
self._equations
but also the derived equations using the operation of the system.INPUT:
index
: the index for the equation desired.apply
: a collection of tuples \((a,n)\) indicating which operations to apply to the equation. In case there is only one operator, an integer means how many times to apply the only operator. Otherwise, an integer means the application of that operation once.
OUTPUT:
A polynomial with the \(i\)-th equation of the system. If
apply
was given, then we return the \(i\)-th equation after applying the operations as many times as requested.EXAMPLES:
sage: from dalgebra import * sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base()(x) sage: eq1 = u[0]*x - v[1] sage: eq2 = u[1] - (x-1)*v[0] sage: system = DifferentialSystem([eq1,eq2], variables=[u,v]) sage: system.equation(0) x*u_0 - v_1 sage: system.equation(1) u_1 + (-x + 1)*v_0
If the index given is not in range, we raise a
IndexError
:sage: system.equation(2) Traceback (most recent call last): ... IndexError: tuple index out of range
And if we provide the
apply
information, we take the corresponding equation and apply all the given operations:sage: system.equation(0,1) == eq1.derivative() True sage: system.equation(0,5) == eq1.derivative(times=5) True
This is specially useful when having several operators:
sage: A = DifferenceRing(DifferentialRing(QQ["x"], diff), QQ["x"].Hom(QQ["x"])("x+1")); x = A("x") sage: R.<u,v> = RWOPolynomialRing(A) sage: eq1 = u[0,0]*x - v[1,0] sage: eq2 = u[0,1] - (x-1)*v[0,0] sage: system = RWOSystem([eq1,eq2]) sage: system.equation(0) x*u_0_0 - v_1_0 sage: system.equation(1) u_0_1 + (-x + 1)*v_0_0
And now, we can use the
apply
argument for each operator:sage: system.equation(0, (0, 1)) # we apply the derivative x*u_1_0 + u_0_0 - v_2_0 sage: system.equation(0, (1, 1)) # we apply the shift (x + 1)*u_0_1 - v_1_1 sage: system.equation(0, (0, 2), (1, 3)) == system.equation(0).derivative(times=2).shift(times=3) True sage: system.equation(0,0,0,1,1,1) == system.equation(0, (0,2), (1,3)) True
- equations(indices=None)¶
Method to get a list of equations to the system.
This method allows to obtain a list of equations from the system, i.e., a list of polynomials that are assumed to be equal to zero. This method can also be used to get equations from extended systems.
INPUT:
indices
: collection of elements to be obtain. See methodindex()
for further information. If the input is aslice
, we convert it into a list. If the input is not a list or a tuple, we create a list with one element and try to get that element. IfNone
is given, then we return all equations.
OUTPUT:
A list of
RWOPolynomial
with the requested equations from this system.EXAMPLES:
sage: from dalgebra import * sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base()(x) sage: eq1 = u[0]*x - v[1] sage: eq2 = u[1] - (x-1)*v[0] sage: system = DifferentialSystem([eq1,eq2], variables=[u,v])
If nothing is given, we return all the equations:
sage: system.equations() (x*u_0 - v_1, u_1 + (-x + 1)*v_0)
If only an element is given, then we return that particular element:
sage: system.equations(1) (u_1 + (-x + 1)*v_0,)
Otherwise, we return the tuple with the equations required. This can be also used to obtained equations after applying the operation (see
equation()
):sage: system.equations([(0,0), (0,1), (1,3)]) (x*u_0 - v_1, x*u_1 + u_0 - v_2, u_4 + (-x + 1)*v_3 + (-3)*v_2)
This method also allows the use of
slice
to provide the indices for equations:sage: system.equations(slice(None,None,-1)) # reversing the equations (u_1 + (-x + 1)*v_0, x*u_0 - v_1)
- extend_by_operation(Ls, operation=None)¶
Method that build an extended system that satisfies SP1.
The condition SP1 is defined in the paper doi:10.1016/j.laa.2013.01.016 (Section 3) in regard with a system of differential polynomial: let \(\mathcal{P} = \{f_1,\ldots,f_m\}\). We say that an extended set of differential polynomials \(SP \subset \partial(\mathcal{P})\) is SP1 for some \(L_1,\ldots,L_m \in \mathbb{N}\) if it can be written as:
\[PS = \left\{\partial^{k}(f_i) \mid k \in \{0,\ldots,L_i\}, i=1,\ldots,m\right\}\]This method provides a way to build an extended system from
self
using the operator of the base ring that satisfies condition SP1 for a fixed set of values of \(L_1,\ldots,L_m\).INPUT:
Ls
: list or tuple of non-negative integers of lengthself.size()
.operation
: index of the operation with respect to which we want to extend the system.
OUTPUT:
Another
RWOSystem
extendingself
with the operation in the base ring that satisfies SP1 for the given list of \(L_i\).EXAMPLES:
sage: from dalgebra import * sage: R.<u> = DifferentialPolynomialRing(QQ) sage: system = DifferentialSystem([u[1]-u[0]]) sage: system.extend_by_operation([0]).equations() (u_1 - u_0,) sage: system.extend_by_operation([1]).equations() (u_1 - u_0, u_2 - u_1) sage: system.extend_by_operation([5]).equations() (u_1 - u_0, u_2 - u_1, u_3 - u_2, u_4 - u_3, u_5 - u_4, u_6 - u_5) sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base().gens()[0] sage: system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]], variables = [u]) sage: system.extend_by_operation([0,0]).equations() (x^2*u_2 + x*u_0 + (x - 1)*v_0, u_1 - v_2 + v_1) sage: system.extend_by_operation([1,0]).equations() (x^2*u_2 + x*u_0 + (x - 1)*v_0, x^2*u_3 + 2*x*u_2 + x*u_1 + u_0 + (x - 1)*v_1 + v_0, u_1 - v_2 + v_1) sage: system.extend_by_operation([1,1]).equations() (x^2*u_2 + x*u_0 + (x - 1)*v_0, x^2*u_3 + 2*x*u_2 + x*u_1 + u_0 + (x - 1)*v_1 + v_0, u_1 - v_2 + v_1, u_2 - v_3 + v_2)
- is_DifferenceSystem()¶
EXAMPLES:
sage: class Foo: ....: def __init__(self, x): ....: self._x = x ....: @cached_method ....: def f(self): ....: return self._x^2 sage: a = Foo(2) sage: print(a.f.cache) None sage: a.f() 4 sage: a.f.cache 4
- is_DifferentialSystem()¶
EXAMPLES:
sage: class Foo: ....: def __init__(self, x): ....: self._x = x ....: @cached_method ....: def f(self): ....: return self._x^2 sage: a = Foo(2) sage: print(a.f.cache) None sage: a.f() 4 sage: a.f.cache 4
- is_difference()¶
- is_differential()¶
- is_homogeneous()¶
This method checks whether the system is homogeneous in the indicated variables.
This method relies on the method
algebraic_equations()
and the methodis_homogeneous()
from the polynomial class in Sage.
- is_linear(variables=None)¶
Method that checks whether a system is linear in its variables.
See method
is_linear()
for further information on how this is computed.
- is_sp2()¶
Method that checks the condition SP2.
The condition SP2 is defined in the paper doi:10.1016/j.laa.2013.01.016 (Section 3) in regard with a system of differential polynomial: let \(\mathcal{P} = \{f_1,\ldots,f_m\}\) be a system of differentially algebraic equations in the differential variables \(\mathcal{U} = \{u_1,\ldots, u_n}\). We say that the system satisfies the condition SP2 if and only if the number of variables is valid to compute a resultant algebraically.
This quantity changing depending on whether the equations are homogeneous (same number of variables and equations) or not (one more equations than variables).
It is interesting to remark that the algebraic variables of a differential polynomial are the total amount of variables that appears in it before the differential relation. Namely, the result of method
variables()
provides the algebraic variables for a differential polynomial.OUTPUT:
True
if the system satisfies the condition SP2,False
otherwise.EXAMPLES:
sage: from dalgebra import * sage: R.<u,v> = DifferentialPolynomialRing(QQ[x]); x = R.base().gens()[0] sage: system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]], variables = [u]) sage: system.is_sp2() False sage: system.extend_by_operation([1,2]).is_sp2() True
WARNING: for this method it is crucial to know that the result depends directly on the set variables for the system. Namely, having different set of active variables change the output of this method for the same differential system:
sage: same_system = DifferentialSystem([x*u[0] + x^2*u[2] - (1-x)*v[0], v[1] - v[2] + u[1]]) sage: system.is_sp2() False sage: system.extend_by_operation([1,2]).is_sp2() True
- maximal_linear_variables()¶
EXAMPLES:
sage: class Foo: ....: def __init__(self, x): ....: self._x = x ....: @cached_method ....: def f(self): ....: return self._x^2 sage: a = Foo(2) sage: print(a.f.cache) None sage: a.f() 4 sage: a.f.cache 4
- order(gen=None, operation=- 1)¶
Method to return the order of the system.
The order of a system is defined as the maximal order of their equations. This method allows a generator to be given and then the order w.r.t. this variable will be computed. For further information, check
order()
.
- parameters¶
Initialize self. See help(type(self)) for accurate signature.
- parent()¶
- size()¶
- subsystem(indices=None, variables=None)¶
Method that creates a subsystem for a given set of equations.
This method create a new
RWOSystem
with the given variables inindices
(seeequations()
to see the format of this input) and setting as main variables those given invariables
(see inRWOSystem
the format for this input).INPUT:
indices
: list or tuple of indices to select the subsystem. (seeequations()
to see the format of this input).variables
: list of variables for the new system. IfNone
is given, we use the variables ofself
.
OUTPUT:
A new
RWOSystem
with the new given equations and the variables stated in the input.EXAMPLES:
sage: from dalgebra import * sage: bR = QQ[x]; x = bR('x') sage: R.<u,v> = DifferentialPolynomialRing(bR) sage: eq1 = u[0]*x - v[1] sage: eq2 = u[1] - (x-1)*v[0] sage: system = DifferentialSystem([eq1,eq2], variables=[u,v]) sage: system.subsystem([(0,0), (0,1), (1,3)]) System over [Ring of operator polynomials in (u, v) over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]] with variables [(u_*, v_*)]: { x*u_0 - v_1 == 0 x*u_1 + u_0 - v_2 == 0 u_4 + (-x + 1)*v_3 + (-3)*v_2 == 0 }
This method is used when using the
__getitem__
notation:sage: system[::-1] # same system but with equations changed in order System over [Ring of operator polynomials in (u, v) over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]] with variables [(u_*, v_*)]: { u_1 + (-x + 1)*v_0 == 0 x*u_0 - v_1 == 0 }
Setting up the argument
variables
allows to change the variables considered for the system:sage: system.subsystem(None, variables=[u]) System over [Ring of operator polynomials in (u, v) over Differential Ring [[Univariate Polynomial Ring in x over Rational Field], (d/dx,)]] with variables [(u_*,)]: { x*u_0 - v_1 == 0 u_1 + (-x + 1)*v_0 == 0 }
- variables¶
Initialize self. See help(type(self)) for accurate signature.
- class dalgebra.rwo_polynomial.rwo_polynomial_system.DifferentialSystem(equations, parent=None, variables=None)¶
Bases:
dalgebra.rwo_polynomial.rwo_polynomial_system.RWOSystem
Class representing a differential system.
- extend_by_derivation = <function RWOSystem.extend_by_operation>¶
new alias for
extend_by_operation()
- class dalgebra.rwo_polynomial.rwo_polynomial_system.DifferenceSystem(equations, parent=None, variables=None)¶
Bases:
dalgebra.rwo_polynomial.rwo_polynomial_system.RWOSystem
Class representing a difference system.
- extend_by_difference = <function RWOSystem.extend_by_operation>¶
new alias for
extend_by_operation()