{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# First contact with SageMath\n", "\n", "This Jupyter notebook illustrates a few elementary features of [SageMath](https://www.sagemath.org/).\n", "\n", "First we set up the display to have LaTeX outputs:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Starting with numbers...\n", "\n", "SageMath knows about $\\pi$, $e$ and $i$ (well, it's mathematical software, isn't it ?):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 0\\)" ], "text/latex": [ "$\\displaystyle 0$" ], "text/plain": [ "0" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e^(i*pi) + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*--- It's nice, but I thought SageMath was based on Python: shouldn't the above be written* `e**(i*pi) + 1`, \n", "*given that* `^` *is the bitwise XOR operator in Python?*\n", "\n", "Actually, the input cells are **preparsed** by SageMath before being sent to the Python interpreter. The action of the preparser is revealed by the function `preparse`:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|e**(i*pi)|\\verb| |\\verb|+|\\verb| |\\verb|Integer(1)|\\)" ], "text/latex": [ "$\\displaystyle \\verb|e**(i*pi)|\\verb| |\\verb|+|\\verb| |\\verb|Integer(1)|$" ], "text/plain": [ "'e**(i*pi) + Integer(1)'" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "preparse(\"e^(i*pi) + 1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We see that indeed, the character `^` has been changed to `**`.\n", "\n", "Another noticable change is `1` $\\to$ `Integer(1)`. This means that the preparser is turning integers into SageMath integers, which belong to the class `Integer`:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|<class|\\verb| |\\verb|'sage.rings.integer.Integer'>|\\)" ], "text/latex": [ "$\\displaystyle \\verb||$" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This type of integer is much more sophisticated than a mere Python integer (`int`). In particular, it knows to which mathematical set it belongs. The latter is returned by the function `parent`:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [] }, "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": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "parent(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To have more information than just the symbol of the parent, one can use the `print` function:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Integer Ring\n" ] } ], "source": [ "print(parent(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us denote this object by the Python variable `Z`:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "tags": [] }, "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": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z = parent(1)\n", "Z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Z` is endowed with many methods, which can be discovered via the **TAB key**:\n", "```\n", " Z.\n", "```\n", "Once a method has been selected, one can get some **documentation** about it via `?`:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [] }, "outputs": [], "source": [ "Z.cardinality?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A double question mark leads directly to the **source code** (recall that SageMath is a free software!):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [] }, "outputs": [], "source": [ "Z.cardinality??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More documentation is available in the online [reference manual](https://doc.sagemath.org/html/en/reference/) as well as in various [tutorials and guides](https://doc.sagemath.org/html/en/)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle +\\infty\\)" ], "text/latex": [ "$\\displaystyle +\\infty$" ], "text/plain": [ "+Infinity" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z.cardinality()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other methods:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z.is_ring()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{False}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{False}$" ], "text/plain": [ "False" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z.is_field()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left(0, 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\left(0, 1\\right)$" ], "text/plain": [ "(0, 1)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z.zero(), Z.one() # the ring zero and unit elements" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Expressing $1\\in \\mathbb{Z}$ in SageMath:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 in Z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1 is actually the unit element of the ring $\\mathbb{Z}$:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 == Z.one()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that there exits a predefined variable, `ZZ`, for $\\mathbb{Z}$:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Z is ZZ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SageMath integers can be arbitrarily large (up to the limit of the computer memory):" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 170141183460469231731687303715884105727\\)" ], "text/latex": [ "$\\displaystyle 170141183460469231731687303715884105727$" ], "text/plain": [ "170141183460469231731687303715884105727" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = 2^127 - 1\n", "m" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\mathrm{True}\\)" ], "text/latex": [ "$\\displaystyle \\mathrm{True}$" ], "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.is_prime()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that one has still access to the Python integers, via `int`:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 1\\)" ], "text/latex": [ "$\\displaystyle 1$" ], "text/plain": [ "1" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int(1)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|<class|\\verb| |\\verb|'int'>|\\)" ], "text/latex": [ "$\\displaystyle \\verb||$" ], "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(_) # the underscore stands for the latest output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "They are automatically converted (coerced) into SageMath integers if necessary, for instance if they are\n", "added to some SageMath integer:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 3\\)" ], "text/latex": [ "$\\displaystyle 3$" ], "text/plain": [ "3" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int(1) + 2" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|<class|\\verb| |\\verb|'sage.rings.integer.Integer'>|\\)" ], "text/latex": [ "$\\displaystyle \\verb||$" ], "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course, SageMath also knows about **rational numbers**:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{2}{3}\\)" ], "text/latex": [ "$\\displaystyle \\frac{2}{3}$" ], "text/plain": [ "2/3" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2/3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python would have returned 0.6666666666666666. This is not the case here because" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|Integer(2)/Integer(3)|\\)" ], "text/latex": [ "$\\displaystyle \\verb|Integer(2)/Integer(3)|$" ], "text/plain": [ "'Integer(2)/Integer(3)'" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "preparse('2/3')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and the division of the (Sage) integer 2 by the (Sage) integer 3 is the (Sage) rational number $2/3$: " ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Q}\\)" ], "text/latex": [ "$\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Q}$" ], "text/plain": [ "Rational Field" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "parent(2/3)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rational Field\n" ] } ], "source": [ "print(_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As the above examples illustrate, SageMath is based on a **Parent/Element scheme**: `parent(a)` is the algebraic or topological/differential structure to which `a` belongs. \n", "\n", "SageMath has also the concept of **mathematical categories**:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Join of Category of euclidean domains and Category of infinite enumerated sets and Category of metric spaces\n" ] } ], "source": [ "print(category(Z))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Real numbers\n", "\n", "SageMath can compute numerical values with an arbitrary number of digits:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199\\)" ], "text/latex": [ "$\\displaystyle 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199$" ], "text/plain": [ "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n(pi, digits=1000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`n` is the shortcut alias for `numerical_approx`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another interesting computation regards the *Hermite-Ramanujan constant*:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle e^{\\left(\\sqrt{163} \\pi\\right)}\\)" ], "text/latex": [ "$\\displaystyle e^{\\left(\\sqrt{163} \\pi\\right)}$" ], "text/plain": [ "e^(sqrt(163)*pi)" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = exp(pi*sqrt(163))\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Actually, this number is very close to an integer, as announced by [Charles Hermite in 1859](https://gallica.bnf.fr/ark:/12148/bpt6k6209489m/f60) (probably without using SageMath...):" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 2.6253741264076874399999999999925007259719818568889 \\times 10^{17}\\)" ], "text/latex": [ "$\\displaystyle 2.6253741264076874399999999999925007259719818568889 \\times 10^{17}$" ], "text/plain": [ "2.6253741264076874399999999999925007259719818568889e17" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n(a, digits=50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's clear if we turn off scientific notation:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 262537412640768743.99999999999925007259719818568888661\\)" ], "text/latex": [ "$\\displaystyle 262537412640768743.99999999999925007259719818568888661$" ], "text/plain": [ "'262537412640768743.99999999999925007259719818568888661'" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n(a, digits=50).str(no_sci=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Symbolic computations\n", "\n", "Beside numerical computations, SageMath can perform symbolic ones. For instance, it can compute a **derivative**:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 2 \\, x \\cos\\left(x^{2}\\right)\\)" ], "text/latex": [ "$\\displaystyle 2 \\, x \\cos\\left(x^{2}\\right)$" ], "text/plain": [ "2*x*cos(x^2)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = diff(sin(x^2), x)\n", "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Due to the command `%display latex` in the first cell of this notebook, SageMath displays all results, such as the one above, in LaTeX format. To get them in console mode, use the function `print`:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2*x*cos(x^2)\n" ] } ], "source": [ "print(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The explicit LaTeX code can be obtained:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2 \\, x \\cos\\left(x^{2}\\right)\n" ] } ], "source": [ "print(latex(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A pdf file with the LaTeX typeset formula is generated by the function `view`:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "view(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`x` is the only generic symbolic variable predefined in a SageMath session. All other symbolic variables must be declared explicitly, via the function `var`:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "y = var('y')\n", "\n", "alp = var('alp', latex_name=r'\\alpha')" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle {\\alpha} y + x\\)" ], "text/latex": [ "$\\displaystyle {\\alpha} y + x$" ], "text/plain": [ "alp*y + x" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = alp*y + x\n", "f" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle y\\)" ], "text/latex": [ "$\\displaystyle y$" ], "text/plain": [ "y" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diff(f, alp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SageMath can also compute a **primitive**:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\int \\frac{x^{5}}{x^{3} - 2 \\, x + 1}\\,{d x}\\)" ], "text/latex": [ "$\\displaystyle \\int \\frac{x^{5}}{x^{3} - 2 \\, x + 1}\\,{d x}$" ], "text/plain": [ "integrate(x^5/(x^3 - 2*x + 1), x)" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3 - 2*x +1), x, hold=True) " ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)$" ], "text/plain": [ "1/3*x^3 + 2/5*sqrt(5)*log((2*x - sqrt(5) + 1)/(2*x + sqrt(5) + 1)) + 2*x - log(x^2 + x - 1) + log(x - 1)" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3 - 2*x + 1), x) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and of course definite integrals: it suffices to provide the two boundaries after the argument `x`. A first attempt with 0 and 1 fails:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "# integrate(x^5/(x^3 - 2*x + 1), x, 0, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Don't panic:** error messages are usually long because they display the whole call stack. The important information lies at the end:\n", "```\n", "ValueError: Integral is divergent\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Choosing the boundaries to be 2 and 3 yields a convergent integral:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{2}{5} \\, \\sqrt{5} \\log\\left(-\\frac{7}{22} \\, \\sqrt{5} + \\frac{27}{22}\\right) - \\frac{2}{5} \\, \\sqrt{5} \\log\\left(-\\frac{1}{2} \\, \\sqrt{5} + \\frac{3}{2}\\right) - \\log\\left(11\\right) + \\log\\left(5\\right) + \\log\\left(2\\right) + \\frac{25}{3}\\)" ], "text/latex": [ "$\\displaystyle \\frac{2}{5} \\, \\sqrt{5} \\log\\left(-\\frac{7}{22} \\, \\sqrt{5} + \\frac{27}{22}\\right) - \\frac{2}{5} \\, \\sqrt{5} \\log\\left(-\\frac{1}{2} \\, \\sqrt{5} + \\frac{3}{2}\\right) - \\log\\left(11\\right) + \\log\\left(5\\right) + \\log\\left(2\\right) + \\frac{25}{3}$" ], "text/plain": [ "2/5*sqrt(5)*log(-7/22*sqrt(5) + 27/22) - 2/5*sqrt(5)*log(-1/2*sqrt(5) + 3/2) - log(11) + log(5) + log(2) + 25/3" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3 - 2*x + 1), x, 2, 3)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 8.50669189170048\\)" ], "text/latex": [ "$\\displaystyle 8.50669189170048$" ], "text/plain": [ "8.50669189170048" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n(_) # numerical approximation of the above result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SageMath proposes various symbolic engines to evaluate a primitive. The default one is [Maxima](https://maxima.sourceforge.io/):" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)$" ], "text/plain": [ "1/3*x^3 + 2/5*sqrt(5)*log((2*x - sqrt(5) + 1)/(2*x + sqrt(5) + 1)) + 2*x - log(x^2 + x - 1) + log(x - 1)" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3 - 2*x + 1), x, algorithm='maxima') # same result as above" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "but [SymPy](https://www.sympy.org) is also available:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} - \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)} \\log\\left(\\frac{1}{80} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)}^{2} + x + \\frac{1}{4} \\, \\sqrt{5} - \\frac{1}{16}\\right) + \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)} \\log\\left(\\frac{1}{80} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)}^{2} + x - \\frac{1}{4} \\, \\sqrt{5} - \\frac{1}{16}\\right) + 2 \\, x + \\log\\left(x - 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} - \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)} \\log\\left(\\frac{1}{80} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)}^{2} + x + \\frac{1}{4} \\, \\sqrt{5} - \\frac{1}{16}\\right) + \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)} \\log\\left(\\frac{1}{80} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)}^{2} + x - \\frac{1}{4} \\, \\sqrt{5} - \\frac{1}{16}\\right) + 2 \\, x + \\log\\left(x - 1\\right)$" ], "text/plain": [ "1/3*x^3 - 1/5*(2*sqrt(5) + 5)*log(1/80*(2*sqrt(5) + 5)^2 + x + 1/4*sqrt(5) - 1/16) + 1/5*(2*sqrt(5) - 5)*log(1/80*(2*sqrt(5) - 5)^2 + x - 1/4*sqrt(5) - 1/16) + 2*x + log(x - 1)" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3 - 2*x + 1), x, algorithm='sympy')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "as well as [Giac](https://www-fourier.ujf-grenoble.fr/~parisse/giac.html): " ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{{\\left| 2 \\, x - \\sqrt{5} + 1 \\right|}}{{\\left| 2 \\, x + \\sqrt{5} + 1 \\right|}}\\right) + 2 \\, x - \\log\\left({\\left| x^{2} + x - 1 \\right|}\\right) + \\log\\left({\\left| x - 1 \\right|}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{{\\left| 2 \\, x - \\sqrt{5} + 1 \\right|}}{{\\left| 2 \\, x + \\sqrt{5} + 1 \\right|}}\\right) + 2 \\, x - \\log\\left({\\left| x^{2} + x - 1 \\right|}\\right) + \\log\\left({\\left| x - 1 \\right|}\\right)$" ], "text/plain": [ "1/3*x^3 + 2/5*sqrt(5)*log(abs(2*x - sqrt(5) + 1)/abs(2*x + sqrt(5) + 1)) + 2*x - log(abs(x^2 + x - 1)) + log(abs(x - 1))" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3-2*x+1), x, algorithm='giac')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can even use [WolframAlpha](https://www.wolframalpha.com/calculators/integral-calculator/) via some internet connection:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} - \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)} \\log\\left(2 \\, x + \\sqrt{5} + 1\\right) + \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)} \\log\\left(-2 \\, x + \\sqrt{5} - 1\\right) + 2 \\, x + \\log\\left(-x + 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} - \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} + 5\\right)} \\log\\left(2 \\, x + \\sqrt{5} + 1\\right) + \\frac{1}{5} \\, {\\left(2 \\, \\sqrt{5} - 5\\right)} \\log\\left(-2 \\, x + \\sqrt{5} - 1\\right) + 2 \\, x + \\log\\left(-x + 1\\right)$" ], "text/plain": [ "1/3*x^3 - 1/5*(2*sqrt(5) + 5)*log(2*x + sqrt(5) + 1) + 1/5*(2*sqrt(5) - 5)*log(-2*x + sqrt(5) - 1) + 2*x + log(-x + 1)" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(x^5/(x^3-2*x+1), x, algorithm='mathematica_free')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Actually SageMath has some interface to Mathematica:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|Cos[(x)^(2)]|\\)" ], "text/latex": [ "$\\displaystyle \\verb|Cos[(x)^(2)]|$" ], "text/plain": [ "'Cos[(x)^(2)]'" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cos(x^2)._mathematica_init_()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "as well as to SymPy, Maxima and Giac:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\verb|cos(x**2)|\\)" ], "text/latex": [ "$\\displaystyle \\verb|cos(x**2)|$" ], "text/plain": [ "cos(x**2)" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cos(x^2)._sympy_()" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 2\n", " cos(_SAGE_VAR_x )\n" ] } ], "source": [ "print(cos(x^2)._maxima_())" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\cos \\left(\\mathrm{sageVARx}^{2}\\right)\\)" ], "text/latex": [ "$\\displaystyle \\cos \\left(\\mathrm{sageVARx}^{2}\\right)$" ], "text/plain": [ "cos(sageVARx^2)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cos(x^2)._giac_()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us check the primitive computation:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{3} \\, x^{3} + \\frac{2}{5} \\, \\sqrt{5} \\log\\left(\\frac{2 \\, x - \\sqrt{5} + 1}{2 \\, x + \\sqrt{5} + 1}\\right) + 2 \\, x - \\log\\left(x^{2} + x - 1\\right) + \\log\\left(x - 1\\right)$" ], "text/plain": [ "1/3*x^3 + 2/5*sqrt(5)*log((2*x - sqrt(5) + 1)/(2*x + sqrt(5) + 1)) + 2*x - log(x^2 + x - 1) + log(x - 1)" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = integrate(x^5/(x^3-2*x+1), x) \n", "f" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle x^{2} + \\frac{4 \\, \\sqrt{5} {\\left(2 \\, x + \\sqrt{5} + 1\\right)} {\\left(\\frac{1}{2 \\, x + \\sqrt{5} + 1} - \\frac{2 \\, x - \\sqrt{5} + 1}{{\\left(2 \\, x + \\sqrt{5} + 1\\right)}^{2}}\\right)}}{5 \\, {\\left(2 \\, x - \\sqrt{5} + 1\\right)}} - \\frac{2 \\, x + 1}{x^{2} + x - 1} + \\frac{1}{x - 1} + 2\\)" ], "text/latex": [ "$\\displaystyle x^{2} + \\frac{4 \\, \\sqrt{5} {\\left(2 \\, x + \\sqrt{5} + 1\\right)} {\\left(\\frac{1}{2 \\, x + \\sqrt{5} + 1} - \\frac{2 \\, x - \\sqrt{5} + 1}{{\\left(2 \\, x + \\sqrt{5} + 1\\right)}^{2}}\\right)}}{5 \\, {\\left(2 \\, x - \\sqrt{5} + 1\\right)}} - \\frac{2 \\, x + 1}{x^{2} + x - 1} + \\frac{1}{x - 1} + 2$" ], "text/plain": [ "x^2 + 4/5*sqrt(5)*(2*x + sqrt(5) + 1)*(1/(2*x + sqrt(5) + 1) - (2*x - sqrt(5) + 1)/(2*x + sqrt(5) + 1)^2)/(2*x - sqrt(5) + 1) - (2*x + 1)/(x^2 + x - 1) + 1/(x - 1) + 2" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diff(f, x)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{x^{5}}{x^{3} - 2 \\, x + 1}\\)" ], "text/latex": [ "$\\displaystyle \\frac{x^{5}}{x^{3} - 2 \\, x + 1}$" ], "text/plain": [ "x^5/(x^3 - 2*x + 1)" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "_.simplify_full()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indefinite integrals can also be computed:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\sqrt{\\pi}\\)" ], "text/latex": [ "$\\displaystyle \\sqrt{\\pi}$" ], "text/plain": [ "sqrt(pi)" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(exp(-x^2), x, -oo, +oo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Other examples of symbolic computations: \n", "\n", "- Taylor expansions:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{40320} \\, x^{8} + \\frac{1}{5040} \\, x^{7} + \\frac{1}{720} \\, x^{6} + \\frac{1}{120} \\, x^{5} + \\frac{1}{24} \\, x^{4} + \\frac{1}{6} \\, x^{3} + \\frac{1}{2} \\, x^{2} + x + 1\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{40320} \\, x^{8} + \\frac{1}{5040} \\, x^{7} + \\frac{1}{720} \\, x^{6} + \\frac{1}{120} \\, x^{5} + \\frac{1}{24} \\, x^{4} + \\frac{1}{6} \\, x^{3} + \\frac{1}{2} \\, x^{2} + x + 1$" ], "text/plain": [ "1/40320*x^8 + 1/5040*x^7 + 1/720*x^6 + 1/120*x^5 + 1/24*x^4 + 1/6*x^3 + 1/2*x^2 + x + 1" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "exp(x).taylor(x, 0, 8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- limits:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 1\\)" ], "text/latex": [ "$\\displaystyle 1$" ], "text/plain": [ "1" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lim(sin(x)/x, x=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- series: Riemann's zeta function $\\zeta(s)$ for $s=2$ and $s=3$ (Apéry's constant):" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle {\\sum_{n=1}^{+\\infty} \\frac{1}{n^{2}}} = \\frac{1}{6} \\, \\pi^{2}\\)" ], "text/latex": [ "$\\displaystyle {\\sum_{n=1}^{+\\infty} \\frac{1}{n^{2}}} = \\frac{1}{6} \\, \\pi^{2}$" ], "text/plain": [ "sum(n^(-2), n, 1, +Infinity) == 1/6*pi^2" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n = var('n') # declaring n as a symbolic variable\n", "sum(1/n^2, n, 1, +oo, hold=True) == sum(1/n^2, n, 1, +oo)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\zeta(3)\\)" ], "text/latex": [ "$\\displaystyle \\zeta(3)$" ], "text/plain": [ "zeta(3)" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(1/n^3, n, 1, +oo)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle 1.20205690315959\\)" ], "text/latex": [ "$\\displaystyle 1.20205690315959$" ], "text/plain": [ "1.20205690315959" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "numerical_approx(_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course, as many standard functions, Riemann's zeta function is already implemented in SageMath:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{1}{6} \\, \\pi^{2}\\)" ], "text/latex": [ "$\\displaystyle \\frac{1}{6} \\, \\pi^{2}$" ], "text/plain": [ "1/6*pi^2" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "zeta(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Solving an equation:" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left[x = -\\frac{1}{2} \\, \\sqrt{5} + \\frac{1}{2}, x = \\frac{1}{2} \\, \\sqrt{5} + \\frac{1}{2}\\right]\\)" ], "text/latex": [ "$\\displaystyle \\left[x = -\\frac{1}{2} \\, \\sqrt{5} + \\frac{1}{2}, x = \\frac{1}{2} \\, \\sqrt{5} + \\frac{1}{2}\\right]$" ], "text/plain": [ "[x == -1/2*sqrt(5) + 1/2, x == 1/2*sqrt(5) + 1/2]" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solve(x^2 == x + 1, x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Solving a differential equation:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle -y\\left(x\\right) + \\frac{\\partial}{\\partial x}y\\left(x\\right) = x y\\left(x\\right)^{4}\\)" ], "text/latex": [ "$\\displaystyle -y\\left(x\\right) + \\frac{\\partial}{\\partial x}y\\left(x\\right) = x y\\left(x\\right)^{4}$" ], "text/plain": [ "-y(x) + diff(y(x), x) == x*y(x)^4" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = function('y')\n", "eq = diff(y(x), x) - y(x) == x*y(x)^4\n", "eq" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\frac{e^{x}}{{\\left(-\\frac{1}{3} \\, {\\left(3 \\, x - 1\\right)} e^{\\left(3 \\, x\\right)} + C\\right)}^{\\frac{1}{3}}}\\)" ], "text/latex": [ "$\\displaystyle \\frac{e^{x}}{{\\left(-\\frac{1}{3} \\, {\\left(3 \\, x - 1\\right)} e^{\\left(3 \\, x\\right)} + C\\right)}^{\\frac{1}{3}}}$" ], "text/plain": [ "e^x/(-1/3*(3*x - 1)*e^(3*x) + _C)^(1/3)" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "desolve(eq, y(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The power of Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, to illustrate the advantage of being built atop of Python, here is a loop for displaying Pascal's triangle with only two instruction lines:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]\n", "[1, 1]\n", "[1, 2, 1]\n", "[1, 3, 3, 1]\n", "[1, 4, 6, 4, 1]\n", "[1, 5, 10, 10, 5, 1]\n", "[1, 6, 15, 20, 15, 6, 1]\n", "[1, 7, 21, 35, 35, 21, 7, 1]\n", "[1, 8, 28, 56, 70, 56, 28, 8, 1]\n", "[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]\n" ] } ], "source": [ "for n in range(10): \n", " print([binomial(n, p) for p in range(n+1)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Next step:\n", "\n", "### Plots and functions in SageMath" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "Graphics object consisting of 1 graphics primitive" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot(sin(x^2), (x, 0, 4), axes_labels=['$x$', '$y$'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See the dedicated [notebook](https://nbviewer.org/github/egourgoulhon/SageMathTour/blob/master/Notebooks/plot_tour_2D.ipynb)." ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 10.2.rc0", "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" }, "widgets": { "state": {}, "version": "1.1.2" } }, "nbformat": 4, "nbformat_minor": 4 }