/// <summary> /// 行列の逆行列計算メソッド /// </summary> /// <param name="mat"></param> /// <returns></returns> public static Matrix Inverse(Matrix mat) { int n = mat.height; Matrix ret = mat.Clone(); LUP lum = DecomposeLUP(mat); if (lum == null) { throw new Exception("Unable to compute inverse"); } double[] b = new double[n]; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; j++) { if (i == lum.perm[j]) { b[j] = 1.0; } else { b[j] = 0.0; } } double[] x = HelperSolve(lum.mat, b); for (int j = 0; j < n; ++j) { ret[j][i] = x[j]; } } return(ret); }
/// <summary> /// 行列の行列式計算メソッド /// </summary> /// <param name="mat"></param> /// <returns></returns> public static double Det(Matrix mat) { LUP lum = DecomposeLUP(mat); if (lum == null) { throw new Exception("Unable to compute MatrixDeterminant"); } double ret = lum.toggle; Parallel.For(0, lum.mat.height, i => { ret *= lum.mat[i][i]; }); return(ret); }
/// <summary> /// 行列のLUP分解メソッド /// </summary> /// <param name="mat"></param> /// <returns></returns> private static LUP DecomposeLUP(Matrix mat) { LUP ret = new LUP(); ret.toggle = 1; ret.mat = mat.Clone(); ret.perm = new int[mat.height]; Parallel.For(0, mat.height, i => { ret.perm[i] = i; }); for (int j = 0; j < mat.height - 1; j++) { double colMax = Math.Abs(ret.mat[j][j]); // largest val in col j int pRow = j; for (int i = j + 1; i < mat.height; ++i) { if (ret.mat[i][j] > colMax) { colMax = ret.mat[i][j]; pRow = i; } } if (pRow != j) // swap rows { double[] rowPtr = ret.mat[pRow]; ret.mat[pRow] = ret.mat[j]; ret.mat[j] = rowPtr; int tmp = ret.perm[pRow]; // and swap perm info ret.perm[pRow] = ret.perm[j]; ret.perm[j] = tmp; ret.toggle = -ret.toggle; // row-swap toggle } if (Math.Abs(ret.mat[j][j]) < 1.0E-20) { return(null); // consider a throw } for (int i = j + 1; i < mat.height; ++i) { ret.mat[i][j] /= ret.mat[j][j]; for (int k = j + 1; k < mat.height; k++) { ret.mat[i][k] -= ret.mat[i][j] * ret.mat[j][k]; } } } return(ret); }