用C ++计算雅可比矩阵(符号数学)

时间:2017-09-16 11:52:00

标签: c++ boost

简介

让我们假设我需要Jacobian矩阵用于以下ODE集:

dxdt[ 0 ] = -90.0 * x[0] - 50.0 * x[1];
dxdt[ 1 ] = x[0] + 3*x[1];
dxdt[ 2 ] = x[1] + 50*x[2];

在Matlab / Octave中,这很容易:

syms x0 x1 x2;
f = [-90.0*x0-50.0*x1, x0+3*x1, x1+50*x2]
v=[x0, x1, x2]
fp = jacobian(f,v)

这将产生以下输出矩阵:

[-90  -50  0 ]
[ 1    3   0 ]
[ 0    1   50]

我需要什么

现在我想在C ++中重现相同的结果。我之前无法计算雅可比行列式并对其进行硬编码,因为它将取决于用户输入和时间。所以我的问题是:怎么做?通常对于数学运算,我使用Boost库,但在这种情况下我找不到任何解决方案。 implicit systems中只有关于此的简短说明,但以下代码不起作用:

sys.second( x , jacobi , t )

它还请求时间(t),因此它可能不会生成解析形式的解析。我是否误解了这些文件?或者我应该使用其他功能?我宁愿呆在Boost中,因为我需要Jacobian为ublas::matrix,我想避免转换。

修改

更具体地说,我将在rosenbrock4 ODE解算器中使用雅可比行列式。示例here - 第47-52行。我需要自动生成这个结构,因为ODE集可能会在以后更改,我想避免手动重写Jacobian。 ODE定义中的一些变量也不是及时的。

2 个答案:

答案 0 :(得分:2)

雅可比基于函数的导数。如果函数f仅在运行时已知(并且没有诸如线性的约束),则必须自动区分。如果您希望这完全发生(与数值估算相反),则需要使用symbolic computation。查找支持此功能的库的示例herehere

请注意,雅可比行列式通常取决于状态和时间,因此不可能将其表示为常量矩阵(例如在您的示例中),除非您的问题太无聊以至于无论如何都可以解析它。

答案 1 :(得分:2)

我知道这已经过了很长时间了,但是最近我一直想做同样的事情,并且遇到了很多自动分化(AD)库,它们做得很好。我主要使用Eigen's AD,因为我已经到处使用Eigen。这是example,介绍了如何使用Eigen的AD按照您的要求来获取雅各布卷。

autodiff.org上还有一堆c ++ AD库。

希望这对某人有帮助!