# 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

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)

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.

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

An abstract class for untwisted derivations.

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

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

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

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