scipy.integrate.quad ошибка функции ctypes quadpack.error: quad: первый аргумент является указателем на функцию ctypes с неверной подписью

Я пытаюсь использовать scipy.integrate.nquad с функцией ctypes. Я точно следовал инструкциям по более быстрой интеграции с использованием Типы.

ctypes интеграцию можно выполнить в несколько простых шагов:

  1. Напишите подынтегральную функцию на C с сигнатурой функции double f(int n, double args[n]), где args — массив, содержащий аргументы функции f.

//testlib.c

double f(int n, double args[n])    
{
   return args[0] - args[1] * args[2]; //corresponds to x0 - x1 * x2
}
  1. Теперь скомпилируйте этот файл в разделяемую/динамическую библиотеку (с этим поможет быстрый поиск, поскольку он зависит от ОС). Пользователь должен связать любые используемые математические библиотеки и т.д. В Linux это выглядит так:

$ gcc -shared -o testlib.so -fPIC testlib.c

Выходная библиотека будет называться testlib.so, но может иметь другое расширение файла. Теперь создана библиотека, которую можно загрузить в Python с помощью ctypes.

  1. Загрузите разделяемую библиотеку в Python с помощью ctypes и установите restypes и argtypes — это позволит Scipy правильно интерпретировать функцию:

>>> import ctypes

>>> from scipy import integrate

>>> lib = ctypes.CDLL('/**/testlib.so') # Use absolute path to testlib

>>> func = lib.f # Assign specific function to name func (for simplicity)

>>> func.restype = ctypes.c_double

>>> func.argtypes = (ctypes.c_int, ctypes.c_double)

Note that the argtypes will always be (ctypes.c_int, ctypes.c_double) regardless of the number of parameters, and restype will always be ctypes.c_double.

  1. Теперь интегрируйте функцию библиотеки, как обычно, используя nquad:

>>> integrate.nquad(func, [[0,10],[-10,0],[-1,1]])

(1000.0, 1.1102230246251565e-11)

However, at the final step, I didn't get the result of the integral, but the following errors instead:

>>> integrate.nquad(func,[[0,1.0],[-2.0,3.0],[1.0,2.0]])

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 618, in nquad
      return _NQuad(func, ranges, opts).integrate(*args)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate

    value, abserr = quad(f, low, high, args=args, **opt)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad

    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad

    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate

    value, abserr = quad(f, low, high, args=args, **opt)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad

    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad

    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate

    value, abserr = quad(f, low, high, args=args, **opt)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad

    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)

  File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad

    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)

quadpack.error: quad: first argument is a ctypes function pointer with incorrect signature

Я использую gcc-4.4.7, python 2.6.6, numpy-1.7.1, scipy-0.13.3.


person Bo Fu    schedule 23.06.2015    source источник
comment
double args[n] в сигнатурах функций идентичен double *args   -  person o11c    schedule 24.06.2015
comment
Вы подписались быстрее -интеграция-с-типами. Кажется, это новая функция, которой нет в 0,14 или 0,13 .   -  person nymk    schedule 24.06.2015
comment
Я использую scipy-0.15.1. integrate.nquad(func,[[0,1.0],[-2.0,3.0],[1.0,2.0]]) дает (-1.25, 1.4017986003800292e-13), где func — это функция ctypes в вашем вопросе.   -  person nymk    schedule 24.06.2015
comment
@nymk ты прав. Пробовал 0.15.1, работает.   -  person Bo Fu    schedule 24.06.2015


Ответы (1)


Тип аргумента должен быть: ctypes.POINTER(ctypes.c_double)

Но рассматривали ли вы возможность использования cffi? Помимо того, что он быстрее, чем ctypes, вам также не нужно вручную писать аргументы, просто скопируйте объявления C и позвольте cffi проанализировать их.

person o11c    schedule 23.06.2015
comment
scipy.integrate.quad не понимает cffi, работает только ctypes. - person pv.; 24.06.2015