pythonnumba

# numba :cannot determine Numba type of <class 'function'> python

Here is my code.

``````from numba import jit
import numpy as np
import time

from pandas.core.common import flatten
from numba import njit
b_wi=[[1,2,3,4],[6,7,8,9,10,11]] #b_wi is a subset of x
f_wi=[[5,4,2,7,9],[5,4,3,7,2,3,4]]

# @jit(nopython=True)
def stopF_w(x,b_wi,f,di):
if di=='left':
return f[np.searchsorted(-b_wi,-x,side='left')]
if di=='right':
return f[np.searchsorted( b_wi, x,side='right')]
# this f :need to be an element in f_nslst
#b_wi :need to be an element in b_wilst

@njit(parallel=True)
def averageF_w(x,b_wilst,f_nslst,di):
a=np.zeros(x.shape[0])
for b_wi,f in zip(b_wilst,f_nslst):
a[:]  += stopF_w(x,np.asarray(b_wi),np.asarray(f),di)
return a

intval= np.unique(list(flatten(b_wi)))
x=np.concatenate(([-10000],(intval[:-1]+intval[1:])/2,[10000]))  #b_wi is a subset of x. That is why I can use this.
averageF_w(x,b_wi,f_wi,'right')
``````

It raises error: TypingError: cannot determine Numba type of <class 'function'>. Does anyone know how to fix it please? Thank you very much.

Solution

• There are several problems to handle: first, you've commented out the `@jit` decorator of your first function, `stopF_w`.

If you uncomment it, you'll resolve your current error. Unfortunately, you will immediately run into several other errors. if your numba version is up to date, you'll see an error pertaining to "reflected lists".

Basically, your inputs `b_wi` and `f_wi` are lists of variable length lists, which cannot be converted into uniform numpy arrays. E.g.: if instead of `[[1,2,3,4],[6,7,8,9,10,11]]`, if `b_wi` was something like `[[1,2,3, 4, 6], [7, 8, 9, 10, 11]]` (easily convertible to an array of shape (2, 5) then it would work without any problems. To get your variable length lists to work with numba, you need to rely on a Typed List, which is a bit cumbersome.

``````from numba import jit
import numpy as np
import time

from pandas.core.common import flatten
from numba import njit

from numba.typed import List

b_wi=[[1,2,3,4], [6,7,8,9,10,11]]
f_wi=[[5,4,2,7,9], [5,4,3,7,2,3,4]]

###########################
# Create typed Lists
###########################
b_wi_nb = List()
for i in range(len(b_wi)):
b = List()
for j in range(len(b_wi[i])):
b.append(b_wi[i][j])
b_wi_nb.append(b)

f_wi_nb = List()
for i in range(len(f_wi)):
f = List()
for j in range(len(f_wi[i])):
f.append(f_wi[i][j])
f_wi_nb.append(f)
``````

We will use `b_wi_nb` and `f_wi_nb` as inputs later on.

Another problem: the function `stopF_w` has two "if" blocks. If neither condition is met, is may return None, which is unacceptable to numba for your use case. So alongside uncommenting the jit decorator, you also need to change the condition to if-else, or if-elif-else as applicable.

``````@jit(nopython=True)
def stopF_w(x,b_wi,f,di):
if di=='left':
return f[np.searchsorted(-b_wi,-x,side='left')]
else:
return f[np.searchsorted( b_wi, x,side='right')]
``````

After the above changes, numba should work.

``````@jit(nopython=True, parallel=True)
def averageF_w(x, b_wilst, f_nslst, di):
a = np.zeros(x.shape[0])
for b_wi, f in zip(b_wilst,f_nslst):
a  += stopF_w(x, np.asarray(b_wi), np.asarray(f), di)
return a

intval= np.unique(list(flatten(b_wi)))
x=np.concatenate(([-10000],(intval[:-1]+intval[1:])/2,[10000]))

##############################
# initial compiles
##############################
stopF_w(np.arange(1),np.arange(1),np.arange(1),'right')
averageF_w(np.arange(10),np.arange(6).reshape(2, 3),np.arange(6).reshape(2, 3),'right')
##############################

averageF_w(x, b_wi_nb, f_wi_nb,'right')
``````