# 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

$d(xy) = x d(y) + d(x) y.$

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

$d(xy) = \theta(x) d(y) + d(x) y.$

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)#

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 from A to QQ:

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 term d/dy disappears (since it vanishes on A):

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)[]                                                     # optional - sage.rings.finite_rings
sage: Dx = R.derivation(x)                                                  # optional - sage.rings.finite_rings
sage: Dx.pth_power()                                                        # optional - sage.rings.finite_rings
0
sage: (x*Dx).pth_power()                                                    # optional - sage.rings.finite_rings
x*d/dx
sage: (x^6*Dx).pth_power()                                                  # optional - sage.rings.finite_rings
x^26*d/dx

sage: Dy = R.derivation(y)                                                  # optional - sage.rings.finite_rings
sage: (x*Dx + y*Dy).pth_power()                                             # optional - sage.rings.finite_rings
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)#

This class handles derivations over fraction fields.

class sage.rings.derivation.RingDerivationWithoutTwist_function(parent, arg=None)#

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)[[]]                                                   # optional - sage.rings.finite_rings
sage: M = R.derivation_module()                                             # optional - sage.rings.finite_rings
sage: M.basis()                                                             # optional - sage.rings.finite_rings
Family (d/dx, d/dy)

sage: R.derivation(x).list()                                                # optional - sage.rings.finite_rings
[1, 0]
sage: R.derivation(y).list()                                                # optional - sage.rings.finite_rings
[0, 1]

sage: f = x*R.derivation(x) + y*R.derivation(y); f                          # optional - sage.rings.finite_rings
x*d/dx + y*d/dy
sage: f.list()                                                              # optional - sage.rings.finite_rings
[x, y]

class sage.rings.derivation.RingDerivationWithoutTwist_quotient(parent, arg=None)#

This class handles derivations over quotient rings.

class sage.rings.derivation.RingDerivationWithoutTwist_wrapper(parent, arg=None)#

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)[]                                                     # optional - sage.rings.finite_rings
sage: S.<x,y> = R.quo([X^5, Y^5])                                           # optional - sage.rings.finite_rings
sage: M = S.derivation_module()                                             # optional - sage.rings.finite_rings
sage: M.basis()                                                             # optional - sage.rings.finite_rings
Family (d/dx, d/dy)

sage: S.derivation(x).list()                                                # optional - sage.rings.finite_rings
[1, 0]
sage: S.derivation(y).list()                                                # optional - sage.rings.finite_rings
[0, 1]

sage: f = x*S.derivation(x) + y*S.derivation(y); f                          # optional - sage.rings.finite_rings
x*d/dx + y*d/dy
sage: f.list()                                                              # optional - sage.rings.finite_rings
[x, y]

class sage.rings.derivation.RingDerivationWithoutTwist_zero(parent, arg=None)#

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()
[]