Difference between sympy.symbols and sympy.Symbol - sympy

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.

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.

Modify an expression involving derivatives of functions by changing variables

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

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()

write reverse in scala, using foldleft

here's an implementation:
def reverse[A](l: List[A]): List[A] = foldLeft(l, List[A]())((acc,h) => Cons(h,acc))
I don't understand what is inderstood by the compiler with (acc,h); initially, the f function meets (ListA,l), which are 2 lists, so is Cons working with 2 lists also?
thanks
Cons works with one list and one element, just as the function passed to foldLeft does.
The declaration of foldLeft on List[A] is:
def foldLeft[B](z: B)(f: (B, A) ⇒ B): B
So we can write your impl as:
l.foldLeft(List[A]())((acc, h) => ...)
and we can see that the type B is List[A], so the two arguments to our f are acc (of type List[A]) and h (of type A).