--- /dev/null
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# **DD-finite functions in Sage**\n",
+ "\n",
+ "In this notebook we provide a brief tutorial explanation (and interactive) to use appropriately the Sage package _dd\\_functions_. We will cover the following parts:\n",
+ "1. How to install the package (good and bad practices)\n",
+ "2. Basics of the package\n",
+ "3. Operations with the package\n",
+ " * Arithmetic operations\n",
+ " * Differential operations\n",
+ " * Sequence operations\n",
+ " * Composition\n",
+ "4. Checking identities\n",
+ "5. Built-in examples\n",
+ "\n",
+ "## **1. Installing the package**\n",
+ "There are three different ways to obtain the package.\n",
+ "\n",
+ "#### **Public _git_ repository**\n",
+ "The package can be obtained freely from the public _git_ repository from RISC (Research Institute for Symbolic Computation): click [here](http://git.risc.jku.at/gitweb/?p=ajpastor/diff_defined_functions.git) for the webpage view or [clone](git.risc.jku.at:pub/ajpastor/diff_defined_functions) the repository (git.risc.jku.at:pub/ajpastor/diff_defined_functions).\n",
+ "\n",
+ "* This method allow the user to get the <font color=\"green\">very last version</font> of the code.\n",
+ "* From time to time, this means the version <font color=\"red\">is not stable</font>.\n",
+ "\n",
+ "#### **Zip download from Webpage**\n",
+ "The last <font color=\"green\">stable version</font> of the code is always available on my [personal webpage](https://www.dk-compmath.jku.at/people/antonio). Just download it and unpack it. To update the code, <font color=\"red\">redownload the zip file and update the folder manually</font>.\n",
+ "\n",
+ "##### **How to actually use the package**\n",
+ "Once the repository is cloned or the zip is unpacked, one can run Sage inside the folder or add it to the standars PATH for Sage for look for packages modifying the file `~/.sage/sage.init` and adding the following lines:\n",
+ "\n",
+ "`import sys, os;\n",
+ "sys.path.append(os.path.expanduser(\"###\");`\n",
+ " \n",
+ "where `###` is the path to the local copy of the package.\n",
+ "\n",
+ "#### **PiPy installation (<font color=\"red\">not available</font>)**\n",
+ "As the package is implemented in Python 2.7, we can use the following pip command:\n",
+ "\n",
+ "`pip install dd_functions`\n",
+ "\n",
+ "Using this method will provide <font color=\"green\">the last stable version</font> with an <font color=\"green\">easy way to update</font>\n",
+ "\n",
+ "## **2. Basics of the package**\n",
+ "Once the package is completely installed, you can start using it after importing the package into your current Sage session:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%display latex # Remove if you prefer the plain representation\n",
+ "from ajpastor.dd_functions import *"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The package is intended to work with an extension for D-finite functions. These functions are power series $f(x)$ that satisfy _linear differential equations_ with **polynomial** coefficients.\n",
+ "\n",
+ "Classical examples include the _exponential_ function ($e^x$), _trigonometric_ functions ($\\sin(x), \\cos(x)$), a large set of _special functions_ (like the Bessel functions, hypergeometric functions, etc.). Several packages are available for working with D-finite functions. The main computable characteristic of this class of power series is that it is enough the coefficients of the differential equation and some initial conditions to completely represent a D-finite function.\n",
+ "\n",
+ "In [this paper](https://doi.org/10.1016/j.jsc.2018.07.002), the authors extended the concept of D-finite to the DD-finite functions. A DD-finite function is a power series that satisfies (again) a linear differential equation with **D-finite** coefficients. In this way several non-D-finite examples can be represented with the same structure (a differential equation and some initial conditions): the _double exponential_ ($e^{e^x}$) or the _tangent_ ($\\tan(x)$).\n",
+ "\n",
+ "However, in [the paper](https://doi.org/10.1016/j.jsc.2018.07.002) it is shown that the only requirement to use this structure of _D.E. + I.C._, the only requirement is a **differential integral domain** $R$. Hence, the set of all power series that satisfy a linear differential equation with coefficients in $R$ is called the set of _differentially definable functions over $R$_. The package provides the implementation to work with these objects and perform different type of operations with them.\n",
+ "\n",
+ "##### **Creating differentially definable rings**\n",
+ "\n",
+ "This package follows the Parent-Element paradigm followed in Sage, and the user can create any _differentially definable ring_ providing the original ring $R$ for the coefficients of the differential equations and the derivative that works on $R$. The class `DDRing` do the job:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "F.<s2> = NumberField(x^2-2); # Coefficients will be rational numbers with sqrt(2)\n",
+ "R.<x> = F[]; # Creating the polynomial ring with those coefficients\n",
+ "A = DDRing(R) # Creating the Diff. definable ring"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|DD-Ring|\\phantom{\\verb!x!}\\verb|over|\\phantom{\\verb!x!}\\verb|(Univariate|\\phantom{\\verb!x!}\\verb|Polynomial|\\phantom{\\verb!x!}\\verb|Ring|\\phantom{\\verb!x!}\\verb|in|\\phantom{\\verb!x!}\\verb|x|\\phantom{\\verb!x!}\\verb|over|\\phantom{\\verb!x!}\\verb|Number|\\phantom{\\verb!x!}\\verb|Field|\\phantom{\\verb!x!}\\verb|in|\\phantom{\\verb!x!}\\verb|s2|\\phantom{\\verb!x!}\\verb|with|\\phantom{\\verb!x!}\\verb|defining|\\phantom{\\verb!x!}\\verb|polynomial|\\phantom{\\verb!x!}\\verb|x^2|\\phantom{\\verb!x!}\\verb|-|\\phantom{\\verb!x!}\\verb|2)|</script></html>"
+ ],
+ "text/plain": [
+ "DD-Ring over (Univariate Polynomial Ring in x over Number Field in s2 with defining polynomial x^2 - 2)"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "A # Printing the new ring"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It is interesting to remark that the package provides by default the differentially definable rings over the polynomial ring ($\\mathbb{Q}[x]$) in the variable `DFinite` and the D-finite ring ($\\text{D}(\\mathbb{Q}[x])$) in the variable `DDFinite`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n",
+ "DD-Ring over (Univariate Polynomial Ring in x over Rational Field)\n"
+ ]
+ }
+ ],
+ "source": [
+ "print DFinite == DDRing(QQ[x]) ## Checking DFinite are the D-finite functions\n",
+ "print DFinite"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n",
+ "DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field))\n"
+ ]
+ }
+ ],
+ "source": [
+ "print DDFinite == DDRing(DFinite) ## Checking DFinite are the D-finite functions\n",
+ "print DDFinite"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### **Creating differentially definable functions**\n",
+ "Once you have a differentially definable ring, you can create any of its elements using the method `element` of the class DDRing. This method requires two arguments:\n",
+ "* A list, representing the coefficients of the linear differential equation.\n",
+ "* A list, with the initial values that defines the function.\n",
+ "\n",
+ "For example, we can create the exponential function from the `DFinite` object:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "f'(x)- f(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 1, f'(0) = 1\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(1:1:1)DD-Function in (DD-Ring over (Univariate Polynomial Ring in x over Rational Field))"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "exponential = DFinite.element([-1,1], [1])\n",
+ "exponential"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also create the sine function and the cosine function:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sine = DFinite.element([1,0,1],[0,1])\n",
+ "cosine = DFinite.element([1,0,1],[1,0])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Or we can create aldo DD-finite elements (like the tangent):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{2}(x)f''(x)- 2 f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{2}:\\left\\{\\begin{array}{c}\n",
+ "g_{2}^{(3)}(x)+ \\left( 4 \\right) g_{2}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{2}(0) = 1, g_{2}'(0) = 0, g_{2}''(0) = -2, g_{2}^{(3)}(0) = 0\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 1, f''(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(2:2:7)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tangent = DDFinite.element([-2, 0, cosine^2], [0,1]);\n",
+ "tangent"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And we can compute with this new elements without any further problem"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "f^{(3)}(x)+ \\left( 4 \\right) f'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 0, f''(0) = 2, f^{(3)}(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(3:3:3)DD-Function in (DD-Ring over (Univariate Polynomial Ring in x over Rational Field))"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sine^2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "f^{(4)}(x)- 2 f^{(3)}(x) + \\left( 3 \\right) f''(x) - 2 f'(x) + \\left( 2 \\right) f(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "f(0) = -1, f'(0) = 0, f''(0) = 0, f^{(3)}(0) = 1, f^{(4)}(0) = 4\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(4:4:4)DD-Function in (DD-Ring over (Univariate Polynomial Ring in x over Rational Field))"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sine - cosine*exponential"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **3. Operations in the package**\n",
+ "With these differentially definable functions we can perform a lot of operations using only the structure of _D.E + I.V_. We can classify the operations into the following categories:\n",
+ "\n",
+ "* **Arithmetic operations**: addition (`+`, `-`), multiplication (`*`), powers (`^`) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "\\left( x - 1 \\right) f^{(3)}(x) + \\left( -x \\right) f''(x) + f'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 1, f''(0) = 0, f^{(3)}(0) = 1\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(3:3:5)DD-Function in (DD-Ring over (Univariate Polynomial Ring in x over Number Field in s2 with defining polynomial x^2 - 2))"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Addition with a polynomial (automatic coercion to DFinite ring)\n",
+ "exponential - 1 - 1/2*x^2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{4}(x)f^{(4)}(x)+ g_{3}(x)f^{(3)}(x)+ g_{2}(x)f''(x)+ g_{1}(x)f'(x)+ g_{0}(x)f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{0}:\\left\\{\\begin{array}{c}\n",
+ "g_{0}^{(7)}(x)+ \\left( 56 \\right) g_{0}^{(5)}(x) + \\left( 784 \\right) g_{0}^{(3)}(x) + \\left( 2304 \\right) g_{0}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{0}(0) = -15, g_{0}'(0) = 0, g_{0}''(0) = 62, g_{0}^{(3)}(0) = 0, g_{0}^{(4)}(0) = -656, g_{0}^{(5)}(0) = 0, g_{0}^{(6)}(0) = 9872, g_{0}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{1}:\\left\\{\\begin{array}{c}\n",
+ "g_{1}^{(5)}(x)+ \\left( 20 \\right) g_{1}^{(3)}(x) + \\left( 64 \\right) g_{1}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{1}(0) = 0, g_{1}'(0) = 28, g_{1}''(0) = 0, g_{1}^{(3)}(0) = -232, g_{1}^{(4)}(0) = 0, g_{1}^{(5)}(0) = 2848\\end{array}\\right.\\\\\n",
+ "g_{2}:\\left\\{\\begin{array}{c}\n",
+ "g_{2}^{(7)}(x)+ \\left( 56 \\right) g_{2}^{(5)}(x) + \\left( 784 \\right) g_{2}^{(3)}(x) + \\left( 2304 \\right) g_{2}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{2}(0) = 6, g_{2}'(0) = 0, g_{2}''(0) = -4, g_{2}^{(3)}(0) = 0, g_{2}^{(4)}(0) = -128, g_{2}^{(5)}(0) = 0, g_{2}^{(6)}(0) = 4256, g_{2}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{3}:\\left\\{\\begin{array}{c}\n",
+ "g_{3}^{(5)}(x)+ \\left( 20 \\right) g_{3}^{(3)}(x) + \\left( 64 \\right) g_{3}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{3}(0) = 0, g_{3}'(0) = 4, g_{3}''(0) = 0, g_{3}^{(3)}(0) = -40, g_{3}^{(4)}(0) = 0, g_{3}^{(5)}(0) = 544\\end{array}\\right.\\\\\n",
+ "g_{4}:\\left\\{\\begin{array}{c}\n",
+ "g_{4}^{(7)}(x)+ \\left( 56 \\right) g_{4}^{(5)}(x) + \\left( 784 \\right) g_{4}^{(3)}(x) + \\left( 2304 \\right) g_{4}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{4}(0) = -3, g_{4}'(0) = 0, g_{4}''(0) = 14, g_{4}^{(3)}(0) = 0, g_{4}^{(4)}(0) = -176, g_{4}^{(5)}(0) = 0, g_{4}^{(6)}(0) = 3344, g_{4}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 1, f''(0) = 0, f^{(3)}(0) = -1, f^{(4)}(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(4:4:35)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Multiplication between DD-finite functions\n",
+ "tangent * cosine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{3}(x)f^{(3)}(x)+ g_{1}(x)f'(x)+ g_{0}(x)f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{0}:\\left\\{\\begin{array}{c}\n",
+ "g_{0}''(x)+ g_{0}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{0}(0) = 0, g_{0}'(0) = -8, g_{0}''(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{1}:\\left\\{\\begin{array}{c}\n",
+ "g_{1}''(x)+ g_{1}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{1}(0) = -8, g_{1}'(0) = 0, g_{1}''(0) = 8\\end{array}\\right.\\\\\n",
+ "g_{3}:\\left\\{\\begin{array}{c}\n",
+ "g_{3}^{(4)}(x)+ \\left( 10 \\right) g_{3}''(x) + \\left( 9 \\right) g_{3}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{3}(0) = 1, g_{3}'(0) = 0, g_{3}''(0) = -3, g_{3}^{(3)}(0) = 0, g_{3}^{(4)}(0) = 21\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 0, f''(0) = 2, f^{(3)}(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(3:3:12)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# A power of an element\n",
+ "tangent^2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* **Differential operations**: with the methods `derivative` and `integrate`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}</script></html>"
+ ],
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Fundamental theorem of calculus:\n",
+ "tangent.integrate().derivative() == tangent"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* **Sequence operations**: we can extract the initial values of the function (methods `getInitialValue` and `getInitialValueList`) and the sequence of the power series (methods `getSequenceElement` and `getSequenceList`). On other words, if we have a function `f` and we consider the sequence $(a_n)_{n \\geq 0}$ where $a_n$ is obtained by `f.getSequenceElement(n)`, then `f` is the _ordinary generating function_ of $(a_n)$. On the other hand, if $(b_n)_{n\\geq 0}$ is the sequence where $b_n$ is obtained by `f.getInitialValue(n)`, then `f` is the _exponential generating function_ of $(b_n)$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[1, 1, 1, 1, 1, 1, 1, 1, 1, 1\\right]</script></html>"
+ ],
+ "text/plain": [
+ "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "exponential.getInitialValueList(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[1, 1, \\frac{1}{2}, \\frac{1}{6}, \\frac{1}{24}, \\frac{1}{120}, \\frac{1}{720}, \\frac{1}{5040}, \\frac{1}{40320}, \\frac{1}{362880}\\right]</script></html>"
+ ],
+ "text/plain": [
+ "[1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040, 1/40320, 1/362880]"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "exponential.getSequenceList(10)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* **Composition**: whenever a function has $f(0) = 0$, we can compute the composition as power series. But usually the result is not in the same differentially definable ring, but in a more complex one. For example, the composition of two D-finite functions is DD-finite (see [this paper](https://www.dk-compmath.jku.at/publications/dk-reports/2019-02-26/view) for further information). The package take care of deciding where the final element will belong, but from the user perspective, the composition can be performed directly using the _magic call_ method of Python (i.e., using the object as a method):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "f'(x)+ g_{0}(x)f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{0}:\\left\\{\\begin{array}{c}\n",
+ "g_{0}'(x)- g_{0}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{0}(0) = -1, g_{0}'(0) = -1\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 1, f'(0) = 1\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(1:1:3)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "exponential(exponential - 1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{2}(x)f''(x)+ g_{1}(x)f'(x)+ g_{0}(x)f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{0}:\\left\\{\\begin{array}{c}\n",
+ "g_{0}^{(4)}(x)+ \\left( 10 \\right) g_{0}''(x) + \\left( 9 \\right) g_{0}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{0}(0) = 1, g_{0}'(0) = 0, g_{0}''(0) = -3, g_{0}^{(3)}(0) = 0, g_{0}^{(4)}(0) = 21\\end{array}\\right.\\\\\n",
+ "g_{1}:\\left\\{\\begin{array}{c}\n",
+ "g_{1}''(x)+ g_{1}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{1}(0) = 0, g_{1}'(0) = 1, g_{1}''(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{2}:\\left\\{\\begin{array}{c}\n",
+ "g_{2}''(x)+ g_{2}(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{2}(0) = 1, g_{2}'(0) = 0, g_{2}''(0) = -1\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 1, f'(0) = 0, f''(0) = -1\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(2:2:10)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "cosine(sine)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **4. Checking identities**\n",
+ "One of the main use for this package is to check identities for objects represented with differential equations. For doing so, we can use the equality in Python (`==`) to check if two objects are the same.\n",
+ "\n",
+ "For example, we saw previously what is the product of the tangent and the cosine:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{4}(x)f^{(4)}(x)+ g_{3}(x)f^{(3)}(x)+ g_{2}(x)f''(x)+ g_{1}(x)f'(x)+ g_{0}(x)f(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{0}:\\left\\{\\begin{array}{c}\n",
+ "g_{0}^{(7)}(x)+ \\left( 56 \\right) g_{0}^{(5)}(x) + \\left( 784 \\right) g_{0}^{(3)}(x) + \\left( 2304 \\right) g_{0}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{0}(0) = -15, g_{0}'(0) = 0, g_{0}''(0) = 62, g_{0}^{(3)}(0) = 0, g_{0}^{(4)}(0) = -656, g_{0}^{(5)}(0) = 0, g_{0}^{(6)}(0) = 9872, g_{0}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{1}:\\left\\{\\begin{array}{c}\n",
+ "g_{1}^{(5)}(x)+ \\left( 20 \\right) g_{1}^{(3)}(x) + \\left( 64 \\right) g_{1}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{1}(0) = 0, g_{1}'(0) = 28, g_{1}''(0) = 0, g_{1}^{(3)}(0) = -232, g_{1}^{(4)}(0) = 0, g_{1}^{(5)}(0) = 2848\\end{array}\\right.\\\\\n",
+ "g_{2}:\\left\\{\\begin{array}{c}\n",
+ "g_{2}^{(7)}(x)+ \\left( 56 \\right) g_{2}^{(5)}(x) + \\left( 784 \\right) g_{2}^{(3)}(x) + \\left( 2304 \\right) g_{2}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{2}(0) = 6, g_{2}'(0) = 0, g_{2}''(0) = -4, g_{2}^{(3)}(0) = 0, g_{2}^{(4)}(0) = -128, g_{2}^{(5)}(0) = 0, g_{2}^{(6)}(0) = 4256, g_{2}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{3}:\\left\\{\\begin{array}{c}\n",
+ "g_{3}^{(5)}(x)+ \\left( 20 \\right) g_{3}^{(3)}(x) + \\left( 64 \\right) g_{3}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{3}(0) = 0, g_{3}'(0) = 4, g_{3}''(0) = 0, g_{3}^{(3)}(0) = -40, g_{3}^{(4)}(0) = 0, g_{3}^{(5)}(0) = 544\\end{array}\\right.\\\\\n",
+ "g_{4}:\\left\\{\\begin{array}{c}\n",
+ "g_{4}^{(7)}(x)+ \\left( 56 \\right) g_{4}^{(5)}(x) + \\left( 784 \\right) g_{4}^{(3)}(x) + \\left( 2304 \\right) g_{4}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{4}(0) = -3, g_{4}'(0) = 0, g_{4}''(0) = 14, g_{4}^{(3)}(0) = 0, g_{4}^{(4)}(0) = -176, g_{4}^{(5)}(0) = 0, g_{4}^{(6)}(0) = 3344, g_{4}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 0, f'(0) = 1, f''(0) = 0, f^{(3)}(0) = -1, f^{(4)}(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "(4:4:35)DD-Function in (DD-Ring over (DD-Ring over (Univariate Polynomial Ring in x over Rational Field)))"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tangent * cosine"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Which it seems quite a mess. However, the initial conditions look similar to the sine function (in fact, we know they are the same). We can check that directly using the `==` symbol:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}</script></html>"
+ ],
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tangent * cosine == sine"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can check other type of identities:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}</script></html>"
+ ],
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# sin(sin(x))^2 + cos(sin(x))^2 == 1\n",
+ "sine(sine)^2 + cosine(sine)^2 == 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}</script></html>"
+ ],
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# tan(x)' == tan(x)^2 + 1\n",
+ "tangent.derivative() == tangent^2 + 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also prove other type of identities. For example, if we look to the [Mathieu differential equation](http://mathworld.wolfram.com/MathieuFunction.html):\n",
+ "$$w''(x) + (a - 2q\\cos(2x))w(x) = 0,$$\n",
+ "and consider the two fundamental solutions $w_1(x)$ and $w_2(x)$ where $w_1(0) = 1, w_1'(0) = 0$ and $w_2(0) = 0, w_2'(0) = 1$, then we know that the _Wronskian_ must be 1. We can do that quickly with this package:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{c}\n",
+ "g_{4}(x)f^{(4)}(x)+ g_{3}(x)f^{(3)}(x)+ g_{2}(x)f''(x)+ g_{1}(x)f'(x) = 0,\\\\\n",
+ "where\\\\\n",
+ "g_{1}:\\left\\{\\begin{array}{c}\n",
+ "g_{1}^{(7)}(x)+ \\left( 56 \\right) g_{1}^{(5)}(x) + \\left( 784 \\right) g_{1}^{(3)}(x) + \\left( 2304 \\right) g_{1}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{1}(0) = 0, g_{1}'(0) = 256 a^{2} + 1280 a q - 3584 q^{2}, g_{1}''(0) = 0, g_{1}^{(3)}(0) = -1024 a^{2} - 20480 a q + 8192 q^{2}, g_{1}^{(4)}(0) = 0, g_{1}^{(5)}(0) = 4096 a^{2} + 327680 a q + 188416 q^{2}, g_{1}^{(6)}(0) = 0, g_{1}^{(7)}(0) = -16384 a^{2} - 5242880 a q - 8716288 q^{2}\\end{array}\\right.\\\\\n",
+ "g_{2}:\\left\\{\\begin{array}{c}\n",
+ "g_{2}^{(7)}(x)+ \\left( 56 \\right) g_{2}^{(5)}(x) + \\left( 784 \\right) g_{2}^{(3)}(x) + \\left( 2304 \\right) g_{2}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{2}(0) = 64 a^{2} - 256 a q + 256 q^{2} - 256 q, g_{2}'(0) = 0, g_{2}''(0) = -256 a^{2} + 512 a q + 512 q, g_{2}^{(3)}(0) = 0, g_{2}^{(4)}(0) = 1024 a^{2} - 8192 a q - 36864 q^{2} - 8192 q, g_{2}^{(5)}(0) = 0, g_{2}^{(6)}(0) = -4096 a^{2} + 131072 a q + 1474560 q^{2} + 131072 q, g_{2}^{(7)}(0) = 0\\end{array}\\right.\\\\\n",
+ "g_{3}:\\left\\{\\begin{array}{c}\n",
+ "g_{3}^{(5)}(x)+ \\left( 20 \\right) g_{3}^{(3)}(x) + \\left( 64 \\right) g_{3}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{3}(0) = 0, g_{3}'(0) = 64 a + 128 q, g_{3}''(0) = 0, g_{3}^{(3)}(0) = -256 a - 2048 q, g_{3}^{(4)}(0) = 0, g_{3}^{(5)}(0) = 1024 a + 32768 q\\end{array}\\right.\\\\\n",
+ "g_{4}:\\left\\{\\begin{array}{c}\n",
+ "g_{4}^{(5)}(x)+ \\left( 20 \\right) g_{4}^{(3)}(x) + \\left( 64 \\right) g_{4}'(x) = 0,\\\\\n",
+ "\\hdashline\n",
+ "g_{4}(0) = 16 a - 32 q, g_{4}'(0) = 0, g_{4}''(0) = -64 a - 128 q, g_{4}^{(3)}(0) = 0, g_{4}^{(4)}(0) = 256 a + 2048 q, g_{4}^{(5)}(0) = 0\\end{array}\\right.\\\\\n",
+ "\\hdashline\n",
+ "f(0) = 1, f'(0) = 0, f''(0) = 0, f^{(3)}(0) = 0, f^{(4)}(0) = 0\\end{array}\\right.</script></html>"
+ ],
+ "text/plain": [
+ "1"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Building the functions w_1 and w_2. We use the method MathieuD (see below)\n",
+ "w1 = MathieuD('a','q',(1,0));\n",
+ "w2 = MathieuD('a','q',(0,1));\n",
+ "\n",
+ "W = w1*w2.derivative() - w2*w1.derivative();\n",
+ "W"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It really seems to be equal to 1. We can check that using the equality method in Python"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "<html><script type=\"math/tex; mode=display\">\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}</script></html>"
+ ],
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "W == 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **5. Built-in functions in the package**\n",
+ "The package provides several built-in examples of D-finite and DD-finite functions that can be built easily fixing a couple of parameters depending on the function.\n",
+ "\n",
+ "Once we have imported the package, a method `ddExamples` is available to get all the information about the built-in functions:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ " Welcome to ddExamples documentation. Here we describe the functions\n",
+ " available in this module. For further information on each function, \n",
+ " please access the documentation for that particular function.\n",
+ " \n",
+ " All the elements that are returned in this module are DDFunction, i.e.,\n",
+ " formal power series defined with a linear differential equation and\n",
+ " some appropriate initial values.\n",
+ " \n",
+ " When possible, the functions returned by this module are associated with\n",
+ " the usual implementation of those functions in SAGE, so using the \n",
+ " method \"to_symbolic()\" returns the same object in the Symbolic Ring.\n",
+ " \n",
+ " The functions available in this module are the following:\n",
+ " \n",
+ " ** TRIGONOMETRIC FUNCTIONS\n",
+ " - Sin\n",
+ " - Cos\n",
+ " - Tan\n",
+ " - Sinh\n",
+ " - Cosh\n",
+ " - Tanh\n",
+ " - Arcsin\n",
+ " - Arccos\n",
+ " - Arctan\n",
+ " - Arcsinh\n",
+ " - Arccosh\n",
+ " - Arctanh\n",
+ " ** EXPONENTIAL FUNCTIONS\n",
+ " - Exp\n",
+ " - Log\n",
+ " - Log1\n",
+ " ** BESSEL TYPE FUNCTIONS (see chapters 10, 11 in https://dlmf.nist.gov)\n",
+ " - BesselD\n",
+ " - StruveD\n",
+ " ** ORTHOGONAL POLRNOMAILS\n",
+ " - LegendreD (see chapter 14 in https://dlmf.nist.gov)\n",
+ " - ChebyshevD (see chapter 18 in https://dlmf.nist.gov)\n",
+ " ** HYPERGEOMETRIC FUNCTIONS (see chapters 15, 16 in https://dlmf.nist.gov)\n",
+ " - HypergeometricFunction\n",
+ " - GenericHypergeometricFunction\n",
+ " - Polylogarithms\n",
+ " ** RICCATI EQUATION (see https://en.wikipedia.org/wiki/Riccati_equation)\n",
+ " - RiccatiD\n",
+ " ** MATHIEU TYPE FUNCTIONS (see chapter 28 in https://dlmf.nist.gov)\n",
+ " - MathieuD\n",
+ " - MathieuSin\n",
+ " - MathieuCos\n",
+ " - MathieuH\n",
+ " - MathieuSinh\n",
+ " - MathieuCosh\n",
+ " - HillD\n",
+ " ** AIRY'S FUNCTIONS\n",
+ " - AiryD\n",
+ " ** PARABOLIC-CYLINDER TYPE FUNCTIONS\n",
+ " - ParabolicCylinderD\n",
+ " ** ELLIPTIC INTEGRALS (see chapter 19 in https://dlmf.nist.gov)\n",
+ " - EllipticLegendreD\n",
+ " ** SPHEROIDAL WAVE FUNCTIONS (see chapter 30 in https://dlmf.nist.gov)\n",
+ " - CoulombSpheroidalFunctionD\n",
+ " - SpheroidalWaveFunctionD\n",
+ " ** HEUN'S FUNCTIONS (see chapter 31 in https://dlmf.nist.gov)\n",
+ " - FuschianD\n",
+ " - HeunD\n",
+ " ** COULOMB WAVE FUNCTION (see chapter 33 in https://dlmf.nist.gov)\n",
+ " - CoulombF\n",
+ " \n",
+ " ** COMBINATORIAL FUNCTIONS\n",
+ " - Catalan\n",
+ " - Fibonacci\n",
+ " \n"
+ ]
+ }
+ ],
+ "source": [
+ "ddExamples()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "For each of these functions we can call the documentation using the `?` syntax from Python. Each of them explains briefly which function they are representing, some links to more proper definitions and the paramters required to initialize the object.\n",
+ "\n",
+ "We can check that all the functions we have defined through the notebook are the same as the built-in functions:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Exponential: True\n",
+ "Sine: True\n",
+ "Cosine: True\n",
+ "Tangent: True\n",
+ "Double exponential: True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print \"Exponential: \", Exp(x) == exponential;\n",
+ "print \"Sine: \", Sin(x) == sine;\n",
+ "print \"Cosine: \", Cos(x) == cosine;\n",
+ "print \"Tangent: \", Tan(x) == tangent;\n",
+ "print \"Double exponential: \", Exp(Exp(x)-1) == exponential(exponential-1);\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Time to experiment**\n",
+ "Now feel free to experiment with the package. Any bug, feature request or suggestion is welcome in the email: ajpastor@risc.uni-linz.ac.at"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "SageMath 8.8.beta3",
+ "language": "",
+ "name": "sagemath"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 2
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython2",
+ "version": "2.7.15"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}