zangmolk
zangmolk

Reputation: 23

using Numba for scipy fsolve, but get error

I want use numba for scipy.fsolve:

from scipy.optimize import fsolve
from numba import njit

@njit
def FUN12():
    XGUESS=[8.0,7.0]

    X =[0.0,0.0]
    try:
         X = fsolve(FCN3, XGUESS)
    except:
         print("error")
    return X

@njit
def FCN3(X):
    F=[0.0,0.0]
    F[0]=4.*pow(X[0],2)-3.*pow(X[1],1)-7
    F[1] = 5.*X[0]  -2. * pow(X[1] , 2)+8
    return F

FUN12()

I got this error for my code: numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend) Untyped global name 'fsolve': Cannot determine Numba type of <class 'function'>

Upvotes: 2

Views: 240

Answers (2)

Nin17
Nin17

Reputation: 3472

Whilst you can't use fsolve itself from within a numba function, there are alternatives that you can use. fsolve is a wrapper of the minpack subroutines hybrd and hybrj, so you can use a numba compatible wrapper of these routines instead. For this, you can use NumbaMinpack or cminpack_numba (disclaimer I'm the author) which wraps a c translation of minpack instead as in my experience it is faster.

This is how you can solve the given problem with these packages:

import cminpack_numba
import NumbaMinpack
from numba import cfunc
import numpy as np

@cfunc(NumbaMinpack.minpack_sig)
def fcn3_numbaminpack(x, fvec, args):
    fvec[0] = 4.*pow(x[0],2)-3.*pow(x[1],1)-7
    fvec[1] = 5.*x[0]  -2. * pow(x[1] , 2)+8
    

@cfunc(cminpack_numba.hybrd_sig)
def fcn3_cminpack_numba(udata, n, x, fvec, iflag):
    fvec[0] = 4.*pow(x[0],2)-3.*pow(x[1],1)-7
    fvec[1] = 5.*x[0]  -2. * pow(x[1] , 2)+8
    return 0

print(FUN12()) # From dankal444's answer
print(NumbaMinpack.hybrd(fcn3_numbaminpack.address, np.array([8.0, 7.0])))
print(cminpack_numba.hybrd1(fcn3_cminpack_numba.address, np.array([8.0, 7.0])))

Output:

[2. 3.]
(array([2., 3.]), array([5.04476461e-10, 2.50027554e-10]), True, 1)
(array([2., 3.]), array([5.04476461e-10, 2.50027554e-10]), 1)

Timings:

%timeit FUN12()
%timeit NumbaMinpack.hybrd(fcn3_numbaminpack.address, np.array([8.0, 7.0]))
%timeit cminpack_numba.hybrd1(fcn3_cminpack_numba.address, np.array([8.0, 7.0]))
14.7 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
3.34 µs ± 40 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
2.68 µs ± 7.68 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Upvotes: 1

dankal444
dankal444

Reputation: 4148

Numba compatible code is only some subset of Python and Numpy functions.

You should not run fsolve inside numba function.

You should remove njit decorator from FUN12 function. You can keep it for FCN3.

from scipy.optimize import fsolve
from numba import njit

# @njit  remove this line, 
def FUN12():
    XGUESS=[8.0,7.0]

    X =[0.0,0.0]
    try:
         X = fsolve(FCN3, XGUESS)
    except:
         print("error")
    return X

@njit
def FCN3(X):
    F=[0.0,0.0]
    F[0]=4.*pow(X[0],2)-3.*pow(X[1],1)-7
    F[1] = 5.*X[0]  -2. * pow(X[1] , 2)+8
    return F

FUN12()

Upvotes: 1

Related Questions