2012-07-13 17 views
6

我想知道是否有C/C++库或Matlab代码技术来确定使用最小化求解器的实数和复数。这是一个代码片段,显示我想要做什么。例如,假设我知道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是合适的值。

有没有在Matlab或C/C++中确保正确收敛的方法,假设Utilde为复数?也许我必须更改上面的代码?

  • 如果没有办法在Matlab本身做到这一点,那么也许这个问题的一个 要点是这样的:有一个多变量(即 内尔德 - 米德或类似的算法)优化库,能够使用 来处理真实和复杂的输入和输出?

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

+0

从我的经验:使用这些内置的最小化过程往往给你更多的麻烦而不是帮助。如果你确实需要这样做,我会坚持Python - 用MATLAB它可能不会更好。 – 2012-07-13 17:16:42

+0

当然 - 设置此优化问题的最佳方式是什么?有没有可以使用复数来优化的Python工具? – 2012-07-13 23:06:15

+0

@NicholasKinar现在我对复数的算术规则有点不确定,但是如果您只想在优化中检索最上面的'x'和'U'值,那么指定'diff 'as'diff = abs(Utilde -U *(1/exp(2 * x))* exp(1i * 2 * x))'?或者从差异的角度来看,差异平方而不是绝对差异更好呢? – 2012-07-24 21:07:07

回答

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

UPDATE,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中也提供了各种实现。例如,您可以访问NR在线here的C版本。

供参考,在这里是我的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)); 
    } 
} 
+0

谢谢你的洞察力的答案。我该如何重新配置​​'Utilde'来为任何'(x,U)'对赋一个唯一值? – 2012-07-31 13:57:53

+0

@NicholasKinar'Utilde'代表什么?你能链接到一些情况下,这是说明? – 2012-07-31 14:07:08

+0

Utilde(作为复数)是频域中两个数字乘积的输出。 '(1/exp(2 * x))* exp(1i * 2 * x)'是滤波器内核,'U'是Gabor变换信号。这是一个地震Q滤波应用,在pg上有一个类似的方程。 “地震反Q滤波”的书籍128:http://www.scribd.com/doc/45448335/SEISMIC-INVERSE-q-FILTERING。你能否就这种类型的优化问题提出一本很好的参考书?也许如果'U'未知,这是一个盲解卷积问题? – 2012-07-31 14:46:25

2

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

fminsearch只有最大限度地减少在实数,也就是x必须只为实数和f(x)绝只返回实际的数字。当x有复杂的变量时,它们必须分成实部和虚部。

您可以使用功能realimag分别提取实部和虚部。

+0

实际上,这可能在这里没有帮助,因为你的函数为真实输入返回一个复杂的输出。如果你的函数是实值的,那么我认为这种方法是可行的。 – zroth 2012-07-13 17:40:43

+0

由于这是复数的绝对值,是不是'diff'变量总是实数?如果是这种情况,那我该如何分解为实部和虚部? – 2012-07-13 23:04:53

+0

@NicholasKinar你是对的。你的功能似乎需要真正的投入,并且是实实在在的。你为什么说'fminsearch'与复杂的'Utilde'没有适当的衔接?你是否发现分析的最小值? – zroth 2012-07-20 18:32:45

0

似乎没有简单的方法来做到这一点,即使xU都是实数。 Utilde的公式不适合优化问题,因此必须对其进行修改。

我试着编写我自己版本的Nelder-Mead优化算法,以及试过鲍威尔的方法。即使我试图修改这些方法,对于这个问题也没有效果。