【问题标题】:Optimization to find complex number as input寻找复数作为输入的优化
【发布时间】:2012-07-13 13:39:15
【问题描述】:

我想知道是否有 C/C++ 库或 Matlab 代码技术可以使用最小化求解器来确定实数和复数。这是一个代码 sn-p 显示我想做的事情。例如,假设我知道Utilde,但不知道xU 变量。我想使用优化(fminsearch)来确定xU,给定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 是正确的值。

在将Utilde 作为复数的情况下,Matlab 或 C/C++ 中是否有办法确保正确收敛?也许我必须更改上面的代码?

  • 如果在 Matlab 中没有本地方法可以做到这一点,那么也许可以 问题的要点是:是否存在多变量(即 Nelder-Mead 或类似算法)优化库,能够 处理真实和复杂的输入和输出?

  • 还有一个问题是函数是否收敛。一世 不知道是算法还是函数。我是否需要更改 Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x) 表达式中的某些内容以使其收敛?

【问题讨论】:

  • 根据我的经验:使用这些内置的最小化程序通常会给您带来更多麻烦而不是帮助。如果您确实需要这样做,我会坚持使用 Python - 使用 MATLAB 可能不会更好。
  • 当然——在 Python 中设置这个优化问题的最佳方法是什么?是否有 Python 工具可以使用复数进行优化?
  • @NicholasKinar 我现在对复数的算术规则有点不确定,但是如果你只想在优化中检索最上面的xU值,会不会将diff 指定为diff = abs( Utilde - U * (1 / exp(2 * x)) * exp( 1i * 2 * x ) ) 是否更合适?或者从微分的角度来看,差的平方而不是绝对差更好?
  • @AndersGustafsson:感谢您的评论。嗯……我试过了,但我仍然无法让所有 xU 收敛。例如,x = 7U = 10。也许我做错了什么。
  • @NicholasKinar 我进一步研究了这个问题并提供了答案。请看看你是否同意。

标签: c++ c matlab mathematical-optimization numerical-methods


【解决方案1】:

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

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

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

【讨论】:

  • 实际上,这在这里可能无济于事,因为您的函数会为实际输入返回复杂的输出。但是,如果您的函数是实值的,那么我认为这种方法会起作用。
  • diff 变量不是总是实数,因为这是复数的绝对值吗?如果是这样的话,那我该如何拆分实部和虚部呢?
  • @NicholasKinar 你是对的。您的功能似乎需要实际输入并具有实际价值。为什么你说fminsearch 不能与复杂的Utilde 正确融合?您是否通过分析找到了最小值?
  • 嗯,不知道是不是功能的问题,还是这里有别的问题。我会调查的。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    这里的主要问题是这个优化或参数拟合问题没有唯一的解决方案。例如,查看上面的预期结果和实际结果,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)U

    因此,这里的解决方案是进一步约束参数拟合问题,以便求解器产生可以被认为可接受的任何解决方案。或者,将 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++ 兼容代码here,并且在 Numerical Recipes 中也有各种可用的实现。比如你可以在线访问C版的NRhere

    作为参考,以下是我的 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));
        }
    }
    

    【讨论】:

    • 感谢您富有洞察力的回答。我如何重新制定 Utilde 以使任何 (x, U) 对具有唯一值?
    • @NicholasKinar Utilde 代表什么?你能链接到一些说明这一点的上下文吗?
    • Utilde(作为复数)是频域中两个数字的乘积的输出。 (1 / exp(2 * x)) * exp( 1i * 2 * x) 是滤波器内核,U 是 Gabor 变换信号。这是一个地震 Q 滤波应用程序,在 pg 上有一个类似的方程。 128本书地震逆Q滤波:scribd.com/doc/45448335/SEISMIC-INVERSE-q-FILTERING。你能推荐一本关于这类优化问题的好参考书吗?也许如果U未知,这是一个盲反卷积问题?
    • @NicholasKinar 请看我的鼓励 :-) 更新这个答案。
    • 谢谢,安德斯;非常感谢。感谢您为我提供了一个出色的框架和代码来解决这个问题。我会再试验一下指数函数参数,然后再回复你。
    猜你喜欢
    • 2023-03-24
    • 2021-10-27
    • 2011-02-08
    • 2011-10-10
    • 2018-03-24
    • 2011-11-15
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多