I have a function defined as below
\begin{equation}
f(x) = e^{-k1/x}x^{-2}(k1/x+56)^{81}
\end{equation}
Now I want to find integrate the function from 0 to infinite.
\begin{equation}
S = \int^{\inf}_{0} f(x) dx
\end{equation}
And then I want to find the cumulative function defined as below
\begin{equation}
CDF(p) = \int^{p}_{0} \frac{f(x)}{S} dx
\end{equation}
To do so, I wrote a program in Python.
from matplotlib import pyplot as plt
from scipy.integrate import quad
from math import pi, exp
import numpy as np
def func(x, k1, n):
w = -1.8*n+15 # scale the function down.
return (10**w)*exp(-k1/x)*x**(-2)*(k1/x+56)**n
def S(k1, n):
return quad(func, 0, 1e+28, args=(k1, n))[0] + quad(func, 1e+28, 1e+33, args=(k1, n))[0]
def CDF(x, k1, n):
return quad(func, 0, x, args=(k1, n))[0]/S(k1, n)
k1 = 7.7e+27 # When it's <3, CDF does not generate error.
n = 81
print(S(k1, n))
print(CDF(1.1e+27, k1, n))
But unfortunately, the CDF(1.1e+27) throws the error "results out of range".
How could I obtain CDF(1.1e+27)?
Related
I am new to Cython. I have written a pyx file that returns a 2D Numpy or a memoryview array.
Here is the pyx code:
import numpy as np
import cython
cimport numpy as np
from libc.math cimport int
#cython.wraparound(False)
#cython.boundscheck(False)
#cython.cdivision(True)
#cython.nonecheck(False)
cdef class TwoDMatrix():
''' make a two dimensional matrix '''
cdef int N
def __init__(self,N):
self.N = N
cpdef twoD(self, int [:,:] vector,str array):
if array == 'numpy':
state = 2*np.random.randint(2,size=(self.N,self.N))-1
return state
else:
vec=self.initialise(vector,self.N)
return vec
cdef int [:,:] initialise(self, int [:,:] s,k) :
cdef int i,j
for i in range(k+1):
for j in range(k+1):
if np.random.rand() <0.5:
s[i,j] = -1
else:
s[i,j] = 1
return s
And here is the main py file where I give input:
import numpy as np
import main
def matrix():
N = 10
vector = main.TwoDMatrix(N)
spin = np.zeros((N,N),dtype=np.int32)
print(f"from numpy: {vector.twoD(spin,'numpy')}")
print(f"from memoryview: {vector.twoD(spin,'memoryview')}")
print("program successfully exited")
if __name__ == "__main__":
matrix()
The problem is for N >5 , when I run in terminal it always shows a segmentation fault(core dumped) message at the bottom. And for N>1, a similar following message is shown:
"corrupted size vs. prev_size while consolidating
Aborted (core dumped)"
Why is this message popping up? Is there anything that I should consider about memory allocation?
The segmentation fault is due to out-of-bounds accesses. Indeed, you create matrices of size (N,N) while initialise iterate over range range(0, k+1) where k=N. Thus you need to either use bigger matrices or to fix the two nested loops so to iterate over range(0, k) / range(0, N).
I have a cython code that I try to parallelize using a prange cython command. The code compiles but when I run it, it runs only on a single thread/core. I read in other posts that most of the cases this was due to the gil which was not properly released but when I look at my code I do not see where this happens. Would you have any idea about what is wrong with my code ?
UPDATE:
compiler: gcc 7.5
cython: 0.29.21
OS: ubuntu 20.04
Cython code:
import cython
from cython.parallel import prange
cimport numpy as cnp
import numpy as np
cdef extern from "math.h" nogil:
double floor(double x)
double ceil(double x)
double sqrt(double x)
cdef inline double round(double r) nogil:
return floor(r + 0.5) if (r > 0.0) else ceil(r - 0.5)
#cython.cdivision(True)
#cython.boundscheck(False)
#cython.wraparound(False)
cdef int atoms_in_shell_inner(double[:,:] coords, int[:,:] indexes, double[:,:] cell, double[:,:] rcell, double[:] boxed_center, double r2, int mol_idx) nogil:
cdef double r, rx, ry, rz, sdx, sdy, sdz, x, y, z, x_boxed, y_boxed, z_boxed
cdef int at_idx, i
# Loop over the selected atoms j of molecule i
for 0 <= i < indexes.shape[0]:
if indexes[mol_idx,i] == -1:
return 0
at_idx = indexes[mol_idx,i]
x = coords[at_idx,0]
y = coords[at_idx,1]
z = coords[at_idx,2]
# Convert real coordinates to box coordinates
x_boxed = x*rcell[0,0] + y*rcell[0,1] + z*rcell[0,2]
y_boxed = x*rcell[1,0] + y*rcell[1,1] + z*rcell[1,2]
z_boxed = x*rcell[2,0] + y*rcell[2,1] + z*rcell[2,2]
sdx = x_boxed - boxed_center[0]
sdy = y_boxed - boxed_center[1]
sdz = z_boxed - boxed_center[2]
# Apply the PBC to the box coordinates distance vector between atom j and the center of the shell
sdx -= round(sdx)
sdy -= round(sdy)
sdz -= round(sdz)
# Convert back the box coordinates distance vector to real coordinates distance vector
rx = sdx*cell[0,0] + sdy*cell[0,1] + sdz*cell[0,2]
ry = sdx*cell[1,0] + sdy*cell[1,1] + sdz*cell[1,2]
rz = sdx*cell[2,0] + sdy*cell[2,1] + sdz*cell[2,2]
# Compute the squared norm of the distance vector in real coordinates
r = rx*rx + ry*ry + rz*rz
# If the distance is below the cutoff mark the molecule i as being in the shell
if r < r2:
return 1
return 0
#cython.cdivision(True)
#cython.boundscheck(False)
#cython.wraparound(False)
def atoms_in_shell(double[:,:] coords,
double[:,:] cell,
double[:,:] rcell,
int[:,:] indexes,
cnp.int32_t center,
cnp.float64_t radius):
cdef int i, n_molecules
cdef double[:] shell_center = coords[center,:]
cdef double[:] boxed_center = np.empty(3,dtype=np.float)
cdef int[:] in_shell = np.zeros(indexes.shape[0],dtype=np.int32)
n_molecules = indexes.shape[0]
boxed_center[0] = shell_center[0]*rcell[0,0] + shell_center[1]*rcell[0,1] + shell_center[2]*rcell[0,2]
boxed_center[1] = shell_center[0]*rcell[1,0] + shell_center[1]*rcell[1,1] + shell_center[2]*rcell[1,2]
boxed_center[2] = shell_center[0]*rcell[2,0] + shell_center[1]*rcell[2,1] + shell_center[2]*rcell[2,2]
# Loop over the molecules
for i in prange(n_molecules,nogil=True):
in_shell[i] = atoms_in_shell_inner(coords, indexes, cell, rcell, boxed_center, radius*radius, i)
return in_shell.base
setup.py file:
from Cython.Distutils import build_ext
from distutils.core import setup, Extension
import numpy
INCLUDE_DIR = [numpy.get_include()]
EXTENSIONS = [Extension('atoms_in_shell',
include_dirs=INCLUDE_DIR,
sources=["atoms_in_shell.pyx"],
extra_compile_args = ["-O3", "-ffast-math", "-march=native", "-fopenmp" ],
extra_link_args=['-fopenmp']),
]
setup(ext_modules=EXTENSIONS, cmdclass={'build_ext': build_ext})
Python code:
from atoms_in_shell import atoms_in_shell
import numpy as np
coords = np.random.uniform(-1000.0,1000.0,(500000000,3))
cell = np.identity(3)
rcell = np.identity(3)
indexes = np.empty((10000,6),dtype=np.int32)
indexes.fill(-1)
for row in indexes:
n_atoms = np.random.randint(1,6)
row[:n_atoms] = np.random.choice(coords.shape[0]-1,n_atoms)
print(atoms_in_shell(coords, cell, rcell, indexes, 5, 1))
I am just starting out learning about Cython. I have some code written in pure Python, and started to convert it to Cython. The first function is below (both versions). I expected Cython to be faster, but there is no difference in speed. Why is this? Am I doing something wrong, or is it expected?
import numpy as np
cimport numpy as np
import time
ctypedef np.int8_t DTYPE_int
cpdef np.ndarray[DTYPE_int, ndim=2] init_population(int N, int pop_size):
cdef np.ndarray[DTYPE_int, ndim=2] p
cdef np.ndarray[DTYPE_int, ndim=2] idx
cdef double t1
t1=time.time()
p = np.full((pop_size, N), np.arange(N, dtype=np.int8))
idx = np.random.rand(p.shape[0], p.shape[1]).argsort(axis=1).astype(np.int8)
print("%.20f" % (time.time() - t1))
return np.take_along_axis(p, idx, axis=1)
def py_init_population(N, pop_size):
t1=time.time()
p = np.full((pop_size, N), np.arange(N, dtype=np.int8))
idx = np.random.rand(p.shape[0], p.shape[1]).argsort(axis=1).astype(np.int8)
print("%.20f" % (time.time() - t1))
return np.take_along_axis(p, idx, axis=1)
init_population(1000, 1000)
py_init_population(1000, 1000)
Output:
7.24499845504760742188
7.26293945312500000000
I have an optimization problem (optimze by changing x[0] and x[1]), where one of the constraints is a function, that uses the same constant variables (a and b) as the optimization function.
min f(x, a, b)
x[0] <= 100
x[1] <= 500
g(x, a, b) >= 0.9
But I am not sure how to realize the connection between function f and g:
x0 = np.array([10, 100])
bnds = ((0, 500), (0, 5000))
arguments = (100, 4) # This are varibles a and b
cons = ({'type': 'ineq', 'fun': lambda x: x[0]},
{'type': 'ineq', 'fun': lambda x: x[1]},
{'type': 'ineq', 'fun': lambda x: g(x, 100, 4)-0.9})
res = minimize(f, x0, args=arguments, method='SLSQP', bounds=bnds, constraints=cons)
print(res.x)
>> x: array([10, 5000])
But using this results function g results in
g(x,a,b)=0.85434
There is an optimal solution with x=[452, 4188], where
g(x,a,b)=0.901839
How do I need to adapt the constraints, that g(x,a,b) is valid.
Edit: Obviously the optimization is not sucessful:
print(res)
>> fun: 1778.86301369863
>> jac: array([1.00019786e+09, 9.31503296e-01])
>> message: 'Inequality constraints incompatible'
>> nfev: 4
>> nit: 1
>> njev: 1
>> status: 4
>> success: False
>> x: array([ 10., 5000.])
Thanks a lot.
UvW
f() and g() are not convex, not smooth and derivates are not available. Nevertheless my questioned aimed for the right syntax (using a function as a constraint). So I tried it with two "simpler" functions (see executeable code below) and it worked. So I assume, that my syntax is right and the problem lies with optimization method "SLSQP".
Is there an optimization method within the SCIPY package (some kind of Evolutionary algorithm) that I can use to solve my problem with g() and f()
not convex,
not smooth and
derivates are not available?
import numpy as np
from scipy.optimize import minimize
def g(x, a, b):
return (x[0]+x[1]+a+b)/100
def f(x, a, b):
return (x[0]*a+x[1]*b)*g(x, a, b)
x0 = np.array([0, 0]) bnds = ((0, 30), (0, 20)) arguments = (2, 3) # This are varibles a and b
cons = ({'type': 'ineq', 'fun': lambda x: x[0]},
{'type': 'ineq', 'fun': lambda x: x[1]},
{'type': 'ineq', 'fun': lambda x: g(x, 2, 3)-0.5}) #<--My question was about the correct syntax of that constraint
res = minimize(f, x0, args=arguments, method='SLSQP', bounds=bnds, constraints=cons)
print(res)
>> fun: 52.50000000000027
>> jac: array([2.05000019, 2.55000019])
>> message: 'Optimization terminated successfully.'
>> nfev: 20
>> nit: 5
>> njev: 5
>> status: 0
>> success: True
>> x: array([30., 15.])
I have just begun using lasagne and Theano to do some machine learning on Python.
I am trying to modify the softmax class in Theano. I want to change how the activation function(softmax) is calculated. Instead of dividing e_x by e_x.sum(axis=1), I want to divide e_x by sum of three consecutive numbers.
For instance, the result will be as follows:
sm[0] = e_x[0]/(e_x[0]+e_x[1]+e_x[2])
sm[1] = e_x[1]/(e_x[0]+e_x[1]+e_x[2])
sm[2] = e_x[2]/(e_x[0]+e_x[1]+e_x[2])
sm[3] = e_x[3]/(e_x[3]+e_x[4]+e_x[5])
sm[4] = e_x[4]/(e_x[3]+e_x[4]+e_x[5])
sm[5] = e_x[5]/(e_x[3]+e_x[4]+e_x[5])
and so on...
The problem is that I cannot quite grasp how theano carries out the computation.
Here is my main question. Does it suffice to just change the perform() function in the softmax class?
Here is the original perform() function:
def perform(self, node, input_storage, output_storage):
x, = input_storage
e_x = numpy.exp(x - x.max(axis=1)[:, None])
sm = e_x / e_x.sum(axis=1)[:, None]
output_storage[0][0] = sm
Here is my modified perform()
def myPerform(self, node, input_storage, output_storage):
x, = input_storage
e_x = numpy.exp(x - x.max(axis=1)[:, None])
sm = numpy.zeros_like(e_x)
for i in range(0,symbolCount):
total = e_x[3*i] + e_x[3*i+1] + e_x[3*i+2]
sm[3*i] = e_x[3*i]/total
sm[3*i+1] = e_x[3*i+1]/total
sm[3*i+2] = e_x[3*i+2]/total
output_storage[0][0] = sm
With the current code, I am getting 'unorderable types:int()>str()' error when I use the predict method in lasagne.
For something like this you're probably better off constructing a custom softmax via symbolic expressions rather than creating (or modifying) an operation.
Your custom softmax can be defined in terms of symbolic expressions. Doing it this way will give you gradients (and other Theano operation bits and pieces) "for free" but might run slightly slower than a custom operation could.
Here's an example:
import numpy
import theano
import theano.tensor as tt
x = tt.matrix()
# Use the built in softmax operation
y1 = tt.nnet.softmax(x)
# A regular softmax operation defined via ordinary Theano symbolic expressions
y2 = tt.exp(x)
y2 = y2 / y2.sum(axis=1)[:, None]
# Custom softmax operation
def custom_softmax(a):
b = tt.exp(a)
b1 = b[:, :3] / b[:, :3].sum(axis=1)[:, None]
b2 = b[:, 3:] / b[:, 3:].sum(axis=1)[:, None]
return tt.concatenate([b1, b2], axis=1)
y3 = custom_softmax(x)
f = theano.function([x], outputs=[y1, y2, y3])
x_value = [[.1, .2, .3, .4, .5, .6], [.1, .3, .5, .2, .4, .6]]
y1_value, y2_value, y3_value = f(x_value)
assert numpy.allclose(y1_value, y2_value)
assert y3_value.shape == y1_value.shape
a = numpy.exp(.1) + numpy.exp(.2) + numpy.exp(.3)
b = numpy.exp(.4) + numpy.exp(.5) + numpy.exp(.6)
c = numpy.exp(.1) + numpy.exp(.3) + numpy.exp(.5)
d = numpy.exp(.2) + numpy.exp(.4) + numpy.exp(.6)
assert numpy.allclose(y3_value, [
[numpy.exp(.1) / a, numpy.exp(.2) / a, numpy.exp(.3) / a, numpy.exp(.4) / b, numpy.exp(.5) / b, numpy.exp(.6) / b],
[numpy.exp(.1) / c, numpy.exp(.3) / c, numpy.exp(.5) / c, numpy.exp(.2) / d, numpy.exp(.4) / d, numpy.exp(.6) / d]
]), y3_value