让我们假设我需要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定义中的一些变量也不是及时的。
答案 0 :(得分:2)
雅可比基于函数的导数。如果函数f
仅在运行时已知(并且没有诸如线性的约束),则必须自动区分。如果您希望这完全发生(与数值估算相反),则需要使用symbolic computation。查找支持此功能的库的示例here和here。
请注意,雅可比行列式通常取决于状态和时间,因此不可能将其表示为常量矩阵(例如在您的示例中),除非您的问题太无聊以至于无论如何都可以解析它。
答案 1 :(得分:2)
我知道这已经过了很长时间了,但是最近我一直想做同样的事情,并且遇到了很多自动分化(AD)库,它们做得很好。我主要使用Eigen's AD,因为我已经到处使用Eigen。这是example,介绍了如何使用Eigen的AD按照您的要求来获取雅各布卷。
autodiff.org上还有一堆c ++ AD库。
希望这对某人有帮助!