Modify an expression involving derivatives of functions by changing variables - sympy

I am attempting to make a YouTube video in which I demonstrate how SymPy can be used to verify the steps in the derivation of a solution to Schrodinger's equation. There is an expression involving derivatives"
u=symbols('u')(r)
diff(u,r,2)
and a change of variables (a is constant):
r=a*x
or
u.subs(r,a*x)
and I want to get back something like:
diff(u,x,2)/a**2
I understand that I may need something like
u=Function('u')(x)
or
u=Symbol('u', class=Function)
But I have already defined u:
u=Function('u')(r)
I have been unable to get anything to work. If I differentiate u with respect to x, I get zero because (apparently) SymPy sees u as depending on r but not x. I do not understand the Sympy Function class.
This works for built-in functions like cos:
diff(cos(a*x),x)
returns
-a*sin(a*x)
I just want the same behavior for my abstract function u.

Substituting for the independent variable in a differential equation is something that is difficult or not yet properly supported in sympy. You can do this:
In [9]: u = Function('u')
In [10]: r = Symbol('r')
In [11]: u(r)
Out[11]: u(r)
In [12]: u(r).diff(r)
Out[12]:
d
──(u(r))
dr
In [13]: a, x = symbols('a, x')
In [15]: u(r).diff(r).subs(r, a*x)
Out[15]:
⎛d ⎞│
⎜──(u(r))⎟│
⎝dr ⎠│r=a⋅x
Part of the problem is that sympy doesn't have a way to represent u' as the derivative of the single argument function u without differentiating with respect to a symbol.
What is needed is something like dchange from Maple:
https://github.com/sympy/sympy/issues/17590
There are complicated ways to make this work in sympy if needed but those are probably not suitable for a youtube video. I suggest to skip over this section in the video :)
In [1]: u = Function('u')
In [2]: a, r, x = symbols('a, r, x')
In [3]: expr = u(r).diff(r, 2)
In [4]: expr
Out[4]:
2
d
───(u(r))
2
dr
In [5]: expr.subs(u(r).diff(r, 2), 1/a**2 * u(x).diff(x, 2)) # cheating
Out[5]:
2
d
───(u(x))
2
dx
─────────
2
a

Related

Simplify expression with assumptions involving relations between variables in SymPy

Is it possible to simplify an expression in SymPy, if we know that variables satisfy certain equation?
For example in Mathematica we can write something like this:
Simplify[a+b-c, a+b==c]
Of course in this case it is possible to solve for a and make a substitution. However, for the long expressions making a global substitution might not make a sense. If the goal is to produce the shortest expression possible, one might need to apply substitution for the certain terms and leave the rest untouched or solve for b instead of a.
I think sympy.assumptions module cannot impose restrictions mutually on the several variables.
Is it possible to achieve the functionality of Mathematica's Simplify[expr, assum] in any other way in SymPy?
Or is there any other open-source project which can do something like this?
SymPy's current assumptions system can not handle relationships between variables although that is being worked on. There are a couple of ways that you can do this though.
The ratsimpmodprime function simplifies an expression that is polynomial in some symbols based on knowing that the symbols themselves satisfy polynomial equations. We can use this to make a function that simplifies the example you showed:
In [26]: a, b, c = symbols('a:c')
In [27]: polysimp = lambda expr, eqs: ratsimpmodprime(expr, groebner(eqs).exprs)
In [28]: polysimp(a + b - c, [a + b - c])
Out[28]: 0
In [29]: polysimp(a + b, [a + b - c])
Out[29]: c
In [31]: polysimp(a**4 + b - c, [a**2 - b, b - c])
Out[31]:
2
c
You can also introduce a new symbol and solve for that along with the other equations as a combined system:
In [33]: solve([z - (a + b - c), a + b - c])[z]
Out[33]: 0
This method has the advantage that you can choose which symbols you want to eliminate e.g.:
In [38]: solve([z - (a + b), a + b - c], [z, c])[z]
Out[38]: a + b
In [39]: solve([z - (a + b), a + b - c], [z, b])[z]
Out[39]: c
Either answer is valid since a + b == c so the expected output from "simplifying" is ambiguous.

sympy division of multivariate polynomials

Why doesn't sympy divide this polynomial?
>>> import sympy as sp
>>> x,y = sp.symbols("x y")
>>> print(sp.div(y+x,y))
(0, x + y)
I was expecting the answer to be (1,x) because the quotient is 1 and the remainder is x. How can I get sympy to divide polynomials?
What I want is to express some polynomial p as p=aq+r where r is the remainder and q is the quotient and a is the divisor. In the example above, notice that y+x=1*x+y and so it seems to me that we should be able to find that 1 is the quotient of p by x.
some more details
Say I am working over a real multivariate polynomial ring, and say I want to express some polynomial p as p=aq+r for some non zero polynomial a and for some r with deg(r)<deg(q). By degree (deg) I mean total degree, that is, the degree of the single variate polynomial that you get when you substitute all variables with x. For example, the total degree of xy^2 is 3. Although such a pair (q,r) may not exist, if it does exist, it is unique given (p,a). Here is a proof:
Say p=aq+r and p=aq'+r' for some r st. deg(r)<deg(a) and assume q≠q'.
By subtracting these equations and rearranging we have a(q-q')=r'-r.
Notice that because q-q'≠0, we have deg(a)≤deg(a(q-q'))=deg(r-r').
Thus because deg(r)<deg(a), we may conclude that deg(a)≤deg(r').
Thus if there exists such an r, this r is unique.
I point this out so as to suggest that the computation I am asking for is well defined.
It seems to me that being able to do multivariate polynomial division is a natural feature
that sympy should support. If I am wrong here, please let me know why.
See here
Given a family (𝑥𝑖) of symbols, or other suitable objects, including numbers, expressions derived from them by repeated addition, subtraction and multiplication are called polynomial expressions in the generators 𝑥𝑖.
You need to specify the generators. Because given the expression y+x, the machine can NOT figure out which variable is the generator. It can be f(y) = x+y or f(x) = x+y.
You need to tell it the order of generators is [x,y].
print(sp.div(y+x, y,gens=[x,y]))
# (0, x + y)
If you set the order of generators to be [y,x].
print(sp.div(y+x, y,gens=[y,x]))
# (1, x)

Difference between sympy.symbols and sympy.Symbol

What's the difference between these similar-sounding methods?
import sympy
from sympy.physics.units.systems import SI
from sympy.physics.units import meter, second
A = sympy.symbols('A')
type(A)
B = sympy.Symbol('B')
type(B)
SI.set_quantity_scale_factor(A, meter**3/second)
SI.set_quantity_scale_factor(B, meter**3/second)
A and B have the same type, and both are acceptable as inputs to SI.set_quantity_scale_factor. Is this not a glaring violation of "only one way to do it"?
Read the docs, and if needed the code. Symbol is a class. symbols is a function that can create multiple instances of the Symbol class.
In [7]: symbols('A')
Out[7]: A
In [8]: Symbol('A')
Out[8]: A
symbols('A B C') is different from Symbol('A B C').
In [9]: symbols('A B C')
Out[9]: (A, B, C)
In [10]: Symbol('A B C')
Out[10]: A B C
In [11]: type(_10)
Out[11]: sympy.core.symbol.Symbol
Defining a class, and a separate function (or syntax) to create object(s) of that class is fairly common in Python.
np.array makes a object of class np.ndarray. [] makes a list object, {a:b} makes a dict object.

How to tell Sympy that one symbol is "greater than other"

Suppose I have two symbols
x,y=symbols('x y')
My objective is to tell Sympy that x is always greater than y (x>y). Is there any way to achieve this?
There is no way to do this directly. The assumptions module does not support relations, and it's not (yet) integrated with the rest of SymPy anyway, so its assumptions won't help you, say, simplify an integral.
The workaround is to introduce a symbol expressing the difference of two symbols, and declare that to be positive. For example,
y = symbols('y')
p = symbols('p', positive=True)
x = y + p
Now SymPy knows that x > y:
>>> (x > y).simplify()
True
How useful this is in computations that involve x depends on whether doing .subs(x, y + p) will turn it into something that simplifies.
It's often easier to directly replace a condition with True or False, as I did here.

How to rewrite an expression in terms of an other expression in sympy

EDIT: I am not asking how to solve an equation in terms of a given variable (as in this supposed duplicated question), but how to represent an expression in terms of an other one, as specified in the question.
I believe it is the "duplicated" question to have a misleading title.
I am very new with SymPy. I have an expression that, once expressed in terms to an other expression, should become very nice.
The problem is that I don't know how to "force" to express the original expression in terms of the other one.
This is a basic example:
import sympy as sp
sp.init_printing(use_unicode=True)
a,b,c = sp.symbols('a b c')
A = a+b+c
B = a+c
C = A.subs(a+c,B) # Expected/wanted: C = B+b
C
A.rewrite(B)
A and B could be rather complex expressions. For reference, this is my real-case scenario:
import sympy as sp
sp.init_printing(use_unicode=True)
t, w, r = sp.symbols('t w r')
S = sp.Function('S')(t)
V = (S-w*(1+r)**t)/(((1+r)**t)-1)
V
St = -(r + 1)**t*(w - S)*sp.log(r + 1)/((r + 1)**t - 1)
St
Once I write St in terms of V, I should be able to simplify to get just
St = rS(t)+rV
But I am unable to do it in SymPy.
First note that when you do something like
a,b,c = sp.symbols('a b c')
A = a+b+c
B = a+c
variables A, B are not new Sympy symbols that Sympy can understand and operate on, rather, they are aliases for the Sympy expressions a+b+c and a+c, respectively. Therefore, A.subs(a+c,B) is essentially the same as A.subs(a+c,a+c), which is, of course, meaningless. You get the idea of why A.rewrite(B) is also of no use.
I do not think that calls like expr.subs({complicated_mutlivariable_formula: new_variable}) work in Sympy. One way to do what you want is to first solve the equation complicated_mutlivariable_formula = new_variable with respect to one of the "old" variables, and, assuming a unique solution exist, use subs() to substitute this variable.
Applying this approach for the second example:
# sympy Symbol A will be used to represent expression V
A = sp.symbols('A')
# Solve the equation V==A with respect to w, which has a unique solution as a function of A
w_A = sp.solve(sp.Eq(V,A), w)[0]
# Now substitute w
St.subs({w:w_A}).simplify()