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
If \(B\) is an algebra over \(A\) and if we are given in addition a ring homomorphism \(\theta : A \to B\), a twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation) is an additive map \(d : A \to B\) such that
When \(\theta\) is the morphism defining the structure of \(A\)-algebra on \(B\), a \(\theta\)-derivation is nothing but a derivation. In general, if \(\iota : A \to B\) denotes the defining morphism above, one easily checks that \(\theta - \iota\) is a \(\theta\)-derivation.
This file provides support for derivations and twisted derivations over commutative rings with values in algebras (i.e. we require that \(B\) is a commutative \(A\)-algebra). In this case, the set of derivations (resp. \(\theta\)-derivations) is a module over \(B\).
Given a ring \(A\), the module of derivations over \(A\) can be created as follows:
sage: A.<x,y,z> = QQ[]
sage: M = A.derivation_module()
sage: M
Module of derivations over
Multivariate Polynomial Ring in x, y, z over Rational Field
>>> 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 fromA
toQQ
: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 termd/dy
disappears (since it vanishes onA
):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.)