zoukankan      html  css  js  c++  java
  • 数学:《线性代数》方阵求逆 之 代码实现

    背景

    给定坐标,我可以使用变换方阵对其进行右乘进行坐标转换,如果使用一个堆栈记录下执行过的变换方阵,然后执行一系列出栈操作,对出栈的方阵求逆,然后使用逆方阵右乘坐标就可以得到之前的坐标。

    方阵求逆

    理论

    求逆

    对 A:E 进行矩阵的最简算法得出 E:A-¹。

    证明:

    D1D2DkA = E

    D1D2DkAA-¹ = EA-¹

    D1D2DkE = A-¹

    上面的三个公式说明,对 A 做有限的初等变换可以得到 E,同样对 E 做同样的初等变换可得到 A-¹,因此 我们求 A:E 的最简矩阵就可以得出  A-¹。

    代码实现

    核心代码

     1             public Matrix Inverse()
     2             {
     3                 if (_m != _n)
     4                 {
     5                     throw new InvalidOperationException("只有方阵可以求逆");
     6                 }
     7 
     8                 var combinedMatrix = this.Combine(this.E());
     9                 combinedMatrix = combinedMatrix.Simplify();
    10 
    11                 var resultMatrix = new Matrix(_m, _m);
    12                 for (var i = 0; i < resultMatrix._m; i++)
    13                 {
    14                     Array.Copy(combinedMatrix._data[i], resultMatrix._m, resultMatrix._data[i], 0, resultMatrix._m);
    15                 }
    16 
    17                 return resultMatrix;
    18             }

    全部代码

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 namespace DataStuctureStudy.Matrixes
      8 {
      9     class MatrixTest
     10     {
     11         public static void Test()
     12         {
     13             var matrixA =
     14                 new Matrix(3, 3)
     15                 .SetRowData(0, 1, 2, 3)
     16                 .SetRowData(1, 1, 2, 7)
     17                 .SetRowData(2, 4, 9, 2);
     18 
     19             var matrixB = matrixA.Simplify();
     20             var matrixC = matrixA.Inverse();
     21 
     22             matrixA.Dispaly();
     23             matrixB.Dispaly();
     24             matrixC.Dispaly();
     25             matrixA.Multiply(matrixC).Dispaly();
     26 
     27         }
     28         class Matrix
     29         {
     30             private readonly int _m;
     31             private readonly int _n;
     32             private readonly double[][] _data;
     33 
     34             public Matrix(int m, int n)
     35             {
     36                 _m = m;
     37                 _n = n;
     38                 _data = new double[m][];
     39                 for (var i = 0; i < m; i++)
     40                 {
     41                     _data[i] = new double[n];
     42                 }
     43             }
     44 
     45             public Matrix SetRowData(int row, params double[] values)
     46             {
     47                 Array.Copy(values, _data[row], _n);
     48 
     49                 return this;
     50             }
     51 
     52             public Matrix SwapRow(int rowX, int rowY)
     53             {
     54                 var resultMatrix = this.ConeSelf();
     55 
     56                 var temp = resultMatrix._data[rowX];
     57                 resultMatrix._data[rowX] = resultMatrix._data[rowY];
     58                 resultMatrix._data[rowY] = temp;
     59 
     60                 return resultMatrix;
     61             }
     62 
     63             public Matrix MultiplyRow(int row, double operand)
     64             {
     65                 var resultMatrix = this.ConeSelf();
     66 
     67                 for (var i = 0; i < resultMatrix._n; i++)
     68                 {
     69                     resultMatrix._data[row][i] *= operand;
     70                 }
     71 
     72                 return resultMatrix;
     73             }
     74 
     75 
     76             public Matrix AddSourceRowToTargetRow(int sourceRow, double operand, int targetRow)
     77             {
     78                 var resultMatrix = this.ConeSelf();
     79 
     80                 for (var i = 0; i < resultMatrix._n; i++)
     81                 {
     82                     resultMatrix._data[targetRow][i] += resultMatrix._data[sourceRow][i] * operand;
     83                 }
     84 
     85                 return resultMatrix;
     86             }
     87 
     88             public Matrix Simplify()
     89             {
     90                 var resultMatrix = this.ConeSelf();
     91 
     92                 for (var col = 0; col < resultMatrix._n; col++)
     93                 {
     94                     if (col >= _m)
     95                     {
     96                         break;
     97                     }
     98 
     99                     if (resultMatrix._data[col][col] == 0)
    100                     {
    101                         var nonZeroRowIndex = resultMatrix.FindNonZeroRowIndex(col, col + 1);
    102                         if (nonZeroRowIndex == -1)
    103                         {
    104                             break;
    105                         }
    106                         resultMatrix = resultMatrix.SwapRow(col, nonZeroRowIndex);
    107                     }
    108 
    109                     resultMatrix = resultMatrix.MultiplyRow(col, 1 / resultMatrix._data[col][col]);
    110 
    111                     for (var row = 0; row < _m; row++)
    112                     {
    113                         if (row == col)
    114                         {
    115                             continue;
    116                         }
    117                         resultMatrix = resultMatrix.AddSourceRowToTargetRow(col, -1 * resultMatrix._data[row][col], row);
    118                     }
    119                 }
    120 
    121                 return resultMatrix;
    122             }
    123 
    124             public Matrix Multiply(Matrix matrix)
    125             {
    126                 if (this._n != matrix._m)
    127                 {
    128                     throw new InvalidOperationException("左侧矩阵的列不等于右侧矩阵的行");
    129                 }
    130 
    131                 var resultMatrix = new Matrix(this._m, matrix._n);
    132 
    133                 for (var i = 0; i < resultMatrix._m; i++)
    134                 {
    135                     for (var j = 0; j < resultMatrix._n; j++)
    136                     {
    137                         resultMatrix._data[i][j] = Enumerable.Range(0, this._n).Sum(k => this._data[i][k] * matrix._data[k][j]);
    138                     }
    139                 }
    140 
    141                 return resultMatrix;
    142             }
    143 
    144             public Matrix Inverse()
    145             {
    146                 if (_m != _n)
    147                 {
    148                     throw new InvalidOperationException("只有方阵可以求逆");
    149                 }
    150 
    151                 var combinedMatrix = this.Combine(this.E());
    152                 combinedMatrix = combinedMatrix.Simplify();
    153 
    154                 var resultMatrix = new Matrix(_m, _m);
    155                 for (var i = 0; i < resultMatrix._m; i++)
    156                 {
    157                     Array.Copy(combinedMatrix._data[i], resultMatrix._m, resultMatrix._data[i], 0, resultMatrix._m);
    158                 }
    159 
    160                 return resultMatrix;
    161             }
    162 
    163             public Matrix Combine(Matrix matrix)
    164             {
    165                 if (this._m != matrix._m)
    166                 {
    167                     throw new InvalidOperationException("左侧矩阵的行不等于右侧矩阵的行");
    168                 }
    169 
    170                 var resultMatrix = new Matrix(this._m, this._n + matrix._n);
    171                 for (var i = 0; i < resultMatrix._m; i++)
    172                 {
    173                     Array.Copy(this._data[i], 0, resultMatrix._data[i], 0, this._data[i].Length);
    174                     Array.Copy(matrix._data[i], 0, resultMatrix._data[i], this._data[i].Length, matrix._data[i].Length);
    175                 }
    176 
    177                 return resultMatrix;
    178             }
    179 
    180             public Matrix E()
    181             {
    182                 return E(_m);
    183             }
    184 
    185             public static Matrix E(int m)
    186             {
    187                 var matrix = new Matrix(m, m);
    188                 for (var i = 0; i < m; i++)
    189                 {
    190                     matrix._data[i][i] = 1;
    191                 }
    192 
    193                 return matrix;
    194             }
    195 
    196             public Matrix ConeSelf()
    197             {
    198                 var resultMatrix = new Matrix(this._m, this._n);
    199                 for (var i = 0; i < this._m; i++)
    200                 {
    201                     Array.Copy(this._data[i], resultMatrix._data[i], this._n);
    202                 }
    203 
    204                 return resultMatrix;
    205             }
    206 
    207             public void Dispaly()
    208             {
    209                 Console.WriteLine();
    210                 foreach (var row in _data)
    211                 {
    212                     Console.WriteLine("[ " + String.Join(" , ", row) + " ]");
    213                 }
    214                 Console.WriteLine();
    215             }
    216 
    217             private int FindNonZeroRowIndex(int col, int startRow)
    218             {
    219                 if (startRow >= _m)
    220                 {
    221                     return -1;
    222                 }
    223 
    224                 for (var i = startRow; i < _m; i++)
    225                 {
    226                     if (_data[i][col] != 0)
    227                     {
    228                         return i;
    229                     }
    230                 }
    231 
    232                 return -1;
    233             }
    234         }
    235     }
    236 }
  • 相关阅读:
    Codeforces Round #398 (Div. 2) B,C
    KMP模板
    HDU1711 KMP(模板题)
    HDU3265 线段树(扫描线)
    HDU2795 线段树
    HDU1828线段树(扫描线)
    HDU1832 二维线段树求最值(模板)
    HDU1698 线段树(区间更新区间查询)
    HDU3251 最大流(最小割)
    cf2.c
  • 原文地址:https://www.cnblogs.com/happyframework/p/3523878.html
Copyright © 2011-2022 走看看