MyMathLib系列(矩阵算法--2)

矩阵相关的算法比较多,也是比较重要的,而且算法之间的性能差异确实比较大,初等变换法求逆比古典法求逆快不是一点点。矩阵的计算量和数值其实都是比较大的,特别是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;
            }
        }

    }
}

时间: 2024-10-12 09:18:12

MyMathLib系列(矩阵算法--2)的相关文章

螺旋矩阵算法

螺旋矩阵算法是一种常用的算法,如图中排列数值: 代码如下: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> *{ padding: 0; margin: 0; } ul{ border: 1px solid black; border-bottom: n

5Python全栈之路系列之算法

ython全栈之路系列之算法 一个算法的优劣可以用空间复杂度与时间复杂度来衡量. 冒泡排序 冒泡排序(英语:Bubble Sort,台湾另外一种译名为:泡沫排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. from random import randint li = [randint

MyMathLib系列(向量及矩阵--准备工作)

因为向量和矩阵的计算工作量比较大,为了更好的书写代码,这里增加了几个定义类,这些定义或者扩展方法将在以后的代码中应用到:1.公共枚举类型 /* 文件:PublicEnums.cs * 目的:定义公共枚举类型. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 初等变换类型(课本上是加,这里

MyMathLib系列(一元多项式运算求初等因子等)

利用TExp类的运算来求矩阵的特征值,初等因子等: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 一元多项式计算 /// </summary> public class PolynomialOfOneBasic { /// <summary> /// 化成对阶梯矩阵

MyMathLib系列(向量运算--1)

主要是线性代数的第2章的算法,由于本章的大部分都是概念性的,而且后面还有矩阵,因此算法较少: /*Vector.cs * Albert.Tian on 20141225 */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 向量相关运算,这里没有给出向量的基本变换.因为 /// 向量组可以用矩

MyMathLib系列(线性空间)

线性空间的算法不是特别多,这里是代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 线性空间 /// </summary> public class LinearSpace { /// <summary> /// 求向量Vector在基底BasisOfLinearS

MyMathLib系列(行列式计算4--向量部分)

1)将向量组进行消元,变换成阶梯矩阵,这是求向量组的极大线性无关组的基本算法.这个方法在前面曾经给出过,但在这里做了改进,目的是为了可以判断是否线性相关: /// <summary> /// 方程组消元,最后一列为系数,结果就在CoefficientDeterminant里. /// 本算法也可以用来求矩阵的秩. /// </summary> /// <param name="CoefficientDeterminant">方程组系数数组</p

MyMathLib系列(行列式计算3)

到今天,行列式和线性方程组部分就完成了. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// <summary> /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见. /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过 /// 严格测试,如需参考,请慎重. ///

MyMathLib系列(订正两个函数)

在行列式消元中的判断条件有问题,这里给出订正后的代码: 1)MyMathLib.LinearAlgebra.CalcDeterminant方法 /// <summary> /// 化三角法行列式计算, /// </summary> /// <param name="Determinants">N阶行列式</param> /// <returns>计算结果</returns> public static double