Nicholaswogan / NumbaMinpack

Python wrapper of Minpack (root finding) which can be called from within numba functions.
MIT License
31 stars 2 forks source link

add shape of array as argument iin optimize? #1

Open MolettoLobos opened 2 years ago

MolettoLobos commented 2 years ago

I use this function for do a fitting in numba

from NumbaMinpack import minpack_sig, lmdif
import numpy as np
import numba as nb

shape_c_array = 1000
@nb.jit
def fit_gaussian_custom(X, A, B, C, D):
    return  A * np.exp(-0.5 * ((X - B) / C) ** 2) + D
@nb.cfunc(minpack_sig)
def fit_gaussian_custom_optimize(u_, fvec, args_):
    u = nb.carray(u_, (4,)) #for variable predictions for gaussian fitting(A,B,C,D)
    args = nb.carray(args_, (shape_c_array,))
    A,B,C,D = u
    lenarray_c = shape_c_array/2
    x = args[:lenarray_c]
    y = args[lenarray_c:]
    for i in range(lenarray_c):
        fvec[i] = fit_gaussian_custom(x[i], A, B,C,D) - y[i]
optimize_ptr = fit_gaussian_custom_optimize.address

However, when i cannot change the value of array shape because i cannot add a fourth argument into the nb.cfunc. How can i add the array shape inside of function?

Regards,

Nicholaswogan commented 2 years ago

One approach is

@njit
def objective_1(u, arr_len, arr):
    # ...
    return yvec

def make_minpack_func(arr_len, arr):
    @cfunc(minpack_sig)
    def objective(u_, fvec, args):
        # convert u_ to numpy array
        fvec_1 = objective_1(u, arr_len, arr)
        # load fvec_1 into fvec
    return objective

Problem with this approach is that the objective will need to be re-compiled every time you change arr, and arr_len. There are other workarounds that are more compilcated

HannoSpreeuw commented 3 months ago

Interesting question, because I thought NumbaMinpack's lmdif and hybrd were about solving and root finding. Does this mean that with NumbaMinpack you can also do least squares fitting from within a njit compiled function, similar to a call to a routine from LEVMAR, e.g. slevmar_dif?