寻找含复数函数的最小值的优化方法

0 投票
1 回答
45 浏览
提问于 2025-04-12 22:37

我正在尝试用Python找出一个向量z的值,这个值能让一个函数达到最小值。z可以是矩形形式,比如z = a+b*j,也可以是极坐标形式,z = 大小, 角度。我尝试了几种输入方式,目前在下面的代码块中把它写成了z = complex(cwx,cwy)。我使用了meshgrid来创建可能的向量空间,以便评估这个函数。

这个函数里包含了z和其他一些复数(我把极坐标形式的向量转换成了矩形形式)。这个函数的结果是一个标量,所以应该有某个向量能让它达到最小值。我希望有人能给我指点一下,因为我对优化还很陌生,目前有点迷茫 :| 有没有什么优化函数能很好地处理复数?

from math import radians
from cmath import rect
import numpy as np
import scipy.optimize as opt

# input variables, to be obtained via GUI
w1 = 0.5
w2 = 0.5
a1m = 53
a1p = 280
a2m = 46
a2p = 245
s11m = 1.8
s11p = 338
s21m = 1.1
s21p = 332
cwm_max = 500

f = lambda z: (w1*abs(rect(a1m,radians(a1p)) + complex(cwx,cwy) / rect(s11m,radians(s11p))) +
                w2*abs(rect(a2m,radians(a2p)) + complex(cwx,cwy) / rect(s21m,radians(s21p))))

# create a grid of potential vectors wrapping from 0 to 360 degress with max amplitude = cwm_max:
cwx, cwy = np.meshgrid(np.linspace(-cwm_max,cwm_max,200),np.linspace(-cwm_max,cwm_max,200))

# opt.minimze requires a guess argument
guess = np.array([0, 200])
sol = opt.minimize(f, guess)
print(sol)

我在函数中使用complex(cwx,cwy)时,它不太喜欢。它好像认为我想输入一个标量?

f = lambda z: (w1*abs(rect(a1m,radians(a1p)) + complex(cwx,cwy) / rect(s11m,radians(s11p))) +
                                                   ^^^^^^^^^^^^^^^^
TypeError: only length-1 arrays can be converted to Python scalars

而且opt.minimize()似乎也不是最合适的工具,因为它抛出了各种Traceback错误。


用嵌套循环的暴力破解方法解决了这个问题:

cwm_max = 500 
dim = 1200 
mag_sum = 1000*np.ones((dim,dim)) 

cwx = np.linspace(-cwm_max,cwm_max,dim)
cwy = np.linspace(-cwm_max,cwm_max,dim)

for p in range(dim):
    for q in range(dim):
        mag_sum[p,q] = (w1 * abs(rect(a1m, radians(a1p)) + complex(cwx[p],cwy[q]) / rect(s11m, radians(s11p)))+ w2 * abs(rect(a2m, radians(a2p)) + complex(cwx[p],cwy[q]) / rect(s21m, radians(s21p))))

# rectangular to polar
def polar_deg(z):
    """expects a single complex number in cartesian form (a+bj),
    returns mag & phase (degrees, 0 to 360)"""
    mag, phase_r = cmath.polar(z)
    phase_d = math.degrees(phase_r)
    if phase_d < 0:
        phase_d += 360
    return mag, phase_d

a,b = np.unravel_index(mag_sum.argmin(), mag_sum.shape)
cwz = complex(cwx[a],cwy[b])
cwm, cwp = polar_deg(cwz)

1 个回答

0

使用嵌套循环的暴力破解方法解决了问题:

cwm_max = 500 
dim = 1200 
mag_sum = 1000*np.ones((dim,dim)) 

cwx = np.linspace(-cwm_max,cwm_max,dim)
cwy = np.linspace(-cwm_max,cwm_max,dim)

for p in range(dim):
    for q in range(dim):
        mag_sum[p,q] = (w1 * abs(rect(a1m, radians(a1p)) + complex(cwx[p],cwy[q]) / rect(s11m, radians(s11p)))+ w2 * abs(rect(a2m, radians(a2p)) + complex(cwx[p],cwy[q]) / rect(s21m, radians(s21p))))

# rectangular to polar
def polar_deg(z):
    """expects a single complex number in cartesian form (a+bj),
    returns mag & phase (degrees, 0 to 360)"""
    mag, phase_r = cmath.polar(z)
    phase_d = math.degrees(phase_r)
    if phase_d < 0:
        phase_d += 360
    return mag, phase_d

a,b = np.unravel_index(mag_sum.argmin(), mag_sum.shape)
cwz = complex(cwx[a],cwy[b])
cwm, cwp = polar_deg(cwz)

撰写回答