Skip to content

Instantly share code, notes, and snippets.

@moorepants
Last active November 1, 2019 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moorepants/aec439a0383ed387f7ebb7693a9927f3 to your computer and use it in GitHub Desktop.
Save moorepants/aec439a0383ed387f7ebb7693a9927f3 to your computer and use it in GitHub Desktop.
Example showing that subs doesn't work as you might expect with derivatives.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Be careful about substituting for derivatives!"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sympy as sm\n",
"import sympy.physics.mechanics as me"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"q1, q2 = me.dynamicsymbols('q1, q2')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"a, b, c = sm.symbols('a, b, c')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle \\operatorname{q_{1}}{\\left(t \\right)} \\left(\\frac{d^{2}}{d t^{2}} \\operatorname{q_{1}}{\\left(t \\right)}\\right)^{2} + \\frac{d}{d t} \\operatorname{q_{1}}{\\left(t \\right)} \\frac{d}{d t} \\operatorname{q_{2}}{\\left(t \\right)}$"
],
"text/plain": [
"q1(t)*Derivative(q1(t), (t, 2))**2 + Derivative(q1(t), t)*Derivative(q2(t), t)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr = q1.diff().diff()**2*q1 + q1.diff()*q2.diff()\n",
"expr"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is worth looking at the raw form (the non-rendered form) to see what is going on:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'q1(t)*Derivative(q1(t), (t, 2))**2 + Derivative(q1(t), t)*Derivative(q2(t), t)'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"repr(expr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are going to be substiting expressions for $q$'s, $\\dot{q}$'s, and $\\dot{u}$'s. There are a couple of key things to be aware of:\n",
"\n",
"- `subs()` and `xreplace()` do not substitute the expression in a fixed order (i.e. Python dictionaries are not ordered), so if you pass in more than one item in a single `subs()` call, things might get substituted in an unexpected order.\n",
"- If you have a `dynamicsymbol` and its deritivate in an expression and substitute something for the symbol, it will get replaced inside the derivative too."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice how $c$ is not replaced first below and thus derivatives are left in the expression:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle a b c \\frac{d}{d t} \\operatorname{q_{2}}{\\left(t \\right)} + a \\left(\\frac{\\partial}{\\partial t} a b c\\right)^{2}$"
],
"text/plain": [
"a*b*c*Derivative(q2(t), t) + a*Derivative(a*b*c, t)**2"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr.subs({q1: a, q1.diff(): a*b*c, q1.diff().diff(): c})"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'a*b*c*Derivative(q2(t), t) + a*Derivative(a*b*c, t)**2'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"repr(expr.subs({q1: a, q1.diff(): a*b*c, q1.diff().diff(): c}))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice how all the $q_1$ are replaced with $a$, even \"inside\" the derivatives:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle a \\left(\\frac{d^{2}}{d t^{2}} a\\right)^{2} + \\frac{d}{d t} a \\frac{d}{d t} \\operatorname{q_{2}}{\\left(t \\right)}$"
],
"text/plain": [
"a*Derivative(a, (t, 2))**2 + Derivative(a, t)*Derivative(q2(t), t)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr.subs({q1: a})"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'a*Derivative(a, (t, 2))**2 + Derivative(a, t)*Derivative(q2(t), t)'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"repr(expr.subs({q1: a}))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To ensure proper substitution make sure to substitute the highest order deriavtives first in a chain of `subs()` calls:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle a c^{2} + b \\frac{d}{d t} \\operatorname{q_{2}}{\\left(t \\right)}$"
],
"text/plain": [
"a*c**2 + b*Derivative(q2(t), t)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr.subs({q1.diff().diff(): c}).subs({q1.diff(): b}).subs({q1: a})"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'a*c**2 + b*Derivative(q2(t), t)'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"repr(expr.subs({q1.diff().diff(): c}).subs({q1.diff(): b}).subs({q1: a}))"
]
}
],
"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.6.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment