見出し画像

ガウスの消去法

だいたいの理屈はここ

ガウスの消去法

       //前進消去
       public static (double[,] A, double[] b) ForwardElimination(double[,] A, double[] b)
       {
           int row_count = A.GetLength(0);//rowの個数
           int col_count = A.GetLength(1);//colの個数
           if (row_count != col_count) { throw new Exception(); }

           int pivot_count = row_count;
           //拡大係数行列
           var ex_matrix = AddCol(A, b);

           for (int pivot_index = 0; pivot_index < pivot_count - 1; pivot_index++)
           {
               //ピボット選択が必要
               if (ex_matrix[pivot_index, pivot_index] == 0)
               {
                   _pivoting(ex_matrix, pivot_index);
               }

               //ピボットから下の全ての行(pivot_count + 1)
               for (int row_index = pivot_index + 1; row_index < row_count; row_index++)
               {
                   var pivot_term = ex_matrix[pivot_index, pivot_index];
                   //各行の0でない先頭(この項をpivot行の先頭を用いて0にしていく)
                   var leading_coefficient = ex_matrix[row_index, pivot_index];
                   var ratio = -leading_coefficient / pivot_term;//ピボット行との比

                   var pivot_row = GetRow(ex_matrix, pivot_index);//ピボット行
                   var m_row = Multiple(pivot_row, ratio);//row_index行の先頭を0にできるようになったピボット行
                   var target_row = GetRow(ex_matrix, row_index);//先頭を0にすべき行
                   var added = Add(target_row, m_row);//0でない先頭が0に更新された
                   SetRow(ex_matrix, row_index, added);
               }
           }
           return (RemoveCol(ex_matrix, pivot_count), GetCol(ex_matrix, pivot_count));
       }
       //後退代入
       public static double[] BackSubstitution(double[,] A, double[] b)
       {
           double[] x = new double[b.Length];
           for (int pivot_index = x.Length - 1; pivot_index >= 0; pivot_index--)
           {
               var tb = b[pivot_index];
               //初回は実行されない
               for (int col_index = A.GetLength(1) - 1; col_index > pivot_index; col_index--)
               {
                   //pivot行のpivotより右のセルをbに統合していく
                   tb -= A[pivot_index, col_index] * x[col_index];
               }
               tb /= A[pivot_index, pivot_index];
               x[pivot_index] = tb;
           }
           return x;
       }
       
       //ガウス消去法
       public static double[] GaussianElimination(double[,] A, double[] b)
       {
           (var tA, var tb) = ForwardElimination(A, b);
           return BackSubstitution(tA, tb);
       }

Pivot

        public static int _get_pivoting_index(double[,] A, int pivot_index)
       {
           int row_count = A.GetLength(0);//rowの個数

           double abs_max = 0;
           int 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;
       }

       //行交換実行関数
       //行交換したかしてないかは行列式の計算に関連する(したら*-1)
       //行t交換した=> return 1;
       //行交換してない=> return 0;
       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;
           }
       }

行と列のGet,Set

        #region 行と列の操作

       //一つの行列を左右に割る
       public static (double[,], double[,]) SplitEx(double[,] matrix, int split_col_count)
       {
           int row_count = matrix.GetLength(0);
           int col_count = matrix.GetLength(1);
           double[,] left = new double[row_count, split_col_count];
           double[,] right = new double[row_count, col_count - split_col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   if (split_col_count - 1 < col_index)
                   {
                       right[row_index, col_index - split_col_count] = matrix[row_index, col_index];
                   }
                   else
                   {
                       left[row_index, col_index] = matrix[row_index, col_index];
                   }
               }
           }
           return (left, right);
       }

       public static double[] GetRow(double[,] matrix, int row_index)
       {
           //int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           double[] ret = new double[col_count];
           //row固定、col走査
           for (int col_index = 0; col_index < col_count; col_index++)
           {
               ret[col_index] = matrix[row_index, col_index];
           }
           return ret;
       }
       
       public static double[] GetCol(double[,] matrix, int col_index)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           //int col_count = matrix.GetLength(1);//colの個数
           double[] ret = new double[row_count];
           //col固定、row走査
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               ret[row_index] = matrix[row_index, col_index];
           }
           return ret;
       }
       public static void SetRow(double[,] matrix, int row_index, double[] new_row)
       {
           //int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           for (int col_index = 0; col_index < col_count; col_index++)
           {
               //入力配列が短い場合は0で埋める
               //必然的に、長い場合は切り落とされる
               if (new_row.Length - 1 < col_index)
               {
                   matrix[row_index, col_index] = 0;
               }
               matrix[row_index, col_index] = new_row[col_index];
           }
       }
       public static void SetCol(double[,] matrix, int col_index, double[] new_col)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           //int col_count = matrix.GetLength(1);//colの個数
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //入力配列が短い場合は0で埋める
               //必然的に、長い場合は切り落とされる
               if (new_col.Length - 1 < row_index)
               {
                   matrix[row_index, col_index] = 0;
               }
               matrix[row_index, col_index] = new_col[row_index];
           }
       }

       public static double[,] GetCols(double[,] matrix, int start_col_index)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           int ret_row_count = row_count;
           int ret_col_count = col_count - start_col_index;
           double[,] ret = new double[ret_row_count, ret_col_count];
           //ret側走査
           for (int row_index = 0; row_index < ret_row_count; row_index++)
           {
               //row固定、col走査
               for (int col_index = 0; col_index < ret_col_count; col_index++)
               {
                   ret[row_index, col_index] = matrix[row_index, start_col_index + col_index];
               }
           }
           return ret;
       }
       
       //指定indexから最後までとっちゃう
       public static double[,] GetRows(double[,] matrix, int start_row_index)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           int ret_row_count = row_count - start_row_index;
           int ret_col_count = col_count;
           double[,] ret = new double[ret_row_count, ret_col_count];
           //ret側走査
           for (int row_index = 0; row_index < ret_row_count; row_index++)
           {
               //row固定、col走査
               for (int col_index = 0; col_index < ret_col_count; col_index++)
               {
                   ret[row_index, col_index] = matrix[start_row_index + row_index, col_index];
               }
           }
           return ret;
       }

Add

       public static double[,] AddRow(double[,] matrix, double[] new_row)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           double[,] ret = new double[row_count+1, col_count];
           for (int row_index = 0; row_index < row_count+1; row_index++)
           {
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   if(row_index==row_count)
                   {
                       ret[row_index, col_index] = new_row[col_index];
                   }
                   else
                   {
                       ret[row_index, col_index] = matrix[row_index, col_index];
                   }
               }
           }
           return ret;
       }
       
       public static double[,] AddRow(double[,] matrix, double[,] new_rows)
       {
           int source_row_count = matrix.GetLength(0);
           int total_row_count = matrix.GetLength(0) + new_rows.GetLength(0);//rowの個数
           int total_col_count = matrix.GetLength(1);//colの個数
           double[,] ret = new double[total_row_count, total_col_count];
           for (int row_index = 0; row_index < total_row_count; row_index++)
           {
               for (int col_index = 0; col_index < total_col_count; col_index++)
               {
                   if(row_index< source_row_count)
                   {
                       ret[row_index, col_index] = matrix[row_index, col_index];
                   }
                   else
                   {
                       ret[row_index, col_index] = new_rows[row_index - source_row_count, col_index];
                   }
               }
           }
           return ret;
       }
       
       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 double[,] AddCol(double[,] matrix, double[,] new_cols)
       {
           int source_col_count = matrix.GetLength(1);//colの個数
           int row_count = matrix.GetLength(0);//rowの個数
           int total_col_count = matrix.GetLength(1)+new_cols.GetLength(1);//colの個数
           double[,] ret = new double[row_count, total_col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               for (int col_index = 0; col_index < total_col_count; col_index++)
               {
                   if (col_index < source_col_count)
                   {
                       ret[row_index, col_index] = matrix[row_index, col_index];
                   }
                   else
                   {
                       ret[row_index, col_index] = new_cols[row_index, col_index - source_col_count];
                   }                  
               }
           }
           return ret;
       }

Remove

       public static double[,] RemoveRow(double[,] matrix, int remove_row_index)
       {
           int row_count = matrix.GetLength(0);
           int col_count = matrix.GetLength(1);
           double[,] ret = new double[row_count - 1, col_count];
           int skip_count = 0;
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //削除対象の行
               if (row_index == remove_row_index)
               {
                   skip_count += 1;
                   continue;
               }

               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   ret[row_index - skip_count, col_index] = matrix[row_index, col_index];
               }
           }
           return ret;
       }
       
       public static double[,] RemoveCol(double[,] matrix, int remove_col_index)
       {
           int row_count = matrix.GetLength(0);
           int col_count = matrix.GetLength(1);
           double[,] ret = new double[row_count, col_count-1];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               int skip_count = 0;
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   //削除対象の列
                   if (col_index == remove_col_index)
                   {
                       skip_count += 1;
                       continue;
                   }
                   ret[row_index, col_index - skip_count] = matrix[row_index , col_index];
               }
           }
           return ret;
       }

Insert

       public static double[,] InsertRow(double[,] matrix, int insert_row_index, double[] new_row)
       {
           double[,] ret = new double[matrix.GetLength(0) + 1, matrix.GetLength(1)];
           int row_count = ret.GetLength(0);
           int col_count = ret.GetLength(1);
           int skip_count = 0;
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   //追加対象の行
                   if (row_index == insert_row_index)
                   {
                       ret[row_index, col_index] = new_row[col_index];
                       if(col_index==col_count-1)
                       {
                           skip_count += 1;
                       }
                       continue;
                   }
                   else
                   {
                       ret[row_index, col_index] = matrix[row_index - skip_count, col_index];
                   }               
               }
           }
           return ret;
       }
       
       public static double[,] InsertCol(double[,] matrix, int insert_col_index, double[] new_col)
       {
           double[,] ret = new double[matrix.GetLength(0), matrix.GetLength(1)+1];
           int row_count = ret.GetLength(0);
           int col_count = ret.GetLength(1);         
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               int skip_count = 0;
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   //追加対象の列
                   if (col_index == insert_col_index)
                   {
                       ret[row_index, col_index] = new_col[row_index];
                       skip_count += 1;
                   }
                   else
                   {
                       ret[row_index, col_index] = matrix[row_index, col_index - skip_count];
                   }
               }
           }
           return ret;
       }

Change,Paste,Replace





       #region Change

       //Changeした=> return 1;
       //Changeしてない=> return 0;
       public static int ChangeRow(double[,] matrix, int row_index1, int row_index2)
       {
           if (row_index1 == row_index2) { return 0; }
           var temp_row1 = GetRow(matrix, row_index1);
           var temp_row2 = GetRow(matrix, row_index2);
           SetRow(matrix, row_index1, temp_row2);
           SetRow(matrix, row_index2, temp_row1);
           return 1;
       }

       public static void _changeRow(double[,] matrix, int row_index1, int row_index2)
       {
           int col_count = matrix.GetLength(1);
           for (int col_index = 0; col_index < col_count; col_index++)
           {
               double temp = matrix[row_index1, col_index];
               matrix[row_index1, col_index] = matrix[row_index2, col_index];
               matrix[row_index2, col_index] = temp;
           }
       }

       public static int ChangeCol(double[,] matrix, int col_index1, int col_index2)
       {
           if (col_index1 == col_index2) { return 0; }
           var temp_col1 = GetCol(matrix, col_index1);
           var temp_col2 = GetCol(matrix, col_index2);
           SetCol(matrix, col_index1, temp_col2);
           SetCol(matrix, col_index2, temp_col1);
           return 1;
       }

       public static void _changeCol(double[,] matrix, int col_index1, int col_index2)
       {
           //colを固定してrowを走査する
           int row_count = matrix.GetLength(0);
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               double temp = matrix[row_index, col_index1];
               matrix[row_index, col_index1] = matrix[row_index, col_index2];
               matrix[row_index, col_index2] = temp;
           }
       }

       public static void _changeComponent(double[] vector, int index1, int index2)
       {
           double temp = vector[index1];
           vector[index1] = vector[index2];
           vector[index2] = temp;
       } 

       #endregion

       //newして戻り値返すタイプ
       //昨日的にはSetと変わらない
       public static double[,] PasteRow(double[,] matrix, int row_index, double[] new_row)
       {
           int row_count = matrix.GetLength(0);//rowの個数
           int col_count = matrix.GetLength(1);//colの個数
           double[,] ret = new double[row_count, col_count];
           for (int col_index = 0; col_index < col_count; col_index++)
           {
               //入力配列が短い場合は0で埋める
               //必然的に、長い場合は切り落とされる
               if (new_row.Length - 1 < col_index)
               {
                   ret[row_index, col_index] = 0;
               }
               ret[row_index, col_index] = new_row[col_index];
           }
           return ret;
       }
       
       public static double[,] PasteCol(double[,] matrix, int col_index, 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];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //入力配列が短い場合は0で埋める
               //必然的に、長い場合は切り落とされる
               if (new_col.Length - 1 < row_index)
               {
                   ret[row_index, col_index] = 0;
               }
               ret[row_index, col_index] = new_col[row_index];
           }
           return ret;
       }

       #region Reprace

       public static void Replace(double[] vector, params int[] indexes)
       {
           for (int col_index = 0; col_index < vector.Length; col_index++)
           {
               double temp = vector[col_index];
               vector[col_index] = vector[indexes[col_index]];
               vector[indexes[col_index]] = temp;
           }
       }
       
       //記録しておいた入れ換えを使用
       public static void ReplaceRow(double[,] matrix, params int[] indexes)
       {
           int row_count = matrix.GetLength(0);
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               _changeRow(matrix, row_index, indexes[row_index]);
           }
       }
       
       //記録しておいた入れ換えを使用
       public static void ReplaceCol(double[,] matrix, params int[] indexes)
       {
           int col_count = matrix.GetLength(1);
           for (int col_index = 0; col_index < col_count; col_index++)
           {
               _changeCol(matrix, col_index, indexes[col_index]);
           }
       }

       //今の所使わなくて良い
       public static void ReplaceBackRow(double[,] matrix, params int[] indexes)
       {
           int row_count = matrix.GetLength(0);
           for (int row_index = row_count - 1; row_index >= 0; row_index--)
           {
               _changeRow(matrix, row_index, indexes[row_index]);
           }
       }
       
       public static void ReplaceBackCol(double[,] matrix, params int[] indexes)
       {
           int col_count = matrix.GetLength(1);
           for (int col_index = col_count - 1; col_index >= 0; col_index--)
           {
               _changeCol(matrix, col_index, indexes[col_index]);
           }
       }

       #endregion

       #endregion

行列の積

       #region 行列の積

       public static double[,] MatrixMultiple_VH(double[] vertical, double[] horizontal)
       {
           int row_count = vertical.Length;
           int col_count = horizontal.Length;
           double[,] ret = new double[row_count, col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   ret[row_index, col_index] = vertical[row_index] * horizontal[col_index];
               }
           }
           return ret;
       }

       public static double[] MatrixMultiple(double[,] m, double[] v)
       {
           int row_count = m.GetLength(0);//row
           int col_count = m.GetLength(1);//col
           double[] ret = new double[col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //右に向かって走査
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   ret[row_index] += m[row_index, col_index] * v[col_index];
               }
           }
           return ret;
       }

       public static double[] MatrixMultiple(double[] h, double[,] m)
       {
           int row_count = m.GetLength(0);//row
           int col_count = m.GetLength(1);//col
           double[] ret = new double[col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //右に向かって走査
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   ret[row_index] += h[col_index] * m[row_index, col_index];
               }
           }
           return ret;
       }

       public static double[,] MatrixMultiple(double[,] m1, double[,] m2)
       {
           int row_count = m1.GetLength(0);//row
           int col_count = m1.GetLength(1);//col
           double[,] ret = new double[row_count, col_count];
           for (int row_index = 0; row_index < row_count; row_index++)
           {
               //右に向かって走査
               for (int col_index = 0; col_index < col_count; col_index++)
               {
                   double s = 0;
                   for (int k = 0; k < col_count; k++)
                   {
                       s += m1[row_index, k] * m2[k, col_index];
                   }
                   ret[row_index, col_index] = s;
               }
           }
           return ret;
       }

       #endregion

Elementwise


       public static double[,] ElementWise_Add(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _add);
       }
       
       public static double[,] ElementWise_Sub(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _sub);
       }
       
       public static double[,] ElementWise_Multiple(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _multiple);
       }
       
       public static double[,] ElementWise_Divide(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _divide);
       }

       
       //配列の定数倍
       public static double[] _calcuElementWise(double[] v1, double c, Func<double, double, double> operation)
       {
           double[] ret = new double[v1.Length];

           for (int i = 0; i < v1.Length; i++)
           {
               ret[i] = operation(v1[i], c);
           }
           return ret;
       }
       
       //配列×配列
       public static double[] _calcuElementWise(double[] v1, double[] v2, Func<double, double, double> operation)
       {
           if (v1.Length != v2.Length) { return null; }

           double[] ret = new double[v1.Length];

           for (int i = 0; i < v1.Length; i++)
           {
               ret[i] = operation(v1[i], v2[i]);
           }
           return ret;
       }
       
       //行列の定数倍
       public static double[,] _calcuElementWise(double[,] m1, double c, Func<double, double, double> operation)
       {
           double[,] ret = new double[m1.GetLength(0), m1.GetLength(1)];

           for (int m = 0; m < m1.GetLength(0); m++)
           {
               //右に向かって走査
               for (int n = 0; n < m1.GetLength(1); n++)
               {
                   ret[m, n] = operation(m1[m, n], c);
               }
           }
           return ret;
       }

       //行列×縦ベクトル
       public static double[] _calcuElementWise(double[,] m, double[] v, Func<double, double, double> operation)
       {
           double[] ret = new double[v.Length];

           for (int row_index = 0; row_index < m.GetLength(0); row_index++)
           {
               //右に向かって走査
               for (int col_index = 0; col_index < m.GetLength(1); col_index++)
               {
                   ret[row_index] = operation(m[row_index, col_index], v[col_index]);
               }
           }
           return ret;
       }

       //行列×行列
       public static double[,] _calcuElementWise(double[,] m1, double[,] m2, Func<double, double, double> operation)
       {
           if (m1.GetLength(0) != m2.GetLength(0)) { return null; }
           if (m1.GetLength(1) != m2.GetLength(1)) { return null; }

           double[,] ret = new double[m1.GetLength(0), m1.GetLength(1)];

           //一行ずつ取り出す[同型なのでどちらの行列を基準にしても良い]
           for (int m = 0; m < m1.GetLength(0); m++)
           {
               //右に向かって走査
               for (int n = 0; n < m1.GetLength(1); n++)
               {
                   ret[m, n] = operation(m1[m, n], m2[m, n]);
               }
           }
           return ret;
       }
       

配列の定数倍(Elementwise)

       //配列の定数倍
       public static double[] Add(double[] v, double c)
       {
           return _calcuElementWise(v, c, _add);
       }
       public static double[] Sub(double[] v, double c)
       {
           return _calcuElementWise(v, c, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[] Multiple(double c, double[] v)
       {
           return _calcuElementWise(v, c, _multiple);
       }
       public static double[] Multiple(double[] v, double c)
       {
           return _calcuElementWise(v, c, _multiple);
       }
       public static double[] Divide(double[] v, double c)
       {
           return _calcuElementWise(v, c, _divide);
       }
       public static double[] Mod(double[] v, double c)
       {
           return _calcuElementWise(v, c, _mod);
       }

配列×配列(Elementwise)

       //配列×配列
       public static double[] Add(double[] v1, double[] v2)
       {
           return _calcuElementWise(v1, v2, _add);
       }
       public static double[] Sub(double[] v1, double[] v2)
       {
           return _calcuElementWise(v1, v2, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[] Multiple(double[] v1, double[] v2)
       {
           return _calcuElementWise(v1, v2, _multiple);
       }
       public static double[] Divide(double[] v1, double[] v2)
       {
           return _calcuElementWise(v1, v2, _divide);
       }
       public static double[] Mod(double[] v1, double[] v2)
       {
           return _calcuElementWise(v1, v2, _mod);
       }

行列の定数倍(Elementwise)

       //行列の定数倍
       public static double[,] Add(double[,] m1, double c)
       {
           return _calcuElementWise(m1, c, _add);
       }
       public static double[,] Sub(double[,] m1, double c)
       {
           return _calcuElementWise(m1, c, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[,] Multiple(double c, double[,] m1)
       {
           return _calcuElementWise(m1, c, _multiple);
       }
       public static double[,] Multiple(double[,] m1, double c)
       {
           return _calcuElementWise(m1, c, _multiple);
       }
       public static double[,] Divide(double[,] m1, double c)
       {
           return _calcuElementWise(m1, c, _divide);
       }
       public static double[,] Mod(double[,] m1, double c)
       {
           return _calcuElementWise(m1, c, _mod);
       }

横ベクトル×行列(Elementwise)

       //横ベクトル×行列
       public static double[] Add(double[] v, double[,] m)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _add);
       }
       public static double[] Sub(double[] v, double[,] m)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[] Multiple(double[] v, double[,] m)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _multiple);
       }
       public static double[] Divide(double[] v, double[,] m)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _divide);
       }
       public static double[] Mod(double[] v, double[,] m)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _mod);
       }

行列×縦ベクトル(Elementwise)

       //行列×縦ベクトル
       public static double[] Add(double[,] m, double[] v)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _add);
       }
       public static double[] Sub(double[,] m, double[] v)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[] Multiple(double[,] m, double[] v)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _multiple);
       }
       public static double[] Divide(double[,] m, double[] v)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _divide);
       }
       public static double[] Mod(double[,] m, double[] v)
       {
           //vは縦ベクトル
           return _calcuElementWise(m, v, _mod);
       }

行列×行列(Elementwise)

       //行列×行列
       public static double[,] Add(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _add);
       }
       public static double[,] Sub(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _sub);
       }
       //これはElementWiseであって行列の積ではない
       public static double[,] Multiple(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _multiple);
       }
       public static double[,] Divide(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _divide);
       }
       public static double[,] Mod(double[,] m1, double[,] m2)
       {
           return _calcuElementWise(m1, m2, _mod);
       }


       #region

       public static double _add(double a, double b)
       {
           return a + b;
       }
       public static double _sub(double a, double b)
       {
           return a - b;
       }
       public static double _multiple(double a, double b)
       {
           return a * b;
       }
       public static double _divide(double a, double b)
       {
           if (b == 0)
           {
               return 0;
           }
           return a / b;
       }
       public static double _mod(double a, double b)
       {
           return a % b;
       }

       public static double _exp(double a)
       {
           return Math.Exp(a);
       }
       //床関数
       public static double _floor(double a)
       {
           return (int)a;
       }
       //天井関数
       public static double _ceil(double a)
       {
           return (int)a + 1;
       }
       //四捨五入
       public static double _round(double a)
       {
           return _floor(a + 0.5);
       }
       //aの小数部分
       public static double _fraction(double a)
       {
           return a - (int)a;
       }
       public static double _rfraction(double a)
       {
           return 1 - (a - (int)a);
       }

       #endregion


processing:ガウスの消去法



class ExMatrix
{
 double[][] A;
 double[] b;
 
 public ExMatrix(double[][] A_, double[] b_)
 {
   this.A = A_;
   this.b = b_;
 }
}

int _get_pivoting_index(double[][] A, int pivot_index)
{
   //pivot列の
   //pivot+1行以降で
   //絶対値最大の行のインデックスを返す

   int row_count = A.length;//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++)
   {
       double 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;
}
       
//行交換実行関数
//行交換したかしてないかは行列式の計算に関連する(したら*-1)
//行t交換した=> return 1;
//行交換してない=> return 0;
int _pivoting(double[][] A, int pivot_index)
{
   int 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;
   }
}        

//前進消去
ExMatrix ForwardElimination(double[][] A, double[] b)
{
   int row_count = A.length;//rowの個数
   int col_count = A[0].length;//colの個数
   //if (row_count != col_count) { throw new Exception(); }

   int pivot_count = row_count;
   //拡大係数行列
   double[][] ex_matrix = AddCol(A, b);

   for (int pivot_index = 0; pivot_index < pivot_count - 1; pivot_index++)
   {
       //ピボット選択が必要
       if (ex_matrix[pivot_index][pivot_index] == 0)
       {
           _pivoting(ex_matrix, pivot_index);
       }

       //ピボットから下の全ての行(pivot_count + 1)
       for (int row_index = pivot_index + 1; row_index < row_count; row_index++)
       {
           double pivot_term = ex_matrix[pivot_index][pivot_index];

           //各行の0でない先頭(この項をpivot行の先頭を用いて0にしていく)
           double leading_coefficient = ex_matrix[row_index][pivot_index];
           double ratio = -leading_coefficient / pivot_term;//ピボット行との比

           double[] pivot_row = GetRow(ex_matrix, pivot_index);//ピボット行
           double[] m_row = Multiple(pivot_row, ratio);//row_index行の先頭を0にできるようになったピボット行
           double[] target_row = GetRow(ex_matrix, row_index);//先頭を0にすべき行
           double[] added = Add(target_row, m_row);//0でない先頭が0に更新された

           SetRow(ex_matrix, row_index, added);
       }
   }
   
   //拡大係数行列を返す
   ExMatrix ret = new ExMatrix(RemoveCol(ex_matrix, pivot_count), GetCol(ex_matrix, pivot_count));    
   return ret;
}
//後退代入
double[] BackSubstitution(double[][] A, double[] b)
{
   double[] x = new double[b.length];

   for (int pivot_index = x.length - 1; pivot_index >= 0; pivot_index--)
   {
       double tb = b[pivot_index];
       //初回は実行されない
       for (int col_index = A[0].length - 1; col_index > pivot_index; col_index--)
       {
           //pivot行のpivotより右のセルをbに統合していく
           tb -= A[pivot_index][col_index] * x[col_index];
       }
       //Amn*Xmn=Bm(二週目以降はこのBmをcol-pivotループで構築する)
       //Xmn=Bm/Amn
       tb /= A[pivot_index][pivot_index];

       x[pivot_index] = tb;
   }
   return x;
}

//ガウス消去法
double[] GaussianElimination(double[][] A, double[] b)
{
   ExMatrix ex = ForwardElimination(A, b);
   return BackSubstitution(ex.A, ex.b);
}

processing:Get,Set,Add,Remove,Insert


//一つの行列を左右に割る
ArrayList<double[][]> SplitEx(double[][] matrix, int split_col_count)
{
 ArrayList<double[][]> ret = new ArrayList<double[][]>();
 int row_count = matrix.length;
 int col_count = matrix[0].length;
 double[][] left = new double[row_count][split_col_count];
 double[][] right = new double[row_count][col_count - split_col_count];
 for (int row_index = 0; row_index < row_count; row_index++)
 {
     for (int col_index = 0; col_index < col_count; col_index++)
     {
         if (split_col_count - 1 < col_index)
         {
             right[row_index][col_index - split_col_count] = matrix[row_index][col_index];
         }
         else
         {
             left[row_index][col_index] = matrix[row_index][col_index];
         }
     }
 }
 ret.add(left);
 ret.add(right);
 return ret;
}

double[] GetRow(double[][] matrix, int row_index)
{
   int col_count = matrix[0].length;//colの個数
   double[] ret = new double[col_count];
   //row固定、col走査
   for (int col_index = 0; col_index < col_count; col_index++)
   {
       ret[col_index] = matrix[row_index][col_index];
   }
   return ret;
}

double[] GetCol(double[][] matrix, int col_index)
{
   int row_count = matrix.length;//rowの個数
   double[] ret = new double[row_count];
   //col固定、row走査
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       ret[row_index] = matrix[row_index][col_index];
   }
   return ret;
}

void SetRow(double[][] matrix, int row_index, double[] new_row)
{
   int col_count = matrix[0].length;//colの個数
   for (int col_index = 0; col_index < col_count; col_index++)
   {
       //入力配列が短い場合は0で埋める
       //必然的に、長い場合は切り落とされる
       if (new_row.length - 1 < col_index)
       {
           matrix[row_index][col_index] = 0;
       }
       matrix[row_index][col_index] = new_row[col_index];
   }
}

void SetCol(double[][] matrix, int col_index, double[] new_col)
{
   int row_count = matrix.length;//rowの個数
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //入力配列が短い場合は0で埋める
       //必然的に、長い場合は切り落とされる
       if (new_col.length - 1 < row_index)
       {
           matrix[row_index][col_index] = 0;
       }
       matrix[row_index][col_index] = new_col[row_index];
   }
}

double[][] GetCols(double[][] matrix, int start_col_index)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//colの個数
   int ret_row_count = row_count;
   int ret_col_count = col_count - start_col_index;
   double[][] ret = new double[ret_row_count][ret_col_count];
   //ret側走査
   for (int row_index = 0; row_index < ret_row_count; row_index++)
   {
       //row固定、col走査
       for (int col_index = 0; col_index < ret_col_count; col_index++)
       {
           ret[row_index][col_index] = matrix[row_index][start_col_index + col_index];
       }
   }
   return ret;
}

//指定indexから最後までとっちゃう
double[][] GetRows(double[][] matrix, int start_row_index)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//colの個数
   int ret_row_count = row_count - start_row_index;
   int ret_col_count = col_count;
   double[][] ret = new double[ret_row_count][ret_col_count];
   //ret側走査
   for (int row_index = 0; row_index < ret_row_count; row_index++)
   {
       //row固定、col走査
       for (int col_index = 0; col_index < ret_col_count; col_index++)
       {
           ret[row_index][col_index] = matrix[start_row_index + row_index][col_index];
       }
   }
   return ret;
}

double[][] AddRow(double[][] matrix, double[] new_row)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//colの個数
   double[][] ret = new double[row_count+1][col_count];
   for (int row_index = 0; row_index < row_count+1; row_index++)
   {
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           if(row_index==row_count)
           {
               ret[row_index][col_index] = new_row[col_index];
           }
           else
           {
               ret[row_index][col_index] = matrix[row_index][col_index];
           }
       }
   }
   return ret;
}

double[][] AddRow(double[][] matrix, double[][] new_rows)
{
   int source_row_count = matrix.length;
   int total_row_count = matrix.length + new_rows.length;//rowの個数
   int total_col_count = matrix[0].length;//colの個数
   double[][] ret = new double[total_row_count][total_col_count];
   for (int row_index = 0; row_index < total_row_count; row_index++)
   {
       for (int col_index = 0; col_index < total_col_count; col_index++)
       {
           if(row_index< source_row_count)
           {
               ret[row_index][col_index] = matrix[row_index][col_index];
           }
           else
           {
               ret[row_index][col_index] = new_rows[row_index - source_row_count][col_index];
           }
       }
   }
   return ret;
}
double[][] AddCol(double[][] matrix, double[] new_col)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//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;
}
double[][] AddCol(double[][] matrix, double[][] new_cols)
{
   int source_col_count = matrix[0].length;//colの個数
   int row_count = matrix.length;//rowの個数
   int total_col_count = matrix[0].length+new_cols[0].length;//colの個数
   double[][] ret = new double[row_count][total_col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       for (int col_index = 0; col_index < total_col_count; col_index++)
       {
           if (col_index < source_col_count)
           {
               ret[row_index][col_index] = matrix[row_index][col_index];
           }
           else
           {
               ret[row_index][col_index] = new_cols[row_index][col_index - source_col_count];
           }                  
       }
   }
   return ret;
}

double[][] RemoveRow(double[][] matrix, int remove_row_index)
{
   int row_count = matrix.length;
   int col_count = matrix[0].length;
   double[][] ret = new double[row_count - 1][col_count];
   int skip_count = 0;
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //削除対象の行
       if (row_index == remove_row_index)
       {
           skip_count += 1;
           continue;
       }
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           ret[row_index - skip_count][col_index] = matrix[row_index][col_index];
       }
   }
   return ret;
}

double[][] RemoveCol(double[][] matrix, int remove_col_index)
{
   int row_count = matrix.length;
   int col_count = matrix[0].length;
   double[][] ret = new double[row_count][col_count-1];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       int skip_count = 0;
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           //削除対象の列
           if (col_index == remove_col_index)
           {
               skip_count += 1;
               continue;
           }
           ret[row_index][col_index - skip_count] = matrix[row_index][col_index];
       }
   }
   return ret;
}

double[][] InsertRow(double[][] matrix, int insert_row_index, double[] new_row)
{
   double[][] ret = new double[matrix.length + 1][ matrix[0].length];
   int row_count = ret.length;
   int col_count = ret[0].length;
   int skip_count = 0;
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           //追加対象の行
           if (row_index == insert_row_index)
           {
               ret[row_index][col_index] = new_row[col_index];
               if(col_index==col_count-1)
               {
                   skip_count += 1;
               }
               continue;
           }
           else
           {
               ret[row_index][col_index] = matrix[row_index - skip_count][col_index];
           }               
       }
   }
   return ret;
}

double[][] InsertCol(double[][] matrix, int insert_col_index, double[] new_col)
{
   double[][] ret = new double[matrix.length][matrix[0].length+1];
   int row_count = ret.length;
   int col_count = ret[0].length;  
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       int skip_count = 0;
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           //追加対象の列
           if (col_index == insert_col_index)
           {
               ret[row_index][col_index] = new_col[row_index];
               skip_count += 1;
           }
           else
           {
               ret[row_index][col_index] = matrix[row_index][col_index - skip_count];
           }
       }
   }
   return ret;
}

processing:Change,Paste,Replace

int ChangeRow(double[][] matrix, int row_index1, int row_index2)
{
   if (row_index1 == row_index2) { return 0; }
   double[] temp_row1 = GetRow(matrix, row_index1);
   double[] temp_row2 = GetRow(matrix, row_index2);
   SetRow(matrix, row_index1, temp_row2);
   SetRow(matrix, row_index2, temp_row1);
   return 1;
}

void _changeRow(double[][] matrix, int row_index1, int row_index2)
{
   int col_count = matrix[0].length;
   for (int col_index = 0; col_index < col_count; col_index++)
   {
       double temp = matrix[row_index1][col_index];
       matrix[row_index1][col_index] = matrix[row_index2][col_index];
       matrix[row_index2][col_index] = temp;
   }
}

int ChangeCol(double[][] matrix, int col_index1, int col_index2)
{
   if (col_index1 == col_index2) { return 0; }
   double[] temp_col1 = GetCol(matrix, col_index1);
   double[] temp_col2 = GetCol(matrix, col_index2);
   SetCol(matrix, col_index1, temp_col2);
   SetCol(matrix, col_index2, temp_col1);
   return 1;
}

void _changeCol(double[][] matrix, int col_index1, int col_index2)
{
   //colを固定してrowを走査する
   int row_count = matrix.length;
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       double temp = matrix[row_index][col_index1];
       matrix[row_index][col_index1] = matrix[row_index][col_index2];
       matrix[row_index][col_index2] = temp;
   }
}

void _changeComponent(double[] vector, int index1, int index2)
{
   double temp = vector[index1];
   vector[index1] = vector[index2];
   vector[index2] = temp;
} 

//newして戻り値返すタイプ
//昨日的にはSetと変わらない
double[][] PasteRow(double[][] matrix, int row_index, double[] new_row)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//colの個数
   double[][] ret = new double[row_count][col_count];
   for (int col_index = 0; col_index < col_count; col_index++)
   {
       //入力配列が短い場合は0で埋める
       //必然的に、長い場合は切り落とされる
       if (new_row.length - 1 < col_index)
       {
           ret[row_index][col_index] = 0;
       }
       ret[row_index][col_index] = new_row[col_index];
   }
   return ret;
}

double[][] PasteCol(double[][] matrix, int col_index, double[] new_col)
{
   int row_count = matrix.length;//rowの個数
   int col_count = matrix[0].length;//colの個数
   double[][] ret = new double[row_count][col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //入力配列が短い場合は0で埋める
       //必然的に、長い場合は切り落とされる
       if (new_col.length - 1 < row_index)
       {
           ret[row_index][col_index] = 0;
       }
       ret[row_index][col_index] = new_col[row_index];
   }
   return ret;
}
​
void Replace(double[] vector, int... indexes)
{
   for (int col_index = 0; col_index < vector.length; col_index++)
   {
       double temp = vector[col_index];
       vector[col_index] = vector[indexes[col_index]];
       vector[indexes[col_index]] = temp;
   }
}

//記録しておいた入れ換えを使用
void ReplaceRow(double[][] matrix, int... indexes)
{
   int row_count = matrix.length;
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       _changeRow(matrix, row_index, indexes[row_index]);
   }
}

//記録しておいた入れ換えを使用
void ReplaceCol(double[][] matrix, int... indexes)
{
   int col_count = matrix[0].length;
   for (int col_index = 0; col_index < col_count; col_index++)
   {
       _changeCol(matrix, col_index, indexes[col_index]);
   }
}

//今の所使わなくて良い
void ReplaceBackRow(double[][] matrix, int... indexes)
{
   int row_count = matrix.length;
   for (int row_index = row_count - 1; row_index >= 0; row_index--)
   {
       _changeRow(matrix, row_index, indexes[row_index]);
   }
}

void ReplaceBackCol(double[][] matrix, int... indexes)
{
   int col_count = matrix[0].length;
   for (int col_index = col_count - 1; col_index >= 0; col_index--)
   {
       _changeCol(matrix, col_index, indexes[col_index]);
   }
}

processing:行列の積



double[][] MatrixMultiple_VH(double[] vertical, double[] horizontal)
{
   int row_count = vertical.length;
   int col_count = horizontal.length;
   double[][] ret = new double[row_count][col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           ret[row_index][col_index] = vertical[row_index] * horizontal[col_index];
       }
   }
   return ret;
}

double[] MatrixMultiple(double[][] m, double[] v)
{
   int row_count = m.length;//row
   int col_count = m[0].length;//col
   double[] ret = new double[col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //右に向かって走査
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           ret[row_index] += m[row_index][col_index] * v[col_index];
       }
   }
   return ret;
}

double[] MatrixMultiple(double[] h, double[][] m)
{
   int row_count = m.length;//row
   int col_count = m[0].length;//col
   double[] ret = new double[col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //右に向かって走査
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           ret[row_index] += h[col_index] * m[row_index][col_index];
       }
   }
   return ret;
}

double[][] MatrixMultiple(double[][] m1, double[][] m2)
{
   int row_count = m1.length;//row
   int col_count = m1[0].length;//col
   double[][] ret = new double[row_count][col_count];
   for (int row_index = 0; row_index < row_count; row_index++)
   {
       //右に向かって走査
       for (int col_index = 0; col_index < col_count; col_index++)
       {
           double s = 0;
           for (int k = 0; k < col_count; k++)
           {
               s += m1[row_index][k] * m2[k][col_index];
           }

           ret[row_index][col_index] = s;
       }
   }
   return ret;
}

processing:Elementwise

processingはstatic使うとワケ分からんなるので使用せず



//配列の定数倍
double[] _calcuElementWise(double[] v1, double c, IFomula2 operation)
{
   double[] ret = new double[v1.length];

   for (int i = 0; i < v1.length; i++)
   {
       ret[i] = operation.exe(v1[i], c);
   }
   return ret;
}

//配列×配列
double[] _calcuElementWise(double[] v1, double[] v2, IFomula2 operation)
{
   if (v1.length != v2.length) { return null; }

   double[] ret = new double[v1.length];

   for (int i = 0; i < v1.length; i++)
   {
       ret[i] = operation.exe(v1[i], v2[i]);
   }
   return ret;
}

//行列の定数倍
double[][] _calcuElementWise(double[][] m1, double c, IFomula2 operation)
{
   double[][] ret = new double[m1.length][m1[0].length];

   for (int m = 0; m < m1.length; m++)
   {
       //右に向かって走査
       for (int n = 0; n < m1[0].length; n++)
       {
           ret[m][n] = operation.exe(m1[m][n], c);
       }
   }
   return ret;
}

//行列×縦ベクトル
double[] _calcuElementWise(double[][] m, double[] v, IFomula2 operation)
{
   double[] ret = new double[v.length];

   for (int row_index = 0; row_index < m.length; row_index++)
   {
       //右に向かって走査
       for (int col_index = 0; col_index < m[0].length; col_index++)
       {
           ret[row_index] = operation.exe(m[row_index][col_index], v[col_index]);
       }
   }
   return ret;
}

//行列×行列
double[][] _calcuElementWise(double[][] m1, double[][] m2, IFomula2 operation)
{
   if (m1.length != m2.length) { return null; }
   if (m1[0].length != m2[0].length) { return null; }

   double[][] ret = new double[m1.length][m1[0].length];

   //一行ずつ取り出す[同型なのでどちらの行列を基準にしても良い]
   for (int m = 0; m < m1.length; m++)
   {
       //右に向かって走査
       for (int n = 0; n < m1[0].length; n++)
       {
           ret[m][n] = operation.exe(m1[m][n], m2[m][n]);
       }
   }
   return ret;
}

//配列の定数倍
double[] Add(double[] v, double c){return _calcuElementWise(v, c, new Add());}
double[] Sub(double[] v, double c){return _calcuElementWise(v, c, new Sub());}
//これはElementWiseであって行列の積ではない
double[] Multiple(double c, double[] v){return _calcuElementWise(v, c, new Mult());}
double[] Multiple(double[] v, double c){return _calcuElementWise(v, c, new Mult());}
double[] Divide(double[] v, double c){return _calcuElementWise(v, c, new Div());}
double[] Mod(double[] v, double c){return _calcuElementWise(v, c, new Mod());}

//配列×配列
double[] Add(double[] v1, double[] v2){return _calcuElementWise(v1, v2, new Add());}
double[] Sub(double[] v1, double[] v2){return _calcuElementWise(v1, v2, new Sub());}
//これはElementWiseであって行列の積ではない
double[] Multiple(double[] v1, double[] v2){return _calcuElementWise(v1, v2, new Mult());}
double[] Divide(double[] v1, double[] v2){return _calcuElementWise(v1, v2, new Div());}
double[] Mod(double[] v1, double[] v2){return _calcuElementWise(v1, v2, new Mod());}

//行列の定数倍
double[][] Add(double[][] m1, double c){return _calcuElementWise(m1, c, new Add());}
double[][] Sub(double[][] m1, double c){return _calcuElementWise(m1, c, new Sub());}
//これはElementWiseであって行列の積ではない
double[][] Multiple(double c, double[][] m1){return _calcuElementWise(m1, c, new Mult());}
double[][] Multiple(double[][] m1, double c){return _calcuElementWise(m1, c, new Mult());}
double[][] Divide(double[][] m1, double c){return _calcuElementWise(m1, c, new Div());}
double[][] Mod(double[][] m1, double c){return _calcuElementWise(m1, c, new Mod());}

//横ベクトル×行列
double[] Add(double[] v, double[][] m){return _calcuElementWise(m, v, new Add());}
double[] Sub(double[] v, double[][] m){return _calcuElementWise(m, v, new Sub());}
//これはElementWiseであって行列の積ではない
double[] Multiple(double[] v, double[][] m){return _calcuElementWise(m, v, new Mult());}
double[] Divide(double[] v, double[][] m){return _calcuElementWise(m, v, new Div());}
double[] Mod(double[] v, double[][] m){return _calcuElementWise(m, v, new Mod());}
//行列×縦ベクトル
double[] Add(double[][] m, double[] v){return _calcuElementWise(m, v, new Add());}
double[] Sub(double[][] m, double[] v){return _calcuElementWise(m, v, new Sub());}
//これはElementWiseであって行列の積ではない
double[] Multiple(double[][] m, double[] v){return _calcuElementWise(m, v, new Mult());}
double[] Divide(double[][] m, double[] v){return _calcuElementWise(m, v, new Div());}
double[] Mod(double[][] m, double[] v){return _calcuElementWise(m, v, new Mod());}

//行列×行列
double[][] Add(double[][] m1, double[][] m2){return _calcuElementWise(m1, m2, new Add());}
double[][] Sub(double[][] m1, double[][] m2){return _calcuElementWise(m1, m2, new Sub());}
//これはElementWiseであって行列の積ではない
double[][] Multiple(double[][] m1, double[][] m2){return _calcuElementWise(m1, m2, new Mult());}
double[][] Divide(double[][] m1, double[][] m2){return _calcuElementWise(m1, m2, new Div());}
double[][] Mod(double[][] m1, double[][] m2){return _calcuElementWise(m1, m2, new Mod());}               

interface IFomula2{double exe(double a, double b);}
class Add implements IFomula2{double exe(double a, double b){return a+b;}}
class Sub implements IFomula2{double exe(double a, double b){return a-b;}}
class Mult implements IFomula2{double exe(double a, double b){return a*b;}}
class Div implements IFomula2{double exe(double a, double b){return a/b;}}
class Mod implements IFomula2{double exe(double a, double b){return a%b;}}
interface IFomula1{double exe(double a);}
class Exp implements IFomula1{double exe(double a){return Math.exp(a);}}
class Floor implements IFomula1{double exe(double a){return (int)a;}}
class Ceil implements IFomula1{double exe(double a){return (int)a+1;}}
class Round implements IFomula1
{
 double exe(double a)
 {
   Floor floor = new Floor();
   return floor.exe(a+0.5);
 }
}
class Fraction implements IFomula1{double exe(double a){return a-(int)a;}}

参考文献

行列あるいは線形代数なら

ガウスの消去法、あるいは反復法等、連立方程式を数値的に解くならば

ソースなり疑似コードから見るなら

最適化方面から


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