見出し画像

ガウス・ジョルダン法

参考
改訂第3版 C言語によるはじめてのアルゴリズム入門 
河西 朝雄 (著) p98

行列の基本操作は以下にまとめてあるが、この記事の下の方にもコピペした。
https://note.com/alchan/n/neaf2b8b9a9e7

        public static double[,] GaussianJordanEliminationSolve(double[,] A, double[] b)
       {
           int row_count = A.GetLength(0);//row
           int col_count = A.GetLength(1);//col

           var ex = AddCol(A, b);

           for (int pivot_index = 0; pivot_index < row_count; pivot_index++)
           {
               //行交換実行
               if (ex[pivot_index, pivot_index] == 0)
               {
                   _pivoting(ex, pivot_index);
               }

               //ピボット行のピボット要素を1にするため
               //ピボット行を全部ピボット要素で除算            
               var w = 1 / ex[pivot_index, pivot_index];
               for (int col_index = 0; col_index < col_count + 1; col_index++)
               {
                   ex[pivot_index, col_index] *= w;
               }

               //ピボット列のピボット行以外の項を上も下も0に掃き出す
               //ピボット列以降の項は修正される
               for (int row_index = 0; row_index < row_count; row_index++)
               {
                   //pivot行以外は死なす
                   if (row_index == pivot_index) { continue; }

                   //ピボット列のピボット行の項の以外の項
                   double leading_coefficient = ex[row_index, pivot_index];
                   //ピボット列より左は0になっているはず
                   for (int col_index = pivot_index; col_index < col_count + 1; col_index++)
                   {
                       ex[row_index, col_index] -= ex[pivot_index, col_index] * leading_coefficient;
                   }
               }
           }
           return ex;
       }


      public static double[,] AddCol(double[,] matrix, double[] new_col)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数

           double[,] ret = new double[row_count, col_count+1];

           for (int row_index = 0; row_index < row_count; row_index++)
           {
               for (int col_index = 0; col_index < col_count+1; col_index++)
               {
                   if (col_index == col_count)
                   {
                       ret[row_index, col_index] = new_col[row_index];
                   }
                   else
                   {
                       ret[row_index, col_index] = matrix[row_index, col_index];
                   }
               }
           }
           return ret;
       }


       public static int _pivoting(double[,] A, int pivot_index)
       {
           var abs_max_index = _get_pivoting_index(A, pivot_index);
           if (pivot_index == abs_max_index) { return 0; }

           if(ChangeRow(A, pivot_index, abs_max_index)==0)
           {
               //Changeしてない
               return 0;
           }
           else
           {
               //Changeした
               //pivot交換した
               return 1;
           }
       }
         public static int _get_pivoting_index(double[,] A, int pivot_index)
       {
           //pivot列の
           //pivot+1行以降で
           //絶対値最大の行のインデックスを返す

           int row_count = A.GetLength(0);//rowの個数

           double abs_max = 0;
           int abs_max_row_index = pivot_index;

           //pivotエレメントは最後の一つまで走査される場合と
           //一つ手前で止まる場合がある
           //if (A.GetLength(0) - 1 < abs_max_row_index) { abs_max_row_index = pivot_index; }

           for (int row_index = pivot_index; row_index < row_count; row_index++)
           {
               var temp = Math.Abs(A[row_index, pivot_index]);
               if (abs_max < temp)
               {
                   abs_max = temp;
                   abs_max_row_index = row_index;
               }
           }

           return abs_max_row_index;
       }




この記事が気に入ったらサポートをしてみませんか?