On Thu, 19 Nov 2020 at 01:23, Aaron Meurer <[email protected]> wrote:
>
> On Wed, Nov 18, 2020 at 5:37 PM Oscar <[email protected]> wrote:
> >
> > Hi David,
> >
> > It's not completely intuitive but you can do the substitution in several
> > stages. In your example (this is run isympy where f and g are both
> > functions):
> >
> > In [24]: eq = Eq(n**2*f(x) - x*Derivative(f(x), x) + (1 -
> > 2*x)*Derivative(f(x), (x, 2)), 0)
> >
> > In [25]: eq
> > Out[25]:
> > 2
> > 2 d d
> > n ⋅f(x) - x⋅──(f(x)) + (1 - 2⋅x)⋅───(f(x)) = 0
> > dx 2
> > dx
> >
> > In [26]: eq.subs(f(x), g(cos(t)))
> > Out[26]:
> > 2
> > 2 d d
> > n ⋅g(cos(t)) - x⋅──(g(cos(t))) + (1 - 2⋅x)⋅───(g(cos(t))) = 0
> > dx 2
> > dx
> >
> > In [27]: eq.subs(f(x), g(cos(t))).doit()
> > Out[27]:
> > 2
> > n ⋅g(cos(t)) = 0
>
> Isn't this wrong? You are replacing f(x) with an expression that does
> not depend on x, then evaluating the derivatives that are still in
> terms of x, so they go to 0.
I obviously wasn't paying enough attention when I wrote that :)
Yes, I remember. This kind of substitution of the independent variable
is more difficult. Here's a different example that works (a
Cauchy-Euler ODE):
In [231]: eq = x**2 * f(x).diff(x, 2) + x * f(x).diff(x) + f(x)
In [232]: eq
Out[232]:
2
2 d d
x ⋅───(f(x)) + x⋅──(f(x)) + f(x)
2 dx
dx
In [233]: xf = Function('x') # make x a function of t
In [234]: xs = exp(t) # substitution
In [235]: eqf = eq.subs(x, xf(t))
In [236]: eqf
Out[236]:
2
2 d d
f(x(t)) + x (t)⋅──────(f(x(t))) + x(t)⋅─────(f(x(t)))
2 dx(t)
dx(t)
In [237]: diffx = lambda e, n: diffx(diffx(e, n-1), 1) if n>1 else
Derivative(e, t) / Derivative(xf(t), t)
In [238]: changex = lambda e: e.replace(Derivative, lambda e, vs:
diffx(e, vs[1]))
In [239]: changex(eqf)
Out[239]:
⎛d ⎞
⎜──(f(x(t)))⎟
2 d ⎜dt ⎟
x (t)⋅──⎜───────────⎟
dt⎜ d ⎟ d
⎜ ──(x(t)) ⎟ x(t)⋅──(f(x(t)))
⎝ dt ⎠ dt
f(x(t)) + ───────────────────── + ────────────────
d d
──(x(t)) ──(x(t))
dt dt
In [240]: changex(eqf).doit()
Out[240]:
2
2 d d
f(x(t)) + x (t)⋅──────(f(x(t))) + x(t)⋅─────(f(x(t)))
2 dx(t)
dx(t)
In [241]: changex(eqf).doit() == eqf
Out[241]: True
In [242]: changex(eqf).subs(f(xf(t)), g(t)).subs(xf(t),
xs).doit().expand()
Out[242]:
2
d
g(t) + ───(g(t))
2
dt
Applying the same technique to the equation you showed doesn't lead to
a simple result though:
In [243]: eq = n**2*f(x) - x*Derivative(f(x), x) + (1 -
2*x)*Derivative(f(x), (x, 2))
In [244]: xs = cos(t)
In [245]: eqf = eq.subs(x, xf(t))
In [246]: changex(eqf).doit() == eqf
Out[246]: True
In [247]: changex(eqf).subs(f(xf(t)), g(t)).subs(xf(t),
xs).doit().expand()
Out[247]:
2 2
d d
d 2⋅cos(t)⋅───(g(t)) ───(g(t)) 2
d d
cos(t)⋅──(g(t)) 2 2 2⋅cos
(t)⋅──(g(t)) cos(t)⋅──(g(t))
2 dt dt dt
dt dt
n ⋅g(t) + ─────────────── - ────────────────── + ───────── +
────────────────── - ───────────────
sin(t) 2 2 3
3
sin (t) sin (t) sin
(t) sin (t)
In [248]: _.collect(g(t))
Out[248]:
2 ⎛ 2
⎞
2 ⎛ 2⋅cos(t) 1 ⎞ d ⎜cos(t) 2⋅cos (t)
cos(t)⎟ d
n ⋅g(t) + ⎜- ──────── + ───────⎟⋅───(g(t)) + ⎜────── + ───────── -
───────⎟⋅──(g(t))
⎜ 2 2 ⎟ 2 ⎜sin(t) 3
3 ⎟ dt
⎝ sin (t) sin (t)⎠ dt ⎝ sin (t) sin (t)⎠
> > Ideally sympy would have a function like maple's dchange:
> > https://www.maplesoft.com/support/help/Maple/view.aspx?path=PDEtools/dchange
> > https://github.com/sympy/sympy/issues/17590
>
> I wonder if we need a separate function or if subs() itself should
> just do this.
I think that subs could do some parts of this but a function for
change of variables in derivatives would still be useful. It's tricky
to keep track of transformations in both directions so I would expect
a dsubs function to return something to help with that as well as the
transformed equation. There are also several different forms of
substitution for ODEs and a dsubs function could handle them all.
Oscar
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/CAHVvXxT3KZY4ZZSE8LdNHdHgn28CsH8KGPcuMneFWJxiNuSzGA%40mail.gmail.com.