Я пытаюсь свести к минимуму функцию комплексной (векторной) переменной, используя scipy.optimize
. Мои результаты пока показывают, что это может быть невозможно. Чтобы исследовать проблему, я выполнил простой пример - свести к минимуму 2-норму комплексного вектора со смещением:
import numpy as np
from scipy.optimize import fmin
def fun(x):
return np.linalg.norm(x - 1j * np.ones(2), 2)
sol = fmin(fun, x0=np.ones(2) + 0j)
Выход
Optimization terminated successfully.
Current function value: 2.000000
Iterations: 38
Function evaluations: 69
>>> sol
array([-2.10235293e-05, 2.54845649e-05])
Очевидно, что решение должно быть
array([0.+1.j, 0.+1.j])
Разочарованный этим результатом, я также попробовал scipy.optimize.minimize
:
from scipy.optimize import minimize
def fun(x):
return np.linalg.norm(x - 1j * np.ones(2), 1)
sol = minimize(fun, x0=np.ones(2) + 0j)
Выход
>>> sol
fun: 2.0
hess_inv: array([[ 9.99997339e-01, -2.66135332e-06],
[-2.66135332e-06, 9.99997339e-01]])
jac: array([0., 0.])
message: 'Optimization terminated successfully.'
nfev: 24
nit: 5
njev: 6
status: 0
success: True
x: array([6.18479071e-09+0.j, 6.18479071e-09+0.j])
Нехорошо. Я попытался указать все возможные методы minimize
(по мере необходимости поставляя якобиан и гессиан), но ни один из них не достигает правильного результата. Большинство из них вызывают ComplexWarning: Casting complex values to real discards the imaginary part
, указывая на то, что они не могут правильно обрабатывать сложные числа.
Возможно ли это вообще с помощью scipy.optimize
?
Если так, я был бы очень признателен, если кто-нибудь скажет мне, что я делаю неправильно.
Если нет, возможно, у вас есть предложения для альтернативных инструментов оптимизации (для Python), которые позволяют это?
Методы минимизации SciPy работают только с реальными аргументами. Но минимизация на комплексном пространстве C n сводится к минимизации на R 2n алгебра комплексных чисел никогда не входит в рассмотрение. Таким образом, добавив две обертки для преобразования из C n в R 2n и обратно, вы можете оптимизировать более сложные числа.
def real_to_complex(z): # real vector of length 2n -> complex of length n
return z[:len(z)//2] + 1j * z[len(z)//2:]
def complex_to_real(z): # complex vector of length n -> real of length 2n
return np.concatenate((np.real(z), np.imag(z)))
sol = minimize(lambda z: fun(real_to_complex(z)), x0=complex_to_real(np.ones(2) + 0j))
print(real_to_complex(sol.x)) # [-7.40376620e-09+1.j -8.77719406e-09+1.j]
Вы упоминаете Якобиана и Гессиана... но минимизация имеет смысл только для вещественнозначных функций, и они никогда не дифференцируемы относительно комплексных переменных. В любом случае, якобиан и гессиан должны были бы вычисляться по R 2n рассматривая реальную и мнимую части как отдельные переменные.