I am trying to solve expression in SymPy.
x,c,m=symbols('x,c,m')
y = x**4 + sym.Rational(11/4)*(c/m)*(x**2)+(sym.Rational(3/2)*(c/m)**2)
solve(y,x)
Is there a way in Sympy where sqrt(-1) will automatically get formatted as i in the output expression instead of containing as -1 in the square root?
The equation results in [-sqrt(2)*sqrt(-c/m), sqrt(2)*sqrt(-c/m), -sqrt(3)*sqrt(-c/m)/2, sqrt(3)*sqrt(-c/m)/2]. Without any hints, all variable can be complex, and c/m could be a positive real. There isn't a reason to bring I out of the square root. (Note that sympy represents I with a capital.)
If, however, c and m are declared as real and positive, the output changes:
import sympy as sym
c, m = sym.symbols('c,m', real=True, positive=True)
x = sym.symbols('x')
y = x ** 4 + sym.Rational(11 / 4) * (c / m) * (x ** 2) + (sym.Rational(3 / 2) * (c / m) ** 2)
sym.solve(y, x)
Result:
[-sqrt(2)*I*sqrt(c)/sqrt(m),
sqrt(2)*I*sqrt(c)/sqrt(m),
-sqrt(3)*I*sqrt(c)/(2*sqrt(m)),
sqrt(3)*I*sqrt(c)/(2*sqrt(m))]
Related
I have one exponential equation with two unknowns, say:
y*exp(ix) = sqrt(2) + i * sqrt(2)
Manually, I can transform it to system of trigonometric equations:
y * cos x = sqrt(2)
y * sin x = sqrt(2)
How can I do it automatically in sympy?
I tried this:
from sympy import *
x = Symbol('x', real=True)
y = Symbol('y', real=True)
eq = Eq(y * cos(I * x), sqrt(2) + I * sqrt(2))
print([e.trigsimp() for e in eq.as_real_imag()])
but only got two identical equations except one had "re" before it and another one "im".
You can call the method .rewrite(sin) or .rewrite(cos) to obtain the desired form of your equation. Unfortunately, as_real_imag cannot be called on an Equation directly but you could do something like this:
from sympy import *
def eq_as_real_imag(eq):
lhs_ri = eq.lhs.as_real_imag()
rhs_ri = eq.rhs.as_real_imag()
return Eq(lhs_ri[0], rhs_ri[0]), Eq(lhs_ri[1], rhs_ri[1])
x = Symbol('x', real=True)
y = Symbol('y', real=True)
original_eq = Eq(y*exp(I*x), sqrt(2) + I*sqrt(2))
trig_eq = original_eq.rewrite(sin) # Eq(y*(I*sin(x) + cos(x)), sqrt(2) + sqrt(2)*I)
eq_real, eq_imag = eq_as_real_imag(trig_eq)
print(eq_real) # Eq(y*cos(x), sqrt(2))
print(eq_imag) # Eq(y*sin(x), sqrt(2))
(You might also have more luck just working with expressions (implicitly understood to be 0) instead of an Equation e.g. eq.lhs - eq.rhs in order to call the method as_real_imag directly)
I have a polynomial: eps * x3 - x2 + 2 + 3 * x * eps-2.
How can I get a list of all coefficients including negative?
I have tried coeffs() and all_coeffs() methods but they do not work with negative powers of epsilon:
import sympy as sp
x, eps = sp.symbols('x E')
expr = eps * x**3 - x**2 + 2 + 3 * x * eps**(-2)
coeffs_list = sp.Poly(expr, eps).coeffs()
I want to get list of coefficients like [x^3, x^2 + 2, 3*x]
If you are not sure what the negative power of eps is you can find the coefficients of the expression when put over a common denominator:
>>> n, d expr.as_numer_denom()
>>> Poly(n, eps).coeffs()
[x**3, 2 - x**2, 3*x]
Multiplying with a large power of eps helps to get the coeffients.
import sympy as sp
x, eps = sp.symbols('x E')
expr = eps * x**3 - x**2 + 2 + 3 * x * eps**(-2)
coeffs_list = sp.Poly(expr*eps**2, eps).coeffs()
gives
[x**3, 2 - x**2, 3*x]
Now I face some problem when I use scipy.integrate.ode.
I want to use spectral method (fourier transform) solve a PDE including dispersive and convection term, such as
du/dt = A * d^3 u / dx^3 + C * du/dx
Then from fourier transform this PDE will convert to a set of ODEs in complex space (uk is complex vector)
duk/dt = (A * coeff^3 + C * coeff) * uk
coeff = (2 * pi * i * k) / L
k is wavenumber, (e.g.. k = 0, 1, 2, 3, -4, -3, -2, -1)
i^2 = -1,
L is length of domain.
When I use r = ode(uODE).set_integrator('zvode', method='adams'), python will warn like:
c ZVODE-- At current T (=R1), MXSTEP (=I1) steps
taken on this call before reaching TOUT
In above message, I1 = 500
In above message, R1 = 0.2191432098050D+00
I feel it is because the time step I chosen is too large, however I cannot decrease time step as every step is time consuming for my real problem. Do I have any other way to resolve this problem?
Did you consider solving the ODEs symbolically? With Sympy you can type
import sympy as sy
sy.init_printing() # use IPython for better results
from sympy.abc import A, C, c, x, t # variables
u = sy.Function(b'u')(x,t)
eq = sy.Eq(u.diff(t), c*u)
sl1 = sy.pde.pdsolve(eq, u)
print("The solution of:")
sy.pprint(eq)
print("was determined to be:")
sy.pprint(sl1)
print("")
print("Substituting the coefficient:")
k,L = sy.symbols("k L", real=True)
coeff = (2 * sy.pi * sy.I * k) / L
cc = (A * coeff**3 + C * coeff)
sl2 = sy.simplify(sl1.replace(c, cc))
sy.pprint(sl2)
gives the following output:
The solution of:
∂
──(u(x, t)) = c⋅u(x, t)
∂t
was determined to be:
c⋅t
u(x, t) = F(x)⋅ℯ
Substituting the coefficient:
⎛ 2 2 2⎞
-2⋅ⅈ⋅π⋅k⋅t⋅⎝4⋅π ⋅A⋅k - C⋅L ⎠
──────────────────────────────
3
L
u(x, t) = F(x)⋅ℯ
Note that F(x) depends on your initial values of u(x,t=0), which you need to provide.
Use sl2.rhs.evalf() to substitute in numbers.
I am using Python 2 and the fairly simple method given in Wikipedia's article "Cubic function". This could also be a problem with the cube root function I have to define in order to create the function mentioned in the title.
# Cube root and cubic equation solver
#
# Copyright (c) 2013 user2330618
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://www.mozilla.org/MPL/2.0/.
from __future__ import division
import cmath
from cmath import log, sqrt
def cbrt(x):
"""Computes the cube root of a number."""
if x.imag != 0:
return cmath.exp(log(x) / 3)
else:
if x < 0:
d = (-x) ** (1 / 3)
return -d
elif x >= 0:
return x ** (1 / 3)
def cubic(a, b, c, d):
"""Returns the real roots to cubic equations in expanded form."""
# Define the discriminants
D = (18 * a * b * c * d) - (4 * (b ** 3) * d) + ((b ** 2) * (c ** 2)) - \
(4 * a * (c ** 3)) - (27 * (a ** 2) * d ** 2)
D0 = (b ** 2) - (3 * a * c)
i = 1j # Because I prefer i over j
# Test for some special cases
if D == 0 and D0 == 0:
return -(b / (3 * a))
elif D == 0 and D0 != 0:
return [((b * c) - (9 * a * d)) / (-2 * D0), ((b ** 3) - (4 * a * b * c)
+ (9 * (a ** 2) * d)) / (-a * D0)]
else:
D1 = (2 * (b ** 3)) - (9 * a * b * c) + (27 * (a ** 2) * d)
# More special cases
if D != 0 and D0 == 0 and D1 < 0:
C = cbrt((D1 - sqrt((D1 ** 2) - (4 * (D0 ** 3)))) / 2)
else:
C = cbrt((D1 + sqrt((D1 ** 2) - (4 * (D0 ** 3)))) / 2)
u_2 = (-1 + (i * sqrt(3))) / 2
u_3 = (-1 - (i * sqrt(3))) / 2
x_1 = (-(b + C + (D0 / C))) / (3 * a)
x_2 = (-(b + (u_2 * C) + (D0 / (u_2 * C)))) / (3 * a)
x_3 = (-(b + (u_3 * C) + (D0 / (u_3 * C)))) / (3 * a)
if D > 0:
return [x_1, x_2, x_3]
else:
return x_1
I've found that this function is capable of solving some simple cubic equations:
print cubic(1, 3, 3, 1)
-1.0
And a while ago I had gotten it to a point where it could solve equations with two roots. I've just done a rewrite and now it's gone haywire. For example, these coefficients are the expanded form of (2x - 4)(x + 4)(x + 2) and it should return [4.0, -4.0, -2.0] or something similar:
print cubic(2, 8, -8, -32)
[(-4+1.4802973661668753e-16j), (2+2.9605947323337506e-16j), (-2.0000000000000004-1.1842378929335002e-15j)]
Is this more a mathematical or a programming mistake I'm making?
Update: Thank you, everyone, for your answers, but there are more problems with this function than I've iterated so far. For example, I often get an error relating to the cube root function:
print cubic(1, 2, 3, 4) # Correct solution: about -1.65
...
if x > 0:
TypeError: no ordering relation is defined for complex numbers
print cubic(1, -3, -3, -1) # Correct solution: about 3.8473
if x > 0:
TypeError: no ordering relation is defined for complex numbers
Wolfram Alpha confirms that the roots to your last cubic are indeed
(-4, -2, 2)
and not as you say
... it should return [4.0, -4.0, -2.0]
Not withstanding that (I presume) typo, your program gives
[(-4+1.4802973661668753e-16j), (2+2.9605947323337506e-16j), (-2.0000000000000004-1.1842378929335002e-15j)]
Which to accuracy of 10**(-15) are the exact same roots as the correct solution. The tiny imaginary part is probably due, as others have said, to rounding.
Note that you'll have to use exact arithmetic to always correctly cancel if you are using a solution like Cardano's. This one of the reasons why programs like MAPLE or Mathematica exist, there is often a disconnect from the formula to the implementation.
To get only the real portion of a number in pure python you call .real. Example:
a = 3.0+4.0j
print a.real
>> 3.0
Hooked's answer is the way to go if you want to do this numerically. You can also do it symbolically using sympy:
>>> from sympy import roots
>>> roots('2*x**3 + 8*x**2 - 8*x - 32')
{2: 1, -4: 1, -2: 1}
This gives you the roots and their multiplicity.
You are using integer values - which are not automatically converted to floats by Python.
The more generic solution will be to write coefficients in the function as float numbers - 18.0 instead of 18, etc. That will do the trick
An illustration - from the code:
>>> 2**(1/3)
1
>>> 2**(1/3.)
1.2599210498948732
>>>
I have the following set of equations, and I want to solve them simultaneously for X and Y. I've been advised that I could use numpy to solve these as a system of linear equations. Is that the best option, or is there a better way?
a = (((f * X) + (f2 * X3 )) / (1 + (f * X) + (f2 * X3 ))) * i
b = ((f2 * X3 ) / (1 + (f * X) + (f2 * X3))) * i
c = ((f * X) / (1 + (j * X) + (k * Y))) * i
d = ((k * Y) / (1 + (j * X) + (k * Y))) * i
f = 0.0001
i = 0.001
j = 0.0001
k = 0.001
e = 0 = X + a + b + c
g = 0.0001 = Y + d
h = i - a
As noted by Joe, this is actually a system of nonlinear equations. You are going to need more firepower than numpy alone provides.
Solution of nonlinear equations is tricky, and the typical approach is to define an objective function
F(z) = sum( e[n]^2, n=1...13 )
where z is a vector containing a value for each of your 13 variables a,b,c,d,e,f,g,h,i,X,Y and e[n] is the amount by which each of your 13 equations is violated. For example
e[3] = (d - ((k * Y) / (1 + (j * X) + (k * Y))) * i )
Once you have that objective function, then you can apply a nonlinear solver to try to find a z for which F(z)=0. That of course corresponds to a solution to your equations.
Commonly used solvers include:
The Solver in Microsoft Excel
The python library scipy.optimize
Fitting routines in the Gnu Scientific Library
Matlab's optimization toolbox
Note that all of them will work far better if you first alter your set of equations to eliminate as many variables as practical before trying to run the solver (e.g. by substituting for k wherever it is found). The reduced dimensionality makes a big difference.