这里的主要问题是这个优化或参数拟合问题没有唯一的解决方案。例如,查看上面的预期结果和实际结果,Utilde
对于两个 (x
, U
) 对,即
Utilde(x = 1.5, U = 50 + 25i) = Utilde(x = 1.7318, U = 88.8760)
虽然我没有深入研究它,但我什至怀疑对于任何价值x
,你可以找到一个U
计算得出Utilde(x, U) = Utilde(x = 1.5, U = 50 + 25i)
.
因此,这里的解决方案是进一步约束参数拟合问题,以便求解器产生any可以认为是可以接受的解决方案。或者,重新制定Utilde
对任何(x
, U
) pair.
8 月 1 日更新
给定合理的起始值,实际上似乎足以限制x
成为真正有价值的。使用以下方法执行无约束非线性优化diff
上面的函数,我得到以下结果:
x = 1.50462926953244
U = 50.6977768845879 + 24.7676554234729i
diff = 3.18731710515855E-06
然而,将起始猜测更改为距期望值更远的值确实会产生不同的解决方案,因此限制x
成为真正的价值观并不能单独提供问题的唯一解决方案。
我已经在 C# 中实现了这个,使用BOBYQA https://github.com/cureos/csbobyqa优化器,但数字应该与上面相同。如果您想在 Matlab 之外尝试,使用以下命令将下面的 C# 代码转换为 C++ 代码也应该相对简单:标准::复杂 http://www.cplusplus.com/reference/std/complex/类和您自己选择的(无约束)非线性 C++ 优化器。你可以找到一些不需要梯度计算的 C++ 兼容代码here http://plato.asu.edu/sub/nlounres.html#function,并且 Numerical Recipes 中还提供了各种实现。例如,您可以在线访问 NR 的 C 版本here http://apps.nrbook.com/c/index.html.
作为参考,以下是我的 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));
}
}