Derivations#
Let \(A\) be a ring and \(B\) be an bimodule over \(A\). A derivation \(d : A \to B\) is an additive map that satisfies the Leibniz rule
If \(B\) is an algebra over \(A\) and if we are given in addition a ring homomorphism \(\theta : A \to B\), a twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation) is an additive map \(d : A \to B\) such that
When \(\theta\) is the morphism defining the structure of \(A\)-algebra on \(B\), a \(\theta\)-derivation is nothing but a derivation. In general, if \(\iota : A \to B\) denotes the defining morphism above, one easily checks that \(\theta - \iota\) is a \(\theta\)-derivation.
This file provides support for derivations and twisted derivations over commutative rings with values in algebras (i.e. we require that \(B\) is a commutative \(A\)-algebra). In this case, the set of derivations (resp. \(\theta\)-derivations) is a module over \(B\).
Given a ring \(A\), the module of derivations over \(A\) can be created as follows:
sage: A.<x,y,z> = QQ[]
sage: M = A.derivation_module()
sage: M
Module of derivations over Multivariate Polynomial Ring in x, y, z over Rational Field
The method gens()
returns the generators of this module:
sage: A.<x,y,z> = QQ[]
sage: M = A.derivation_module()
sage: M.gens()
(d/dx, d/dy, d/dz)
We can combine them in order to create all derivations:
sage: d = 2*M.gen(0) + z*M.gen(1) + (x^2 + y^2)*M.gen(2)
sage: d
2*d/dx + z*d/dy + (x^2 + y^2)*d/dz
and now play with them:
sage: d(x + y + z)
x^2 + y^2 + z + 2
sage: P = A.random_element()
sage: Q = A.random_element()
sage: d(P*Q) == P*d(Q) + d(P)*Q
True
Alternatively we can use the method
derivation()
of the ring \(A\) to create derivations:
sage: Dx = A.derivation(x); Dx
d/dx
sage: Dy = A.derivation(y); Dy
d/dy
sage: Dz = A.derivation(z); Dz
d/dz
sage: A.derivation([2, z, x^2+y^2])
2*d/dx + z*d/dy + (x^2 + y^2)*d/dz
Sage knows moreover that \(M\) is a Lie algebra:
sage: M.category()
Join of Category of lie algebras with basis over Rational Field
and Category of modules with basis over Multivariate Polynomial Ring in x, y, z over Rational Field
Computations of Lie brackets are implemented as well:
sage: Dx.bracket(Dy)
0
sage: d.bracket(Dx)
-2*x*d/dz
At the creation of a module of derivations, a codomain can be specified:
sage: B = A.fraction_field()
sage: A.derivation_module(B)
Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field
to Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field
Alternatively, one can specify a morphism \(f\) with domain \(A\). In this case, the codomain of the derivations is the codomain of \(f\) but the latter is viewed as an algebra over \(A\) through the homomorphism \(f\). This construction is useful, for example, if we want to work with derivations on \(A\) at a certain point, e.g. \((0,1,2)\). Indeed, in order to achieve this, we first define the evaluation map at this point:
sage: ev = A.hom([QQ(0), QQ(1), QQ(2)])
sage: ev
Ring morphism:
From: Multivariate Polynomial Ring in x, y, z over Rational Field
To: Rational Field
Defn: x |--> 0
y |--> 1
z |--> 2
Now we use this ring homomorphism to define a structure of \(A\)-algebra on \(\QQ\) and then build the following module of derivations:
sage: M = A.derivation_module(ev)
sage: M
Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field to Rational Field
sage: M.gens()
(d/dx, d/dy, d/dz)
Elements in \(M\) then acts as derivations at \((0,1,2)\):
sage: Dx = M.gen(0)
sage: Dy = M.gen(1)
sage: Dz = M.gen(2)
sage: f = x^2 + y^2 + z^2
sage: Dx(f) # = 2*x evaluated at (0,1,2)
0
sage: Dy(f) # = 2*y evaluated at (0,1,2)
2
sage: Dz(f) # = 2*z evaluated at (0,1,2)
4
Twisted derivations are handled similarly:
sage: theta = B.hom([B(y),B(z),B(x)])
sage: theta
Ring endomorphism of Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field
Defn: x |--> y
y |--> z
z |--> x
sage: M = B.derivation_module(twist=theta)
sage: M
Module of twisted derivations over Fraction Field of Multivariate Polynomial Ring
in x, y, z over Rational Field (twisting morphism: x |--> y, y |--> z, z |--> x)
Over a field, one proves that every \(\theta\)-derivation is a multiple of \(\theta - id\), so that:
sage: d = M.gen(); d
[x |--> y, y |--> z, z |--> x] - id
and then:
sage: d(x)
-x + y
sage: d(y)
-y + z
sage: d(z)
x - z
sage: d(x + y + z)
0
AUTHOR:
Xavier Caruso (2018-09)
- class sage.rings.derivation.RingDerivation#
Bases:
ModuleElement
An abstract class for twisted and untwisted derivations over commutative rings.
- codomain()#
Return the codomain of this derivation.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = R.derivation(); f d/dx sage: f.codomain() Univariate Polynomial Ring in x over Rational Field sage: f.codomain() is R True
sage: S.<y> = R[] sage: M = R.derivation_module(S) sage: M.random_element().codomain() Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field sage: M.random_element().codomain() is S True
- domain()#
Return the domain of this derivation.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: f = R.derivation(y); f d/dy sage: f.domain() Multivariate Polynomial Ring in x, y over Rational Field sage: f.domain() is R True
- class sage.rings.derivation.RingDerivationModule(domain, codomain, twist=None)#
Bases:
Module
,UniqueRepresentation
A class for modules of derivations over a commutative ring.
- basis()#
Return a basis of this module of derivations.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy)
- codomain()#
Return the codomain of the derivations in this module.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module(); M Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring sage: M.codomain() Multivariate Polynomial Ring in x, y over Integer Ring
- defining_morphism()#
Return the morphism defining the structure of algebra of the codomain over the domain.
EXAMPLES:
sage: R.<x> = QQ[] sage: M = R.derivation_module() sage: M.defining_morphism() Identity endomorphism of Univariate Polynomial Ring in x over Rational Field sage: S.<y> = R[] sage: M = R.derivation_module(S) sage: M.defining_morphism() Polynomial base injection morphism: From: Univariate Polynomial Ring in x over Rational Field To: Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field sage: ev = R.hom([QQ(0)]) sage: M = R.derivation_module(ev) sage: M.defining_morphism() Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 0
- domain()#
Return the domain of the derivations in this module.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module(); M Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring sage: M.domain() Multivariate Polynomial Ring in x, y over Integer Ring
- dual_basis()#
Return the dual basis of the canonical basis of this module of derivations (which is that returned by the method
basis()
).Note
The dual basis of \((d_1, \dots, d_n)\) is a family \((x_1, \ldots, x_n)\) of elements in the domain such that \(d_i(x_i) = 1\) and \(d_i(x_j) = 0\) if \(i \neq j\).
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: M.dual_basis() Family (x, y)
- gen(n=0)#
Return the
n
-th generator of this module of derivations.INPUT:
n
– an integer (default:0
)
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module(); M Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring sage: M.gen() d/dx sage: M.gen(1) d/dy
- gens()#
Return the generators of this module of derivations.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module(); M Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring sage: M.gens() (d/dx, d/dy)
We check that, for a nontrivial twist over a field, the module of twisted derivation is a vector space of dimension 1 generated by
twist - id
:sage: K = R.fraction_field() sage: theta = K.hom([K(y),K(x)]) sage: M = K.derivation_module(twist=theta); M Module of twisted derivations over Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring (twisting morphism: x |--> y, y |--> x) sage: M.gens() ([x |--> y, y |--> x] - id,)
- ngens()#
Return the number of generators of this module of derivations.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module(); M Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring sage: M.ngens() 2
Indeed, generators are:
sage: M.gens() (d/dx, d/dy)
We check that, for a nontrivial twist over a field, the module of twisted derivation is a vector space of dimension 1 generated by
twist - id
:sage: K = R.fraction_field() sage: theta = K.hom([K(y),K(x)]) sage: M = K.derivation_module(twist=theta); M Module of twisted derivations over Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring (twisting morphism: x |--> y, y |--> x) sage: M.ngens() 1 sage: M.gen() [x |--> y, y |--> x] - id
- random_element(*args, **kwds)#
Return a random derivation in this module.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module() sage: M.random_element() # random (x^2 + x*y - 3*y^2 + x + 1)*d/dx + (-2*x^2 + 3*x*y + 10*y^2 + 2*x + 8)*d/dy
- ring_of_constants()#
Return the subring of the domain consisting of elements \(x\) such that \(d(x) = 0\) for all derivation \(d\) in this module.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: M.ring_of_constants() Rational Field
- some_elements()#
Return a list of elements of this module.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: M = R.derivation_module() sage: M.some_elements() [d/dx, d/dy, x*d/dx, x*d/dy, y*d/dx, y*d/dy]
- twisting_morphism()#
Return the twisting homomorphism of the derivations in this module.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: theta = R.hom([y,x]) sage: M = R.derivation_module(twist=theta); M Module of twisted derivations over Multivariate Polynomial Ring in x, y over Integer Ring (twisting morphism: x |--> y, y |--> x) sage: M.twisting_morphism() Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring Defn: x |--> y y |--> x
When the derivations are untwisted, this method returns nothing:
sage: M = R.derivation_module() sage: M.twisting_morphism()
- class sage.rings.derivation.RingDerivationWithTwist_generic(parent, scalar=0)#
Bases:
RingDerivation
The class handles \(\theta\)-derivations of the form \(\lambda (\theta - \iota)\) (where \(\iota\) is the defining morphism of the codomain over the domain) for a scalar \(\lambda\) varying in the codomain.
- extend_to_fraction_field()#
Return the extension of this derivation to fraction fields of the domain and the codomain.
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: theta = R.hom([y,x]) sage: d = R.derivation(x, twist=theta) sage: d x*([x |--> y, y |--> x] - id) sage: D = d.extend_to_fraction_field() sage: D x*([x |--> y, y |--> x] - id) sage: D.domain() Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring sage: D(1/x) (x - y)/y
- list()#
Return the list of coefficient of this twisted derivation on the canonical basis.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: K = R.fraction_field() sage: theta = K.hom([y,x]) sage: M = K.derivation_module(twist=theta) sage: M.basis() Family (twisting_morphism - id,) sage: f = (x+y) * M.gen() sage: f (x + y)*(twisting_morphism - id) sage: f.list() [x + y]
- postcompose(morphism)#
Return the twisted derivation obtained by applying first this twisted derivation and then
morphism
.INPUT:
morphism
– a homomorphism of rings whose domain is the codomain of this derivation or a ring into which the codomain of this derivation
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: theta = R.hom([y,x]) sage: D = R.derivation(x, twist=theta); D x*([x |--> y, y |--> x] - id) sage: f = R.hom([x^2, y^3]) sage: g = D.precompose(f); g x*([x |--> y^2, y |--> x^3] - [x |--> x^2, y |--> y^3])
Observe that the \(g\) is no longer a \(\theta\)-derivation but a \((\theta \circ f)\)-derivation:
sage: g.parent().twisting_morphism() Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring Defn: x |--> y^2 y |--> x^3
- precompose(morphism)#
Return the twisted derivation obtained by applying first
morphism
and then this twisted derivation.INPUT:
morphism
– a homomorphism of rings whose codomain is the domain of this derivation or a ring that coerces to the domain of this derivation
EXAMPLES:
sage: R.<x,y> = ZZ[] sage: theta = R.hom([y,x]) sage: D = R.derivation(x, twist=theta); D x*([x |--> y, y |--> x] - id) sage: f = R.hom([x^2, y^3]) sage: g = D.postcompose(f); g x^2*([x |--> y^3, y |--> x^2] - [x |--> x^2, y |--> y^3])
Observe that the \(g\) is no longer a \(\theta\)-derivation but a \((f \circ \theta)\)-derivation:
sage: g.parent().twisting_morphism() Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring Defn: x |--> y^3 y |--> x^2
- class sage.rings.derivation.RingDerivationWithoutTwist#
Bases:
RingDerivation
An abstract class for untwisted derivations.
- extend_to_fraction_field()#
Return the extension of this derivation to fraction fields of the domain and the codomain.
EXAMPLES:
sage: S.<x> = QQ[] sage: d = S.derivation() sage: d d/dx sage: D = d.extend_to_fraction_field() sage: D d/dx sage: D.domain() Fraction Field of Univariate Polynomial Ring in x over Rational Field sage: D(1/x) -1/x^2
- is_zero()#
Return
True
if this derivation is zero.EXAMPLES:
sage: R.<x,y> = ZZ[] sage: f = R.derivation(); f d/dx sage: f.is_zero() False sage: (f-f).is_zero() True
- list()#
Return the list of coefficient of this derivation on the canonical basis.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: R.derivation(x).list() [1, 0] sage: R.derivation(y).list() [0, 1] sage: f = x*R.derivation(x) + y*R.derivation(y); f x*d/dx + y*d/dy sage: f.list() [x, y]
- monomial_coefficients()#
Return dictionary of nonzero coordinates (on the canonical basis) of this derivation.
More precisely, this returns a dictionary whose keys are indices of basis elements and whose values are the corresponding coefficients.
EXAMPLES:
sage: R.<x,y> = QQ[] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: R.derivation(x).monomial_coefficients() {0: 1} sage: R.derivation(y).monomial_coefficients() {1: 1} sage: f = x*R.derivation(x) + y*R.derivation(y); f x*d/dx + y*d/dy sage: f.monomial_coefficients() {0: x, 1: y}
- postcompose(morphism)#
Return the derivation obtained by applying first this derivation and then
morphism
.INPUT:
morphism
– a homomorphism of rings whose domain is the codomain of this derivation or a ring into which the codomain of this derivation coerces
EXAMPLES:
sage: A.<x,y>= QQ[] sage: ev = A.hom([QQ(0), QQ(1)]) sage: Dx = A.derivation(x) sage: Dy = A.derivation(y)
We can define the derivation at \((0,1)\) just by postcomposing with
ev
:sage: dx = Dx.postcompose(ev) sage: dy = Dy.postcompose(ev) sage: f = x^2 + y^2 sage: dx(f) 0 sage: dy(f) 2
Note that we cannot avoid the creation of the evaluation morphism: if we pass in
QQ
instead, an error is raised since there is no coercion morphism fromA
toQQ
:sage: Dx.postcompose(QQ) Traceback (most recent call last): ... TypeError: the codomain of the derivation does not coerce to the given ring
Note that this method cannot be used to compose derivations:
sage: Dx.precompose(Dy) Traceback (most recent call last): ... TypeError: you must give an homomorphism of rings
- precompose(morphism)#
Return the derivation obtained by applying first
morphism
and then this derivation.INPUT:
morphism
– a homomorphism of rings whose codomain is the domain of this derivation or a ring that coerces to the domain of this derivation
EXAMPLES:
sage: A.<x> = QQ[] sage: B.<x,y> = QQ[] sage: D = B.derivation(x) - 2*x*B.derivation(y); D d/dx - 2*x*d/dy
When restricting to
A
, the termd/dy
disappears (since it vanishes onA
):sage: D.precompose(A) d/dx
If we restrict to another well chosen subring, the derivation vanishes:
sage: C.<t> = QQ[] sage: f = C.hom([x^2 + y]); f Ring morphism: From: Univariate Polynomial Ring in t over Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field Defn: t |--> x^2 + y sage: D.precompose(f) 0
Note that this method cannot be used to compose derivations:
sage: D.precompose(D) Traceback (most recent call last): ... TypeError: you must give an homomorphism of rings
- pth_power()#
Return the \(p\)-th power of this derivation where \(p\) is the characteristic of the domain.
Note
Leibniz rule implies that this is again a derivation.
EXAMPLES:
sage: R.<x,y> = GF(5)[] sage: Dx = R.derivation(x) sage: Dx.pth_power() 0 sage: (x*Dx).pth_power() x*d/dx sage: (x^6*Dx).pth_power() x^26*d/dx sage: Dy = R.derivation(y) sage: (x*Dx + y*Dy).pth_power() x*d/dx + y*d/dy
An error is raised if the domain has characteristic zero:
sage: R.<x,y> = QQ[] sage: Dx = R.derivation(x) sage: Dx.pth_power() Traceback (most recent call last): ... TypeError: the domain of the derivation must have positive and prime characteristic
or if the characteristic is not a prime number:
sage: R.<x,y> = Integers(10)[] sage: Dx = R.derivation(x) sage: Dx.pth_power() Traceback (most recent call last): ... TypeError: the domain of the derivation must have positive and prime characteristic
- class sage.rings.derivation.RingDerivationWithoutTwist_fraction_field(parent, arg=None)#
Bases:
RingDerivationWithoutTwist_wrapper
This class handles derivations over fraction fields.
- class sage.rings.derivation.RingDerivationWithoutTwist_function(parent, arg=None)#
Bases:
RingDerivationWithoutTwist
A class for untwisted derivations over rings whose elements are either polynomials, rational fractions, power series or Laurent series.
- is_zero()#
Return
True
if this derivation is zero.EXAMPLES:
sage: R.<x,y> = ZZ[] sage: f = R.derivation(); f d/dx sage: f.is_zero() False sage: (f-f).is_zero() True
- list()#
Return the list of coefficient of this derivation on the canonical basis.
EXAMPLES:
sage: R.<x,y> = GF(5)[[]] sage: M = R.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: R.derivation(x).list() [1, 0] sage: R.derivation(y).list() [0, 1] sage: f = x*R.derivation(x) + y*R.derivation(y); f x*d/dx + y*d/dy sage: f.list() [x, y]
- class sage.rings.derivation.RingDerivationWithoutTwist_quotient(parent, arg=None)#
Bases:
RingDerivationWithoutTwist_wrapper
This class handles derivations over quotient rings.
- class sage.rings.derivation.RingDerivationWithoutTwist_wrapper(parent, arg=None)#
Bases:
RingDerivationWithoutTwist
This class is a wrapper for derivation.
It is useful for changing the parent without changing the computation rules for derivations. It is used for derivations over fraction fields and quotient rings.
- list()#
Return the list of coefficient of this derivation on the canonical basis.
EXAMPLES:
sage: R.<X,Y> = GF(5)[] sage: S.<x,y> = R.quo([X^5, Y^5]) sage: M = S.derivation_module() sage: M.basis() Family (d/dx, d/dy) sage: S.derivation(x).list() [1, 0] sage: S.derivation(y).list() [0, 1] sage: f = x*S.derivation(x) + y*S.derivation(y); f x*d/dx + y*d/dy sage: f.list() [x, y]
- class sage.rings.derivation.RingDerivationWithoutTwist_zero(parent, arg=None)#
Bases:
RingDerivationWithoutTwist
This class can only represent the zero derivation.
It is used when the parent is the zero derivation module (e.g., when its domain is
ZZ
,QQ
, a finite field, etc.)- is_zero()#
Return
True
if this derivation vanishes.EXAMPLES:
sage: M = QQ.derivation_module() sage: M().is_zero() True
- list()#
Return the list of coefficient of this derivation on the canonical basis.
EXAMPLES:
sage: M = QQ.derivation_module() sage: M().list() []