Using Sympy, say we have an expression f, which is a polynomial of the Symbol "x" (and of potentially other symbols).
I would like to know what if there is an efficient way to drop all terms in f of order greater than some integer n.
As a special case I have a very complicated function but i want to only keep terms up to 2nd order in x. What's the efficient way to do this?
The obvious, not-very-efficient way to do it would be for each m less than n, take m derivatives and set x to 0 to obtain the coefficient of x^m. We obtain each coefficient this way then reconstruct the polynomial. But taking derivatives is not the most efficient thing.
An easy way to do this is to add O(x**n) to the expression, like
In [23]: x + x**2 + x**4 + x**10 + O(x**3)
Out[23]:
2 ⎛ 3⎞
x + x + O⎝x ⎠
If you want to later remove it, use the removeO method
In [24]: (x + x**2 + x**4 + x**10 + O(x**3)).removeO()
Out[24]:
2
x + x
You can also use series to take the series expansion of the expression. The difference here is the behavior if a non-polynomial term ends up in the expression:
In [25]: x + sin(x) + O(x**3)
Out[25]:
⎛ 3⎞
sin(x) + x + O⎝x ⎠
In [26]: (x + sin(x)).series(x, 0, 3)
Out[26]:
⎛ 3⎞
2⋅x + O⎝x ⎠
If you take a look at the polynomial module docs:
http://docs.sympy.org/latest/modules/polys/reference.html
there will be plenty of ways to go about it, depending on the specifics of your situation. A couple different ways that would work:
Using .coeffs():
>>> f = 3 * x**3 + 2 * x**2 + x * y + y**3 + 1
>>> order = 2
>>> coeffs = Poly(f, x).coeffs()
>>> f_new = sum(x**n * coeffs[-(n+1)] for n in range(order+1)) # the +1 is to get 0th order
>>> f_new
2*x**2 + x*y + y**3 + 1
Alternatively, you could iterate over items in .all_terms():
>>> all_terms = Poly(f, x).all_terms()
>>> sum(x**n * term for (n,), term in all_terms() if n <= order)
There are plenty of manipulation functions in the module that you should be able to work with the expression directly rather than doing calculations/taking derivatives/etc.
Related
I am attempting a very simple sympy example as following ;
from sympy import *
x,y,z = symbols('x,y,z', real=True)
expr = 256 * exp(-Pow((x-(y/2)/(z/2)),2))
solve(expr,x)
trying to get x in terms of y and z. Execution results in an empty list. What am I doing wrong ?
Your equation doesn't have any solutions for x so solve returns an empty list. Here is your equation:
In [2]: expr
Out[2]:
2
⎛ y⎞
-⎜x - ─⎟
⎝ z⎠
256⋅ℯ
When you pass that to solve you are asking "for what values of x is this expression equal to zero?". The exponential function exp(t) is nonzero for all possible complex numbers t. Since there are no finite values of x for which the given expression is zero solve returns an empty list meaning that there are no solutions:
In [3]: solve(expr, x)
Out[3]: []
If you make an equation that actually has solutions then solve can potentially find them for you:
In [6]: eq = Eq(expr, 1)
In [7]: eq
Out[7]:
2
⎛ y⎞
-⎜x - ─⎟
⎝ z⎠
256⋅ℯ = 1
In [8]: solve(eq, x)
Out[8]:
⎡y ________ y ________⎤
⎢─ - 2⋅√2⋅╲╱ log(2) , ─ + 2⋅√2⋅╲╱ log(2) ⎥
⎣z z ⎦
Let fx = Symbol('fx', real=True). You will get solve(exp(fx),fx) == [] because there is no real value of fx that can make exp(fx) zero. If there were such a value, say fx = 2 then you could try solve(fx - 2, x) to find the value for x...but if there is no value for fx there is no value you can find for x.
I am only really trying to use sympy to produce full equations using Latex. I don't need it to find me any answers necessarily. I have the following expression:
expr = Eq(S(DeltaX), ((V1 + V2) / 2) * DeltaT)
When it displays in latex it distributes the 2 denominator to both V1 and V2.
(V1/2 + V2/2)
When I use UnevaluatedExpr() it converts it to a negative exponent:
(V1 + V2)*2**(-1)
And I haven't been able to use evaluate=false in any way it's happy with the syntax. Which is the only other possible solution I've found.
The default behaviour in SymPy is to distribute a Rational in a 2-arg Mul:
In [9]: (x + y) / 2
Out[9]:
x y
─ + ─
2 2
You can either control this using evaluate=False or the distribute context manager:
In [10]: Mul(Rational(1, 2), x + y, evaluate=False)
Out[10]:
x + y
─────
2
In [13]: from sympy.core.parameters import distribute
In [14]: with distribute(False):
...: e = (x + y) / 2
...:
In [15]: e
Out[15]:
x + y
─────
2
In sympy I have laurent polynomials in several variables (e.g. x,y,...) and I need the smallest exponent of the expression.
e.g.
expr = x**-3+y/x+2
The smallest power of x is -3 and the smallest power of y is 1. What I actually wish to do is normalize the laurent polynomial by multiplying by x^a y^b to obtain a non-laurent polynomial.
Maybe this is what you want:
In [14]: expr = x**-3+y/x+2
In [15]: expr
Out[15]:
y 1
2 + ─ + ──
x 3
x
In [16]: cancel(expr)
Out[16]:
3 2
2⋅x + x ⋅y + 1
───────────────
3
x
In [17]: cancel(expr).as_numer_denom()
Out[17]:
⎛ 3 2 3⎞
⎝2⋅x + x ⋅y + 1, x ⎠
This works for your example (returns -3), and believe it will work in general for any Laurent polynomial:
min((z.as_base_exp()[1] for z in expr.atoms(sympy.Pow)), default=1)
Explanation:
Extract the atoms from expr that are raised to powers other than 1. Convert each atom to a (base, exponent) pair, discard the base, and return the smallest exponent value. Default to 1 in the event that expr.atoms(sympy.Pow) is empty.
Edit:
It should be noted that atoms(*types) will return every atomic object that is matched by types. so if expr looked like this:
x**2 + y + exp(x**(-2)) - 5/y
the result set will include x**(-2) since it matches sympy.Pow, and that may not be desirable in some cases. Since this question is specifically about Laurent polynomials, it shouldn't be a problem here.
x**3-2*x-5=0
To the following forms [x = p(x)] where p(x) is continuously differentiable:
x=5/(x**2-2)
x=(2*x+5)**(1/3)
x=(x**3-5)/2
Given an expression, such as expr = x**3-2*x-5, assumed to be zero, one can form an equation x = p(x) in many ways. The simplest is to add x to both sides: Eq(x, expr + x).
This prints as one would expect: pprint(Eq(x, expr + x)):
3
x = x - x - 5
A couple of more interesting rewrites:
Iteration for Newton method: Eq(x, simplify(x - expr/diff(expr, x)))
3
2⋅x + 5
x = ────────
2
3⋅x - 2
Isolating the leading term on one side and taking a root:
p = poly(expr)
Eq(x, (LM(p) - expr)**(1/degree(p)))
3 _________
x = ╲╱ 2⋅x + 5
This is rough solution only..
from sympy import *
import numpy as np
var('x')
expr=sympify('x**3-2*x-5')
p = poly(expr);
p1=factor(p-(p).coeff_monomial(1))
for i in p1.args:
if (poly(i).is_monomial):
z=(np.prod([j for j in p1.args if j!=i]))
p2=(-(p).coeff_monomial(1)/z)**(1/degree(i));
v=i.coeff(x)
if p2:print(p2)
elif v:
p2=(-z/v)
print(p2)
for i in (p.all_terms())[:-1]:
if i[1]:
p3= ((i[1]*x**i[0][0]-expr)/i[1])**(1/Integer(i[0][0])) ;print(p3);
'''o
5/(x**2 - 2)
(2*x + 5)**(1/3)
x**3/2 - 5/2
'''
I have a huge symbolic sympy expression on the form
expression = factor * (f1*a + f2*b + f3*c + f4*d + f5*e)
where all of the factors a through e all consists of several terms. I.e:
a = exp(2x) + exp(3x) + sin(Ix).
I want to create en array on the form
array = factor * [a,b,c,d,e]
But dont see a cleaver way to do this. I´ve tried to use the factor function, but it only gives me the expression on the form of "expression" above.
Until now i have used
print(expression)
and then done some brute force copy paste of the factors a through e. Since I am going to get expressions with way more terms than in this example, I want to do this without the copy paste routine. Any ideas?
Here's a simple example you can extrapolate for more terms
import sympy as sp
x = sp.var('x')
f1, f2 = sp.symbols('f1:3')
factor = sp.symbols('factor')
a = x**2 + sp.sin(x) + sp.exp(sp.I * x)
b = sp.log(x)/(x+1)**2
# example expression:
expression = (factor * (f1 * a + f2 * b)).expand()
print(expression)
# collect coefficients of f1 and f2
coeffs = sp.collect(expression.expand(),[f1,f2], evaluate=False)
print(coeffs)
# show the coefficients w/o the factor factor
[(coeffs[f]/factor).simplify() for f in (f1,f2)]
f1*factor*x**2 + f1*factor*exp(I*x) + f1*factor*sin(x) + f2*factor*log(x)/(x**2 + 2*x + 1)
{f2: factor*log(x)/(x**2 + 2*x + 1), f1: factor*x**2 + factor*exp(I*x) + factor*sin(x)}
[x**2 + exp(I*x) + sin(x), log(x)/(x**2 + 2*x + 1)]