How to find a region of acceptability in sympy? - python

Firstly, sorry about machine translate of "region of acceptability", I'm not sure that is exactly what I mean. "region of acceptability" must tell me where f(x) exists.
I'm using sumpy to code a script which will be give me a full f(x) analysis:
f(x)=0, d/dxf(x)=0,"region of acceptability", etc.
Which function in sympy is what I'm searching and how to use it correctly?

There is a function in sympy called singularities that tries to identify the set of singularities for an expression in a given symbol:
In [21]: from sympy import *
In [22]: x = Symbol('x', complex=True)
In [23]: expr = x**2 / ((1 - x) * (2 + x**2))
In [24]: expr
Out[24]:
2
x
────────────────
⎛ 2 ⎞
(1 - x)⋅⎝x + 2⎠
In [25]: singularities(expr, x)
Out[25]: {1, -√2⋅ⅈ, √2⋅ⅈ}
If the broader domain of the function is supposed to be the reals then you can remove those singularities from the set of real numbers using set subtraction:
In [26]: Reals - singularities(expr, x)
Out[26]: (-∞, 1) ∪ (1, ∞)
You can also convert that into relations on x with:
In [27]: (Reals - singularities(expr, x)).as_relational(x)
Out[27]: x ≠ 1

Related

Sympy returns empty result

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.

Sympy calculus: when evaluating a sympy expression, python outputs log(2), and e^0.3, as symbols, instead of computing their value

So I have to write a python script for finding the root of a function using Newton's Method, and my code isn't computing a float when evaluating the derivative at a point, it's only evaluating the sin(x) part, leaving e^x and log(2) as they are.
I'm stuck, please help.
This is my code so far:
from sympy import *
x=symbols('x')
f="(e**x)+(2**(-x))+2*cos(x) - 6"
func=sympify(f)
fdiff=Derivative(func, x) #this returns an expression for the derivative
val=fdiff.doit().subs({x: 0.4})
print(val) #this should output 0.187681.... instead it returns another expression
PS: evalf doesn't work either, neither does subs(x, 0.4)
Using E instead of e:
In [19]: x=symbols('x')
...:
...: f="(E**x)+(2**(-x))+2*cos(x) - 6"
...: func=sympify(f)
In [20]: func
Out[20]:
x -x
ℯ + 2⋅cos(x) - 6 + 2
Note the different script for e.
In [21]: fdiff=Derivative(func, x)
In [22]: fdiff
Out[22]:
d ⎛ x -x⎞
──⎝ℯ + 2⋅cos(x) - 6 + 2 ⎠
dx
In [23]: fdiff.doit()
Out[23]:
x -x
ℯ - 2⋅sin(x) - 2 ⋅log(2)
In [24]: fdiff.doit().subs({x:.4})
Out[24]: 0.712988013023969 - 0.757858283255199⋅log(2)
In [25]: N(fdiff.doit().subs({x:.4}))
Out[25]: 0.187680680721628
With your expression
In [14]: func
Out[14]:
x -x
e + 2⋅cos(x) - 6 + 2
In [15]: func.free_symbols
Out[15]: {e, x}
To use this, you have to include both e and x in the subs.
In [38]: e=list(Out[15])[0]

Prevent simplification/flattening/distribution of Simply

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

Get smallest power of variable in SymPy?

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.

Sympy: Drop higher order terms in polynomial

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.

Categories