# Derivations#

Let $$A$$ be a ring and $$B$$ be a 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

>>> from sage.all import *
>>> A = QQ['x, y, z']; (x, y, z,) = A._first_ngens(3)
>>> M = A.derivation_module()
>>> 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)

>>> from sage.all import *
>>> A = QQ['x, y, z']; (x, y, z,) = A._first_ngens(3)
>>> M = A.derivation_module()
>>> 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

>>> from sage.all import *
>>> d = Integer(2)*M.gen(Integer(0)) + z*M.gen(Integer(1)) + (x**Integer(2) + y**Integer(2))*M.gen(Integer(2))
>>> 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

>>> from sage.all import *
>>> d(x + y + z)
x^2 + y^2 + z + 2
>>> P = A.random_element()
>>> Q = A.random_element()
>>> 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

>>> from sage.all import *
>>> Dx = A.derivation(x); Dx
d/dx
>>> Dy = A.derivation(y); Dy
d/dy
>>> Dz = A.derivation(z); Dz
d/dz
>>> A.derivation([Integer(2), z, x**Integer(2)+y**Integer(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

>>> from sage.all import *
>>> 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

>>> from sage.all import *
>>> Dx.bracket(Dy)
0
>>> 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

>>> from sage.all import *
>>> B = A.fraction_field()
>>> 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

>>> from sage.all import *
>>> ev = A.hom([QQ(Integer(0)), QQ(Integer(1)), QQ(Integer(2))])
>>> 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)

>>> from sage.all import *
>>> M = A.derivation_module(ev)
>>> M
Module of derivations
from Multivariate Polynomial Ring in x, y, z over Rational Field
to Rational Field
>>> 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

>>> from sage.all import *
>>> Dx = M.gen(Integer(0))
>>> Dy = M.gen(Integer(1))
>>> Dz = M.gen(Integer(2))
>>> f = x**Integer(2) + y**Integer(2) + z**Integer(2)
>>> Dx(f)  # = 2*x evaluated at (0,1,2)
0
>>> Dy(f)  # = 2*y evaluated at (0,1,2)
2
>>> 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)

>>> from sage.all import *
>>> theta = B.hom([B(y),B(z),B(x)])
>>> theta
Ring endomorphism of Fraction Field of
Multivariate Polynomial Ring in x, y, z over Rational Field
Defn: x |--> y
y |--> z
z |--> x

>>> M = B.derivation_module(twist=theta)
>>> 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

>>> from sage.all import *
>>> 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

>>> from sage.all import *
>>> d(x)
-x + y
>>> d(y)
-y + z
>>> d(z)
x - z
>>> d(x + y + z)
0


AUTHOR:

• Xavier Caruso (2018-09)

class sage.rings.derivation.RingDerivation[source]#

Bases: ModuleElement

An abstract class for twisted and untwisted derivations over commutative rings.

codomain()[source]#

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

>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> f = R.derivation(); f
d/dx
>>> f.codomain()
Univariate Polynomial Ring in x over Rational Field
>>> 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

>>> from sage.all import *
>>> S = R['y']; (y,) = S._first_ngens(1)
>>> M = R.derivation_module(S)
>>> M.random_element().codomain()
Univariate Polynomial Ring in y over
Univariate Polynomial Ring in x over Rational Field
>>> M.random_element().codomain() is S
True

domain()[source]#

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

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.derivation(y); f
d/dy
>>> f.domain()
Multivariate Polynomial Ring in x, y over Rational Field
>>> f.domain() is R
True

class sage.rings.derivation.RingDerivationModule(domain, codomain, twist=None)[source]#

A class for modules of derivations over a commutative ring.

basis()[source]#

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)

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)

codomain()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module(); M
Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring
>>> M.codomain()
Multivariate Polynomial Ring in x, y over Integer Ring

defining_morphism()[source]#

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

>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> M = R.derivation_module()
>>> M.defining_morphism()
Identity endomorphism of Univariate Polynomial Ring in x over Rational Field

>>> S = R['y']; (y,) = S._first_ngens(1)
>>> M = R.derivation_module(S)
>>> 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

>>> ev = R.hom([QQ(Integer(0))])
>>> M = R.derivation_module(ev)
>>> M.defining_morphism()
Ring morphism:
From: Univariate Polynomial Ring in x over Rational Field
To:   Rational Field
Defn: x |--> 0

domain()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module(); M
Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring
>>> M.domain()
Multivariate Polynomial Ring in x, y over Integer Ring

dual_basis()[source]#

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)

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)
>>> M.dual_basis()
Family (x, y)

gen(n=0)[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module(); M
Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring
>>> M.gen()
d/dx
>>> M.gen(Integer(1))
d/dy

gens()[source]#

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)

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module(); M
Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring
>>> 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,)

>>> from sage.all import *
>>> K = R.fraction_field()
>>> theta = K.hom([K(y),K(x)])
>>> 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)
>>> M.gens()
([x |--> y, y |--> x] - id,)

ngens()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module(); M
Module of derivations over Multivariate Polynomial Ring in x, y over Integer Ring
>>> M.ngens()
2


Indeed, generators are:

sage: M.gens()
(d/dx, d/dy)

>>> from sage.all import *
>>> 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

>>> from sage.all import *
>>> K = R.fraction_field()
>>> theta = K.hom([K(y),K(x)])
>>> 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)
>>> M.ngens()
1
>>> M.gen()
[x |--> y, y |--> x] - id

random_element(*args, **kwds)[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> 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()[source]#

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

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)
>>> M.ring_of_constants()
Rational Field

some_elements()[source]#

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]

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.some_elements()
[d/dx, d/dy, x*d/dx, x*d/dy, y*d/dx, y*d/dy]

twisting_morphism()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> theta = R.hom([y,x])
>>> 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)
>>> 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()

>>> from sage.all import *
>>> M = R.derivation_module()
>>> M.twisting_morphism()

class sage.rings.derivation.RingDerivationWithTwist_generic(parent, scalar=0)[source]#

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

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(); D                                   # needs sage.libs.singular
x*([x |--> y, y |--> x] - id)
sage: D.domain()                                                            # needs sage.libs.singular
Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring

sage: D(1/x)                                                                # needs sage.libs.singular
(x - y)/y

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> theta = R.hom([y,x])
>>> d = R.derivation(x, twist=theta)
>>> d
x*([x |--> y, y |--> x] - id)

>>> D = d.extend_to_fraction_field(); D                                   # needs sage.libs.singular
x*([x |--> y, y |--> x] - id)
>>> D.domain()                                                            # needs sage.libs.singular
Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring

>>> D(Integer(1)/x)                                                                # needs sage.libs.singular
(x - y)/y

list()[source]#

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]

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> K = R.fraction_field()
>>> theta = K.hom([y,x])
>>> M = K.derivation_module(twist=theta)
>>> M.basis()
Family (twisting_morphism - id,)
>>> f = (x+y) * M.gen()
>>> f
(x + y)*(twisting_morphism - id)
>>> f.list()
[x + y]

postcompose(morphism)[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> theta = R.hom([y,x])
>>> D = R.derivation(x, twist=theta); D
x*([x |--> y, y |--> x] - id)

>>> f = R.hom([x**Integer(2), y**Integer(3)])
>>> 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

>>> from sage.all import *
>>> 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)[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> theta = R.hom([y,x])
>>> D = R.derivation(x, twist=theta); D
x*([x |--> y, y |--> x] - id)

>>> f = R.hom([x**Integer(2), y**Integer(3)])
>>> 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

>>> from sage.all import *
>>> 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[source]#

Bases: RingDerivation

An abstract class for untwisted derivations.

extend_to_fraction_field()[source]#

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

>>> from sage.all import *
>>> S = QQ['x']; (x,) = S._first_ngens(1)
>>> d = S.derivation()
>>> d
d/dx

>>> D = d.extend_to_fraction_field()
>>> D
d/dx
>>> D.domain()
Fraction Field of Univariate Polynomial Ring in x over Rational Field

>>> D(Integer(1)/x)
-1/x^2

is_zero()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.derivation(); f
d/dx
>>> f.is_zero()
False

>>> (f-f).is_zero()
True

list()[source]#

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]

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)

>>> R.derivation(x).list()
[1, 0]
>>> R.derivation(y).list()
[0, 1]

>>> f = x*R.derivation(x) + y*R.derivation(y); f
x*d/dx + y*d/dy
>>> f.list()
[x, y]

monomial_coefficients()[source]#

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}

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)

>>> R.derivation(x).monomial_coefficients()
{0: 1}
>>> R.derivation(y).monomial_coefficients()
{1: 1}

>>> f = x*R.derivation(x) + y*R.derivation(y); f
x*d/dx + y*d/dy
>>> f.monomial_coefficients()
{0: x, 1: y}

postcompose(morphism)[source]#

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)

>>> from sage.all import *
>>> A = QQ['x, y']; (x, y,) = A._first_ngens(2)
>>> ev = A.hom([QQ(Integer(0)), QQ(Integer(1))])
>>> Dx = A.derivation(x)
>>> 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

>>> from sage.all import *
>>> dx = Dx.postcompose(ev)
>>> dy = Dy.postcompose(ev)
>>> f = x**Integer(2) + y**Integer(2)
>>> dx(f)
0
>>> 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

>>> from sage.all import *
>>> 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 a homomorphism of rings

>>> from sage.all import *
>>> Dx.precompose(Dy)
Traceback (most recent call last):
...
TypeError: you must give a homomorphism of rings

precompose(morphism)[source]#

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

>>> from sage.all import *
>>> A = QQ['x']; (x,) = A._first_ngens(1)
>>> B = QQ['x, y']; (x, y,) = B._first_ngens(2)
>>> D = B.derivation(x) - Integer(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

>>> from sage.all import *
>>> 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

>>> from sage.all import *
>>> C = QQ['t']; (t,) = C._first_ngens(1)
>>> f = C.hom([x**Integer(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
>>> 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 a homomorphism of rings

>>> from sage.all import *
>>> D.precompose(D)
Traceback (most recent call last):
...
TypeError: you must give a homomorphism of rings

pth_power()[source]#

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: # needs sage.rings.finite_rings
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)                                                  # needs sage.rings.finite_rings
sage: (x*Dx + y*Dy).pth_power()                                             # needs sage.rings.finite_rings
x*d/dx + y*d/dy

>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> R = GF(Integer(5))['x, y']; (x, y,) = R._first_ngens(2)
>>> Dx = R.derivation(x)
>>> Dx.pth_power()
0
>>> (x*Dx).pth_power()
x*d/dx
>>> (x**Integer(6)*Dx).pth_power()
x^26*d/dx

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

>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> Dx = R.derivation(x)
>>> 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

>>> from sage.all import *
>>> R = Integers(Integer(10))['x, y']; (x, y,) = R._first_ngens(2)
>>> Dx = R.derivation(x)
>>> 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)[source]#

This class handles derivations over fraction fields.

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

A class for untwisted derivations over rings whose elements are either polynomials, rational fractions, power series or Laurent series.

is_zero()[source]#

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

>>> from sage.all import *
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.derivation(); f
d/dx
>>> f.is_zero()
False

>>> (f-f).is_zero()
True

list()[source]#

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]

>>> from sage.all import *
>>> R = GF(Integer(5))[['x, y']]; (x, y,) = R._first_ngens(2)
>>> M = R.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)

>>> R.derivation(x).list()
[1, 0]
>>> R.derivation(y).list()
[0, 1]

>>> f = x*R.derivation(x) + y*R.derivation(y); f
x*d/dx + y*d/dy
>>> f.list()
[x, y]

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

This class handles derivations over quotient rings.

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

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

Return the list of coefficient of this derivation on the canonical basis.

EXAMPLES:

sage: # needs sage.libs.singular
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]

>>> from sage.all import *
>>> # needs sage.libs.singular
>>> R = GF(Integer(5))['X, Y']; (X, Y,) = R._first_ngens(2)
>>> S = R.quo([X**Integer(5), Y**Integer(5)], names=('x', 'y',)); (x, y,) = S._first_ngens(2)
>>> M = S.derivation_module()
>>> M.basis()
Family (d/dx, d/dy)
>>> S.derivation(x).list()
[1, 0]
>>> S.derivation(y).list()
[0, 1]
>>> f = x*S.derivation(x) + y*S.derivation(y); f
x*d/dx + y*d/dy
>>> f.list()
[x, y]

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

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

Return True if this derivation vanishes.

EXAMPLES:

sage: M = QQ.derivation_module()
sage: M().is_zero()
True

>>> from sage.all import *
>>> M = QQ.derivation_module()
>>> M().is_zero()
True

list()[source]#

Return the list of coefficient of this derivation on the canonical basis.

EXAMPLES:

sage: M = QQ.derivation_module()
sage: M().list()
[]

>>> from sage.all import *
>>> M = QQ.derivation_module()
>>> M().list()
[]