优化查找复数作为输入
我想知道是否有一个C / C ++库或Matlab代码技术来使用最小化求解器来确定实数和复数。 这是一个代码片段,显示了我想要做的事情。 例如,假设我知道Utilde
,但不知道x
和U
变量。 在给定的Utilde
,我想使用优化( fminsearch
)来确定x
和U
请注意, Utilde
是一个复数。
x = 1.5; U = 50 + 1i*25; x0 = [1 20]; % starting values Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x); xout = fminsearch(@(v)optim(v, Utilde), x0); function diff = optim(v, Utilde) x = v(1); U = v(2); diff = abs( -(Utilde/U) + (1 / exp(2 * x)) * exp( 1i * 2 * x ) );
上面的代码没有收敛到正确的值, xout = 1.7318 88.8760
。 但是,如果U = 50
,这不是一个复数,则xout = 1.5000 50.0000
,这是正确的值。
有没有一种方法在Matlab或C / C ++中确保适当的收敛,给定Utilde
作为复数? 也许我必须更改上面的代码?
-
如果没有办法在Matlab中本地执行此操作,那么问题的一个要点可能就是:是否存在能够处理实数和复数输入的多变量(即Nelder-Mead或类似算法)优化库输出?
-
另一个问题是函数是否收敛。 我不知道它是算法还是函数。 可能我需要在
Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x)
表达式中更改某些内容以使其收敛?
这里的主要问题是这种优化或参数拟合问题没有独特的解决方案。 例如,查看上面的预期和实际结果, Utilde
对于两个( x
, U
)对是等效的(忽略舍入差异),即
Utilde(x = 1.5, U = 50 + 25i) = Utilde(x = 1.7318, U = 88.8760)
虽然我没有深入研究过,但我甚至怀疑对于x
任何值,你可以找到一个计算到Utilde(x, U) = Utilde(x = 1.5, U = 50 + 25i)
因此,这里的解决方案是进一步约束参数拟合问题,以便求解器产生任何可被认为是可接受的解。 或者,重新Utilde
以使任何( x
, U
)对具有唯一值。
更新,8月1日
给定合理的起始值,实际上似乎将x
限制为实值是足够的。 使用上面给出的diff
函数执行无约束的非线性优化,得到以下结果:
x = 1.50462926953244 U = 50.6977768845879 + 24.7676554234729i diff = 3.18731710515855E-06
然而,将起始猜测更改为更远离期望值的值确实产生不同的解决方案,因此将x
限制为实值并不单独提供问题的唯一解决方案。
我已经使用BOBYQA优化器在C#中实现了它 ,但是数字应该与上面相同。 如果你想在Matlab之外尝试,使用std :: complex类和你自己选择的(无约束)非线性C ++优化器,将下面的C#代码转换为C ++代码也应该相对简单。 您可以在这里找到一些不需要梯度计算的C ++兼容代码,并且Numerical Recipes中还提供了各种实现。 例如,您可以在此处在线访问C版本的NR。
供参考,以下是我的C#代码的相关部分:
class Program { private static readonly Complex Coeff = new Complex(-2.0, 2.0); private static readonly Complex UTilde0 = GetUTilde(1.5, new Complex(50.0, 25.0)); static void Main(string[] args) { double[] vars = new[] {1.0, 25.0, 0.0}; // xstart = 1.0, Ustart = 25.0 BobyqaExitStatus status = Bobyqa.FindMinimum(GetObjfnValue, vars.Length, vars); } public static Complex GetUTilde(double x, Complex U) { return U * Complex.Exp(Coeff * x); } public static double GetObjfnValue(int n, double[] vars) { double x = vars[0]; Complex U = new Complex(vars[1], vars[2]); return Complex.Abs(-UTilde0 / U + Complex.Exp(Coeff * x)); } }
fminsearch
的文档说明如何处理限制部分中的复杂数字:
fminsearch
仅对实数进行最小化,即x
必须仅由实数组成,而f(x)
必须仅返回实数。 当x
具有复杂变量时,它们必须分成实部和虚部。
您可以使用real
和imag
函数分别提取实部和虚部。
似乎没有简单的方法可以做到这一点,即使x
和U
都是实数。 对于优化问题, Utilde
的等式Utilde
,因此必须进行修改。
我试图编写自己的Nelder-Mead优化算法版本,以及尝试Powell的方法。 即使我试图修改这些方法,这两个似乎都不能很好地解决这个问题。