将复数作为输入进行优化
Optimization to find complex number as input
我想知道是否有C/C++库或Matlab代码技术可以使用最小化求解器来确定实数和复数。这里有一个代码片段,显示了我想做的事情。例如,假设我知道Utilde
,但不知道x
和U
变量。在给定Utilde
的情况下,我想使用优化(fminsearch
)来确定x
和U
。注意,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)
表达式中的某些内容以使其收敛?
这里的主要问题是,这个优化或参数拟合问题没有唯一的解决方案。例如,从上面的预期和实际结果来看,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++兼容代码,在Numerical Recipes中也有各种实现。例如,您可以在此处在线访问NR的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));
}
}
fminsearch
的文档在限制部分介绍了如何处理复数:
fminsearch
只在实数上最小化,即x
必须只由实数组成,f(x)
必须只返回实数。当x
有复杂的变量时,它们必须分为实部和虚部。
可以使用函数real
和imag
分别提取实部和虚部。
似乎没有简单的方法可以做到这一点,即使x
和U
都是实数。对于优化问题,Utilde
的方程不是适定的,因此必须对其进行修改。
我试着编写我自己版本的Nelder-Mead优化算法,并尝试了Powell的方法。两者似乎都不能很好地解决这个问题,即使我试图修改这些方法。
- 空基优化子对象的地址
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 2D数组来自文本输入,中间有空格
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 检查输入是否不是整数或数字
- 正在尝试了解输入验证循环
- 读取文件并输入到矢量中
- C++如何通过用户输入删除列表元素
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何使用用户输入在C++中正确填充2D数组
- C++MySQL C api用户输入行
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 用户定义函数中的指针和输入
- std::unordered_map 如果输入大小已知,如何优化批量插入
- 如何优化C 中的输入/输出
- 优化的c++代码,时间复杂度为O(n2),空间复杂度为0(1),用于后续输入
- 将复数作为输入进行优化
- C++ 标准输入的 IO 优化和字符串处理