■ 逆行列の求め方
* 逆行列の求め方は以下の通り。 [1] 掃き出し法 (Row reduction)・ガウス・ジョルダンの消去法 (Gauss–Jordan elimination) [2] ガウスの消去法 (Gaussian elimination) [3] LU分解 (LU Factorization) etc...http://mugichoko.hatenablog.com/entry/2018/04/05/184100
[1] 掃き出し法
* とりあえず「単位行列E」の形にすることを目標(=連立方程式を解くことになる)に 対角成分を1に、それ以外の成分を0にするhttps://linky-juku.com/row-reduction/
https://www.youtube.com/watch?v=Da73Ra7gWKU
[2] ガウスの消去法
* 行列表示された連立方程式の係数行列を上三角行列に変形(前進消去)し 今度は逆方向に解を求めていく(後退代入)という手法 + 前進消去 (Forward Elimination) : 文字を1つずつ消していく操作 + 後退代入 (Backward Substitution) : 1成分ずつ答えを求めていく操作https://mathtrain.jp/gausssyokyo
http://imagingsolution.blog.fc2.com/blog-entry-106.html
[3] LU分解
* 行列を下三角行列L(Lower triangle matrix)と上三角行列U(Upper triangle matrix)の積LUに分解すること 【下三角行列 L】 【上三角行列 U】 | □ □ □ | | □ ■ ■ | | ■ □ □ | | □ □ ■ | | ■ ■ □ | | □ □ □ | Ax = b (A : 行列、b : 行列) => LUx = b で、Aを「L」と「U」という行列に分解する
■ サンプル
例1:掃き出し法
using System; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { var inputs= new double[][]{ new double[] {1,2,0,-1}, new double[] {-1,1,2,0}, new double[] {2,0,1,1}, new double[] {1,-2,-1,1} }; CalculateInverseMatrix(inputs, out double[][] outputs); this.label1.Text = string.Empty; foreach (var rows in outputs) { foreach (var value in rows) { this.label1.Text += value + ", "; } this.label1.Text += "\n"; } } private static bool CalculateInverseMatrix( double[][] targetMatrixes, out double[][] outInverseMatrixes) { var dataNumber = targetMatrixes.GetLength(0); outInverseMatrixes = new double[dataNumber][]; //単位行列を作る for (int i = 0; i < dataNumber; i++) { outInverseMatrixes[i] = new double[dataNumber]; for (int j = 0; j < dataNumber; j++) { outInverseMatrixes[i][j] = (i == j) ? 1.0f : 0.0f; } } // 掃き出し法 for (int i = 0; i < dataNumber; i++) { if (targetMatrixes[i][i] == 0) { return false; } var tempValue = 1.0 / targetMatrixes[i][i]; for (int j = 0; j < dataNumber; j++) { targetMatrixes[i][j] *= tempValue; outInverseMatrixes[i][j] *= tempValue; } for (int j = 0; j < dataNumber; j++) { if (i != j) { tempValue = targetMatrixes[j][i]; for (int k = 0; k < dataNumber; k++) { targetMatrixes[j][k] -= targetMatrixes[i][k] * tempValue; outInverseMatrixes[j][k] -= outInverseMatrixes[i][k] * tempValue; } } } } return true; } } }出力結果
2, 2, -1, 3, -4, -5, 3, -7, 3, 4, -2, 5, -7, -8, 5, -11,
■ 補足:double型 ⇒ float型に変えた場合
* 以下のように変換すると、誤差が出てダメだった。 (以下の「出力結果(float型)」参照)変換前
private static bool CalculateInverseMatrix( double[][] targetMatrixes, out double[][] outInverseMatrixes) etc...変換後
private static bool CalculateInverseMatrix( float[][] targetMatrixes, out float[][] outInverseMatrixes) etc...
出力結果(float型)
誤差が出て使えない...1.999998, 1.999998, -0.9999989, 2.999997, -3.999996, -4.999995, 2.999997, -6.999992, 2.999997, 3.999997, -1.999998, 4.999995, -6.999993, -7.999992, 4.999995, -10.99999,