ValueError shape <= 0 for distribution function - python

I need to complete a distribution function which looks like this into python:
−∞< x <∞,
P(x)dx= ((1+x^2/n)^-(n+1)/2) * Γ(n+1/2)/Γ(n/2)*(nπ)**1/2 dx, n=1.
So i tried it like this:
from numpy import *
from scipy import stats
from scipy.special import gammaln
from pylab import *
def studentstPDF(x,n=1):
"""
Call:
d = studentstPDF(x,n)
Input argument:
x: float (array)
n: float, default = 1.0
Output argument:
p: float
Examples:
In [1]: studentstPDF(1,1)
Out[1]: 0.1591549
"""
p = (1+((x**2)/n))**((-n+1)/2) * gamma((n+1)/2) / gamma(n/2) * (n*math.pi)**1/2
p[x<inf] = 0.0
p[x>-inf] = 0.0
return(p)
but now I get the error 'ValueError: shape <= 0'
What does that mean? And where am I wrong with my function?
In [16]:
studentstPDF(1,1)
Traceback (most recent call last):
File "<ipython-input-16-ddd6d9df823d>", line 1, in <module>
studentstPDF(1,1)
File "/Users/Veysel/Downloads/Exercise4-2/exercise4.py", line 122, in studentstPDF
p = (1+((x**2)/n))**((-n+1)/2) * gamma((n+1)/2) / gamma(n/2) * (n*math.pi)**1/2
File "mtrand.pyx", line 1871, in mtrand.RandomState.gamma (numpy/random/mtrand/mtrand.c:13491)
ValueError: shape <= 0

Your gamma function from scipy.special is most likely being overwritten by another gamma function of another nature, perhaps a random variable function from your mass imports. Import like this instead:
from scipy.special import gamma as Gamma
and write out your expression like this:
p = (1+((x**2)/n))**((-n+1)/2) * Gamma((n+1)/2) / Gamma(n/2) * (n*math.pi)**1/2
If you absolutely have to import the same way, use scipy.special.gamma in place of your current gamma calls and import scipy.
Your error itself is a result of attempting to use the multiplicative operator * on operands that do not have the same shape.

Related

python numba with complex numbers global array

I am trying to optimize my code with numba.
I designed the code to contain a gl.py file which contains some arrays which will be used by main.py and functions called inside main() from main.py.
The auxiliary.py looks like:
import numpy as np
from numba import jit, types
from cmath import sqrt, exp, sin
N_timesteps_imag = 100
N_epsilon_divs = 60
N_z_divs = 2000
K = N_z_divs # equal to the variable N_z_divs
delta_epsilon = 0.1
delta_z = 0.1
lambd = 1.5
z_max = (N_z_divs/2) * delta_z
epsilon_range = np.linspace(0.0, N_epsilon_divs*delta_epsilon, N_epsilon_divs+1)
z_range = np.linspace(-z_max, z_max, N_z_divs+1)
psi_ground = np.zeros((N_z_divs+1, N_epsilon_divs+1, N_timesteps_imag+1), dtype=types.complex128)
#jit(nopython=True)
def pop_psiground_t0():
for c1 in range(1, psi_ground.shape[0]-1):
for c2 in range(1, psi_ground.shape[1]-1):
zed = (c1 - N_z_divs/2) * delta_z
epsi = c2 * delta_epsilon
psi_ground[c1, c2, 0] = sqrt(3) * epsi * exp(-sqrt(epsi**(2*lambd) + zed**2))
pop_psiground_t0()
The main.py looks like (MWE):
import numpy as np
import auxiliary
def main():
print(auxiliary.psi_ground[1000, 40, 0]) # shall NOT be 0 + 0j !!!
if __name__ == '__main__':
main()
Irrespective to what I put for the keyword argument dtype for the declaration of psi_ground inside auxiliary.py, be it numba.types.complex128, np.complex128, np.clongdouble, nothing works.
In particular, for np.complex128, I get the following error when running python3 main.py:
No implementation of function Function(<built-in function setitem>) found for signature:
>>> setitem(readonly array(complex128, 3d, C), Tuple(int64, int64, Literal[int](0)), complex128)
There are 16 candidate implementations:
- Of which 14 did not match due to:
Overload of function 'setitem': File: <numerous>: Line N/A.
With argument(s): '(readonly array(complex128, 3d, C), UniTuple(int64 x 3), complex128)':
No match.
- Of which 2 did not match due to:
Overload in function 'SetItemBuffer.generic': File: numba/core/typing/arraydecl.py: Line 171.
With argument(s): '(readonly array(complex128, 3d, C), UniTuple(int64 x 3), complex128)':
Rejected as the implementation raised a specific error:
TypeError: Cannot modify value of type readonly array(complex128, 3d, C)
raised from /home/velenos14/.local/lib/python3.8/site-packages/numba/core/typing/arraydecl.py:177
During: typing of setitem at /mnt/c/Users/iusti/Desktop/test_python/auxiliary.py (45)
File "auxiliary.py", line 45:
def pop_psiground_t0():
<source elided>
epsi = c2 * delta_epsilon
psi_ground[c1, c2, 0] = sqrt(3) * epsi * exp(-sqrt(epsi**(2*lambd) + zed**2))
How can I proceed with this? I tried to follow what it's written here: numba TypingError with complex numpy array and native data types
And yes, I need that psi_ground array to be of complex type, with a lot of precision, even if initially it's populated by real numbers. Later in the main() will get re-populated by complex numbers. Thank you!
psi_ground = np.zeros((N_z_divs+1, N_epsilon_divs+1, N_timesteps_imag+1), dtype=types.complex128)
must be defined inside numba function. The error clearly states that numba is unable to change the values of the psi_ground array.
Below is the modified code
import numpy as np
from numba import jit, types
from cmath import sqrt, exp, sin
N_timesteps_imag = 100
N_epsilon_divs = 60
N_z_divs = 2000
K = N_z_divs # equal to the variable N_z_divs
delta_epsilon = 0.1
delta_z = 0.1
lambd = 1.5
z_max = (N_z_divs/2) * delta_z
epsilon_range = np.linspace(0.0, N_epsilon_divs*delta_epsilon, N_epsilon_divs+1)
z_range = np.linspace(-z_max, z_max, N_z_divs+1)
#jit(nopython=True)
def pop_psiground_t0():
psi_ground = np.zeros((N_z_divs+1, N_epsilon_divs+1, N_timesteps_imag+1), dtype=types.complex128)
for c1 in range(1, psi_ground.shape[0]-1):
for c2 in range(1, psi_ground.shape[1]-1):
zed = (c1 - N_z_divs/2) * delta_z
epsi = c2 * delta_epsilon
psi_ground[c1, c2, 0] = sqrt(3) * epsi * exp(-sqrt(epsi**(2*lambd) + zed**2))
pop_psiground_t0()

Error When Trying to Create Function Grapher

I am trying to make a program using Python that allows the user to pick a function and graph it over specified values. I have this:
import matplotlib.pyplot as plt
import math
import numpy as np
from sympy import Symbol, Derivative, sin, sympify
from sympy.core.sympify import SympifyError
x = Symbol('x')
fx = sympify(input("What is your function? "))
x_min = float(input("Enter x minimum: "))
x_max = float(input("Enter x maximum: "))
x_values = np.linspace(x_min, x_max, 3)
y_values = fx.doit().subs({x:x_values})
plt.plot(x_values, y_values)
plt.show()
I input x**2 for the function, 0 for x_min, and 3 for x_max. The error I get is:
Traceback (most recent call last):
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/sympify.py", line 178, in sympify
expr = parse_expr(a, locals or {}, rational, convert_xor)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/parsing/sympy_parser.py", line 163, in parse_expr
expr = eval(code, global_dict, local_dict) # take local objects in preference
File "<string>", line 1
[Float ('0.' )Float ('1.5' )Float ('3.' )]
^
SyntaxError: invalid syntax
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/joe126/Dropbox/Python/Chapter02.py", line 16, in <module>
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/basic.py", line 831, in subs
so, sn = sympify(o), sympify(n)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/sympify.py", line 180, in sympify
raise SympifyError('could not parse %r' % a)
sympy.core.sympify.SympifyError: SympifyError: "could not parse '[0. 1.5 3. ]'"
What is going wrong? Thanks.
I cannot reproduce the error. I get the same error as Georgy: a shape mismatch when plotting. But why don't you try using lambdify to evaluate the function like this:
import matplotlib.pyplot as plt
import math
import numpy as np
from sympy import Symbol, Derivative, sin, sympify, lambdify
from sympy.core.sympify import SympifyError
x = Symbol('x')
fx = sympify(input("What is your function? "))
x_min = float(input("Enter x minimum: "))
x_max = float(input("Enter x maximum: "))
x_values = np.linspace(x_min, x_max, 3)
fx_lambda = lambdify(x,fx)
y_values = fx_lambda(x_values)
plt.plot(x_values, y_values)
plt.show()
Result for x**2 from 0 to 3

keep getting "only length-1 arrays can be converted to Python scalars"

I kept getting the error only length-1 arrays can be converted to Python scalars. Most people suggest sometimes numpy is not compatible with other existing math functions. but I changed every math function to np functions.
The error states:
Traceback (most recent call last): File "/Users/jimmy/Documents/2.py", line 20, in <module>
eu = mc_simulation(89,102,0.5,0.03,0.3,1000) File "/Users/jimmy/Documents/2.py", line 12, in mc_simulation
ST = s0 * exp((r - 0.5 * sigma ** 2) * T + sigma * a * z) TypeError: only length-1 arrays can be converted to Python scalars
My code:
from numpy import *
import numpy as np
from math import exp
def mc_simulation(s0, K, T, r, sigma, no_t):
random.seed(1000)
z = random.standard_normal(no_t)
ST = s0 * exp((r - 0.5 * sigma ** 2) * T + sigma * np.sqrt(T) * z)
payoff = maximum(ST - K, 0)
eu_call = exp(-r * T) * sum(payoff) / no_t
return eu_call
eu = mc_simulation(89,102,0.5,0.03,0.3,1000)
You don't need math here. Use numpy.exp. Furthermore, consider getting into the habit of not using the * operator with imports.
import numpy as np
np.random.seed(1000)
def mc_simulation(s0, K, T, r, sigma, no_t):
z = np.random.standard_normal(no_t)
ST = s0 * np.exp((r - 0.5 * sigma ** 2) * T + sigma * np.sqrt(T) * z)
payoff = np.maximum(ST - K, 0)
eu_call = np.exp(-r * T) * np.sum(payoff) / no_t
return eu_call
print(mc_simulation(89,102,0.5,0.03,0.3,1000))
3.4054951916465099
To your comment of "why shouldn't I use the * operator": there are a ton of good discussions on why this can create trouble. But here is what the official documentation has to say on that: when you use from numpy import *:
This imports all names except those beginning with an underscore (_).
In most cases Python programmers do not use this facility since it
introduces an unknown set of names into the interpreter, possibly
hiding some things you have already defined.
Your own example illustrates that. If you were to use:
from numpy import *
from math import *
Both have an exp function that gets imported into the namespace as exp. Python might then have trouble knowing which exp you want to use and, as you saw here, they are quite different. The same applies if you have already defined an exp function yourself, or any other function that shares a name with any in those two packages.
In general, be wary of any tutorials you run across that use from x import * consistently.

python complex_ode pass matrix-valued parameters

I'm having some trouble with python's complex_ode solver.
I'm trying to solve the following equation:
dy/dt = -iAy - icos(Omegat)By
where A and B are NxN arrays and the unknown y is an Nx1 array, i is the imaginary unit and Omega is a parameter.
Here's my code:
import numpy as np
from scipy.integrate import ode,complex_ode
N = 3 #linear matrix dim
Omega = 1.0 #parameter
# define symmetric matrices A and B
A = np.random.ranf((N,N))
A = (A + A.T)/2.0
B = np.random.ranf((N,N))
B = (B + B.T)/2.0
# define RHS of ODE
def f(t,y,Omega,A,B):
return -1j*A.dot(y)-1j*np.cos(Omega*t)*B.dot(y)
# define list of parameter
params=[Omega,A,B]
# choose solver: need complex_ode for this ODE
#solver = ode(f)
solver = complex_ode(f)
solver.set_f_params(*params)
solver.set_integrator("dop853")
# set initial value
v0 = np.zeros((N,),dtype=np.float64)
v0[0] = 1.0
# check that the function f works properly
print f(0,v0,Omega,A,B)
# solve-check the ODE
solver.set_initial_value(v0)
solver.integrate(10.0)
print solver.successful()
Running this script produces the error
capi_return is NULL
Call-back cb_fcn_in___user__routines failed.
Traceback (most recent call last):
File "ode_test.py", line 37, in <module>
solver.integrate(10.0)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate
y = ode.integrate(self, t, step, relax)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate
self.f_params, self.jac_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run
tuple(self.call_args) + (f_params,)))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args))
TypeError: f() takes exactly 5 arguments (2 given)
If instead I use solver = ode(f), ie. the real-valued solver, it runs fine. Except that it doesn't solve the ODE I want which is complex-valued :(
I then tried to reduce the number of parameters by making the matrices A and B global variables. This way the only parameter the function f accepts is Omega. The error changes to
capi_return is NULL
Call-back cb_fcn_in___user__routines failed.
Traceback (most recent call last):
File "ode_test.py", line 37, in <module>
solver.integrate(10.0)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate
y = ode.integrate(self, t, step, relax)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate
self.f_params, self.jac_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run
tuple(self.call_args) + (f_params,)))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args))
TypeError: 'float' object has no attribute '__getitem__'
where I figured out that float refers to the parameter Omega [by trying an integer]. Again, "ode" alone works in this case as well.
Last, I tried the same complex valued equation, but now A and B are just numbers. I tried to pass them both as parameters, i.e. params = [Omega,A,B], as well as making them global variables in which case params=[Omega]. The error is the
TypeError: 'float' object has no attribute '__getitem__'
error - the full error is the same as above. And once again this problem does not occur for the real-valued "ode".
I know zvode is an alternative, but it appears to become quite slow for large N. In the real problem I have, A is a diagonal matrix but B is a non-sparse full matrix.
Any insights are much appreciated! I'm interested both in (i) alternative ways to solve this complex-valued ODE with array-valued parameters, and (ii) how to get complex_ode to run :)
Thanks!
It seems like the link that Reti43 posted contains the answer, so let me put it here for the benefit of future users:
from scipy.integrate import complex_ode
import numpy as np
N = 3
Omega = 1.0;
class myfuncs(object):
def __init__(self, f, fargs=[]):
self._f = f
self.fargs=fargs
def f(self, t, y):
return self._f(t, y, *self.fargs)
def f(t, y, Omega,A,B):
return -1j*(A+np.cos(Omega*t)*B).dot(y)
A = np.random.ranf((N,N))
A = (A + A.T)/2.0
B = np.random.ranf((N,N))
B = (B + B.T)/2.0
v0 = np.zeros((N,),dtype=np.float64)
v0[0] = 1.0
t0 = 0
case = myfuncs(f, fargs=[Omega, A, B] )
solver = complex_ode(case.f)
solver.set_initial_value(v0, t0)
solver.integrate([10.0])
print solver.successful()
"""
t1 = 10
dt = 1
while solver.successful() and solver.t < t1:
solver.integrate(solver.t+dt)
print(solver.t, solver.y)
"""
Could maybe someone comment on why this trick does the job?

What causes this error (AttributeError: 'Mul' object has no attribute 'cos') in Python?

I am getting the following error code when trying to evaluate a definite integral in Python.
AttributeError Traceback (most recent call last)
<ipython-input-7-2be8718c68ec> in <module>()
7 x, n = symbols('x n')
8
----> 9 f = (cos(n*x))*(x**2-pi**2)^2
10 integrate(f,(x,-n*pi,n*pi))
11
AttributeError: 'Mul' object has no attribute 'cos'
I have copied my input code below. Thanks for any help.
from pylab import *
from sympy import *
from numpy import *
init_printing(use_unicode=False, wrap_line=False, no_global=True)
x, n = symbols('x n')
f = (cos(n*x))*(x**2-pi**2)^2
integrate(f,(x,-n*pi,n*pi))
Your problem is with namespace clash, here
from sympy import *
from numpy import *
Since both numpy and and sympy have their own definition of cos. The error is telling you that the Mul object (which is n*x) does not have a cosine method, since the interpreter is now confused between the sympy and numpy methods. Do this instead
import pylab as pl
import numpy as np
import sympy as sp
x, n = sp.symbols('x n')
f = (sp.cos(n*x))*(x**2-sp.pi**2)**2
sp.integrate(f,(x,-n*sp.pi,n*sp.pi))
Also note that I have changed ^ to ** as ^ is the Not operator in sympy. Here, I am assuming that you need the symbolic Pi from sympy.core.numbers.Pi and not the numeric one from numpy. If you want the latter, then do this
f = (sp.cos(n*x))*(x**2-np.pi**2)**2
sp.integrate(f,(x,-n*np.pi,n*np.pi))

Categories