6

我想知道是否有 C/C++ 库或 Matlab 代码技术来使用最小化求解器确定实数和复数。这是一个代码片段,显示了我想做的事情。例如,假设我知道Utilde,但不知道xU变量。我想使用 optimization( fminsearch) 来确定xand U,给定Utilde. 请注意,这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)表达式中的某些内容以使其收敛吗?

4

3 回答 3

2

这里的主要问题是这个优化或参数拟合问题没有唯一的解决方案。例如,查看上面的预期结果和实际结果,对于两个 ( , ) 对Utilde来说是等价的(忽略舍入差异),即xU

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)

因此,这里的解决方案是进一步约束参数拟合问题,以便求解器产生可以被认为可接受的任何解决方案。或者,重新制定Utilde任何 ( x, U) 对的唯一值。

更新,8 月 1 日

给定合理的起始值,实际上似乎限制x为实值就足够了。使用上面公式化的函数执行无约束非线性优化diff,我得到以下结果:

x = 1.50462926953244
U = 50.6977768845879 + 24.7676554234729i
diff = 3.18731710515855E-06

但是,将初始猜测更改为与期望值更远的值确实会产生不同的解决方案,因此限制x为实值并不能单独为问题提供唯一的解决方案。

我已经在 C# 中使用BOBYQA优化器实现了这一点,但数字应该与上面相同。如果您想在 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));
    }
}
于 2012-07-31T07:32:12.083 回答
2

的文档说明了如何在限制部分fminsearch处理复数:

fminsearchonly 对实数进行最小化,即x必须只包含实数并且f(x)必须只返回实数。当x有复变量时,它们必须分成实部和虚部。

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

于 2012-07-13T17:22:54.520 回答
0

似乎没有简单的方法可以做到这一点,即使两者x都是U实数。方程对于Utilde优化问题不是适定的,因此必须对其进行修改。

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

于 2012-07-24T18:41:09.407 回答