Last active
November 20, 2023 19:21
-
-
Save shane5ul/ad76316f9dab036ebc927d1dd2f5d424 to your computer and use it in GitHub Desktop.
Jupyter notebook demonstrating the "change of variables" functionality in sympy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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