How to make user-input for Symbols case insensitive - python

I want to avoid caps lock errors in a scypy base script that I made.
The script calculate partial derivatives
from sympy import *
from sympy.parsing.sympy_parser import parse_expr
from sympy.parsing.sympy_parser import standard_transformations, \
x, y, z = symbols('x y z ', real=True)
transformations = (standard_transformations + (implicit_multiplication_application,)
self.eq1 = parse_expr(self.entry_5.get(), locals(), transformations=transformations)
self.dfx = diff(self.eq1, x)
self.dfy = diff(self.eq1, y)
self.dfz = diff(self.eq1, z)
It work fine for this example entry_5 is x ** 2 + y ** 2 + z ** 2
'Partial derivatives calculation:
Partial der by X: 2*x
Partial der by Y: 2*y
Partial der by Z: 2*z
but now, I'm trying to add capital X,Y,Z with the same code:
.
.
.
x, y, z, X, Y, Z = symbols('x y z X Y Z', real=True)
.
.
.
now, entry_5 is- X ** 2 + y ** 2 + z ** 2 (capital x)
and the output is:
'Partial derivatives calculation:
Partial der by X: 0
Partial der by Y: 2*y
Partial der by Z: 2*z

If you are wanting your input to be recast to lowercase so the derivatives that you hard coded always work you could either convert the input to lower case or, more safely, provide locals that remap the uppercase symbols of interest to lower case symbols. For clarity in the following I use S to sympify rather than the parser:
>>> S('x', {'x':'upper'}) # example showing you can replace 'x' with 'upper'
upper
>>> S('X', dict([(str(i), str(i).lower()) for i in symbols('X:Z')]))
x
In your code you will have to update your locals with the dict() that is being used in my example: loc = locals(); loc.update(dict([(str(i), str(i).lower()) for i in symbols('X:Z')])) and use loc instead of locals() in your code.

Related

Speeding up Sympy solve() on a particular equation

I am trying to solve an equation but the solve() function is taking over 10 minutes even on a high RAM colab notebook. Are there any simplifications to the problem that I can take to speed this along? Here is the code:
x, y, x_0, y_0, x_new, y_new, t, f = symbols('x y x_0 y_0 x_new y_new t f')
D = (2 * (1 - t) * sqrt(x * y) + t * (x + y)) / (2 * (x + y) * sqrt(x * y))
D_old = D.subs([(x, x_0), (y, y_0)])
D_new = D.subs([(x, x_new), (y, y_new)])
delta_D = D_new - D_old
target = Eq(delta_D, f)
answer = solve(target, x_new)
If it is taking a long time you must be trying to solve for one of the x or y values. This will require solving a messy cubic equation in many variables. It would be better if you just substituted in the values of interest and then used nsolve to find the roots of interest. Otherwise, you can get a symbolic solution to the generic cubic g3 = solve(a*x**3 + b*x**2 + c*x + d, x) and then substitute in the corresponding expressions for the coefficients of collect(sympy.solvers.solvers.unrad(target.rewrite(Add))[0], v) where v is the variable of interest. But I won't bog this down with more details until it is clear what you really want to do.

How to substitute variable in multiple equations in Sympy

for example, if I want to use solve a set of linear equations
eq1: x + y + 8z = 2
eq2: 2x + 6y + z = 5
suppose I already know the value of z, is there any way I can subsitute the z in eq1 and eq2 in one operation such as
linear_equations([eq1, eq2]).subs({z: 100})
You can use the Sympy library to achieve what exactly you are looking to solve.
Below is the code which will perform the substitution of the Z value and then solve the linear equation to find the values of x & Y values
from sympy import symbols
from sympy.solvers import solve
x,y,z = symbols('x y z')
expression1 = x + y + 8*z - 2
expression2 = 2*x + 6*y + z - 5
expression1 = expression1.subs(z,100)
expression2 = expression2.subs(z,100)
solution = solve([expression1, expression2], [x, y])
print(solution)

Simplify in sympy with custom symbols

Suppose that I have sympy variables x, y and z
I have the expression (x + y) (x + y) + x
Is it possible that I am able to define z as x + y so that I can "simplify" the expression above to z^2 + x?
That is, I want to use z wherever I can in the simplified expression.
Yes, use subs as in
>>> var('x:z')
(x, y, z)
>>> ((x + y)*(x + y) + x).subs(x+y,z)
x + z**2
The subs routine will sometimes try to be smart about substitutions, but works best when the substitution target is a symbol (and hence unambiguous). So if you want to try the replacement x+y->z in a more ambiguous expression, try replacing x->z-y, simplify, and then resubstitute z-y->x to restore anything that didn't change:
>>> ((x*x + 2 * x * y + y * y) + x).subs(x,z-y).expand().subs(z-y,x)
x + z**2

How to find the difference of x -y using sympy

As you see in the code, I want to find the difference of x-y using the resulting R of solve. But, the code keeps returning x-y as value. Please help me. I am a 10 year old kid that just started coding.
import sympy as sp
x, y = sp.symbols ('x, y')
eq1 = sp.Eq(7 * x, 12 * y)
eq2 = sp.Eq(x+y, 9500)
R = sp.solve ((eq1, eq2), (x, y))
print (x-y)
The result R of sp.solve is a Python dictionary with values for x and for y:
import sympy as sp
x, y = sp.symbols('x, y')
eq1 = sp.Eq(7 * x, 12 * y)
eq2 = sp.Eq(x + y, 9500)
R = sp.solve((eq1, eq2), (x, y))
Result: {x: 6000, y: 3500}
To apply the resulting dictionary to an expression, use subs(R):
print((x - y).subs(R))
Result: 2500

In Sympy, how do I define a generic function like f(x), such that sympy.diff(f(x), x) returns f' rather than 0.

I am trying to take derivatives of this function
x, y, z, P, k, q = sp.symbols('x y z P k q')
expr = sp.exp(-sp.I*(P+k/(2*q)*(x**2 + y**2)))
where P and q are functions of z. How can I define P and q such that sp.diff(P, z) returns P' rather than 0?
From what you wrote, sympy can't know P and q are functions of z, can it? So it's treating them as constants - just like all the other variables except z. Your expression does not mention z at all, so it is all a constant expression - and the derivation of a constant is 0, no exceptions.
Make sure sympy knows P and q are functions of z. And obviously, it matters what those functions are - you can't just leave them blank. A square differentiates differently than a square root. If you don't know, sympy will do the best it can:
x, y, z, k = sp.symbols('x y z k')
P = sp.Function('P')
q = sp.Function('q')
expr = sp.exp(-sp.I*(P(z)+k/(2*q(z))*(x**2 + y**2)))
sp.diff(expr, z)
# => -I*(-k*(x**2 + y**2)*Derivative(q(z), z)/(2*q(z)**2) + Derivative(P(z), z))*
# exp(-I*(k*(x**2 + y**2)/(2*q(z)) + P(z)))
but if you do know, it can calculate it exactly:
x, y, z, k = sp.symbols('x y z k')
P = sp.Lambda(z, z * z)
q = sp.Lambda(z, sp.sqrt(z))
expr = sp.exp(-sp.I*(P(z)+k/(2*q(z))*(x**2 + y**2)))
sp.diff(expr, z)
# => -I*(-k*(x**2 + y**2)/(4*z**(3/2)) + 2*z)*
# exp(-I*(k*(x**2 + y**2)/(2*sqrt(z)) + z**2))
Similarly, I don't think you can differentiate P, but this works:
sp.diff(P(z), z)
# => 2*z
You can use idiff to get a fragile result with unevaluated derivatives: dPdz = idiff(expr, (P, q), z). It is fragile in the sense that dPdz.doit() will give 0 because there is no explicit dependence on z for q.
>>> idiff(expr,(P,q),z)
k*(x**2 + y**2)*Derivative(q, z)/(2*q**2)
>>> _.doit()
0

Categories