优化查找复数作为输入

我想知道是否有一个C / C ++库或Matlab代码技术来使用最小化求解器来确定实数和复数。 这是一个代码片段,显示了我想要做的事情。 例如,假设我知道Utilde ,但不知道xU变量。 在给定的Utilde ,我想使用优化( fminsearch )来确定xU 请注意, 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对于两个( xU )对是等效的(忽略舍入差异),即

 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以使任何( xU )对具有唯一值。

更新,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具有复杂变量时,它们必须分成实部和虚部。

您可以使用realimag函数分别提取实部和虚部。

似乎没有简单的方法可以做到这一点,即使xU都是实数。 对于优化问题, Utilde的等式Utilde ,因此必须进行修改。

我试图编写自己的Nelder-Mead优化算法版本,以及尝试Powell的方法。 即使我试图修改这些方法,这两个似乎都不能很好地解决这个问题。