Search code examples
pythoncscipytypeerrorctypes

Wrapping C code with ctypes and using Scipy in python to do optimization with it


I have successfully wrapped some C code using ctypes and brought into Python. I am trying to use Scipy to do optimization on it using the direct method and I am getting this error: TypeError: this function takes at least 2 arguments (1 given). Below is my code and the print statments and errors that I am getting:

in file ctype_tutorial.py:

import ctypes
from ctypes import *
import numpy as np
from numpy import ctypeslib
from scipy.optimize import minimize
from scipy.optimize import direct, Bounds, basinhopping

clibrary = ctypes.CDLL(r"C:\Users\mhaja\OneDrive\Desktop\Github\Honours\ctypes\clibrary.so")

styblinski_tang = clibrary.styblinski_tang

styblinski_tang.argtypes = [ctypes.c_int, ctypes.c_int]
styblinski_tang.restype = ctypes.c_int


print(styblinski_tang(1, 1))

result = direct(styblinski_tang, [[-4,4], [-4,4]])
print(result.x, result.fun, result.nfev)

in clibrary.c file:

#include <stdio.h>
#include <math.h>

int styblinski_tang(int x, int y){
    return 0.5 * (pow(x, 4) - 16*pow(x, 2) + 5*x + pow(y, 4) - 16*pow(y, 2) + 5*y);
}

Error that I am getting:

-10
Traceback (most recent call last):
  File "c:\Users\mhaja\OneDrive\Desktop\Github\Honours\ctypes\ctypes_tutorial.py", line 44, in <module>
    result = direct(styblinski_tang, [[-4,4], [-4,4]])
  File "C:\Users\mhaja\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\scipy\optimize\_direct_py.py", line 256, in direct
    x, fun, ret_code, nfev, nit = _direct(
  File "C:\Users\mhaja\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\scipy\optimize\_direct_py.py", line 249, in _func_wrap
    f = func(x)
TypeError: this function takes at least 2 arguments (1 given)

I can see that I am successfully wrapping the function cause when I try the input of 1,1 on the function I get the correct output of -10 but when I try to use Scipy on it, i get the error. I think it might be due to the ctypes and how it converts between C and python. Any help will be appreciated with either Ctypes or Scipy. I am doing this for my honours so please help.

update: It was suggested to me to add a wrapper method so I did and this is the updated code:

import ctypes
from ctypes import *
import numpy as np
from numpy import ctypeslib
from scipy.optimize import minimize
from scipy.optimize import direct, Bounds, basinhopping

clibrary = ctypes.CDLL(r"C:\Users\mhaja\OneDrive\Desktop\Github\Honours\ctypes\clibrary.so")

styblinski_tang = clibrary.styblinski_tang

styblinski_tang.argtypes = [ctypes.c_int, ctypes.c_int]
styblinski_tang.restype = ctypes.c_int


print(styblinski_tang(1, 1))

# Using a wrapper function 
def foo(xy):
    x,y = xy
    return styblinski_tang(x, y)

print(foo([1,1]))

result = direct(foo, [[-4,4], [-4,4]])
print(result.x, result.fun, result.nfev)

This helped a bit but I am still getting this error message:

-10
-10
Traceback (most recent call last):
  File "c:\Users\mhaja\OneDrive\Desktop\Github\Honours\ctypes\ctypes_tutorial.py", line 51, in <module>
    result = direct(foo, [[-4,4], [-4,4]])
  File "C:\Users\mhaja\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\scipy\optimize\_direct_py.py", line 256, in direct
    x, fun, ret_code, nfev, nit = _direct(
  File "C:\Users\mhaja\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\scipy\optimize\_direct_py.py", line 249, in _func_wrap
    f = func(x)
  File "c:\Users\mhaja\OneDrive\Desktop\Github\Honours\ctypes\ctypes_tutorial.py", line 47, in foo
    return styblinski_tang(x, y)
ctypes.ArgumentError: argument 1: TypeError: wrong type

Solution

  • Try a wrapper function

    def foo(xy):
       x,y = xy
       # or x=xy[0]; y=xy[1]
       return styblinski_tang(x, y)