矩阵相关的算法比较多,也是比较重要的,而且算法之间的性能差异确实比较大,初等变换法求逆比古典法求逆快不是一点点。矩阵的计算量和数值其实都是比较大的,特别是20阶以上,我在机器上最多只搞到40阶,随机产生的矩阵,很容易就爆掉decimal和double类型。
另外,这里使用了操作符重载,后面的一元符号运算也用到了操作符重载,后面如果有时间,我会将这些算法利用这些特性统一起来,本来它们的计算就应该是统一的。特别是符号运算。如果符号运算搞完,还可以试试自动命题证明玩玩。
好了,上矩阵的菜(有点长,但基本都调试过,至少书上的题都能正确计算出来!):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyMathLib
{
/// <summary>
/// 矩阵及相关算法.
/// </summary>
public class TMatrix
{
private int _Rank = -1;
public bool IsZero { get; private set; }
public bool IsUnit { get; private set; }
private double[][] _Elements;
public double[,] Elements
{
get
{
var theElements = new double[RowCount, ColCount];
for (int i = 0; i < RowCount; i++)
{
for (int j = 0; j < ColCount; j++)
{
theElements[i, j] = _Elements[i][j];
}
}
return theElements;
}
}
public int ColCount { get; private set; }
public int RowCount { get; private set; }
/// <summary>
/// 构造Row行,Col列矩阵,并用InitValue初始化。
/// </summary>
/// <param name="Row">矩阵行数</param>
/// <param name="Col">矩阵列数</param>
/// <param name="InitValue">初始值</param>
public TMatrix(int Row, int Col, double InitValue = 0)
{
IsZero = InitValue == 0;
IsUnit = true;
this.RowCount = Row;
this.ColCount = Col;
_Elements = new double[this.RowCount][];
for (int i = 0; i < Row; i++)
{
_Elements[i] = new double[this.ColCount];
for (int j = 0; j < this.ColCount; j++)
{
_Elements[i][j] = InitValue;
if (Row == Col)
{
if (i == j)
{
if (InitValue != 1)
{
IsUnit = false;
}
}
else
{
if (InitValue != 0)
{
IsUnit = false;
}
}
}
else
{
IsUnit = false;
}
}
}
}
/// <summary>
/// 构造Row行,Row列方阵.并用InitValue初始化
/// </summary>
/// <param name="Row">方阵行列数</param>
/// <param name="OnlyInitDiagonal">仅初始化对角线</param>
public TMatrix(int Row, double InitValue = 0, bool OnlyInitDiagonal = false)
{
IsZero = InitValue == 0;
IsUnit = (InitValue == 1 && OnlyInitDiagonal);
this.RowCount = Row;
this.ColCount = Row;
_Elements = new double[this.RowCount][];
for (int i = 0; i < Row; i++)
{
_Elements[i] = new double[this.ColCount];
if (OnlyInitDiagonal)
{
_Elements[i][i] = InitValue;
}
else
{
for (int j = 0; j < this.ColCount; j++)
{
_Elements[i][j] = InitValue;
}
}
}
}
public TMatrix(double[][] InitElements)
{
if (InitElements == null)
{
throw new Exception("矩阵不能为空!");
}
IsZero = true;
IsUnit = true;
_Elements = InitElements;
RowCount = _Elements.Length;
ColCount = _Elements[0].Length;
for (int i = 0; i < RowCount; i++)
{
for (int j = 0; j < this.ColCount; j++)
{
if (_Elements[i][j] != 0)
{
IsZero = false;
}
if (RowCount == ColCount)
{
if (i == j)
{
if (_Elements[i][j] != 1)
{
IsUnit = false;
}
}
else
{
if (_Elements[i][j] != 0)
{
IsUnit = false;
}
}
}
else
{
IsUnit = false;
}
}
}
}
public TMatrix(double[,] InitElements)
{
if (InitElements == null)
{
throw new Exception("矩阵不能为空!");
}
IsZero = true;
IsUnit = true;
RowCount = InitElements.GetLength(0);
ColCount = InitElements.GetLength(1);
_Elements = new double[RowCount][];
for (int i = 0; i < RowCount; i++)
{
_Elements[i] = new double[ColCount];
for (int j = 0; j < ColCount; j++)
{
this[i, j] = InitElements[i, j];
}
}
}
public double this[int i, int j]
{
get
{
return _Elements[i][j];
}
set
{
if (value != 0)
{
this.IsZero = false;
}
if (Math.Round(value,8) != 1)
{
this.IsUnit = false;
}
else
{
if (i != j)
{
this.IsUnit = false;
}
}
_Elements[i][j] = value;
}
}
public double[] this[int i]
{
get
{
return _Elements[i];
}
}
public double[] this[int i, bool GetCol]
{
get
{
double[] theResult = new double[RowCount];
for (int k = 0; k < RowCount; k++)
{
theResult[k] = _Elements[k][i];
}
return theResult;
}
}
public void SwapRow(int i, int j)
{
if (i != j)
{
double[] theTemp = _Elements[i];
_Elements[i] = _Elements[j];
_Elements[j] = theTemp;
}
}
public void SwapCol(int i, int j)
{
if (i != j)
{
for (int k = 0; k < RowCount; k++)
{
double theTemp = _Elements[k][j];
_Elements[k][j] = _Elements[k][i];
_Elements[k][i] = theTemp;
}
}
}
public bool IsSquareMatrix
{
get
{
return this.ColCount == this.RowCount;
}
}
public void CopyFrom(TMatrix A)
{
if (A.RowCount != this.RowCount || A.ColCount != this.ColCount)
{
throw new Exception("不是同型矩阵不能拷贝!");
}
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
this[i, j] = A[i, j];
}
}
}
#region 初等变换
/// <summary>
/// 行初等变换1:交换两行.
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
private void EleTransRow1(int i, int j)
{
SwapRow(i, j);
}
/// <summary>
/// 行初等变换2:用一个非零数乘以一行.
/// </summary>
/// <param name="RowIndex">行号</param>
/// <param name="Multiplier">乘数,不能为零</param>
private void EleTransRow2(int RowIndex, double Multiplier)
{
if (Multiplier == 1)
{
return;
}
if (Multiplier != 0)
{
for (int j = 0; j < ColCount; j++)
{
this[RowIndex, j] = this[RowIndex, j] * Multiplier;
}
}
}
/// <summary>
/// 行初等变换3:行1减行2
/// </summary>
/// <param name="Row1">行号1</param>
/// <param name="Row2">行号2</param>
private void EleTransRow3(int Row1, int Row2, double Multiplier)
{
for (int j = 0; j < ColCount; j++)
{
this[Row1, j] = this[Row1, j] - this[Row2, j] * Multiplier;
}
}
/// <summary>
/// 行初等变换4:行1 * 系数1 - 行2 * 系数2
/// </summary>
/// <param name="Row1">行号</param>
/// <param name="M1">乘数1,不能为零</param>
/// <param name="M2">乘数2,不能为零</param>
private void EleTransRow4(int Row1, int Row2,double M1,double M2)
{
for (int j = 0; j < ColCount; j++)
{
this[Row1, j] = this[Row1, j] * M1 - this[Row2, j] * M2;
}
}
/// <summary>
/// 列初等变换1:交换两列.
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
public void EleTransCol1(int i, int j)
{
SwapCol(i, j);
}
/// <summary>
/// 列初等变换2:用一个非零数乘以一列.
/// </summary>
/// <param name="ColIndex">列号</param>
/// <param name="Multiplier">乘数,不能为零</param>
public void EleTransCol2(int ColIndex, double Multiplier)
{
if (Multiplier != 0)
{
for (int j = 0; j < RowCount; j++)
{
this[j, ColIndex] = this[j, ColIndex] * Multiplier;
}
}
}
/// <summary>
/// 列初等变换3:列1减列2
/// </summary>
/// <param name="Row1">列号1</param>
/// <param name="Row2">列号2</param>
public void EleTransCol3(int Col1, int Col2, double Multiplier)
{
for (int j = 0; j < RowCount; j++)
{
this[j, Col1] = this[j, Col1] - this[j, Col2] * Multiplier;
}
}
/// <summary>
/// 列初等变换4:列1 * 系数1 - 列2 * 系数2
/// </summary>
/// <param name="Col1">列号</param>
/// <param name="Col2">列号2</param>
/// <param name="M1">乘数1,不能为零</param>
/// <param name="M2">乘数2,不能为零</param>
public void EleTransCol4(int Col1, int Col2, double M1, double M2)
{
for (int j = 0; j < RowCount; j++)
{
this[j, Col1] = this[j, Col1] * M1 - this[j, Col2] * M2;
}
}
#endregion
/// <summary>
/// 矩阵消元,转换成阶梯矩阵
/// 本算法也可以用来求矩阵的秩.
/// 仅用行初等变换.
/// </summary>
public void TransToEchelonMatrix(List<TransformItem> TransformRecords)
{
//从第1列到第theE列进行变换.
//最大非0行,用以标记进行变换到现在,可以继续进行处理的最小行号.
var theNoZeroIndex = 0;
for (int i = 0; i < this.ColCount; i++)
{
var theR = -1;
for (int j = theNoZeroIndex; j < this.RowCount; j++)
{
if (this[j, i] != 0)
{
theR = j;
break;
}
}
if (theR >= 0)
{
//将找到非零元素行交换到当前行.
TransformRecords.Add(TransformItem.CreateEleTransRow1(theR, theNoZeroIndex));
EleTransRow1(theR, theNoZeroIndex);
//将大于当前行的列初等变换为0
var theM1 = this[theNoZeroIndex, i];
for (int k = theNoZeroIndex + 1; k < this.RowCount; k++)
{
var theRate = Math.Round(this[k, i] / theM1,ConstDef.Decimals);
TransformRecords.Add(TransformItem.CreateEleTransRow4(k, theNoZeroIndex, 1, theRate));
EleTransRow4(k, theNoZeroIndex, 1, theRate);
}
theNoZeroIndex++;
}
}
}
/// <summary>
/// 变换成标准形.方法很简单:先用行初等变换,尽量消元,然后用列初等变换,尽量消元.
/// 但在这里会同时用到行列的初等变换.这里采用变换函数,如果为了效率,其实可以将初等
/// 变换代码直接写到函数里。
/// </summary>
public List<TransformItem> TransToStandardForm()
{
var theTransList = new List<TransformItem>();
//从第i=1行开始,使得[i,i]不等于0,然后将剩余的i行,i列的元素通过初等变换变成0.
//如果[i,i]无法获得非零元素则变换终止.
for (int i = 0; i < this.RowCount; i++)
{
//如果[i,i]等于0,则进行行交换直到到交换到[i,i]变为非零元素,
//如果没找到,就找列,如果都没找到,则终止
var theRow = -1;
var theCol = -1;
//在行>i,列>i的所有元素中找到一个非零值,如果找到,就进行初等变换
//如果没找到,则说明完成标准型转换.
var theFind = false;
for (int r = i; r < this.RowCount; r++)
{
for (int c = i; c < this.ColCount; c++)
{
if (this[r, c] != 0)
{
theRow = r;
theCol = c;
theFind = true;
break;
}
}
if (theFind)
{
break;
}
}
if (theFind)
{
//先做行变换,再做列变换,目的是将找到的非零元素交换到当前位置.
//行初等变换1,
theTransList.Add(TransformItem.CreateEleTransRow1(i, theRow));
EleTransRow1(i, theRow);
//列初等变换
theTransList.Add(TransformItem.CreateEleTransCol1(i, theCol));
EleTransCol1(i, theCol);
//将[i,i] 变为1
double theMultipler = Math.Round((double)1 / this[i, i], ConstDef.Decimals);
//行初等变换2(这里采用列也是一样,是等价的)
theTransList.Add(TransformItem.CreateEleTransRow2(i, theMultipler));
EleTransRow2(i, theMultipler);
//将i行上>i的列上的其它元素变换成0
for (int c = i + 1; c < this.ColCount; c++)
{
var theM2 = this[i,c];
//c=c*1-i*theM2,这个函数其实是综合了几个初等变换.
theTransList.Add(TransformItem.CreateEleTransCol4(c, i,1, theM2));
EleTransCol4(c, i, 1, theM2);
}
//将i列上>i的行上的其它元素变换成0
for (int r = i + 1; r < this.RowCount; r++)
{
var theM2 = this[r, i];
//c=c*1-i*theM2,这个函数其实是综合了几个初等变换.
theTransList.Add(TransformItem.CreateEleTransRow4(r, i,1,theM2));
EleTransRow4(r, i, 1, theM2);
}
}
else
{
break;
}
}
return theTransList;
}
/// <summary>
/// 变换成标准形:这里仅采用行变换.但需要注意的是这里如果不是满秩矩阵,
/// 得到的就不一定是标准型.这个转换主要用于求矩阵的逆.
/// </summary>
/// <returns>变换过程记录.</returns>
public List<TransformItem> TransToStandardForm2()
{
var theTransfromRecords = new List<TransformItem>();
//先把矩阵转换成上三角矩阵。
TransToEchelonMatrix(theTransfromRecords);
//然后从最后一列开始,第1行开始变换为0.
for (int j = this.ColCount - 1; j >= 0; j--)
{
//从下到上找到第1个非0行,作为基准行(减少行)
//因为矩阵的下半部分全为0,则开始找的位置在对角线上开始.
int theR = -1;
int theStartIndex = Math.Min(j,this.RowCount-1);
for (int i = theStartIndex; i >= 0; i--)
{
if (this[i, j] != 0)
{
theR = i;
break;
}
}
//如果找到基准行,则开始变换,利用减去基准行*一个系数来消除第0到thR-1行的元素
if (theR >= 0)
{
for (int i = 0; i < theR; i++)
{
var theRate = Math.Round(this[i, j] / this[theR, j], ConstDef.Decimals);
theTransfromRecords.Add(TransformItem.CreateEleTransRow4(i, theR, 1, theRate));
EleTransRow4(i, theR, 1, theRate);
}
}
}
//将对角线上的元素化为1
var theMinRC = Math.Min(this.ColCount, this.RowCount);
for (int i = 0; i < theMinRC; i++)
{
if (this[i, i] != 0)
{
var theRate = Math.Round((double)1.0 / this[i, i], ConstDef.Decimals);
EleTransRow2(i, theRate);
theTransfromRecords.Add(TransformItem.CreateEleTransRow2(i, theRate));
}
}
return theTransfromRecords;
}
/// <summary>
/// 对矩阵按照TransformItems里的变换做变换
/// </summary>
/// <param name="TransformItems">变换集合</param>
public void DoTransform(List<TransformItem> TransformItems)
{
if (TransformItems == null)
{
return;
}
for (int i = 0; i < TransformItems.Count; i++)
{
var theTransItem = TransformItems[i];
switch (theTransItem.RowOrCol)
{
case TransRowOrCol.Row:
switch (theTransItem.TransMethod)
{
case BasicTransMethod.Swap:
EleTransRow1(theTransItem.i, theTransItem.j);
break;
case BasicTransMethod.Multipler:
EleTransRow2(theTransItem.i, theTransItem.M1);
break;
case BasicTransMethod.CoPlus1:
EleTransRow3(theTransItem.i, theTransItem.j, theTransItem.M1);
break;
case BasicTransMethod.CoPlus2:
EleTransRow4(theTransItem.i, theTransItem.j,theTransItem.M1,theTransItem.M2);
break;
}
break;
case TransRowOrCol.Col:
switch (theTransItem.TransMethod)
{
case BasicTransMethod.Swap:
EleTransCol1(theTransItem.i, theTransItem.j);
break;
case BasicTransMethod.Multipler:
EleTransCol2(theTransItem.i, theTransItem.M1);
break;
case BasicTransMethod.CoPlus1:
EleTransCol3(theTransItem.i, theTransItem.j, theTransItem.M1);
break;
case BasicTransMethod.CoPlus2:
EleTransCol4(theTransItem.i, theTransItem.j, theTransItem.M1, theTransItem.M2);
break;
}
break;
}
}
}
public TMatrix Clone()
{
var theA = new TMatrix(this.RowCount, this.ColCount);
for (int i = 0; i < theA.RowCount; i++)
{
for (int j = 0; j < theA.ColCount; j++)
{
theA[i, j] = this[i, j];
}
}
return theA;
}
public static TMatrix NewZeroMatrix(int Row, int Col)
{
return new TMatrix(Row, Col, 0);
}
public static TMatrix NewSquareMatrix(int n)
{
return new TMatrix(n, 1, true);
}
/// <summary>
/// 转置矩阵
/// </summary>
/// <param name="A">矩阵</param>
/// <returns>转置矩阵</returns>
public static TMatrix Transposition(TMatrix A)
{
var theRetM = new TMatrix(A.ColCount, A.RowCount);
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
theRetM[j, i] = A[i, j];
}
}
return theRetM;
}
public static TMatrix SwapRow(TMatrix A, int i, int j)
{
var theA = A.Clone();
theA.SwapRow(i, j);
return theA;
}
public static TMatrix SwapCol(TMatrix A, int i, int j)
{
var theA = A.Clone();
theA.SwapCol(i, j);
return theA;
}
public static TMatrix operator +(TMatrix A, TMatrix B)
{
if (A.RowCount != B.RowCount || A.ColCount != B.ColCount)
{
throw new Exception("不是同型矩阵不能相加!");
}
double[][] theResult = new double[A.RowCount][];
for (int i = 0; i < A.RowCount; i++)
{
theResult[i] = new double[A.ColCount];
for (int j = 0; j < A.ColCount; j++)
{
theResult[i][j] = A[i, j] + B[i, j];
}
}
return new TMatrix(theResult);
}
public static TMatrix operator -(TMatrix A)
{
var theA = new TMatrix(A.RowCount, A.ColCount);
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
theA[i, j] = 0 - A[i, j];
}
}
return theA;
}
public static TMatrix operator -(TMatrix A, TMatrix B)
{
if (A.RowCount != B.RowCount || A.ColCount != B.ColCount)
{
throw new Exception("不是同型矩阵,不能相减");
}
var theA = new TMatrix(A.RowCount, A.ColCount);
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
theA[i, j] = A[i, j] - B[i, j];
}
}
return theA;
}
public static TMatrix operator *(double K, TMatrix A)
{
if (A.IsZero)
{
return TMatrix.NewZeroMatrix(A.RowCount, A.ColCount);
}
var theA = new TMatrix(A.RowCount, A.ColCount);
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
theA[i, j] = K * A[i, j];
}
}
return theA;
}
public static TMatrix operator *(decimal K, TMatrix A)
{
return K * A;
}
public static TMatrix operator *(TMatrix A, double K)
{
return K * A;
}
public static TMatrix operator *(TMatrix A, TMatrix B)
{
if (A.ColCount != B.RowCount)
{
throw new Exception("A的列数不等于B的行数,不能相乘!");
}
if (A.IsZero)
{
return TMatrix.NewZeroMatrix(A.RowCount, B.ColCount);
}
if (A.IsUnit)
{
return B.Clone();
}
if (B.IsUnit)
{
return A.Clone();
}
double[][] theResult = new double[A.RowCount][];
for (int i = 0; i < A.RowCount; i++)
{
theResult[i] = new double[B.ColCount];
for (int j = 0; j < B.ColCount; j++)
{
theResult[i][j] = 0;
for (int k = 0; k < A.ColCount; k++)
{
theResult[i][j] += A[i, k] * B[k, j];
}
}
}
return new TMatrix(theResult);
}
public static TMatrix operator ^(TMatrix A, int K)
{
if (A.IsSquareMatrix)
{
if (A.IsUnit)
{
return A.Clone();
}
if (A.IsZero)
{
return TMatrix.NewZeroMatrix(A.RowCount, A.ColCount);
}
if (K == 0)
{
return TMatrix.NewSquareMatrix(A.RowCount);
}
if (K == 1)
{
return A.Clone();
}
var theA = A;
if (K < 0)
{
theA = GetInverseMatrix(A);
}
var theRet = theA;
for (int i = 1; i < K; K++)
{
theRet = theRet * theA;
}
return theRet;
}
throw new Exception("只有方阵才能做幂运算!");
}
public static bool operator ==(TMatrix A, TMatrix B)
{
if (A.RowCount != B.RowCount || A.ColCount != B.ColCount)
{
throw new Exception("不是同型矩阵,不能比较");
}
if (A.IsUnit && B.IsUnit || A.IsZero && B.IsZero)
{
return true;
}
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
if (A[i, j] != B[i, j])
{
return false;
}
}
}
return true;
}
public static bool operator !=(TMatrix A, TMatrix B)
{
if (A.RowCount != B.RowCount || A.ColCount != B.ColCount)
{
throw new Exception("不是同型矩阵,不能比较");
}
if (A.IsUnit && B.IsUnit || A.IsZero && B.IsZero)
{
return false;
}
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
if (A[i, j] != B[i, j])
{
return true;
}
}
}
return true;
}
/// <summary>
/// 初等变换法求矩阵A的逆.
/// </summary>
/// <param name="A"></param>
/// <returns></returns>
public static TMatrix GetInverseMatrix(TMatrix A)
{
var theA = A.Clone();
var theTransItems = theA.TransToStandardForm2();
var theE = new TMatrix(theA.RowCount, 1, true);
theE.DoTransform(theTransItems);
return theE;
}
/// <summary>
/// 古典法求逆矩阵
/// </summary>
/// <param name="A">方阵</param>
/// <returns></returns>
public static TMatrix GetInverseMatrix2(TMatrix A)
{
if (A.RowCount != A.ColCount)
{
throw new Exception("次函数仅支持方阵!");
}
//计算其行列式的值
var theValOfA = LinearAlgebra.CalcDeterminant(A.Elements);
if (theValOfA == 0)
{
throw new Exception("不可逆!");
}
if (A.RowCount == 1)
{
return new TMatrix(1, 1, Math.Round((double)1.0 / theValOfA,ConstDef.Decimals));
}
//求伴随矩阵
//var theAdjoint = new TMatrix(A.RowCount);
var theAElements = A.Elements;
var theMElements = new double[A.RowCount, A.ColCount];
for (int i = 0; i < A.RowCount; i++)
{
for (int j = 0; j < A.ColCount; j++)
{
var theMij = LinearAlgebra.GetDeterminantMij(theAElements, i + 1, j + 1);
var theSign = LinearAlgebra.CalcDeterMijSign(i+1, j+1);
var theValOfAij = theSign * LinearAlgebra.CalcDeterminant(theMij);
//注意这里.弄反了,结果就是逆矩阵的转置矩阵.
theMElements[j, i] = theValOfAij;
}
}
//计算伴随矩阵结果.
return (Math.Round((double)1.0 / theValOfA,ConstDef.Decimals)) * (new TMatrix(theMElements));
}
/// <summary>
/// 获取矩阵的秩.
/// </summary>
/// <returns></returns>
public int GetRank()
{
if (_Rank < 0)
{
var theA = this.Clone();
theA.TransToStandardForm();
_Rank = GetRank(theA);
}
return _Rank;
}
public static int GetRank(TMatrix StdForm)
{
int theRank = 0;
for (int i = 0; i < StdForm.ColCount && i < StdForm.RowCount; i++)
{
if (StdForm[i, i] == 1)
{
theRank++;
continue;
}
}
return theRank;
}
/// <summary>
/// 是否是标量矩阵
/// </summary>
public bool IsScalarMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
var theScalar = _Elements[0][0];
for (int i = 0; i < this.RowCount; i++)
{
for (int j = 0; j < this.ColCount; j++)
{
if (i != j)
{
if (_Elements[i][j] != 0)
{
return false;
}
}
else
{
if (_Elements[i][i] != theScalar)
{
return false;
}
}
}
}
return true;
}
}
/// <summary>
/// 对角矩阵 非对角线上的元素全部为0方阵
/// </summary>
public bool IsDiagonalMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
for (int i = 0; i < this.RowCount; i++)
{
for (int j = 0; j < this.ColCount; j++)
{
if (i != j)
{
if (_Elements[i][j] != 0)
{
return false;
}
}
}
}
return true;
}
}
/// <summary>
/// 上三角矩阵
/// </summary>
public bool IsUpperTriangularMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
for (int i = 0; i < this.ColCount; i++)
{
for (int j = i + 1; j < this.RowCount; j++)
{
if (_Elements[j][i] != 0)
{
return false;
}
}
}
return true;
}
}
/// <summary>
/// 下三角矩阵
/// </summary>
public bool IsLowerTriangularMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
for (int i = 0; i < this.ColCount; i++)
{
for (int j = 0; j < i; j++)
{
if (_Elements[j][i] != 0)
{
return false;
}
}
}
return true;
}
}
/// <summary>
/// 对称矩阵Aij=Aij.
/// </summary>
public bool IsSymmetricMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
for (int i = 0; i < this.RowCount; i++)
{
for (int j = 0; j < this.ColCount; j++)
{
if (_Elements[j][i] != _Elements[i][j])
{
return false;
}
}
}
return true;
}
}
/// <summary>
/// 反对称矩阵Aij=-Aji.注意其对角线元素为0.
/// </summary>
public bool IsAntisymmetricMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
for (int i = 0; i < this.RowCount; i++)
{
for (int j = 0; j < this.ColCount; j++)
{
if (i == j)
{
if (_Elements[j][i] != 0)
{
return false;
}
}
else
{
if (_Elements[j][i] != -_Elements[i][j])
{
return false;
}
}
}
}
return true;
}
}
/// <summary>
/// 正交矩阵A*t(A)=E.
/// </summary>
public bool IsOrthogonalMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
var theA = this.Clone();
var theAt = Transposition(theA);
var theRet = theA * theAt;
return theRet.IsUnit;
}
}
/// <summary>
/// 零幂矩阵(A^k=O)。
/// |A|==0
/// </summary>
public bool IsZeroPowerMatrix
{
get
{
if (this.RowCount != this.ColCount)
{
return false;
}
var theVal = LinearAlgebra.CalcDeterminant(this.Elements);
return theVal == 0;
}
}
}
}