我正在尝试编写一个计算方阵矩阵指数的方法。在这种情况下,矩阵是值的正方形数组:
并且该方法应返回值:
然而,当我运行我的代码时,我得到一系列值取决于我重新排列的位数,非特别接近预期值。
该方法的工作方式是利用矩阵的幂级数,因此基本上对于矩阵A,n步和单位矩阵I:
exp(A)= I + A + 1/2!* AA + 1/3!* AAA + ... + 1 / n!* AAA ..
代码如下。我遇到问题的方法是指数方法(Matrix A,int nSteps)。附带的方法是封闭的,Matrix对象接受参数(int m,int n)来创建一个大小为double [m] [n]的数组。
public static Matrix multiply(Matrix m1, Matrix m2){
if(m1.getN()!=m2.getM()) return null;
Matrix res = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m1.getM(); i++){
for(int j = 0; j < m2.getN(); j++){
res.getArray()[i][j] = 0;
for(int k = 0; k < m1.getN(); k++){
res.getArray()[i][j] = res.getArray()[i][j] + m1.getArray()[i][k]*m2.getArray()[k][j];
}
}
}
return res;
}
public static Matrix identityMatrix(int M){
Matrix id = new Matrix(M, M);
for(int i = 0; i < id.getM(); i++){
for(int j = 0; j < id.getN(); j++){
if(i==j) id.getArray()[i][j] = 1;
else id.getArray()[i][j] = 0;
}
}
return id;
}
public static Matrix addMatrix(Matrix m1, Matrix m2){
Matrix m3 = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m3.getM(); i++){
for(int j = 0; j < m3.getN(); j++){
m3.getArray()[i][j] = m1.getArray()[i][j] + m2.getArray()[i][j];
}
}
return m3;
}
public static Matrix scaleMatrix(Matrix m, double scale){
Matrix res = new Matrix(m.getM(), m.getN());
for(int i = 0; i < res.getM(); i++){
for(int j = 0; j < res.getN(); j++){
res.getArray()[i][j] = m.getArray()[i][j]*scale;
}
}
return res;
}
public static Matrix exponential(Matrix A, int nSteps){
Matrix runtot = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
double factorial = 1.0;
for(int i = 1; i <= nSteps; i++){
sum = Matrix.multiply(Matrix.scaleMatrix(sum, factorial), A);
runtot = Matrix.addMatrix(runtot, sum);
factorial /= (double)i;
}
return runtot;
}
所以我的问题是,我应该如何修改我的代码,以便我可以输入矩阵和多个时间步长来计算所述时间步之后所述矩阵的指数?
答案 0 :(得分:2)
我的方法是保留两个累加器:
请注意,与M_n有一个很好的递归关系:M_ {n + 1} = M_n * A /(n + 1)
哪个收益率:
public static Matrix exponential(Matrix A, int nSteps){
Matrix seriesTerm = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
for(int i = 1; i <= nSteps; i++){
seriesTerm = Matrix.scaleMatrix(Matrix.multiply(seriesTerm,A),1.0/i);
sum = Matrix.addMatrix(seriesTerm, sum);
}
return sum;
}
我完全理解实现此类算法可以带给您的那种刺激。但如果这不是一个爱好项目,我同意你应该使用一个库来做这种事情。精确而有效地进行这样的计算确实不是一件小事,而且需要重新发明巨大的轮。