Skip to content

Instantly share code, notes, and snippets.

@shane5ul
Last active November 20, 2023 19:21
Show Gist options
  • Save shane5ul/ad76316f9dab036ebc927d1dd2f5d424 to your computer and use it in GitHub Desktop.
Save shane5ul/ad76316f9dab036ebc927d1dd2f5d424 to your computer and use it in GitHub Desktop.
Jupyter notebook demonstrating the "change of variables" functionality in sympy
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from sympy import *\n",
"sp.init_printing(use_latex='mathjax')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sympy can perform \"change of variables\" substitution for integrals out of the box using the `Integral.transform()` method.\n",
"\n",
"For documentation see [here](https://docs.sympy.org/latest/modules/integrals/integrals.html#sympy.integrals.integrals.Integral.transform).\n",
"\n",
"Note that the goal here is not necessarily to evaluate the integral, but to transform a definite integral. Thus, the input and output are both integrals. Therefore we use `Integral` rather than `integrate`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"x, u = symbols('x, u')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example 1**: This is the example from the documentation."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{1} x \\cos{\\left(x^{2} - 1 \\right)}\\, dx$"
],
"text/plain": [
"1 \n",
"⌠ \n",
"⎮ ⎛ 2 ⎞ \n",
"⎮ x⋅cos⎝x - 1⎠ dx\n",
"⌡ \n",
"0 "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"I1 = Integral(x*cos(x**2 - 1), (x, 0, 1))\n",
"display(I1)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{1} u \\cos{\\left(u^{2} - 1 \\right)}\\, du$"
],
"text/plain": [
"1 \n",
"⌠ \n",
"⎮ ⎛ 2 ⎞ \n",
"⎮ u⋅cos⎝u - 1⎠ du\n",
"⌡ \n",
"0 "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# subs x = u, and rewrite the integral\n",
"I1.transform(x, u)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{-1}^{0} \\frac{\\cos{\\left(u \\right)}}{2}\\, du$"
],
"text/plain": [
"0 \n",
"⌠ \n",
"⎮ cos(u) \n",
"⎮ ────── du\n",
"⎮ 2 \n",
"⌡ \n",
"-1 "
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# more interesting subs x^2 - 1 = u, and rewrite the integral\n",
"I1.transform(x**2 - 1, u)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{1} \\frac{\\cos{\\left(u \\right)}}{2}\\, du$"
],
"text/plain": [
"1 \n",
"⌠ \n",
"⎮ cos(u) \n",
"⎮ ────── du\n",
"⎮ 2 \n",
"⌡ \n",
"0 "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# this inspires another substitution\n",
"I1.transform(1 - x**2, u)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No ambiguity in this, even though $x = \\pm \\sqrt{1 - u}$, since the $-2 x dx = du$. The transform function complains in case of ambiguity. For example, consider the integral without the prefactor."
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{1} \\cos{\\left(x^{2} - 1 \\right)}\\, dx$"
],
"text/plain": [
"1 \n",
"⌠ \n",
"⎮ ⎛ 2 ⎞ \n",
"⎮ cos⎝x - 1⎠ dx\n",
"⌡ \n",
"0 "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"I2 = Integral(cos(x**2 - 1), (x, 0, 1))\n",
"display(I2)\n",
"#I2.transform(x**2 - 1, u) # elicits a complaint"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can re-transform back to check."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{-1}^{0} \\frac{\\cos{\\left(u \\right)}}{2}\\, du$"
],
"text/plain": [
"0 \n",
"⌠ \n",
"⎮ cos(u) \n",
"⎮ ────── du\n",
"⎮ 2 \n",
"⌡ \n",
"-1 "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"uI = I1.transform(x**2 - 1, u)\n",
"display(uI)"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"uI.transform(sqrt(u+1), x) == I1\n",
"#or\n",
"uI.transform(u, x**2 - 1) == I1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If the substitution involves additional variable, the actual variable of integration has to be made explicity by passing a tuple."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"a = symbols('a')"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{- a}^{1 - a} \\left(a + u\\right)\\, du$"
],
"text/plain": [
"1 - a \n",
" ⌠ \n",
" ⎮ (a + u) du\n",
" ⌡ \n",
" -a "
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Integral(x, (x, 0, 1)).transform(x, (u + a, u))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*** Example 2**\n",
"\n",
"From Monte Carlo class: infinite domain integral."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{\\infty} x^{2} e^{- x}\\, dx$"
],
"text/plain": [
"∞ \n",
"⌠ \n",
"⎮ 2 -x \n",
"⎮ x ⋅ℯ dx\n",
"⌡ \n",
"0 "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"I3 = Integral(x**2 * exp(-x), (x, 0, oo))\n",
"display(I3)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\int\\limits_{0}^{1} \\log{\\left(\\frac{1}{u} \\right)}^{2}\\, du$"
],
"text/plain": [
"1 \n",
"⌠ \n",
"⎮ 2⎛1⎞ \n",
"⎮ log ⎜─⎟ du\n",
"⎮ ⎝u⎠ \n",
"⌡ \n",
"0 "
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I3.transform(exp(-x), u)"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\log{\\left(x^{2} \\right)}$"
],
"text/plain": [
" ⎛ 2⎞\n",
"log⎝x ⎠"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle \\log{\\left(x \\right)}^{2}$"
],
"text/plain": [
" 2 \n",
"log (x)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# note how sympy displays exponents of logs\n",
"display(log(x**2), (log(x))**2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment