{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](img/logocurso.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "d9e822f9-0a52-43f2-90ef-e8fd6860aacc"
    }
   },
   "source": [
    "![](img/sesion6.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cálculo con Sympy\n",
    "\n",
    "El cálculo o análisis matemático es la rama de las matemáticas que, definida a grandes rasgos, involucra cálculos basados en el concepto de límite y en procesos de paso al límite como la derivación o la integración. Límites, derivadas e integrales son las operaciones esenciales que abordaremos en esta sección.\n",
    "<div class=\"alert alert-info\">Instrucciones de cálculo matemático con Sympy:\n",
    "<ol>\n",
    "<li><b>Calculo de límites (limit)</b>: \n",
    "<table>\n",
    "    <tr><td><b>Matemáticas</b></td><td><b>Python</b></td></tr>\n",
    "    <tr><td>$\\displaystyle\\lim_{x\\rightarrow x_0} f(x)$</td><td>limit(f(x),x,x<sub>0</sub>)</td></tr>\n",
    "    <tr><td>$\\displaystyle\\lim_{x\\rightarrow x_0^-} f(x)$</td><td>limit(f(x),x,x<sub>0</sub>,\"-\")</td></tr>\n",
    "    <tr><td>$\\displaystyle\\lim_{x\\rightarrow x_0^+} f(x)$</td><td>limit(f(x),x,x<sub>0</sub>,\"+\")</td></tr>\n",
    "    <tr><td>$\\displaystyle\\lim_{x\\rightarrow \\infty} f(x)$</td><td>limit(f(x),x,oo)</td></tr>\n",
    "</table>\n",
    "\n",
    "\n",
    "<li><b>Calculo de derivadas (diff)</b>:\n",
    "<table>\n",
    "    <tr><td><b>Matemáticas</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td><b>Python</b></td></tr>\n",
    "    <tr><td>$\\displaystyle \\frac{df(x)}{dx}$</td><td>diff(f(x), x)</td></tr>\n",
    "    <tr><td>$\\displaystyle \\frac{d^2f(x)}{d x^2}$</td><td>diff(f(x),x,x)</td></tr>\n",
    "    <tr><td>$\\displaystyle \\frac{\\partial^n f(x)}{\\partial x^n}$</td><td>diff(f(x),x,n)</td></tr>\n",
    "    <tr><td>$\\displaystyle \\frac{\\partial^{n_1+n_2+n_3}f(x)}{\\partial x^{n_1}\\partial y^{n_2}\\partial z^{n_3}}$</td>\n",
    "                <td>diff(f(x),x,n<sub>1</sub>,y,n<sub>2</sub>,z,n<sub>3</sub>)</td></tr>\n",
    "</table>\n",
    "\n",
    "<li><b>Calculo de integrales (integrate)</b>:\n",
    "<table> <tr><td><b>Matemáticas</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td><b>Python</b></td></tr>\n",
    "    <tr><td>$\\displaystyle \\int f(x)dx$</td><td>integrate(f(x), x)</td></tr>\n",
    "    <tr><td>$\\displaystyle \\int_a^b f(x)dx$</td><td>integrate(f(x),(x,a,b))</td></tr>\n",
    "    <tr><td>$\\displaystyle \\int\\int f(x,y)dxdy$</td><td>integrate(f(x),x,y)</td></tr>\n",
    "    <tr><td>$\\displaystyle \\int_c^d\\int_a^b f(x,y)dxdy$</td><td>integrate(f(x),(x,a,b),(y,c,d))</td></tr>\n",
    "</table>\n",
    "\n",
    "\n",
    "<li><b>Desarrollo en serie de Taylor (series)</b>: El desarrollo en serie de Taylor de f(x) de orden n en $x_0$ es\n",
    "<p style=\"text-align:center;\">$\\displaystyle f(x_0)+f'(x_0)(x-x_0)+\\frac{f''(x_0)}{2!}(x-x_0)^2+\\cdots+\\frac{f^{(n-1)}(x_0)}{(n-1)!}(x-x_0)^{n-1}+O((x-x_0)^n)$</p>\n",
    "puede obtenerse mediante\n",
    "<p style=\"text-align:center;\">f(x).series(x,x<sub>0</sub>,n)</p>\n",
    "Si necesitamos eliminar la expresión infinitesimal podemos utilizar el método removeO(),\n",
    "<p style=\"text-align:center;\">f(x).series(x,x<sub>0</sub>,n).removeO()</p>\n",
    "</ol>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sympy import *\n",
    "init_printing()\n",
    "x,y,z,k=symbols(\"x y z k\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para calcular $\\displaystyle\\lim_{x\\rightarrow 0}\\frac{\\sin(x)}{x}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "limit(sin(x)/x,x,0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para $\\displaystyle\\lim_{x\\rightarrow 0^-}e^{\\frac{1}{x}}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "limit(E**(1/x),x,0,\"+\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\displaystyle\\lim_{x\\rightarrow \\infty}e^{\\frac{1}{x}}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "limit(E**(1/x),x,oo)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos definir la función $f(x)=x^2e^x$ y calcular sus derivadas o derivadas sucesivas o su desarrollo en serie de Taylor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):\n",
    "    return x**2*E**x\n",
    "\n",
    "# f'(x)\n",
    "f(x).diff(x,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "diff(f(x),x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# f''(x)\n",
    "f(x).diff(x,x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Derivada de orden 4\n",
    "f(x).diff(x,4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos considerar también una función de varias variables como $g(x,y,z)=\\cos(x^2+y^2 z)$ y calcular sus derivadas parciales, por ejemplo $\\displaystyle \\frac{\\partial^6 g(x,y,z)}{\\partial x^2\\partial y\\partial z^3}$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def g(x,y,z):\n",
    "    return cos(x**2+y**2*z)\n",
    "\n",
    "\n",
    "g(x,y,z).diff(x,2,y,1,z,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos utlizar subs para calcular $\\displaystyle \\frac{\\partial^6 g}{\\partial x^2\\partial y\\partial z^3}(1,2,-1)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g(x,y,z).diff(x,2,y,1,z,3).subs([(x,1),(y,2),(z,-1)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Es también sencillo calcular $\\int (x^2+1)e^x dx$ o $\\int_0^1 (x^2+1)e^x dx$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "integrate((x**2+1)*E**x,x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "integrate((x**2+1)*E**x,(x,0,1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El desarrollo en serie de Taylor en el punto $x=5$ de orden 3 sería para la función f(x) que hemos definido antes sería: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f(x).series(x,5,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Si necesitamos eliminar la parte infinitesimal para poder manipular más fácilmente la expresión haremos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f(x).series(x,5,3).removeO()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Ejercicio 1\n",
    "Definir la función $f(x)=x \\sin(x e^x)$ y calcular $\\displaystyle \\frac{d^5f(x)}{dx^5}$ y $\\displaystyle \\frac{d^5f}{dx^5}(0)$ y $\\int f(x)dx$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 2\n",
    "Calcular la integral $\\int_0^\\infty \\frac{\\sin(x)}{x}dx$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 3\n",
    "Dada la función $h(x,y,z)=x^2 cos(y z)$, calcular $\\frac{\\partial^4 h}{\\partial x^2\\partial y\\partial z}(-2,3,-1)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Ejercicio 4\n",
    "Calcular un desarrollo en serie de Taylor para la función $\\log(x)$ en $x=1$ de orden 20. Eliminar la parte infinitesimal y utilizar el desarrollo para aproximar $\\log(x)$. Calcular el valor exacto de $\\log(1.5)$ y comparar con el resultado que proporciona el desarrollo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Uso simbólico de funciones\n",
    "\n",
    "Del mismo modo que en matemáticas se trabaja con símbolos como x ó y para los que no se conoce el valor, igualmente trabajamos también con funciones genéricas f(x) ó g(x) de las que no conocemos su fórmula. Cuando consideramos funciones genéricas podemos ofrecer fórmulas que sean válidas para cualquier definición concreta que luego demos a esas funciones simbólicas. Así por ejemplo la conocida fórmula de derivacion\n",
    "<p style=\"text-align:center;\">$(f(x)g(x))'=f'(x)g(x)+f(x)g'(x)$</p>\n",
    "expresa una regla general que es válida para cualesquiera funciones f(x) y g(x).\n",
    "\n",
    "Sympy permite manejar funciones simbólicas de modo similar. Para ello debemos primero declararlas mediante **Function** o **symbols**, en este último caso con la etiqueta adicional **cls=Function**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Declaramos dos funciones simbólicas\n",
    "f=Function(\"f\")\n",
    "g=Function(\"g\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Alternativamente también podemos hacerlo con symbols\n",
    "f,g=symbols(\"f g\",cls=Function)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una vez declaradas las funciones simbólicas podemos utilizarlas en cualquier tipo de expresión o fórmula. Por supuesto los cálculos de derivación e integración quedarán indicados ya que involucran funciones desconocidas.\n",
    "<div class=\"alert alert-info\">Las operaciones de derivación o integración en forma indicada son:\n",
    "<ul>\n",
    "<li><b>Derivative(f(x),x)</b>: expresa una derivada en forma indicada.</li>\n",
    "<li><b>Integral(f(x)),x)</b>: expresa una integral indicada.</li>\n",
    "<li><b>Subs(expresion,x,val)</b> o <b>Subs(expresion,(x1,x2,...),(val1,val2,...))</b>: expresa una sustitución indicada.</li>\n",
    "<li><b>Lambda(x, formula(x))</b> o <b>Lambda((x,y),formula(x,y))</b> es una función inmediata de Sympy. El formato es similar al de <b>lambda</b> en Python.\n",
    "<li><b>expresion.doit()</b>: ejecuta las operaciones indicadas que aparecen en <b>expresion</b> siempre que sea posible.\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos obtener la fórmula de derivación para un producto\n",
    "(f(x)*g(x)).diff(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Derivative(f(x)*g(x),x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Subs(Derivative(f(x)*g(x),x),g(x),cos(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Subs(Derivative(f(x)*g(x),x),g(x),cos(x)).doit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Integral y Derivative declaran operaciones de integración indicadas que no se realizarán.\n",
    "Integral(x**2,x)+Derivative(cos(x),x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos forzar la realización de estas operaciones mediante doit()\n",
    "(Integral(x**2,x)+Derivative(cos(x),x)).doit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos sustituir una función simbólica por cualquier otra función\n",
    "f(x**2).subs([(f,Lambda(x,x**2+x)),(x,pi)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Para sustituir una función simbólica de Sympy necesitamos usar Lambda.\n",
    "# lambda de Python no funcionará\n",
    "f(x**2).subs([(f,lambda x:x**2+x),(x,pi)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Una substitución indicada no se ejecutará\n",
    "Subs(f(x**2),(f,x),(Lambda(x,x**2+x),pi))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "_.doit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos usar también funciones inmediatas con el comando Lambda (cuidado, en Sympy es L mayúscula)\n",
    "Lambda(x,x**2+x)(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Con una o más variables\n",
    "Lambda((x,y,z),(x+y+z)/3)(2,1,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos sustituir una función simbólica por una función Lambda\n",
    "f(x+1).subs(f,Lambda(x,x**2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f(x+1).subs(f,lambda x:x**2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos obtener la regla de la cadena para una composición y como vemos el resultado se da mediante un sustitución indicada\n",
    "f(g(x)).diff(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Mediante .doit() podemos forzar la evalución de la sustitución indicada.\n",
    "f(g(x)).diff(x).subs(g,cos).doit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f(cos(x)).diff(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos también definir funciones con la notación habitual de Python\n",
    "def f(x):\n",
    "    return x**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# A partir de declarar la nueva función f(x) pasa de ser una función simbólica a una función con una fórmula concreta.\n",
    "f(cos(x)).diff(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Evidentemente\n",
    "integrate(g(x),x).diff(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# También podemos manejar varias variables\n",
    "g(x,y,x**2).diff(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "Subs(Derivative(g(x,y,x**2),x),x,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "_.doit()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Ejercicio 5\n",
    "Calcular la fórmula de derivación para $(f(x)g(x)h(x))'$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 6\n",
    "Calcular la fórmula de derivación para $f(cos(x^2))$. Sustituir f por la función $x^3e^x\\sin(x^2)$ y obtener el resultado para $x=1$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 7 \n",
    "Calcular $\\frac{\\partial f(x,x^2,y)g(y)}{\\partial x}$. Reescribir la fórmula obtenida utilizando Subs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f=Function(\"f\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 8\n",
    "Obtener el valor de la expresión anterior para $f(x,y,z)=\\cos(xyz),\\sin(xyz),\\cos(x+y+z),\\sin(x+y+z)$ y $g(y)=cos(y),sin(y),tan(y)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "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.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
