Sympy solveset store results as float, integer etc - python

I am solving cumulative probability functions (or equations in general if you want to think about it this way) with sympy solveset. So far so good. They return however "sets" as a type of result output. I am having troubles converting those to or saving those as standard python variable types: In my case I would like it to be a float.
My code is as follows:
import sympy as sp
from sympy import Symbol
from sympy import erf
from sympy import log
from sympy import sqrt
x = Symbol('x')
p = 0.1
sp.solveset((0.5 + 0.5*erf((log(x) - mu)/(sqrt(2)*sigma)))-p)
Out[91]:
FiniteSet(7335.64225447845*exp(-1.77553477605362*sqrt(2)))
Is there a possibility to convert this to float? just using float() does not work as I have tried this and I also have gotten so far to somehow store it as a list and then extracting the number again. However this way seems very cumbersome and not suited to my purpose. In the end I will let us say solve this equation above a 1000 times and I would like to have all the results as a neat array containing floating point numbers.
If you store the above result as follows:
q = sp.solveset((0.5 + 0.5*erf((log(x) - mu)/(sqrt(2)*sigma)))-p)
then Python says the type is sets.setsFiniteSet and if you try to access the variable q it gives you an error (working in Spyder btw):
"Spyder was unable to retrieve the value of this variable from the console - The error message was: 'tuple object has no attribute 'raise_error'".
I have no idea what that means. Thanks a lot.

The FiniteSet works like a Python set. You can convert it to a list and extract the element by indexing e.g.:
In [3]: S = FiniteSet(7335.64225447845*exp(-1.77553477605362*sqrt(2)))
In [4]: S
Out[4]:
⎧ -1.77553477605362⋅√2⎫
⎨7335.64225447845⋅ℯ ⎬
⎩ ⎭
In [5]: list(S)
Out[5]:
⎡ -1.77553477605362⋅√2⎤
⎣7335.64225447845⋅ℯ ⎦
In [6]: list(S)[0]
Out[6]:
-1.77553477605362⋅√2
7335.64225447845⋅ℯ
In [7]: list(S)[0].n()
Out[7]: 595.567591563886

Related

Runtime error for matplotlib using np.arange [duplicate]

I am working with Python 3.6.
I am really confused, why this happened ?
In [1]: import numpy as np
In [2]: a = np.array(-1)
In [3]: a
Out[3]: array(-1)
In [4]: a ** (1/3)
/Users/wonderful/anaconda/bin/ipython:1: RuntimeWarning: invalid value encountered in power
#!/Users/wonderful/anaconda/bin/python
Out[4]: nan
Numpy does not seem to allow fractional powers of negative numbers, even if the power would not result in a complex number. (I actually had this same problem earlier today, unrelatedly). One workaround is to use
np.sign(a) * (np.abs(a)) ** (1 / 3)
change the dtype to complex numbers
a = np.array(-1, dtype=np.complex)
The problem arises when you are working with roots of negative numbers.

SymPy prints function names instead of its value

I recently started learning IPython. I have a problem with Sympy library. It only prints the function instead of exact value.
import matplotlib.pyplot as plt
import numpy as nm
from sympy import *
x,y = symbols("x y")
expr = cos(x)
a = expr.subs(x,1)
print(a)
The output of above program is cos(1). But I want to print the exact value of cos(1).
First of all some nitpicking: “cos(1)” is the most concise way to represent the exact value of cos(1). Numerical representations like “0.54”, “0.540302”, or “0.54030230587” are not exact but are only accurate within the respective number of digits. The fact that cos(1) is not simply translated to one of those numerical approximations is one of the features of SymPy, as it ensures that something like simplify(acos(cos(1))) actually yields 1 and not 0.99999999.
That being said, there are of course purposes where you really need a numerical representation. In this case, you can use the class function n of SymPy expressions or the function N from SymPy, for example:
from sympy import cos, N
expr = cos(1)
print(expr.n()) # 0.540302305868140
print(N(expr)) # 0.540302305868140

Multiplication of floating point numbers gives different results in Numpy and R

I am doing data analysis in Python (Numpy) and R. My data is a vector 795067 X 3 and computing the mean, median, standard deviation, and IQR on this data yields different results depending on whether I use Numpy or R. I crosschecked the values and it looks like R gives the "correct" value.
Median:
Numpy:14.948499999999999
R: 14.9632
Mean:
Numpy: 13.097945407088607
R: 13.10936
Standard Deviation:
Numpy: 7.3927612774052083
R: 7.390328
IQR:
Numpy:12.358700000000002
R: 12.3468
Max and min of the data are the same on both platforms. I ran a quick test to better understand what is going on here.
Multiplying 1.2*1.2 in Numpy gives 1.4 (same with R).
Multiplying 1.22*1.22 gives 1.4884 in Numpy and the same with R.
However, multiplying 1.222*1.222 in Numpy gives 1.4932839999999998 which is clearly wrong! Doing the multiplication in R gives the correct answer of 1.49324.
Multiplying 1.2222*1.2222 in Numpy gives 1.4937728399999999 and 1.493773 in R. Once more, R is correct.
In Numpy, the numbers are float64 datatype and they are double in R. What is going on here? Why are Numpy and R giving different results? I know R uses IEEE754 double-precision but I don't know what precision Numpy uses. How can I change Numpy to give me the "correct" answer?
Python
The print statement/function in Python will print single-precision floats. Calculations will actually be done in the precision specified. Python/numpy uses double-precision float by default (at least on my 64-bit machine):
import numpy
single = numpy.float32(1.222) * numpy.float32(1.222)
double = numpy.float64(1.222) * numpy.float64(1.222)
pyfloat = 1.222 * 1.222
print single, double, pyfloat
# 1.49328 1.493284 1.493284
print "%.16f, %.16f, %.16f"%(single, double, pyfloat)
# 1.4932839870452881, 1.4932839999999998, 1.4932839999999998
In an interactive Python/iPython shell, the shell prints double-precision results when printing the results of statements:
>>> 1.222 * 1.222
1.4932839999999998
In [1]: 1.222 * 1.222
Out[1]: 1.4932839999999998
R
It looks like R is doing the same as Python when using print and sprintf:
print(1.222 * 1.222)
# 1.493284
sprintf("%.16f", 1.222 * 1.222)
# "1.4932839999999998"
In contrast to interactive Python shells, the interactive R shell also prints single-precision when printing the results of statements:
> 1.222 * 1.222
[1] 1.493284
Differences between Python and R
The differences in your results could result from using single-precision values in numpy. Calculations with a lot of additions/subtractions will ultimately make the problem surface:
In [1]: import numpy
In [2]: a = numpy.float32(1.222)
In [3]: a*6
Out[3]: 7.3320000171661377
In [4]: a+a+a+a+a+a
Out[4]: 7.3320003
As suggested in the comments to your actual question, make sure to use double-precision floats in your numpy calculations.

How to properly cast mpmath matrix to numpy ndarray ( and mpmath.mpf to float)

I'm working with mpmath python library to gain precision during some computations, but i need to cast the result in a numpy native type.
More precisely i need to cast an mpmath matrix (that contains mpf object types) in an numpy.ndarray (that contains float types).
I have solved the problem with a raw approach:
# My input Matrix:
matr = mp.matrix(
[[ '115.80200375', '22.80402473', '13.69453064', '54.28049263'],
[ '22.80402473', '86.14887381', '53.79999432', '42.78548627'],
[ '13.69453064', '53.79999432', '110.9695448' , '37.24270321'],
[ '54.28049263', '42.78548627', '37.24270321', '95.79388469']])
# multiple precision computation
D = MPDBiteration(matr)
# Create a new ndarray
Z = numpy.ndarray((matr.cols,matr.rows),dtype=numpy.float)
# I fill it pretty "manually"
for i in range(0,matr.rows):
for j in range(0,matr.cols):
Z[i,j] = D[i,j] # or float(D[i,j]) seems to work the same
My question is:
Is there a better/more elegant/easier/clever way to do it?
UPDATE:
Reading again and again the mpmath documentation I've found this very useful method: tolist() , it can be used as follows:
Z = np.array(matr.tolist(),dtype=np.float32)
It seems slightly better and elegant (no for loops needed)
Are there better ways to do it? Does my second solution round or chop extra digits?
Your second method is to be preferred, but using np.float32 means casting numbers to single precision. For your matrix, this precision is too low: 115.80200375 becomes 115.80200195 due to truncation. You can set double precition explicitly with numpy.float64, or just pass Python's float type as an argument, which means the same.
Z = numpy.array(matr.tolist(), dtype=float)
or, to keep the matrix structure,
Z = numpy.matrix(matr.tolist(), dtype=float)
You can do that when vectorizing a function (which is what we usually want to do anyway). The following example vectorizes and converts the theta function
import numpy as np
import mpmath as mpm
jtheta3_fn = lambda z,q: mpm.jtheta(n=3,z=z,q=q)
jtheta3_fn = np.vectorize(jtheta3_fn,otypes=(float,))

Operations for Long and Float in Python

I'm trying to compute this:
from scipy import *
3600**3400 * (exp(-3600)) / factorial(3400)
the error: unsupported long and float
Try using logarithms instead of working with the numbers directly. Since none of your operations are addition or subtraction, you could do the whole thing in logarithm form and convert back at the end.
Computing with numbers of such magnitude, you just can't use ordinary 64-bit-or-so floats, which is what Python's core runtime supports. Consider gmpy (do not get the sourceforge version, it's aeons out of date) -- with that, math, and some care...:
>>> e = gmpy.mpf(math.exp(1))
>>> gmpy.mpz(3600)**3400 * (e**(-3600)) / gmpy.fac(3400)
mpf('2.37929475533825366213e-5')
(I'm biased about gmpy, of course, since I originated and still participate in that project, but I'd never make strong claims about its floating point abilities... I've been using it mostly for integer stuff... still, it does make this computation possible!-).
You could try using the Decimal object. Calculations will be slower but you won't have trouble with really small numbers.
from decimal import Decimal
I don't know how Decimal interacts with the scipy module, however.
This numpy discussion might be relevant.
Well the error is coming about because you are trying to multiply
3600**3400
which is a long with
exp(-3600)
which is a float.
But regardless, the error you are receiving is disguising the true problem. It seems exp(-3600) is too big a number to fit in a float anyway. The python math library is fickle with large numbers, at best.
exp(-3600) is too smale, factorial(3400) is too large:
In [1]: from scipy import exp
In [2]: exp(-3600)
Out[2]: 0.0
In [3]: from scipy import factorial
In [4]: factorial(3400)
Out[4]: array(1.#INF)
What about calculate it step by step as a workaround(and it makes sense
to check the smallest and biggest intermediate result):
from math import exp
output = 1
smallest = 1e100
biggest = 0
for i,j in izip(xrange(1, 1701), xrange(3400, 1699, -1)):
output = output * 3600 * exp(-3600/3400) / i
output = output * 3600 * exp(-3600/3400) / j
smallest = min(smallest, output)
biggest = max(biggest, output)
print "output: ", output
print "smallest: ", smallest
print "biggest: ", biggest
output is:
output: 2.37929475534e-005
smallest: 2.37929475534e-005
biggest: 1.28724174494e+214

Categories

Resources