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]

Bases: Module, UniqueRepresentation

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

Bases: RingDerivationWithoutTwist_wrapper

This class handles derivations over fraction fields.

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

Bases: RingDerivationWithoutTwist

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]

Bases: RingDerivationWithoutTwist_wrapper

This class handles derivations over quotient rings.

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

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

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