How to add assumptions in limit in Sympy? - python

I want to add some assumptions in limit.
Suppose 0<x<1, then $$limit_{n \to \infty} x^n = 0$$
from sympy import *
x = var('x, n')
limit(x**n, n, oo)
But I get an error NotImplementedError: Result depends on the sign of sign(log(x)).
Is there some way in sympy to handle this?

EDIT: As pointed out in the comments the solution below fails with the same NotImplementedError as in the question (as of November 2019) saying that the answer depends on sign(log(x)). It seems that this sign problem can not be solved with assuming but only with the positive parameter of Symbol. So one way around the issue is to describe 0 < x < 1 as exp(-y) for y > 0:
from sympy import *
y = Symbol("y", positive=True)
n = Symbol("n")
print(limit(exp(-y)**n, n, oo)) # outputs 0
To assume something you can say:
from sympy.assumptions import assuming, Q
with assuming(...):
see here: http://docs.sympy.org/latest/modules/assumptions/assume.html
In your case:
from sympy import *
from sympy.assumptions import assuming, Q
x, n = symbols("x n")
with assuming(Q.is_true(0 < x), Q.is_true(x <1)):
print(limit(x**n, n, oo))

Related

Python sympy symbols

When I use "x" and "z" as symbols, I have no problem with this code:
from sympy import *
x, z = symbols('x z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
y.subs({x: 5, z: 25})
But when I use "q" and "a", solve does not give me any solution.
q, a = symbols('q a')
y = -6*q**2 + 2*q*a**0.5 + 50*q - a
solve((diff(y, q), diff(y, a)))
y.subs({q: 5, a: 25})
As you can see I use "subs" to check that there is no typo in the objective function.
UPDATE: I used "Symbol" to set each variable individually, but again using "q" and "a" does not work.
# This works
x = Symbol('x')
z = Symbol('z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
# This does not work
q = Symbol('q')
a = Symbol('a')
y = -6*q**2 + 2*q*a**0.5 + 50*q-a
solve((diff(y, q), diff(y, a)))
Thank you.
Got it!
It all depends on an alphabetic order of your variables.
If you substitute x for z and z for x in your first example it will also stop working.
Internally solve sends the expression to the function _solve in sympy.solvers which then tries to solve your equation and fails many times.
Finally as a last effort what it does is it tries to solve -sqrt(a) + q or x - sqrt(z) by picking symbols from it through an internal function _ok_syms, with an argument that sorts those alphabetically (even without this argument it still would, but if wrapped with reversed it magically makes your examples works in the exactly opposite way).
And so it does solve x - sqrt(z) as x: sqrt(z) and -sqrt(a) + q as a: q**2.
While in the first case it ends up with an easily solvable 50 - 10*sqrt(z), in the second case it is lost on -12*q + 2*sqrt(q**2) + 50 as it is not able to simplify sqrt(q**2).
source:
a lot of testing on:
https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py

evalf and subs in sympy on single variable expression returns expression instead of expected float value

I'm new to sympy and I'm trying to use it to get the values of higher order Greeks of options (basically higher order derivatives). My goal is to do a Taylor series expansion. The function in question is the first derivative.
f(x) = N(d1)
N(d1) is the P(X <= d1) of a standard normal distribution. d1 in turn is another function of x (x in this case is the price of the stock to anybody who's interested).
d1 = (np.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
As you can see, d1 is a function of only x. This is what I have tried so far.
import sympy as sp
from math import pi
from sympy.stats import Normal,P
x = sp.symbols('x')
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # This should be 0.5155
f1 = sp.simplify(sp.diff(f,x))
f1.evalf(subs={x:100}) # This should also return a float value
The last line of code however returns an expression, not a float value as I expected like in the case with f. I feel like I'm making a very simple mistake but I can't find out why. I'd appreciate any help.
Thanks.
If you define x with positive=True (which is implied by the log in the definition of u assuming u is real which is implied by the definition of f) it looks like you get almost the expected result (also using f1.subs({x:100}) in the version without the positive x assumption shows the trouble is with unevaluated polar_lift(0) terms):
import sympy as sp
from sympy.stats import Normal, P
x = sp.symbols('x', positive=True)
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*sp.sqrt(0.5)) # changed np to sp
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # 0.541087287864516
f1 = sp.simplify(sp.diff(f,x))
print(f1.evalf(subs={x:100})) # 0.0510177033783834

Writing a function for x * sin(3/x) in python

I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162

Equation solver in Python

Given a simple equation such as:
x = y + z
You can get the third variable if you bind the other two (ie: y = x - z and z = x - y). A straightforward way to put this in code:
def solve(args):
if 'x' not in args:
return args['y'] + args['z']
elif 'z' not in args:
return args['x'] - args['y']
elif 'y' not in args:
return args['x'] - args['z']
else:
raise SomeError
I obviously can take an equation, parse it and simplify it to achieve the same effect.
But I believe in doing so I would be re-inventing the wheel. So where's my ready-made wheel?
Consider using Sympy. It includes various tools to solve equations and a lot more.
The following is an excerpt from the docs:
>>> from sympy import I, solve
>>> from sympy.abc import x, y
>>> solve(x**4-1, x)
[1, -1, -I, I]

Cubic root of the negative number on python

Can someone help me to find a solution on how to calculate a cubic root of the negative number using python?
>>> math.pow(-3, float(1)/3)
nan
it does not work. Cubic root of the negative number is negative number. Any solutions?
A simple use of De Moivre's formula, is sufficient to show that the cube root of a value, regardless of sign, is a multi-valued function. That means, for any input value, there will be three solutions. Most of the solutions presented to far only return the principle root. A solution that returns all valid roots, and explicitly tests for non-complex special cases, is shown below.
import numpy
import math
def cuberoot( z ):
z = complex(z)
x = z.real
y = z.imag
mag = abs(z)
arg = math.atan2(y,x)
return [ mag**(1./3) * numpy.exp( 1j*(arg+2*n*math.pi)/3 ) for n in range(1,4) ]
Edit: As requested, in cases where it is inappropriate to have dependency on numpy, the following code does the same thing.
def cuberoot( z ):
z = complex(z)
x = z.real
y = z.imag
mag = abs(z)
arg = math.atan2(y,x)
resMag = mag**(1./3)
resArg = [ (arg+2*math.pi*n)/3. for n in range(1,4) ]
return [ resMag*(math.cos(a) + math.sin(a)*1j) for a in resArg ]
You could use:
-math.pow(3, float(1)/3)
Or more generally:
if x > 0:
return math.pow(x, float(1)/3)
elif x < 0:
return -math.pow(abs(x), float(1)/3)
else:
return 0
math.pow(abs(x),float(1)/3) * (1,-1)[x<0]
You can get the complete (all n roots) and more general (any sign, any power) solution using:
import cmath
x, t = -3., 3 # x**(1/t)
a = cmath.exp((1./t)*cmath.log(x))
p = cmath.exp(1j*2*cmath.pi*(1./t))
r = [a*(p**i) for i in range(t)]
Explanation:
a is using the equation xu = exp(u*log(x)). This solution will then be one of the roots, and to get the others, rotate it in the complex plane by a (full rotation)/t.
Taking the earlier answers and making it into a one-liner:
import math
def cubic_root(x):
return math.copysign(math.pow(abs(x), 1.0/3.0), x)
The cubic root of a negative number is just the negative of the cubic root of the absolute value of that number.
i.e. x^(1/3) for x < 0 is the same as (-1)*(|x|)^(1/3)
Just make your number positive, and then perform cubic root.
You can also wrap the libm library that offers a cbrt (cube root) function:
from ctypes import *
libm = cdll.LoadLibrary('libm.so.6')
libm.cbrt.restype = c_double
libm.cbrt.argtypes = [c_double]
libm.cbrt(-8.0)
gives the expected
-2.0
numpy has an inbuilt cube root function cbrt that handles negative numbers fine:
>>> import numpy as np
>>> np.cbrt(-8)
-2.0
This was added in version 1.10.0 (released 2015-10-06).
Also works for numpy array / list inputs:
>>> np.cbrt([-8, 27])
array([-2., 3.])
You can use cbrt from scipy.special:
>>> from scipy.special import cbrt
>>> cbrt(-3)
-1.4422495703074083
This also works for arrays.
this works with numpy array as well:
cbrt = lambda n: n/abs(n)*abs(n)**(1./3)
Primitive solution:
def cubic_root(nr):
if nr<0:
return -math.pow(-nr, float(1)/3)
else:
return math.pow(nr, float(1)/3)
Probably massively non-pythonic, but it should work.
I just had a very similar problem and found the NumPy solution from this forum post.
In a nushell, we can use of the NumPy sign and absolute methods to help us out. Here is an example that has worked for me:
import numpy as np
x = np.array([-81,25])
print x
#>>> [-81 25]
xRoot5 = np.sign(x) * np.absolute(x)**(1.0/5.0)
print xRoot5
#>>> [-2.40822469 1.90365394]
print xRoot5**5
#>>> [-81. 25.]
So going back to the original cube root problem:
import numpy as np
y = -3.
np.sign(y) * np.absolute(y)**(1./3.)
#>>> -1.4422495703074083
I hope this helps.
For an arithmetic, calculator-like answer in Python 3:
>>> -3.0**(1/3)
-1.4422495703074083
or -3.0**(1./3) in Python 2.
For the algebraic solution of x**3 + (0*x**2 + 0*x) + 3 = 0 use numpy:
>>> p = [1,0,0,3]
>>> numpy.roots(p)
[-3.0+0.j 1.5+2.59807621j 1.5-2.59807621j]
New in Python 3.11
There is now math.cbrt which handles negative roots seamlessly:
>>> import math
>>> math.cbrt(-3)
-1.4422495703074083

Categories

Resources