Mam obecnie funkcję Fortran, którą chcę zoptymalizować za pomocą SciPy owijając ją przy pomocy Ctypes. czy to możliwe? Być może popełniłem błąd w mojej implementacji. Na przykład załóżmy, że mam:Niepoprawny wynik z scipy.optimize.minimize użyty w funkcji Fortran przy użyciu ctypów
cost.f90
module cost_fn
use iso_c_binding, only: c_float
implicit none
contains
function sin_2_cos(x,y) bind(c)
real(c_float) :: x, y, sin_2_cos
sin_2_cos = sin(x)**2 * cos(y)
end function sin_2_cos
end module cost_fn
że mogę skompilować z:
gfortran -fPIC -shared -g -o cost.so cost.f90
a następnie spróbuj znaleźć (lokalne) minimum z:
kosztów .py
#!/usr/bin/env python
from ctypes import *
import numpy as np
import scipy.optimize as sopt
cost = cdll.LoadLibrary('./cost.so')
cost.sin_2_cos.argtypes = [POINTER(c_float), POINTER(c_float)]
cost.sin_2_cos.restype = c_float
def f2(x):
return cost.sin_2_cos(c_float(x[0]), c_float(x[1]))
# return np.sin(x[0])**2 * np.cos(x[1])
# print(f2([1, 1]))
# print(f2([0.5 * np.pi, np.pi]))
print(sopt.minimize(f2, (1.0, 1.0), options={'disp': True}, tol=1e-8))
I ex pect lokalne minimum f2 (pi/2, pi) = -1. Kiedy wywołuję f2 z zwracaną wartością cost.sin_2_cos, "minimimum" jest podawane po początkowym odgadnięciu (1, 1). Jeśli wywołasz f2 z wartością zwracaną "Python", optymalizacja znajdzie prawidłowe minimum.
Próbowałem przedefiniować sin_2_cos, aby przyjąć wejście wymiarowe (2), ale widziałem podobne zachowanie. Być może muszę wywołać sin_2_cos bezpośrednio przy zminimalizowaniu (ale w jaki sposób powinienem określić c_float dla argumentów)? Wszelkie przemyślenia są doceniane!
Edytuj: W komentarzu poniżej zauważ, że dwie skomentowane linie print(f2(...))
dają oczekiwane wartości. Dlatego uważam, że funkcja Fortran jest poprawnie wywoływana przez funkcję Python f2.
Musisz dodać co najmniej (mogą występować inne problemy) atrybut "value" do argumentów, zobacz http://www.fortran90.org/src/best-practices.html # using-ctypes –
Dlaczego muszę to zrobić? Jeśli odkomentuję wywołania f2, działa poprawnie. Wyszczególniona strona nie wyjaśnia, dlaczego "wartość" jest tam, ani nie używa jej we wcześniejszym przykładzie "iso_c_binding". Pamiętaj, że dodanie wartości nie rozwiązuje problemu. –
Zmieniłem tytuł na bardziej szczegółowy. Zakładam "Tak, może." nie byłoby dla ciebie odpowiednią odpowiedzią. –