How to express a system of equations in terms of another variable - python

I want to solve a system of equations symbolically such as A = ax + by and B = cx + dy, for x and y explicitly on sympy.
I tried the solve function of sympy as
solve([A, B], [x, y]), but isn't working. It's returning an empty list, [].
How can I solve it using sympy?
This is the actual equation I'm trying to solve:
from sympy import*
i,j,phi, p, e_phi, e_rho = symbols(r'\hat{i} \hat{j} \phi \rho e_\phi e_\rho')
e_rho = cos(phi)*i + sin(phi)*j
e_phi = -p*sin(phi)*i + p*cos(phi)*j
solve([e_rho,e_phi], [i,j])

I don't know what version of SymPy you're using but I just tried with the latest version and I get an answer:
In [4]: from sympy import*
...: i,j,phi, p, e_phi, e_rho = symbols(r'i j phi rho e_phi e_rho')
...: e_rho = cos(phi)*i + sin(phi)*j
...: e_phi = -p*sin(phi)*i + p*cos(phi)*j
...: solve([e_rho,e_phi], [i,j])
Out[4]: {i: 0, j: 0}
That's the correct answer to your equations (provided rho is nonzero):
In [5]: e_rho
Out[5]: i⋅cos(φ) + j⋅sin(φ)
In [6]: e_phi
Out[6]: -i⋅ρ⋅sin(φ) + j⋅ρ⋅cos(φ)
If you meant to solve for e_rho and e_phi to be equal to something other than zero then you should include a right hand side either by subtracting it from the expressions or by using Eq:
In [2]: A, B = symbols('A, B')
In [3]: solve([Eq(e_rho, A), Eq(e_phi, B)], [i, j])
Out[3]:
⎧ A⋅ρ⋅cos(φ) B⋅sin(φ) A⋅ρ⋅sin(φ) B⋅cos(φ) ⎫
⎪i: ───────────────────── - ─────────────────────, j: ───────────────────── + ─────────────────────⎪
⎨ 2 2 2 2 2 2 2 2 ⎬
⎪ ρ⋅sin (φ) + ρ⋅cos (φ) ρ⋅sin (φ) + ρ⋅cos (φ) ρ⋅sin (φ) + ρ⋅cos (φ) ρ⋅sin (φ) + ρ⋅cos (φ)⎪
⎩ ⎭
In [4]: solve([Eq(e_rho, A), Eq(e_phi, B)], [i, j], simplify=True)
Out[4]:
⎧ B⋅sin(φ) B⋅cos(φ)⎫
⎨i: A⋅cos(φ) - ────────, j: A⋅sin(φ) + ────────⎬
⎩ ρ ρ ⎭
Again that's the correct answer (assuming rho != 0).

Related

Why won't SymPy directly solve for the normalization of this wavefunction?

Here is some minimal code demonstrating the problem.
from sympy import *
x = Symbol('x', real=True)
t = Symbol('t', real=True)
A = Symbol('A', real=True, positive=True)
λ = Symbol('λ', real=True, positive=True)
ω = Symbol('ω', real=True, positive=True)
# Define wavefunction
psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
# Normalize
print(solve(integrate(psi_x_t**2, (x, -oo, oo)) - 1))
print(solve(integrate(psi_x_t**2, (x, -oo, oo)) - 1, A))
Where I simply call solve it returns [{t: 0, λ: A**2}]. What I am looking for is actually A=sqrt(λ). But when I include A as the symbol I am solving for I don't get a plus/minus sqrt(λ) but rather an empty collection [].
Why is solve giving me an empty list of solutions, and is there a way to make it directly return the solution for A?
You are not getting a solution because you have declared assumptions on your variables and those assumptions are inconsistent with the solution. Let's try without those assumptions:
In [20]: from sympy import *
...:
...: x = Symbol('x')
...: t = Symbol('t')
...: A = Symbol('A')
...: λ = Symbol('λ')
...: ω = Symbol('ω')
...:
...: # Define wavefunction
...: psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
In [21]: psi_x_t
Out[21]:
-λ⋅│x│ -ⅈ⋅t⋅ω
A⋅ℯ ⋅ℯ
In [22]: eq = integrate(psi_x_t**2, (x, -oo, oo)) - 1
In [23]: eq
Out[23]:
⎛⎧ 2 -2⋅ⅈ⋅t⋅ω ⎞
⎜⎪ A ⋅ℯ π⎟
⎜⎪ ──────────── for │arg(λ)│ < ─⎟
⎜⎪ λ 2⎟
⎜⎪ ⎟
⎜⎨∞ ⎟ - 1
⎜⎪⌠ ⎟
⎜⎪⎮ 2 -2⋅λ⋅│x│ -2⋅ⅈ⋅t⋅ω ⎟
⎜⎪⎮ A ⋅ℯ ⋅ℯ dx otherwise ⎟
⎜⎪⌡ ⎟
⎝⎩-∞ ⎠
I'm guessing that this Piecewise is the reason that you set those assumptions. Let's just manually select the first case of the Piecewise and work from there:
In [26]: eq1 = piecewise_fold(eq).args[0][0]
In [27]: eq1
Out[27]:
2 -2⋅ⅈ⋅t⋅ω
A ⋅ℯ
──────────── - 1
λ
Now we solve this:
In [28]: solve([eq1], [A])
Out[28]:
⎡⎛ ⅈ⋅t⋅ω ⎞ ⎛ ⅈ⋅t⋅ω ⎞⎤
⎣⎝-√λ⋅ℯ ,⎠, ⎝√λ⋅ℯ ,⎠⎦
Now for almost all possible values of omega this is not going to be real which is a violation of the assumptions you stated that A should be positive.
Presumably the equation you actually wanted comes from integrating abs(psi)^2:
In [34]: from sympy import *
...:
...: x = Symbol('x', real=True)
...: t = Symbol('t', real=True)
...: A = Symbol('A', real=True, positive=True)
...: λ = Symbol('λ', real=True, positive=True)
...: ω = Symbol('ω', real=True, positive=True)
...:
...: # Define wavefunction
...: psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
In [35]: eq = integrate(abs(psi_x_t)**2, (x, -oo, oo)) - 1
In [36]: eq
Out[36]:
2
A
── - 1
λ
In [37]: solve([eq], [A])
Out[37]: [(√λ,)]
Here only the positive root is returned because we assumed A to be positive.
Why is solve giving me an empty list of solutions, and is there a way to make it directly return the solution for A?
I can't answer this question. However, when solve fails I usually give a try to solveset:
print(solveset(integrate(psi_x_t**2, (x, -oo, oo)) - 1, A))
# {-sqrt(λ)*exp(I*t*ω), sqrt(λ)*exp(I*t*ω)}
It did not solve for A as expected because it doesn't choose some time in which to solve for it. If we first set time, such as t=0, then it will find a suitable solution.
from sympy import *
x = Symbol('x', real=True)
t = Symbol('t', real=True)
A = Symbol('A', real=True, positive=True)
λ = Symbol('λ', real=True, positive=True)
ω = Symbol('ω', real=True, positive=True)
# Define wavefunction
psi_x_t = A * exp(-λ *Abs(x)) * exp(-I*ω*t)
# Intergrate
result = integrate(psi_x_t**2, (x, -oo, oo)) - 1
result = result.subs(t, 0)
# Normalize
print(solve(result))
print(solve(result, A))

how to solve a system of differential ecuations and a linear equation in Python

I tried to solve this equation system that are two ordinary differential equations and a linear equation
dx(t)/dt = (-x(t) + u(t)) / 2.0,
dy(t)/dt = (-y(t) + x(t)) / 5.0
u(t) = x(t) + 3*y(t)
With this initial conditions x(0) = 0, y(0) = 0 and u(0)=1. I have been trying to solve the system using odeint but I don't know hoy to define the linear function, this is, the function u. I don't know if it is another way to solve this system.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def f(z,t,u):
dzdt = np.zeros(2,)
x = z[0]
y = z[1]
dzdt[0] = (-x + u) / 2.0
dzdt[1] = (-y + x) / 5.0
return dzdt
z0 = [0,0]
n = 150
t = np.linspace(0,15, n)
u = np.zeros(n)
u[0] = 1
x = np.zeros(n)
y = np.zeros(n)
for i in range (1,n):
tspan = [t[i-1],t[i]]
z = odeint(f,z0,t,args=(u[i],))
u[i] = x[i] + 3*y[i]
z0 = z[1]
x[i] = z0[0]
y[i] = z0[1]
plt.plot(t,u)
plt.plot(t,x)
plt.plot(t,y)
plt.show()
You can just substitute u into the other equations. Also these particular ODEs can be solved symbolically using SymPy:
In [34]: x, y, u = symbols('x, y, u', cls=Function)
In [35]: t = symbols('t')
In [36]: eqs = [Eq(x(t).diff(t), (-x(t) + u(t)) / 2.0),
...: Eq(y(t).diff(t), (-y(t) + x(t)) / 5.0),
...: Eq(u(t), x(t) + 3*y(t))]
In [37]: eqs[2]
Out[37]: u(t) = x(t) + 3⋅y(t)
In [38]: eqs_new = [eq.subs(eqs[2].lhs, eqs[2].rhs) for eq in eqs[:2]]
In [39]: eqs_new
Out[39]:
⎡d d ⎤
⎢──(x(t)) = 1.5⋅y(t), ──(y(t)) = 0.2⋅x(t) - 0.2⋅y(t)⎥
⎣dt dt ⎦
In [41]: dsolve(eqs_new)[0]
Out[41]:
-0.656776436283002⋅t 0.456776436283002⋅t
x(t) = - 2.28388218141501⋅C₁⋅ℯ + 3.28388218141501⋅C₂⋅ℯ
In [42]: dsolve(eqs_new)[1]
Out[42]:
-0.656776436283002⋅t 0.456776436283002⋅t
y(t) = 1.0⋅C₁⋅ℯ + 1.0⋅C₂⋅ℯ

No converging solution with sympy.nonlinsolve() in Python

I'm trying to solve a system with three nonlinear equations in Python 3.8. I'm using the function sympy.nonlinsolve(). However, I received the error message "convergence to root failed; try n < 15 or maxsteps > 50".
This is my code:
import sympy as sp
x_1 = 0.0
z_1 = 1.0
x_2 = 15.81
z_2 = 0.99
x_3 = 23.8
z_3 = 0.98
r, x_m, z_m = sp.symbols('r, x_m, z_m', real=True)
Eq_1 = sp.Eq((x_1 - x_m) ** 2 + (z_1 - z_m) ** 2 - r ** 2, 0)
Eq_2 = sp.Eq((x_2 - x_m) ** 2 + (z_2 - z_m) ** 2 - r ** 2, 0)
Eq_3 = sp.Eq((x_3 - x_m) ** 2 + (z_3 - z_m) ** 2 - r ** 2, 0)
ans = sp.nonlinsolve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])
I would welcome every help. Thanks in advance.
I get an answer from solve:
In [56]: sp.solve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])
Out[56]:
[(-5.71609538434502e+18, -4.80343980343979e+15, -5.71609336609336e+18), (-19222.9235141152, -4.2537
0843989772, -19221.9230434783), (19222.9235141152, -4.25370843989772, -19221.9230434783), (5.716095
38434502e+18, -4.80343980343979e+15, -5.71609336609336e+18)]
I'm not sure why nonlinsolve works but from the large numbers in the answer I guess that this isn't well conditioned.
If you use exact rational numbers then you can get the same solution from both solve and nonlinsolve:
In [59]: import sympy as sp
...:
...: x_1 = 0
...: z_1 = 1
...: x_2 = sp.Rational('15.81')
...: z_2 = sp.Rational('0.99')
...: x_3 = sp.Rational('23.8')
...: z_3 = sp.Rational('0.98')
...:
...: r, x_m, z_m = sp.symbols('r, x_m, z_m', real=True)
...: Eq_1 = sp.Eq((x_1 - x_m) ** 2 + (z_1 - z_m) ** 2 - r ** 2, 0)
...: Eq_2 = sp.Eq((x_2 - x_m) ** 2 + (z_2 - z_m) ** 2 - r ** 2, 0)
...: Eq_3 = sp.Eq((x_3 - x_m) ** 2 + (z_3 - z_m) ** 2 - r ** 2, 0)
...: ans = sp.solve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])
In [60]: ans
Out[60]:
⎡⎛-√564927076558939081 -8316 -44210423 ⎞ ⎛√564927076558939081 -8316 -44210423 ⎞⎤
⎢⎜─────────────────────, ──────, ──────────⎟, ⎜───────────────────, ──────, ──────────⎟⎥
⎣⎝ 39100 1955 2300 ⎠ ⎝ 39100 1955 2300 ⎠⎦
This is another of those cases where it is good to emphasize the A of CAS and let it help you as you work through the problem by hand:
_ solve first equation for r**2
>>> from sympy import solve
>>> r2 = solve(Eq_1, r**2)
_ substitute into the other two equations and expand them
>>> eqs = [i.subs(r**2, r2[0]).expand() for i in (Eq_2, Eq_3)]
_ see what you've get
>>> eqs
[Eq(-31.62*x_m + 0.02*z_m + 249.9362, 0), Eq(-47.6*x_m + 0.04*z_m + 566.4004, 0)]
_ That's two linear equations. Solve with solve -- nonlinsolve is not needed
>>> xz = solve(eqs); xz
{x_m: -4.25370843989770, z_m: -19221.9230434783}
_ substitute into r2 and set equal to r**2 and solve for r
>>> ris = solve(Eq(r**2, r2[0].subs(xz))); ris
[-19222.9235141152, 19222.9235141152]
_ collect the solutions
soln = []
>>> for i in ris:
... xz[r] = i
... soln.append(xz)
...
>>> soln
[{x_m: -4.25370843989770, z_m: -19221.9230434783, r: -19222.9235141152},
{x_m: -4.25370843989770, z_m: -19221.9230434783, r: 19222.9235141152}]
[print out has been edited for viewing pleasure]
When solving nonlinear systems, try reduce the number of systems that you have to deal with. Eliminate linear variables for sure -- other (r**2 in this case) if possible -- before trying to solve the nonlinear parts.
The very large numbers obtained when solving all 3 at once might be a reflection of the ill-posed nature of the system ("not well conditioned" as Oscar noted. Perhaps the problem was designed to teach that point.

Sympy differentiation, equation is in numpy array?

I have a function that is updated -- I'm optimizing using the method of newton and steepest.
I'm new to sympy, and hoping to get some quick clarification.
x1,x2 = sym.symbols('x1 x2')
y = 2*x1 + 3*x2**2 + sym.exp(2*x1**2 + x2**2)
gy1 = sym.diff(y,x1)
gy2 = sym.diff(y,x2)
grad1 = sym.lambdify([x1,x2],gy1)(x[0],x[1])
grad2 = sym.lambdify([x1,x2],gy2)(x[0],x[1])
d = np.array([-1*grad1,-1*grad2])
l = sym.symbols('l')
theta = 2*(x[0]+l*d[0]) + 3*(x[1]+l*d[1])**2 + sym.exp(2*(x[0]+l*d[0])**2 + (x[1]+l*d[1])**2)
theta_p = sym.diff(theta,l)
my function, y is updated as follow: f(x_n) --> f(x_n + lambda*d_n) -- call this theta(lambda)
I've updated as above ('theta' function), and when printed to screen, it gives a numpy array:
array([-63.1124487914452*l + 2 + exp([1991.5905962264*(0.0316894691665188 - l)**2])],
dtype=object)
That is the equation I need, but now I want to differentiate it with respect to l, my lambda. But sympy doesn't work like this.
When I run
sym.diff(theta,l)
I get this output:
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coeff_Mul'
Any ideas?
Try sym.diff(theta[0], l) and sym.diff(theta[1], l)
For some reason you end up with a ndarray containing objects that are sympy expressions. Print the type of each element to confirm.
Oh, there are nested ndarray expressions. You need to review what you are passing to theta.
You should end up with:
-63.1124487914452*l + 2 + exp(1991.5905962264*(0.0316894691665188 - l)**2)
instead of
array([-63.1124487914452*l + 2 + exp([1991.5905962264*(0.0316894691665188 - l)**2])],
dtype=object)
Replace x[0] and x[1] with symbols in theta, then diff, lambdify and evaluate with x[0] and x[1]
If xx (your unspecified x) is (2,1) array:
In [153]: xx = np.array([[1],[1]])
In [154]: grad1 = sym.lambdify([x1,x2],gy1)(xx[0],xx[1])
...: grad2 = sym.lambdify([x1,x2],gy2)(xx[0],xx[1])
...: d = np.array([-1*grad1,-1*grad2])
In [155]: d
Out[155]:
array([[-82.34214769],
[-46.17107385]])
In [156]: theta = 2*(xx[0]+l*d[0]) + 3*(xx[1]+l*d[1])**2 + sym.exp(2*(xx[0]+l*d[0])**2 + (xx[1]+l*d[1])
...: **2)
In [157]: theta
Out[157]:
array([-164.684295385501*l + 6395.30418038233*(0.0216585822397654 - l)**2 + 2 + exp([13560.4585733095*(0.0121444488396316 - l)**2 + 2131.76806012744*(0.0216585822397654 - l)**2])],
dtype=object)
If instead it is (2,) or a simple list
In [158]: xx = np.array([1,1]) # [1,1]
...
In [160]: d
Out[160]: array([-82.34214769, -46.17107385])
and theta is then a simple sympy expression, not an object array containing an expression. Then theta_p evaluates fine.
We can evaluate gy1 at specific x1,x2 with evalf instead of lambdify:
In [174]: xsub = {x1:1, x2:1}
In [175]: d = [-1*gy1.evalf(subs=xsub), -1*gy2.evalf(subs=xsub)]
In [176]: d
Out[176]: [-82.3421476927507, -46.1710738463753]

Harder equations (with Derivatives and Integrals) and ConditionSet in SymPy

I am planning to calculate b (Its also x on Xo axis) for which curve (function) length from 0 to x is equal 1.
By knowing: https://www.mathsisfun.com/calculus/arc-length.html
(integral from 0 to b) ∫ (1 + ((f’(x))^2)^(1/2) dx = 1
and that:
(integral from a to b) ∫ f(x)dx = F(b) - F(a)
We can calculate it by
1 - F(0) + F(b) = 0 , where this is now an Equation in terms of x, beacuse b as I said is x on Xo axis.
So now I tried it for f(x) = x**3 (full code will be below)
F(b) is equal to this monster: https://www.wolframalpha.com/input/?i=integral&assumption=%7B%22C%22%2C+%22integral%22%7D+-%3E+%7B%22Calculator%22%7D&assumption=%7B%22F%22%2C+%22Integral%22%2C+%22integrand%22%7D+-%3E%22%281+%2B+9x%5E4%29%5E%281%2F2%29%22
All I get from SymPy is ConditionSet but not number. Of course ConditionSet cannot be evauluated by evalf()
So here are my questions:
Did I make a mistake in math?
Is my code wrong and how to improve it?
Is SymPy enough to calculate this?
Did I misunderstand documentation?
Code:
from __future__ import division
import matplotlib.pyplot as plt
from sympy import *
x, y, z = symbols('x y z', real=True)
function1 = x**3
Antiderivative1 = integrate((1+(diff(function1))**2)**(1/2), x)
b = solveset(Eq(1 + Antiderivative1.subs(x, 0).evalf() - Antiderivative1, 0), x)
print(b)
Thats the output:
ConditionSet(x, Eq(x*hyper((-0.5, 1/4), (5/4,), 9*x**4*exp_polar(I*pi)) - 4.0*gamma(5/4)/gamma(1/4), 0), Complexes)
Thanks in advance and sorry for mistakes in grammar.
Note that you should use S(1)/2 or Rational(1, 2) (or sqrt) rather than 1/2 which will give you a float in Python. With that we have
In [16]: integrand = sqrt(1 + ((x**3).diff(x))**2)
In [17]: integrand
Out[17]:
__________
╱ 4
╲╱ 9⋅x + 1
In [18]: antiderivative = integrand.integrate(x)
In [19]: antiderivative
Out[19]:
┌─ ⎛-1/2, 1/4 │ 4 ⅈ⋅π⎞
x⋅Γ(1/4)⋅ ├─ ⎜ │ 9⋅x ⋅ℯ ⎟
2╵ 1 ⎝ 5/4 │ ⎠
─────────────────────────────────────
4⋅Γ(5/4)
While that isn't the same form as the result from Wolfram Alpha it could easily be the same function (up to an additive constant). From this result or the one on Wolfram Alpha I very much doubt that you will find an analytic solution (using SymPy or anything else).
You can however find a numerical solution. Unfortunately there is a bug in SymPy's lambdify function that means nsolve doesn't work with this function:
In [22]: nsolve(equation, x, 1)
...
NameError: name 'exp_polar' is not defined
We can do it ourselves with Newton steps though:
In [76]: f = equation.lhs
In [77]: fd = f.diff(x)
In [78]: newton = lambda xi: (xi - f.subs(x, xi)/fd.subs(x, xi)).evalf()
In [79]: xj = 1.0
In [80]: xj = newton(xj); print(xj)
0.826749667942050
In [81]: xj = newton(xj); print(xj)
0.791950624620750
In [82]: xj = newton(xj); print(xj)
0.790708415511451
In [83]: xj = newton(xj); print(xj)
0.790706893629886
In [84]: xj = newton(xj); print(xj)
0.790706893627605
In [85]: xj = newton(xj); print(xj)
0.790706893627605

Categories

Resources