{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tensors on free modules\n", "## A tutorial\n", "\n", "This notebook provides some introduction to **tensors on free modules of finite rank** in SageMath. This is a pure algebraic subpart of the [SageManifolds](https://sagemanifolds.obspm.fr/) project, which does not depend on other parts of SageManifolds and which has been integrated in SageMath 6.6." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 10.3.beta6, Release Date: 2024-01-21'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display mathematical objects using LaTeX rendering:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Constructing a free module of finite rank\n", "\n", "Let $R$ be a commutative ring and $M$ a *free module of finite rank over* $R$, i.e. a module over $R$ that admits a *finite basis* (finite family of linearly independent generators). Since $R$ is commutative, it has the invariant basis number property: all bases of $M$ have the same cardinality, which is called the *rank of* $M$. In this tutorial, we consider a free module of rank 3 over the integer ring $\\mathbb{Z}$:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first two arguments are the ring and the rank; the third one is a string to denote the module and the last one defines the range of indices to be used for tensor components on the module: setting it to 1 means that indices will range in $\\{1,2,3\\}$. The default value is `start_index=0`. \n", " \n", "The function`print` returns a short description of the just constructed module:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we ask just for M, the module's LaTeX symbol is returned; by default, this is the same as the argument `name` in the constructor (this can be changed by providing the optional argument `latex_name`:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle M\\)" ], "text/latex": [ "$\\displaystyle M$" ], "text/plain": [ "Rank-3 free module M over the Integer Ring" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathcal{M}\\)" ], "text/latex": [ "$\\displaystyle \\mathcal{M}$" ], "text/plain": [ "Rank-3 free module M over the Integer Ring" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M1 = FiniteRankFreeModule(ZZ, 3, name='M', latex_name=r'\\mathcal{M}', start_index=1)\n", "M1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The indices of basis elements or tensor components on the module are generated by the method `irange()`, to be used in loops:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] } ], "source": [ "for i in M.irange(): \n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the parameter `start_index` had not been specified, the default range of the indices would have been $\\{0,1,2\\}$ instead:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n" ] } ], "source": [ "M0 = FiniteRankFreeModule(ZZ, 3, name='M')\n", "for i in M0.irange():\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

$M$ is the category of finite dimensional modules over $\\mathbb{Z}$:

" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Category of finite dimensional modules over Integer Ring\n" ] } ], "source": [ "print(M.category())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Self-inquiry commands are

" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}\\)" ], "text/latex": [ "$\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}$" ], "text/plain": [ "Integer Ring" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.base_ring()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 3\\)" ], "text/latex": [ "$\\displaystyle 3$" ], "text/plain": [ "3" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.rank()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining bases on the free module\n", "\n", "At construction, the free module $M$ has no pre-defined basis:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No basis has been defined on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "M.print_bases()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[\\right]$" ], "text/plain": [ "[]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For this reason, the class `FiniteRankFreeModule` does not inherit from Sage class `CombinatorialFreeModule`" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{False}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{False}$" ], "text/plain": [ "False" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(M, CombinatorialFreeModule)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and $M$ does not belong to the category of modules with a distinguished basis:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{False}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{False}$" ], "text/plain": [ "False" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M in ModulesWithBasis(ZZ)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It simply belongs to the category of modules over $\\mathbb{Z}$:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M in Modules(ZZ)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More precisely, it belongs to the subcategory of finite dimensional modules over $\\mathbb{Z}$:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M in Modules(ZZ).FiniteDimensional()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

We define a first basis on $M$ as follows:

" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(e_{1},e_{2},e_{3}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(e_{1},e_{2},e_{3}\\right)$" ], "text/plain": [ "Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e = M.basis('e')\n", "e" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bases defined on the Rank-3 free module M over the Integer Ring:\n", " - (e_1,e_2,e_3) (default basis)\n" ] } ], "source": [ "M.print_bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The elements of the basis are accessed via their indices:

" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{1}\\)" ], "text/latex": [ "$\\displaystyle e_{1}$" ], "text/plain": [ "Element e_1 of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1]" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element e_1 of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(e[1])" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1] in M" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle M\\)" ], "text/latex": [ "$\\displaystyle M$" ], "text/plain": [ "Rank-3 free module M over the Integer Ring" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1].parent()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us introduce a second basis on the free module $M$ from a family of 3 linearly independent module elements:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring\n" ] }, { "data": { "text/html": [ "\\(\\displaystyle \\left(f_{1},f_{2},f_{3}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(f_{1},f_{2},f_{3}\\right)$" ], "text/plain": [ "Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = M.basis('f', from_family=(-e[1]+2*e[2]-4*e[3], \n", " e[2]+2*e[3], \n", " e[2]+3*e[3]))\n", "print(f)\n", "f" ] }, { "cell_type": "markdown", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "We may ask to view each element of basis $f$ in terms of its expansion onto basis $e$, via the method `display()`:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}\\)" ], "text/latex": [ "$\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}$" ], "text/plain": [ "f_1 = -e_1 + 2 e_2 - 4 e_3" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[1].display(e)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{2} = e_{2} + 2 e_{3}\\)" ], "text/latex": [ "$\\displaystyle f_{2} = e_{2} + 2 e_{3}$" ], "text/plain": [ "f_2 = e_2 + 2 e_3" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[2].display(e)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{3} = e_{2} + 3 e_{3}\\)" ], "text/latex": [ "$\\displaystyle f_{3} = e_{2} + 3 e_{3}$" ], "text/plain": [ "f_3 = e_2 + 3 e_3" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[3].display(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conversely, the expression of basis $e$ is terms of basis $f$ is" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}\\)" ], "text/latex": [ "$\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}$" ], "text/plain": [ "e_1 = -f_1 + 10 f_2 - 8 f_3" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1].display(f)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{2} = 3 f_{2} -2 f_{3}\\)" ], "text/latex": [ "$\\displaystyle e_{2} = 3 f_{2} -2 f_{3}$" ], "text/plain": [ "e_2 = 3 f_2 - 2 f_3" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[2].display(f)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{3} = -f_{2}+f_{3}\\)" ], "text/latex": [ "$\\displaystyle e_{3} = -f_{2}+f_{3}$" ], "text/plain": [ "e_3 = -f_2 + f_3" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[3].display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The module automorphism $a$ relating the two bases is obtained as" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mbox{Automorphism of the Rank-3 free module M over the Integer Ring}\\)" ], "text/latex": [ "$\\displaystyle \\mbox{Automorphism of the Rank-3 free module M over the Integer Ring}$" ], "text/plain": [ "Automorphism of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = M.change_of_basis(e,f)\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It belongs to the general linear group of the free module $M$:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{GL}\\left( M \\right)\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{GL}\\left( M \\right)$" ], "text/plain": [ "General linear group of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.parent()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

and its matrix w.r.t. basis $e$ is

" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "-1 & 0 & 0 \\\\\n", "2 & 1 & 1 \\\\\n", "-4 & 2 & 3\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "-1 & 0 & 0 \\\\\n", "2 & 1 & 1 \\\\\n", "-4 & 2 & 3\n", "\\end{array}\\right)$" ], "text/plain": [ "[-1 0 0]\n", "[ 2 1 1]\n", "[-4 2 3]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.matrix(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Let us check that the elements of basis $f$ are images of the elements of basis $e$ via $a$:

" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all([f[i] == a(e[i]) for i in M.irange()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The reverse change of basis is of course the inverse automorphism:

" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.change_of_basis(f,e) == a^(-1)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "-1 & 0 & 0 \\\\\n", "10 & 3 & -1 \\\\\n", "-8 & -2 & 1\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "-1 & 0 & 0 \\\\\n", "10 & 3 & -1 \\\\\n", "-8 & -2 & 1\n", "\\end{array}\\right)$" ], "text/plain": [ "[-1 0 0]\n", "[10 3 -1]\n", "[-8 -2 1]" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(a^(-1)).matrix(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this stage, two bases have been defined on $M$:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bases defined on the Rank-3 free module M over the Integer Ring:\n", " - (e_1,e_2,e_3) (default basis)\n", " - (f_1,f_2,f_3)\n" ] } ], "source": [ "M.print_bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first defined basis, $e$, is considered as the *default basis*, which means that it can be skipped in any method argument requirying a basis. For instance, let us consider the method `display()`:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}\\)" ], "text/latex": [ "$\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}$" ], "text/plain": [ "f_1 = -e_1 + 2 e_2 - 4 e_3" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[1].display(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Since $e$ is the default basis, the above command is fully equivalent to

" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}\\)" ], "text/latex": [ "$\\displaystyle f_{1} = -e_{1} + 2 e_{2} -4 e_{3}$" ], "text/plain": [ "f_1 = -e_1 + 2 e_2 - 4 e_3" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[1].display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Of course, the names of non-default bases have to be specified:

" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle f_{1} = f_{1}\\)" ], "text/latex": [ "$\\displaystyle f_{1} = f_{1}$" ], "text/plain": [ "f_1 = f_1" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f[1].display(f)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}\\)" ], "text/latex": [ "$\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}$" ], "text/plain": [ "e_1 = -f_1 + 10 f_2 - 8 f_3" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1].display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the concept of ***default basis*** is different from that of ***distinguished basis*** which is implemented in other free module constructions in Sage (e.g. `CombinatorialFreeModule`): the default basis is intended only for shorthand notations in user commands, avoiding to repeat the basis name many times; it is by no means a privileged basis on the module. For user convenience, the default basis can be changed at any moment by means of the method `set_default_basis()`:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}\\)" ], "text/latex": [ "$\\displaystyle e_{1} = -f_{1} + 10 f_{2} -8 f_{3}$" ], "text/plain": [ "e_1 = -f_1 + 10 f_2 - 8 f_3" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.set_default_basis(f)\n", "e[1].display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Let us revert to $e$ as the default basis:

" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "M.set_default_basis(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Module elements\n", "\n", "Elements of the free module $M$ are constructed by providing their components with respect to a given basis to the operator `()` acting on the module:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element v of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "v = M([3,-4,1], basis=e, name='v')\n", "print(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Since $e$ is the default basis, its mention can be skipped:

" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element v of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "v = M([3,-4,1], name='v')\n", "print(v)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle v = 3 e_{1} -4 e_{2} +e_{3}\\)" ], "text/latex": [ "$\\displaystyle v = 3 e_{1} -4 e_{2} +e_{3}$" ], "text/plain": [ "v = 3 e_1 - 4 e_2 + e_3" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While $v$ has been defined from the basis $e$, its expression in terms of the basis $f$ can be evaluated, thanks to the known relation between the two bases:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle v = -3 f_{1} + 17 f_{2} -15 f_{3}\\)" ], "text/latex": [ "$\\displaystyle v = -3 f_{1} + 17 f_{2} -15 f_{3}$" ], "text/plain": [ "v = -3 f_1 + 17 f_2 - 15 f_3" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

According to Sage terminology, the parent of $v$ is of course $M$:

" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle M\\)" ], "text/latex": [ "$\\displaystyle M$" ], "text/plain": [ "Rank-3 free module M over the Integer Ring" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.parent()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

We have also

" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v in M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define a second module element, from the basis $f$ this time:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle u = -f_{1} + 3 f_{2} + 5 f_{3}\\)" ], "text/latex": [ "$\\displaystyle u = -f_{1} + 3 f_{2} + 5 f_{3}$" ], "text/plain": [ "u = -f_1 + 3 f_2 + 5 f_3" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u = M([-1,3,5], basis=f, name='u')\n", "u.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Another way to define module elements is of course via linear combinations:

" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "w = 2*e[1] - e[2] - 3*e[3]\n", "print(w)" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 2 e_{1} -e_{2} -3 e_{3}\\)" ], "text/latex": [ "$\\displaystyle 2 e_{1} -e_{2} -3 e_{3}$" ], "text/plain": [ "2 e_1 - e_2 - 3 e_3" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As the result of a linear combination, $w$ has no name; it can be given one by the method `set_name()` and the LaTeX symbol can be specified if different from the name:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\omega = 2 e_{1} -e_{2} -3 e_{3}\\)" ], "text/latex": [ "$\\displaystyle \\omega = 2 e_{1} -e_{2} -3 e_{3}$" ], "text/plain": [ "w = 2 e_1 - e_2 - 3 e_3" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w.set_name('w', latex_name=r'\\omega')\n", "w.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Module operations are implemented, independently of the bases:

" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "s = u + 3*v\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 10 e_{1} -6 e_{2} + 28 e_{3}\\)" ], "text/latex": [ "$\\displaystyle 10 e_{1} -6 e_{2} + 28 e_{3}$" ], "text/plain": [ "10 e_1 - 6 e_2 + 28 e_3" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -10 f_{1} + 54 f_{2} -40 f_{3}\\)" ], "text/latex": [ "$\\displaystyle -10 f_{1} + 54 f_{2} -40 f_{3}$" ], "text/plain": [ "-10 f_1 + 54 f_2 - 40 f_3" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display(f)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element u-v of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "s = u - v\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle u-v = -2 e_{1} + 10 e_{2} + 24 e_{3}\\)" ], "text/latex": [ "$\\displaystyle u-v = -2 e_{1} + 10 e_{2} + 24 e_{3}$" ], "text/plain": [ "u-v = -2 e_1 + 10 e_2 + 24 e_3" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle u-v = 2 f_{1} -14 f_{2} + 20 f_{3}\\)" ], "text/latex": [ "$\\displaystyle u-v = 2 f_{1} -14 f_{2} + 20 f_{3}$" ], "text/plain": [ "u-v = 2 f_1 - 14 f_2 + 20 f_3" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The components of a module element with respect to a given basis are given by the method `components()`:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|1-index|\\verb| |\\verb|components|\\verb| |\\verb|w.r.t.|\\verb| |\\verb|Basis|\\verb| |\\verb|(f_1,f_2,f_3)|\\verb| |\\verb|on|\\verb| |\\verb|the|\\verb| |\\verb|Rank-3|\\verb| |\\verb|free|\\verb| |\\verb|module|\\verb| |\\verb|M|\\verb| |\\verb|over|\\verb| |\\verb|the|\\verb| |\\verb|Integer|\\verb| |\\verb|Ring|\\)" ], "text/latex": [ "$\\displaystyle \\verb|1-index|\\verb| |\\verb|components|\\verb| |\\verb|w.r.t.|\\verb| |\\verb|Basis|\\verb| |\\verb|(f_1,f_2,f_3)|\\verb| |\\verb|on|\\verb| |\\verb|the|\\verb| |\\verb|Rank-3|\\verb| |\\verb|free|\\verb| |\\verb|module|\\verb| |\\verb|M|\\verb| |\\verb|over|\\verb| |\\verb|the|\\verb| |\\verb|Integer|\\verb| |\\verb|Ring|$" ], "text/plain": [ "1-index components w.r.t. Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.components(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A shortcut is `comp()`:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.comp(f) is v.components(f)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-3\n", "17\n", "-15\n" ] } ], "source": [ "for i in M.irange(): \n", " print(v.comp(f)[i])" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[-3, 17, -15\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[-3, 17, -15\\right]$" ], "text/plain": [ "[-3, 17, -15]" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.comp(f)[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function `display_comp()` provides a list of components w.r.t. to a given basis:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\begin{array}{lcl} v_{\\phantom{\\, 1}}^{\\,1} & = & -3 \\\\ v_{\\phantom{\\, 2}}^{\\,2} & = & 17 \\\\ v_{\\phantom{\\, 3}}^{\\,3} & = & -15 \\end{array}\\)" ], "text/latex": [ "$\\displaystyle \\begin{array}{lcl} v_{\\phantom{\\, 1}}^{\\,1} & = & -3 \\\\ v_{\\phantom{\\, 2}}^{\\,2} & = & 17 \\\\ v_{\\phantom{\\, 3}}^{\\,3} & = & -15 \\end{array}$" ], "text/plain": [ "v^1 = -3 \n", "v^2 = 17 \n", "v^3 = -15 " ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display_comp(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a shortcut, instead of calling the method `comp()`, the basis can be provided as the first argument of the square bracket operator:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 17\\)" ], "text/latex": [ "$\\displaystyle 17$" ], "text/plain": [ "17" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[f,2]" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[-3, 17, -15\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[-3, 17, -15\\right]$" ], "text/plain": [ "[-3, 17, -15]" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[f,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

For the default basis, the basis can be omitted:

" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[3, -4, 1\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[3, -4, 1\\right]$" ], "text/plain": [ "[3, -4, 1]" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[:]" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -4\\)" ], "text/latex": [ "$\\displaystyle -4$" ], "text/plain": [ "-4" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

A specific module element is the zero one:

" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element zero of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(M.zero())" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[0, 0, 0\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[0, 0, 0\\right]$" ], "text/plain": [ "[0, 0, 0]" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.zero()[:]" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[0, 0, 0\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[0, 0, 0\\right]$" ], "text/plain": [ "[0, 0, 0]" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.zero()[f,:]" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v + M.zero() == v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Linear forms\n", "\n", "Let us introduce some linear form on the free module $M$:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Linear form a on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "a = M.linear_form('a')\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$a$ is specified by its components with respect to the basis dual to $e$:" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle a = 2 e^{1} -e^{2} + 3 e^{3}\\)" ], "text/latex": [ "$\\displaystyle a = 2 e^{1} -e^{2} + 3 e^{3}$" ], "text/plain": [ "a = 2 e^1 - e^2 + 3 e^3" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[:] = [2,-1,3]\n", "a.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The notation $e^i$ stands for the elements of the basis dual to $e$, i.e. the basis of the dual module $M^*$ such that \n", "\n", "$$e^i(e_j) = \\delta^i_{\\ \\, j} $$\n", "\n", "Indeed" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(e^{1},e^{2},e^{3}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(e^{1},e^{2},e^{3}\\right)$" ], "text/plain": [ "Dual basis (e^1,e^2,e^3) on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ed = e.dual_basis()\n", "ed" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Linear form e^1 on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(ed[1])" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(1, 0, 0\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(1, 0, 0\\right)$" ], "text/plain": [ "(1, 0, 0)" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ed[1](e[1]), ed[1](e[2]), ed[1](e[3])" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(0, 1, 0\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(0, 1, 0\\right)$" ], "text/plain": [ "(0, 1, 0)" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ed[2](e[1]), ed[2](e[2]), ed[2](e[3])" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(0, 0, 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(0, 0, 1\\right)$" ], "text/plain": [ "(0, 0, 1)" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ed[3](e[1]), ed[3](e[2]), ed[3](e[3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The linear form $a$ can also be defined by its components with respect to the basis dual to $f$:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle a = 2 f^{1} -f^{2} + 3 f^{3}\\)" ], "text/latex": [ "$\\displaystyle a = 2 f^{1} -f^{2} + 3 f^{3}$" ], "text/plain": [ "a = 2 f^1 - f^2 + 3 f^3" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[f,:] = [2,-1,3]\n", "a.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For consistency, the previously defined components with respect to the basis dual to $e$ are automatically deleted and new ones are computed from the change-of-basis formula:" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle a = -36 e^{1} -9 e^{2} + 4 e^{3}\\)" ], "text/latex": [ "$\\displaystyle a = -36 e^{1} -9 e^{2} + 4 e^{3}$" ], "text/plain": [ "a = -36 e^1 - 9 e^2 + 4 e^3" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

By definition, linear forms belong to the dual module:

" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle M^*\\)" ], "text/latex": [ "$\\displaystyle M^*$" ], "text/plain": [ "Dual of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.parent()" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dual of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(a.parent())" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.parent() is M.dual()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The dual module is itself a free module of the same rank as $M$:

" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{False}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{False}$" ], "text/plain": [ "False" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(M.dual(), FiniteRankFreeModule)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 3\\)" ], "text/latex": [ "$\\displaystyle 3$" ], "text/plain": [ "3" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.dual().rank()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Linear forms map module elements to ring elements:

" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -68\\)" ], "text/latex": [ "$\\displaystyle -68$" ], "text/plain": [ "-68" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a(v)" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 10\\)" ], "text/latex": [ "$\\displaystyle 10$" ], "text/plain": [ "10" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

in a linear way:

" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a(u+2*v) == a(u) + 2*a(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Alternating forms

\n", "

Let us introduce a second linear form, $b$, on the free module $M$:

" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [], "source": [ "b = M.linear_form('b')\n", "b[:] = [-4,2,5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

and take its exterior product with the linear form $a$:

" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alternating form a∧b of degree 2 on the Rank-3 free module M over the Integer Ring\n" ] }, { "data": { "text/html": [ "\\(\\displaystyle a\\wedge b\\)" ], "text/latex": [ "$\\displaystyle a\\wedge b$" ], "text/plain": [ "Alternating form a∧b of degree 2 on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = a.wedge(b)\n", "print(c)\n", "c" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle a\\wedge b = -108 e^{1}\\wedge e^{2} -164 e^{1}\\wedge e^{3} -53 e^{2}\\wedge e^{3}\\)" ], "text/latex": [ "$\\displaystyle a\\wedge b = -108 e^{1}\\wedge e^{2} -164 e^{1}\\wedge e^{3} -53 e^{2}\\wedge e^{3}$" ], "text/plain": [ "a∧b = -108 e^1∧e^2 - 164 e^1∧e^3 - 53 e^2∧e^3" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.display()" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle a\\wedge b = 12 f^{1}\\wedge f^{2} + 70 f^{1}\\wedge f^{3} -53 f^{2}\\wedge f^{3}\\)" ], "text/latex": [ "$\\displaystyle a\\wedge b = 12 f^{1}\\wedge f^{2} + 70 f^{1}\\wedge f^{3} -53 f^{2}\\wedge f^{3}$" ], "text/plain": [ "a∧b = 12 f^1∧f^2 + 70 f^1∧f^3 - 53 f^2∧f^3" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.display(f)" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 8894\\)" ], "text/latex": [ "$\\displaystyle 8894$" ], "text/plain": [ "8894" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c(u,v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

$c$ is antisymmetric:

" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -8894\\)" ], "text/latex": [ "$\\displaystyle -8894$" ], "text/plain": [ "-8894" ] }, "execution_count": 95, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c(v,u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

and is multilinear:

" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c(u+4*w,v) == c(u,v) + 4*c(w,v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

We may check the standard formula for the exterior product of two linear forms:

" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c(u,v) == a(u)*b(v) - b(u)*a(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

In terms of tensor product (denoted here by *), it reads

" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c == a*b - b*a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The parent of the alternating form $c$ is the second external power of the dual module $M^*$, which is denoted by $\\Lambda^2(M^*)$:

" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\Lambda^{2}\\left(M^*\\right)\\)" ], "text/latex": [ "$\\displaystyle \\Lambda^{2}\\left(M^*\\right)$" ], "text/plain": [ "2nd exterior power of the dual of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.parent()" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2nd exterior power of the dual of the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(c.parent())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$c$ is a tensor of type $(0,2)$:" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(0, 2\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(0, 2\\right)$" ], "text/plain": [ "(0, 2)" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.tensor_type()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

whose components with respect to any basis are antisymmetric:

" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -108 & -164 \\\\\n", "108 & 0 & -53 \\\\\n", "164 & 53 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -108 & -164 \\\\\n", "108 & 0 & -53 \\\\\n", "164 & 53 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -108 -164]\n", "[ 108 0 -53]\n", "[ 164 53 0]" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c[:] # components with respect to the default basis (e)" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 12 & 70 \\\\\n", "-12 & 0 & -53 \\\\\n", "-70 & 53 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 12 & 70 \\\\\n", "-12 & 0 & -53 \\\\\n", "-70 & 53 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 12 70]\n", "[-12 0 -53]\n", "[-70 53 0]" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c[f,:] # components with respect to basis f" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|Fully|\\verb| |\\verb|antisymmetric|\\verb| |\\verb|2-indices|\\verb| |\\verb|components|\\verb| |\\verb|w.r.t.|\\verb| |\\verb|Basis|\\verb| |\\verb|(f_1,f_2,f_3)|\\verb| |\\verb|on|\\verb| |\\verb|the|\\verb| |\\verb|Rank-3|\\verb| |\\verb|free|\\verb| |\\verb|module|\\verb| |\\verb|M|\\verb| |\\verb|over|\\verb| |\\verb|the|\\verb| |\\verb|Integer|\\verb| |\\verb|Ring|\\)" ], "text/latex": [ "$\\displaystyle \\verb|Fully|\\verb| |\\verb|antisymmetric|\\verb| |\\verb|2-indices|\\verb| |\\verb|components|\\verb| |\\verb|w.r.t.|\\verb| |\\verb|Basis|\\verb| |\\verb|(f_1,f_2,f_3)|\\verb| |\\verb|on|\\verb| |\\verb|the|\\verb| |\\verb|Rank-3|\\verb| |\\verb|free|\\verb| |\\verb|module|\\verb| |\\verb|M|\\verb| |\\verb|over|\\verb| |\\verb|the|\\verb| |\\verb|Integer|\\verb| |\\verb|Ring|$" ], "text/plain": [ "Fully antisymmetric 2-indices components w.r.t. Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.comp(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

An alternating form can be constructed from scratch:

" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [], "source": [ "c1 = M.alternating_form(2) # 2 stands for the degree" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Only the non-zero and non-redundant components are to be defined (the others are deduced by antisymmetry); for the components with respect to the default basis, we write:

" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "c1[1,2] = -108\n", "c1[1,3] = -164\n", "c1[2,3] = -53" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Then

" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -108 & -164 \\\\\n", "108 & 0 & -53 \\\\\n", "164 & 53 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -108 & -164 \\\\\n", "108 & 0 & -53 \\\\\n", "164 & 53 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -108 -164]\n", "[ 108 0 -53]\n", "[ 164 53 0]" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c1[:]" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c1 == c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Internally, only non-redundant components are stored, in a dictionary whose keys are the indices:

" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left\\{\\left(1, 2\\right) : -108, \\left(1, 3\\right) : -164, \\left(2, 3\\right) : -53\\right\\}\\)" ], "text/latex": [ "$\\displaystyle \\left\\{\\left(1, 2\\right) : -108, \\left(1, 3\\right) : -164, \\left(2, 3\\right) : -53\\right\\}$" ], "text/plain": [ "{(1, 2): -108, (1, 3): -164, (2, 3): -53}" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.comp(e)._comp" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left\\{\\left(1, 2\\right) : 12, \\left(1, 3\\right) : 70, \\left(2, 3\\right) : -53\\right\\}\\)" ], "text/latex": [ "$\\displaystyle \\left\\{\\left(1, 2\\right) : 12, \\left(1, 3\\right) : 70, \\left(2, 3\\right) : -53\\right\\}$" ], "text/plain": [ "{(1, 2): 12, (1, 3): 70, (2, 3): -53}" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.comp(f)._comp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The other components are deduced by antisymmetry.

\n", "\n", "

The exterior product of a linear form with an alternating form of degree 2 leads to an alternating form of degree 3:

" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alternating form d∧a∧b of degree 3 on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "d = M.linear_form('d')\n", "d[:] = [-1,-2,4]\n", "s = d.wedge(c)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle d\\wedge a\\wedge b = -707 e^{1}\\wedge e^{2}\\wedge e^{3}\\)" ], "text/latex": [ "$\\displaystyle d\\wedge a\\wedge b = -707 e^{1}\\wedge e^{2}\\wedge e^{3}$" ], "text/plain": [ "d∧a∧b = -707 e^1∧e^2∧e^3" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle d\\wedge a\\wedge b = 707 f^{1}\\wedge f^{2}\\wedge f^{3}\\)" ], "text/latex": [ "$\\displaystyle d\\wedge a\\wedge b = 707 f^{1}\\wedge f^{2}\\wedge f^{3}$" ], "text/plain": [ "d∧a∧b = 707 f^1∧f^2∧f^3" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display(f)" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -707\\)" ], "text/latex": [ "$\\displaystyle -707$" ], "text/plain": [ "-707" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s(e[1], e[2], e[3])" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 707\\)" ], "text/latex": [ "$\\displaystyle 707$" ], "text/plain": [ "707" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s(f[1], f[2], f[3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

$s$ is antisymmetric:

" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(-144228, 144228, -144228, 144228, -144228, 144228\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(-144228, 144228, -144228, 144228, -144228, 144228\\right)$" ], "text/plain": [ "(-144228, 144228, -144228, 144228, -144228, 144228)" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s(u,v,w), s(u,w,v), s(v,w,u), s(v,u,w), s(w,u,v), s(w,v,u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tensors\n", "$k$ and $l$ being non negative integers, a tensor of type $(k,l)$ on the free module $M$ is a multilinear map\n", "\n", "$$ t: \\underbrace{M^*\\times\\cdots\\times M^*}_{k\\ \\; \\mbox{times}}    \n", "\\times \\underbrace{M\\times\\cdots\\times M}_{l\\ \\; \\mbox{times}}\n", "\\longrightarrow R $$\n", "\n", "In the present case the ring $R$ is $\\mathbb{Z}$.\n", "\n", "For free modules of finite rank, we have the canonical isomorphism $M^{**} \\simeq M$, so that the set of all tensors of type $(k,l)$ can be identified with the tensor product\n", "\n", "$$ T^{(k,l)}(M) = \\underbrace{M\\otimes\\cdots\\otimes M}_{k\\ \\; \\mbox{times}}  \\otimes \\underbrace{M^*\\otimes\\cdots\\otimes M^*}_{l\\ \\; \\mbox{times}}$$\n", "\n", "In particular, tensors of type $(1,0)$ are identified with elements of $M$:" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 117, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.tensor_module(1,0) is M" ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(1, 0\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(1, 0\\right)$" ], "text/plain": [ "(1, 0)" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.tensor_type()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

According to the above definition, linear forms are tensors of type (0,1):

" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a in M.tensor_module(0,1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have the identification of $T^{(0,1)}(M)$ with $M^*$:" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.tensor_module(0,1) is M.dual()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arbitrary tensors are constructed via the module method `tensor()`, by providing the tensor type $(k,l)$ and possibly the symbol to denote the tensor:" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(1,1) tensor t on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "t = M.tensor((1,1), name='t')\n", "print(t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Let us set some component of $t$ in the basis $e$, for instance the component $t^1_{\\ \\, 2}$:

" ] }, { "cell_type": "code", "execution_count": 122, "metadata": {}, "outputs": [], "source": [ "t[e,1,2] = -3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Since $e$ is the default basis, a shortcut for the above is

" ] }, { "cell_type": "code", "execution_count": 123, "metadata": {}, "outputs": [], "source": [ "t[1,2] = -3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The unset components are zero:

" ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 0 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 0 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -3 0]\n", "[ 0 0 0]\n", "[ 0 0 0]" ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Components can be set at any time:

" ] }, { "cell_type": "code", "execution_count": 125, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -3 0]\n", "[ 0 0 4]\n", "[ 0 0 0]" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[2,3] = 4\n", "t[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The components with respect to the basis $f$ are evaluated by the change-of-basis formula $e\\rightarrow f$:

" ] }, { "cell_type": "code", "execution_count": 126, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 6 3 3]\n", "[-108 -6 6]\n", "[ 80 8 0]" ] }, "execution_count": 126, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[f,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Another view of $t$, which reflects the fact that $T^{(1,1)}(M) = M\\otimes M^*$, is

" ] }, { "cell_type": "code", "execution_count": 127, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t = -3 e_{1}\\otimes e^{2} + 4 e_{2}\\otimes e^{3}\\)" ], "text/latex": [ "$\\displaystyle t = -3 e_{1}\\otimes e^{2} + 4 e_{2}\\otimes e^{3}$" ], "text/plain": [ "t = -3 e_1⊗e^2 + 4 e_2⊗e^3" ] }, "execution_count": 127, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Recall that $(e^i)$ is the basis of $M^*$ that is dual to the basis $(e_i)$ of $M$.

\n", "

In term of the basis $(f_i)$ and its dual basis $(f^i)$, we have

" ] }, { "cell_type": "code", "execution_count": 128, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t = 6 f_{1}\\otimes f^{1} + 3 f_{1}\\otimes f^{2} + 3 f_{1}\\otimes f^{3} -108 f_{2}\\otimes f^{1} -6 f_{2}\\otimes f^{2} + 6 f_{2}\\otimes f^{3} + 80 f_{3}\\otimes f^{1} + 8 f_{3}\\otimes f^{2}\\)" ], "text/latex": [ "$\\displaystyle t = 6 f_{1}\\otimes f^{1} + 3 f_{1}\\otimes f^{2} + 3 f_{1}\\otimes f^{3} -108 f_{2}\\otimes f^{1} -6 f_{2}\\otimes f^{2} + 6 f_{2}\\otimes f^{3} + 80 f_{3}\\otimes f^{1} + 8 f_{3}\\otimes f^{2}$" ], "text/plain": [ "t = 6 f_1⊗f^1 + 3 f_1⊗f^2 + 3 f_1⊗f^3 - 108 f_2⊗f^1 - 6 f_2⊗f^2 + 6 f_2⊗f^3 + 80 f_3⊗f^1 + 8 f_3⊗f^2" ] }, "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

As a tensor of type (1,1), $t$ maps pairs (linear form, module element) to ring elements:

" ] }, { "cell_type": "code", "execution_count": 129, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -468\\)" ], "text/latex": [ "$\\displaystyle -468$" ], "text/plain": [ "-468" ] }, "execution_count": 129, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t(a,v)" ] }, { "cell_type": "code", "execution_count": 130, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}\\)" ], "text/latex": [ "$\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}$" ], "text/plain": [ "Integer Ring" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t(a,v).parent()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tensors of type (1,1) can be considered as endomorphisms, thanks to the isomorphism\n", "\n", "$$ \\begin{array}{cccccc} \\mathrm{End}(M) & \\longrightarrow & T^{(1,1)}(M) \\\\ \\tilde t & \\longmapsto &  t: & M^*\\times M & \\longrightarrow & R \\\\&     & & (a,v) & \\longmapsto & a(\\tilde t(v)) \\end{array} $$\n" ] }, { "cell_type": "code", "execution_count": 131, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Generic endomorphism of Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "tt = End(M)(t)\n", "print(tt)" ] }, { "cell_type": "code", "execution_count": 132, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{Hom}\\left(M,M\\right)\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{Hom}\\left(M,M\\right)$" ], "text/plain": [ "Set of Morphisms from Rank-3 free module M over the Integer Ring to Rank-3 free module M over the Integer Ring in Category of finite dimensional modules over Integer Ring" ] }, "execution_count": 132, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt.parent()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In a given basis, the matrix ${\\tilde t}^i_{\\ \\, j}$ of the endomorphism $\\tilde t$ is identical to the matrix of the tensor $t$:" ] }, { "cell_type": "code", "execution_count": 133, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -3 0]\n", "[ 0 0 4]\n", "[ 0 0 0]" ] }, "execution_count": 133, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt.matrix(e)" ] }, { "cell_type": "code", "execution_count": 134, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -3 & 0 \\\\\n", "0 & 0 & 4 \\\\\n", "0 & 0 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -3 0]\n", "[ 0 0 4]\n", "[ 0 0 0]" ] }, "execution_count": 134, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[e,:]" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 135, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt.matrix(e) == t[e,:]" ] }, { "cell_type": "code", "execution_count": 136, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 6 3 3]\n", "[-108 -6 6]\n", "[ 80 8 0]" ] }, "execution_count": 136, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt.matrix(f)" ] }, { "cell_type": "code", "execution_count": 137, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "6 & 3 & 3 \\\\\n", "-108 & -6 & 6 \\\\\n", "80 & 8 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 6 3 3]\n", "[-108 -6 6]\n", "[ 80 8 0]" ] }, "execution_count": 137, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[f,:]" ] }, { "cell_type": "code", "execution_count": 138, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 138, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt.matrix(f) == t[f,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

As an endomorphism, $t$ maps module elements to module elements:

" ] }, { "cell_type": "code", "execution_count": 139, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\left(v\\right)\\)" ], "text/latex": [ "$\\displaystyle t\\left(v\\right)$" ], "text/plain": [ "Element t(v) of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 139, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt(v)" ] }, { "cell_type": "code", "execution_count": 140, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle M\\)" ], "text/latex": [ "$\\displaystyle M$" ], "text/plain": [ "Rank-3 free module M over the Integer Ring" ] }, "execution_count": 140, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt(v).parent()" ] }, { "cell_type": "code", "execution_count": 141, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\left(v\\right) = 12 e_{1} + 4 e_{2}\\)" ], "text/latex": [ "$\\displaystyle t\\left(v\\right) = 12 e_{1} + 4 e_{2}$" ], "text/plain": [ "t(v) = 12 e_1 + 4 e_2" ] }, "execution_count": 141, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tt(v).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

$t$ belongs to the module $T^{(1,1)}(M)$:

" ] }, { "cell_type": "code", "execution_count": 142, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 142, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t in M.tensor_module(1,1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

or, in Sage terminology,

" ] }, { "cell_type": "code", "execution_count": 143, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 143, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.parent() is M.tensor_module(1,1)" ] }, { "cell_type": "code", "execution_count": 144, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}\\)" ], "text/latex": [ "$\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}$" ], "text/plain": [ "Integer Ring" ] }, "execution_count": 144, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.tensor_module(1,1).base_ring()" ] }, { "cell_type": "code", "execution_count": 145, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 9\\)" ], "text/latex": [ "$\\displaystyle 9$" ], "text/plain": [ "9" ] }, "execution_count": 145, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.tensor_module(1,1).rank()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tensor calculus

\n", "

In addition to the arithmetic operations inherent to the module structure of $T^{(k,l)}(M)$, the following operations are implemented:

\n", "\n", "\n", "

Tensor product

\n", "

The tensor product is formed with the * operator. For instance the tensor product $t\\otimes a$ is

" ] }, { "cell_type": "code", "execution_count": 146, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(1,2) tensor t⊗a on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "ta = t*a\n", "print(ta)" ] }, { "cell_type": "code", "execution_count": 147, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\otimes a\\)" ], "text/latex": [ "$\\displaystyle t\\otimes a$" ], "text/plain": [ "Type-(1,2) tensor t⊗a on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 147, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta" ] }, { "cell_type": "code", "execution_count": 148, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\otimes a = 108 e_{1}\\otimes e^{2}\\otimes e^{1} + 27 e_{1}\\otimes e^{2}\\otimes e^{2} -12 e_{1}\\otimes e^{2}\\otimes e^{3} -144 e_{2}\\otimes e^{3}\\otimes e^{1} -36 e_{2}\\otimes e^{3}\\otimes e^{2} + 16 e_{2}\\otimes e^{3}\\otimes e^{3}\\)" ], "text/latex": [ "$\\displaystyle t\\otimes a = 108 e_{1}\\otimes e^{2}\\otimes e^{1} + 27 e_{1}\\otimes e^{2}\\otimes e^{2} -12 e_{1}\\otimes e^{2}\\otimes e^{3} -144 e_{2}\\otimes e^{3}\\otimes e^{1} -36 e_{2}\\otimes e^{3}\\otimes e^{2} + 16 e_{2}\\otimes e^{3}\\otimes e^{3}$" ], "text/plain": [ "t⊗a = 108 e_1⊗e^2⊗e^1 + 27 e_1⊗e^2⊗e^2 - 12 e_1⊗e^2⊗e^3 - 144 e_2⊗e^3⊗e^1 - 36 e_2⊗e^3⊗e^2 + 16 e_2⊗e^3⊗e^3" ] }, "execution_count": 148, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta.display()" ] }, { "cell_type": "code", "execution_count": 149, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\otimes a = 12 f_{1}\\otimes f^{1}\\otimes f^{1} -6 f_{1}\\otimes f^{1}\\otimes f^{2} + 18 f_{1}\\otimes f^{1}\\otimes f^{3} + 6 f_{1}\\otimes f^{2}\\otimes f^{1} -3 f_{1}\\otimes f^{2}\\otimes f^{2} + 9 f_{1}\\otimes f^{2}\\otimes f^{3} + 6 f_{1}\\otimes f^{3}\\otimes f^{1} -3 f_{1}\\otimes f^{3}\\otimes f^{2} + 9 f_{1}\\otimes f^{3}\\otimes f^{3} -216 f_{2}\\otimes f^{1}\\otimes f^{1} + 108 f_{2}\\otimes f^{1}\\otimes f^{2} -324 f_{2}\\otimes f^{1}\\otimes f^{3} -12 f_{2}\\otimes f^{2}\\otimes f^{1} + 6 f_{2}\\otimes f^{2}\\otimes f^{2} -18 f_{2}\\otimes f^{2}\\otimes f^{3} + 12 f_{2}\\otimes f^{3}\\otimes f^{1} -6 f_{2}\\otimes f^{3}\\otimes f^{2} + 18 f_{2}\\otimes f^{3}\\otimes f^{3} + 160 f_{3}\\otimes f^{1}\\otimes f^{1} -80 f_{3}\\otimes f^{1}\\otimes f^{2} + 240 f_{3}\\otimes f^{1}\\otimes f^{3} + 16 f_{3}\\otimes f^{2}\\otimes f^{1} -8 f_{3}\\otimes f^{2}\\otimes f^{2} + 24 f_{3}\\otimes f^{2}\\otimes f^{3}\\)" ], "text/latex": [ "$\\displaystyle t\\otimes a = 12 f_{1}\\otimes f^{1}\\otimes f^{1} -6 f_{1}\\otimes f^{1}\\otimes f^{2} + 18 f_{1}\\otimes f^{1}\\otimes f^{3} + 6 f_{1}\\otimes f^{2}\\otimes f^{1} -3 f_{1}\\otimes f^{2}\\otimes f^{2} + 9 f_{1}\\otimes f^{2}\\otimes f^{3} + 6 f_{1}\\otimes f^{3}\\otimes f^{1} -3 f_{1}\\otimes f^{3}\\otimes f^{2} + 9 f_{1}\\otimes f^{3}\\otimes f^{3} -216 f_{2}\\otimes f^{1}\\otimes f^{1} + 108 f_{2}\\otimes f^{1}\\otimes f^{2} -324 f_{2}\\otimes f^{1}\\otimes f^{3} -12 f_{2}\\otimes f^{2}\\otimes f^{1} + 6 f_{2}\\otimes f^{2}\\otimes f^{2} -18 f_{2}\\otimes f^{2}\\otimes f^{3} + 12 f_{2}\\otimes f^{3}\\otimes f^{1} -6 f_{2}\\otimes f^{3}\\otimes f^{2} + 18 f_{2}\\otimes f^{3}\\otimes f^{3} + 160 f_{3}\\otimes f^{1}\\otimes f^{1} -80 f_{3}\\otimes f^{1}\\otimes f^{2} + 240 f_{3}\\otimes f^{1}\\otimes f^{3} + 16 f_{3}\\otimes f^{2}\\otimes f^{1} -8 f_{3}\\otimes f^{2}\\otimes f^{2} + 24 f_{3}\\otimes f^{2}\\otimes f^{3}$" ], "text/plain": [ "t⊗a = 12 f_1⊗f^1⊗f^1 - 6 f_1⊗f^1⊗f^2 + 18 f_1⊗f^1⊗f^3 + 6 f_1⊗f^2⊗f^1 - 3 f_1⊗f^2⊗f^2 + 9 f_1⊗f^2⊗f^3 + 6 f_1⊗f^3⊗f^1 - 3 f_1⊗f^3⊗f^2 + 9 f_1⊗f^3⊗f^3 - 216 f_2⊗f^1⊗f^1 + 108 f_2⊗f^1⊗f^2 - 324 f_2⊗f^1⊗f^3 - 12 f_2⊗f^2⊗f^1 + 6 f_2⊗f^2⊗f^2 - 18 f_2⊗f^2⊗f^3 + 12 f_2⊗f^3⊗f^1 - 6 f_2⊗f^3⊗f^2 + 18 f_2⊗f^3⊗f^3 + 160 f_3⊗f^1⊗f^1 - 80 f_3⊗f^1⊗f^2 + 240 f_3⊗f^1⊗f^3 + 16 f_3⊗f^2⊗f^1 - 8 f_3⊗f^2⊗f^2 + 24 f_3⊗f^2⊗f^3" ] }, "execution_count": 149, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta.display(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The components w.r.t. a given basis can also be displayed as an array:

" ] }, { "cell_type": "code", "execution_count": 150, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[\\left[\\left[0, 0, 0\\right], \\left[108, 27, -12\\right], \\left[0, 0, 0\\right]\\right], \\left[\\left[0, 0, 0\\right], \\left[0, 0, 0\\right], \\left[-144, -36, 16\\right]\\right], \\left[\\left[0, 0, 0\\right], \\left[0, 0, 0\\right], \\left[0, 0, 0\\right]\\right]\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[\\left[\\left[0, 0, 0\\right], \\left[108, 27, -12\\right], \\left[0, 0, 0\\right]\\right], \\left[\\left[0, 0, 0\\right], \\left[0, 0, 0\\right], \\left[-144, -36, 16\\right]\\right], \\left[\\left[0, 0, 0\\right], \\left[0, 0, 0\\right], \\left[0, 0, 0\\right]\\right]\\right]$" ], "text/plain": [ "[[[0, 0, 0], [108, 27, -12], [0, 0, 0]],\n", " [[0, 0, 0], [0, 0, 0], [-144, -36, 16]],\n", " [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]" ] }, "execution_count": 150, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta[:] # components w.r.t. the default basis (e)" ] }, { "cell_type": "code", "execution_count": 151, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[\\left[\\left[12, -6, 18\\right], \\left[6, -3, 9\\right], \\left[6, -3, 9\\right]\\right], \\left[\\left[-216, 108, -324\\right], \\left[-12, 6, -18\\right], \\left[12, -6, 18\\right]\\right], \\left[\\left[160, -80, 240\\right], \\left[16, -8, 24\\right], \\left[0, 0, 0\\right]\\right]\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[\\left[\\left[12, -6, 18\\right], \\left[6, -3, 9\\right], \\left[6, -3, 9\\right]\\right], \\left[\\left[-216, 108, -324\\right], \\left[-12, 6, -18\\right], \\left[12, -6, 18\\right]\\right], \\left[\\left[160, -80, 240\\right], \\left[16, -8, 24\\right], \\left[0, 0, 0\\right]\\right]\\right]$" ], "text/plain": [ "[[[12, -6, 18], [6, -3, 9], [6, -3, 9]],\n", " [[-216, 108, -324], [-12, 6, -18], [12, -6, 18]],\n", " [[160, -80, 240], [16, -8, 24], [0, 0, 0]]]" ] }, "execution_count": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta[f,:] # components w.r.t. basis f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Each component ca be accessed individually:

" ] }, { "cell_type": "code", "execution_count": 152, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -12\\)" ], "text/latex": [ "$\\displaystyle -12$" ], "text/plain": [ "-12" ] }, "execution_count": 152, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta[1,2,3] # access to a component w.r.t. the default basis" ] }, { "cell_type": "code", "execution_count": 153, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 9\\)" ], "text/latex": [ "$\\displaystyle 9$" ], "text/plain": [ "9" ] }, "execution_count": 153, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta[f,1,2,3]" ] }, { "cell_type": "code", "execution_count": 154, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle T^{(1, 2)}\\left(M\\right)\\)" ], "text/latex": [ "$\\displaystyle T^{(1, 2)}\\left(M\\right)$" ], "text/plain": [ "Free module of type-(1,2) tensors on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 154, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta.parent()" ] }, { "cell_type": "code", "execution_count": 155, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 155, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta in M.tensor_module(1,2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The tensor product is not commutative:

" ] }, { "cell_type": "code", "execution_count": 156, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(1,2) tensor a⊗t on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "print(a*t)" ] }, { "cell_type": "code", "execution_count": 157, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{False}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{False}$" ], "text/plain": [ "False" ] }, "execution_count": 157, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a*t == t*a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Forming a tensor of rank 4:

" ] }, { "cell_type": "code", "execution_count": 158, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(2,2) tensor t⊗a⊗v on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "tav = ta*v\n", "print(tav)" ] }, { "cell_type": "code", "execution_count": 159, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle t\\otimes a\\otimes v = 324 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{1} + 81 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{2} -36 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{3} -432 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{1} -108 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{2} + 48 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{3} + 108 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{1} + 27 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{2} -12 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{3} -432 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{1} -108 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{2} + 48 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{3} + 576 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{1} + 144 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{2} -64 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{3} -144 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{1} -36 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{2} + 16 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{3}\\)" ], "text/latex": [ "$\\displaystyle t\\otimes a\\otimes v = 324 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{1} + 81 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{2} -36 e_{1}\\otimes e_{1}\\otimes e^{2}\\otimes e^{3} -432 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{1} -108 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{2} + 48 e_{1}\\otimes e_{2}\\otimes e^{2}\\otimes e^{3} + 108 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{1} + 27 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{2} -12 e_{1}\\otimes e_{3}\\otimes e^{2}\\otimes e^{3} -432 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{1} -108 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{2} + 48 e_{2}\\otimes e_{1}\\otimes e^{3}\\otimes e^{3} + 576 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{1} + 144 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{2} -64 e_{2}\\otimes e_{2}\\otimes e^{3}\\otimes e^{3} -144 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{1} -36 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{2} + 16 e_{2}\\otimes e_{3}\\otimes e^{3}\\otimes e^{3}$" ], "text/plain": [ "t⊗a⊗v = 324 e_1⊗e_1⊗e^2⊗e^1 + 81 e_1⊗e_1⊗e^2⊗e^2 - 36 e_1⊗e_1⊗e^2⊗e^3 - 432 e_1⊗e_2⊗e^2⊗e^1 - 108 e_1⊗e_2⊗e^2⊗e^2 + 48 e_1⊗e_2⊗e^2⊗e^3 + 108 e_1⊗e_3⊗e^2⊗e^1 + 27 e_1⊗e_3⊗e^2⊗e^2 - 12 e_1⊗e_3⊗e^2⊗e^3 - 432 e_2⊗e_1⊗e^3⊗e^1 - 108 e_2⊗e_1⊗e^3⊗e^2 + 48 e_2⊗e_1⊗e^3⊗e^3 + 576 e_2⊗e_2⊗e^3⊗e^1 + 144 e_2⊗e_2⊗e^3⊗e^2 - 64 e_2⊗e_2⊗e^3⊗e^3 - 144 e_2⊗e_3⊗e^3⊗e^1 - 36 e_2⊗e_3⊗e^3⊗e^2 + 16 e_2⊗e_3⊗e^3⊗e^3" ] }, "execution_count": 159, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tav.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Symmetrization / antisymmetrization

\n", "

The (anti)symmetrization of a tensor $t$ over $n$ arguments involve the division by $n!$, which does not always make sense in the base ring $R$. In the present case, $R=\\mathbb{Z}$ and to (anti)symmetrize over 2 arguments, we restrict to tensors with even components:

" ] }, { "cell_type": "code", "execution_count": 160, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 2 & 0 \\\\\n", "-4 & 8 & 0 \\\\\n", "0 & 2 & -6\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 2 & 0 \\\\\n", "-4 & 8 & 0 \\\\\n", "0 & 2 & -6\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 2 0]\n", "[-4 8 0]\n", "[ 0 2 -6]" ] }, "execution_count": 160, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = M.tensor((0,2), name='g')\n", "g[1,2], g[2,1], g[2,2], g[3,2], g[3,3] = 2, -4, 8, 2, -6\n", "g[:]" ] }, { "cell_type": "code", "execution_count": 161, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mbox{Symmetric bilinear form on the Rank-3 free module M over the Integer Ring}\\)" ], "text/latex": [ "$\\displaystyle \\mbox{Symmetric bilinear form on the Rank-3 free module M over the Integer Ring}$" ], "text/plain": [ "Symmetric bilinear form on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 161, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = g.symmetrize() ; s" ] }, { "cell_type": "code", "execution_count": 162, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "symmetry: (0, 1); no antisymmetry\n" ] } ], "source": [ "s.symmetries()" ] }, { "cell_type": "code", "execution_count": 163, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -1 & 0 \\\\\n", "-1 & 8 & 1 \\\\\n", "0 & 1 & -6\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & -1 & 0 \\\\\n", "-1 & 8 & 1 \\\\\n", "0 & 1 & -6\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 -1 0]\n", "[-1 8 1]\n", "[ 0 1 -6]" ] }, "execution_count": 163, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Symmetrization can be performed on an arbitray number of arguments, by providing their positions (first position = 0). In the present case

" ] }, { "cell_type": "code", "execution_count": 164, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 164, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g.symmetrize(0,1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

One may use index notation to specify the symmetry:

" ] }, { "cell_type": "code", "execution_count": 165, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 165, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g['_(ab)']" ] }, { "cell_type": "code", "execution_count": 166, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 166, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g['_{(ab)}'] # LaTeX type notation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Of course, since $s$ is already symmetric:

" ] }, { "cell_type": "code", "execution_count": 167, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 167, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.symmetrize() == s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The antisymmetrization proceeds accordingly:

" ] }, { "cell_type": "code", "execution_count": 168, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mbox{Alternating form of degree 2 on the Rank-3 free module M over the Integer Ring}\\)" ], "text/latex": [ "$\\displaystyle \\mbox{Alternating form of degree 2 on the Rank-3 free module M over the Integer Ring}$" ], "text/plain": [ "Alternating form of degree 2 on the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 168, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = g.antisymmetrize() ; s" ] }, { "cell_type": "code", "execution_count": 169, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "no symmetry; antisymmetry: (0, 1)\n" ] } ], "source": [ "s.symmetries()" ] }, { "cell_type": "code", "execution_count": 170, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 3 & 0 \\\\\n", "-3 & 0 & -1 \\\\\n", "0 & 1 & 0\n", "\\end{array}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(\\begin{array}{rrr}\n", "0 & 3 & 0 \\\\\n", "-3 & 0 & -1 \\\\\n", "0 & 1 & 0\n", "\\end{array}\\right)$" ], "text/plain": [ "[ 0 3 0]\n", "[-3 0 -1]\n", "[ 0 1 0]" ] }, "execution_count": 170, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[:]" ] }, { "cell_type": "code", "execution_count": 171, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 171, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g.antisymmetrize(0,1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As for symmetries, index notation can be used, instead of`antisymmetrize()`:" ] }, { "cell_type": "code", "execution_count": 172, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 172, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g['_[ab]']" ] }, { "cell_type": "code", "execution_count": 173, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 173, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == g['_{[ab]}'] # LaTeX type notation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Of course, since $s$ is already antisymmetric:

" ] }, { "cell_type": "code", "execution_count": 174, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 174, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == s.antisymmetrize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tensor contractions

\n", "

Contracting the type-(1,1) tensor $t$ with the module element $v$ results in another module element:

" ] }, { "cell_type": "code", "execution_count": 175, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mbox{Element of the Rank-3 free module M over the Integer Ring}\\)" ], "text/latex": [ "$\\displaystyle \\mbox{Element of the Rank-3 free module M over the Integer Ring}$" ], "text/plain": [ "Element of the Rank-3 free module M over the Integer Ring" ] }, "execution_count": 175, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.contract(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The components (w.r.t. a given basis) of the contraction are of course $t^i_{\\\\  j} v^j$:

" ] }, { "cell_type": "code", "execution_count": 176, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 176, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.contract(v)[i] == sum(t[i,j]*v[j] for j in M.irange())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

This contraction coincides with the action of $t$ as an endomorphism:

" ] }, { "cell_type": "code", "execution_count": 177, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 177, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.contract(v) == tt(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of `contract()`, index notations can be used to denote the contraction:" ] }, { "cell_type": "code", "execution_count": 178, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 178, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^i_j']*v['j'] == t.contract(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Contracting the linear form $a$ with the module element $v$ results in a ring element:

" ] }, { "cell_type": "code", "execution_count": 179, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -68\\)" ], "text/latex": [ "$\\displaystyle -68$" ], "text/plain": [ "-68" ] }, "execution_count": 179, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.contract(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

It is of course the result of the linear form acting on the module element:

" ] }, { "cell_type": "code", "execution_count": 180, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 180, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.contract(v) == a(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

By default, the contraction is performed on the last index of the first tensor and the first index of the second one. To perform contraction on other indices, one should specify the indices positions (with the convention position=0 for the first index): for instance to get the contraction $z^i_{\\ \\, j} = T^i_{\\ \\, kj} v^k$ (with $T=t\\otimes a$):

" ] }, { "cell_type": "code", "execution_count": 181, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "z = ta.contract(1,v) # 1 -> second index of ta\n", "print(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

To get $z^i_{\\ \\, jk} = t^l_{\\ \\, j} T^i_{\\ \\, l k}$:

" ] }, { "cell_type": "code", "execution_count": 182, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring\n" ] } ], "source": [ "z = t.contract(0, ta, 1) # 0 -> first index of t, 1 -> second index of ta\n", "print(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

or, in terms of index notation:

" ] }, { "cell_type": "code", "execution_count": 183, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 183, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z1 = t['^l_j']*ta['^i_lk']\n", "z1 == z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As for any function, inline documentation is obtained via the question mark:" ] }, { "cell_type": "code", "execution_count": 184, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[1;31mSignature:\u001b[0m \u001b[0mt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcontract\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mDocstring:\u001b[0m \n", " Contraction on one or more indices with another tensor.\n", "\n", " INPUT:\n", "\n", " * \"pos1\" -- positions of the indices in \"self\" involved in the\n", " contraction; \"pos1\" must be a sequence of integers, with 0\n", " standing for the first index position, 1 for the second one, etc;\n", " if \"pos1\" is not provided, a single contraction on the last index\n", " position of \"self\" is assumed\n", "\n", " * \"other\" -- the tensor to contract with\n", "\n", " * \"pos2\" -- positions of the indices in \"other\" involved in the\n", " contraction, with the same conventions as for \"pos1\"; if \"pos2\"\n", " is not provided, a single contraction on the first index position\n", " of \"other\" is assumed\n", "\n", " OUTPUT:\n", "\n", " * tensor resulting from the contraction at the positions \"pos1\" and\n", " \"pos2\" of \"self\" with \"other\"\n", "\n", " EXAMPLES:\n", "\n", " Contraction of a tensor of type (0,1) with a tensor of type (1,0):\n", "\n", " sage: M = FiniteRankFreeModule(ZZ, 3, name='M')\n", " sage: e = M.basis('e')\n", " sage: a = M.linear_form() # tensor of type (0,1) is a linear form\n", " sage: a[:] = [-3,2,1]\n", " sage: b = M([2,5,-2]) # tensor of type (1,0) is a module element\n", " sage: s = a.contract(b) ; s\n", " 2\n", " sage: s in M.base_ring()\n", " True\n", " sage: s == a[0]*b[0] + a[1]*b[1] + a[2]*b[2] # check of the computation\n", " True\n", "\n", " The positions of the contraction indices can be set explicitly:\n", "\n", " sage: s == a.contract(0, b, 0)\n", " True\n", " sage: s == a.contract(0, b)\n", " True\n", " sage: s == a.contract(b, 0)\n", " True\n", "\n", " Instead of the explicit call to the method \"contract()\", the index\n", " notation can be used to specify the contraction, via Einstein\n", " convention (summation on repeated indices); it suffices to pass the\n", " indices as a string inside square brackets:\n", "\n", " sage: s1 = a['_i']*b['^i'] ; s1\n", " 2\n", " sage: s1 == s\n", " True\n", "\n", " In the present case, performing the contraction is identical to\n", " applying the linear form to the module element:\n", "\n", " sage: a.contract(b) == a(b)\n", " True\n", "\n", " or to applying the module element, considered as a tensor of type\n", " (1,0), to the linear form:\n", "\n", " sage: a.contract(b) == b(a)\n", " True\n", "\n", " We have also:\n", "\n", " sage: a.contract(b) == b.contract(a)\n", " True\n", "\n", " Contraction of a tensor of type (1,1) with a tensor of type (1,0):\n", "\n", " sage: a = M.tensor((1,1))\n", " sage: a[:] = [[-1,2,3],[4,-5,6],[7,8,9]]\n", " sage: s = a.contract(b) ; s\n", " Element of the Rank-3 free module M over the Integer Ring\n", " sage: s.display()\n", " 2 e_0 - 29 e_1 + 36 e_2\n", "\n", " Since the index positions have not been specified, the contraction\n", " takes place on the last position of a (i.e. no. 1) and the first\n", " position of \"b\" (i.e. no. 0):\n", "\n", " sage: a.contract(b) == a.contract(1, b, 0)\n", " True\n", " sage: a.contract(b) == b.contract(0, a, 1)\n", " True\n", " sage: a.contract(b) == b.contract(a, 1)\n", " True\n", "\n", " Using the index notation with Einstein convention:\n", "\n", " sage: a['^i_j']*b['^j'] == a.contract(b)\n", " True\n", "\n", " The index \"i\" can be replaced by a dot:\n", "\n", " sage: a['^._j']*b['^j'] == a.contract(b)\n", " True\n", "\n", " and the symbol \"^\" may be omitted, the distinction between\n", " contravariant and covariant indices being the position with respect\n", " to the symbol \"_\":\n", "\n", " sage: a['._j']*b['j'] == a.contract(b)\n", " True\n", "\n", " Contraction is possible only between a contravariant index and a\n", " covariant one:\n", "\n", " sage: a.contract(0, b)\n", " Traceback (most recent call last):\n", " ...\n", " TypeError: contraction on two contravariant indices not permitted\n", "\n", " Contraction of a tensor of type (2,1) with a tensor of type (0,2):\n", "\n", " sage: a = a*b ; a\n", " Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: b = M.tensor((0,2))\n", " sage: b[:] = [[-2,3,1], [0,-2,3], [4,-7,6]]\n", " sage: s = a.contract(1, b, 1) ; s\n", " Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: s[:]\n", " [[[-9, 16, 39], [18, -32, -78], [27, -48, -117]],\n", " [[36, -64, -156], [-45, 80, 195], [54, -96, -234]],\n", " [[63, -112, -273], [72, -128, -312], [81, -144, -351]]]\n", "\n", " Check of the computation:\n", "\n", " sage: all(s[i,j,k] == a[i,0,j]*b[k,0]+a[i,1,j]*b[k,1]+a[i,2,j]*b[k,2]\n", " ....: for i in range(3) for j in range(3) for k in range(3))\n", " True\n", "\n", " Using index notation:\n", "\n", " sage: a['il_j']*b['_kl'] == a.contract(1, b, 1)\n", " True\n", "\n", " LaTeX notation are allowed:\n", "\n", " sage: a['^{il}_j']*b['_{kl}'] == a.contract(1, b, 1)\n", " True\n", "\n", " Indices not involved in the contraction may be replaced by dots:\n", "\n", " sage: a['.l_.']*b['_.l'] == a.contract(1, b, 1)\n", " True\n", "\n", " The two tensors do not have to be defined on the same basis for the\n", " contraction to take place, reflecting the fact that the contraction\n", " is basis-independent:\n", "\n", " sage: A = M.automorphism()\n", " sage: A[:] = [[0,0,1], [1,0,0], [0,-1,0]]\n", " sage: h = e.new_basis(A, 'h')\n", " sage: b.comp(h)[:] # forces the computation of b's components w.r.t. basis h\n", " [-2 -3 0]\n", " [ 7 6 -4]\n", " [ 3 -1 -2]\n", " sage: b.del_other_comp(h) # deletes components w.r.t. basis e\n", " sage: list(b._components) # indeed:\n", " [Basis (h_0,h_1,h_2) on the Rank-3 free module M over the Integer Ring]\n", " sage: list(a._components) # while a is known only in basis e:\n", " [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring]\n", " sage: s1 = a.contract(1, b, 1) ; s1 # yet the computation is possible\n", " Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: s1 == s # ... and yields the same result as previously:\n", " True\n", "\n", " The contraction can be performed on more than a single index; for\n", " instance a 2-indices contraction of a type-(2,1) tensor with a\n", " type-(1,2) one is:\n", "\n", " sage: a # a is a tensor of type-(2,1)\n", " Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: b = M([1,-1,2])*b ; b # a tensor of type (1,2)\n", " Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: s = a.contract(1,2,b,1,0) ; s # the double contraction\n", " Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring\n", " sage: s[:]\n", " [ -36 30 15]\n", " [-252 210 105]\n", " [-204 170 85]\n", " sage: s == a['^.k_l']*b['^l_k.'] # the same thing in index notation\n", " True\n", "\u001b[1;31mInit docstring:\u001b[0m Initialize self. See help(type(self)) for accurate signature.\n", "\u001b[1;31mFile:\u001b[0m ~/sage/10.3/src/sage/tensor/modules/free_module_tensor.py\n", "\u001b[1;31mType:\u001b[0m method" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "t.contract?" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 10.3.beta6", "language": "sage", "name": "sagemath" }, "language": "python", "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" } }, "nbformat": 4, "nbformat_minor": 4 }