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

mymathlab:在线运行数学和逻辑实验的地方-开源 一个在线运行数学和逻辑实验的地方,无需下载,无需安装。 直接上网就行了。 立即下载

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


    }
}

JAVA MATCH 类库---JMathLib JMathLib是一个用于计算复杂数学表达式并能够图形化显示计算结果的Java开源类库。它是Matlab、Octave、FreeMat、Scilab的一个克隆,但完全采用纯Java实现。 立即下载

相关推荐

群晖NAS从入门到精通的所有帖子汇总,只要这一篇就够了

本站陆陆续续的转载、原创帖子也有十几二十篇了,从不同的角度对群晖NAS的各种骚操作都有深入的讲解,虽然很多文章都不是讲的很深入,但是针对小白入门已经是足够了,希望对小白来说是一个入门,群晖NAS的大佬们勿喷,哪里写的不对的,请随时留言西安SEO优化站长一定在第一时间纠正修改。

西安SEO优化网站资源 8万+

MyMathLib系列(一元多项式-准备)

这里定义的类TExp是基本的计算项,这里的表达式与C#自带的表达式有很大的区别,这里定义这个类主要是为了进行矩阵运算,当然本身也支持普通的运算,但目前不支持除法。这个类目前的用途主要是为了计算矩阵的特征值,特征向量,有时间,再扩展成支持常见的复数域类的数值和符号运算。代码有点长,需要有点耐心:using System; using System.Collections.Generic; using

三人行必有我师,手写三行必有所悟 2236

ArcGIS Enterprise10.9.1的Windows安装部署

ArcGIS Enterprise10.9.1中Windows版本安装介绍。

qq_36250702的博客 2446

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

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

三人行必有我师,手写三行必有所悟 2419

【Qt】解决 FTH: (11284): *** Fault tolerant heap shim applied to current process. (亲测有效)

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers。容错堆垫片应用到当前的过程。这通常是由于以前的崩溃。win + r,输入regedit。

Fanjufei的博客 830

Apollo Control——超详细入门教程(六):MPC二次规划问题转化

专栏文章列表 Apollo Control——超详细入门教程(一):基于道路误差的车辆动力学模型 Apollo Control——超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导 Apollo Control——超详细入门教程(三):基于Frenet坐标系及XY坐标系的多项式轨迹生成 Apollo Control——超详细入门教程(四):控制模块轨迹误差计算 Apollo Control——超详细入门教程(五):油门刹车标定表之双线性插值算法 ...

凉了鸭的博客 2233

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

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

三人行必有我师,手写三行必有所悟 2192

英伟达 Jetson AGX Thor 官方入门教程(一)系统U盘安装

NVIDIA Jetson AGX Thor开发套件快速安装指南 本指南详细介绍了NVIDIA Jetson AGX Thor开发套件的安装流程。该套件搭载T5000 SoM,为物理AI和机器人应用提供强大支持。安装过程采用全新的JetPack 7.0方案,通过USB闪存盘即可完成BSP(Jetson Linux)安装,无需依赖Ubuntu主机。指南包含硬件开箱说明、两种配置模式(带显示器/无显示器)、详细的ISO镜像下载和USB制作步骤(推荐使用Balena Etcher工具),以及首次启动后的初始设置流

机器人控制与仿真应用 2869

MyMathLib系列(行列式计算2)

/// /// 行列式计算,本程序属于MyMathLib的一部分,欢迎使用,参考,提意见。 /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过 /// 严格测试,如需参考,请慎重. /// public static partial class LinearAlgebra { /// /// 获取

三人行必有我师,手写三行必有所悟 2273

【定位模块项目实战】gnss_localizer、lidar_localizer功能包解析

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、1.2.3.4.二、1.2.3.4.三、1.2.3.4.四、1.2.3.4.总结参考资料 前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 本文先对**【无人驾驶autoware项目实战】感知–定位模块**做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章 提示:以下是本篇文章正文内容 一、 1. 2. 3. 4. . . 二、

qq_35635374的博客 1931

建设银行核心系统建设历程全网最详细记录

中国建设银行核心系统数字化转型之路 摘要:中国建设银行自1954年成立以来,其核心系统经历了从分散到集中、再到分布式架构的演进历程。2002-2005年完成的数据大集中工程(DCC)实现了全行业务统一管理,2010年启动的"新一代核心系统"构建了企业级架构,率先实现"一次研发,全行共享"。2020年起全面推进主机下移战略,通过分布式架构改造,攻克八大关键技术难题,于2024年7月完成境内外全量核心业务下移,日均同步数据8亿条,实现金融核心系统完全自主可控。这一转型不仅

银行信息系统应用架构详解 4872

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

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

三人行必有我师,手写三行必有所悟 2622

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

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

主要是线性代数的第2章的算法,由于本章的大部分都是概念性的,而且后面还有矩阵,因此算法较少:/*Vector.cs * Albert.Tian on 20141225 */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib {

三人行必有我师,手写三行必有所悟 2101

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

MyMathLib系列(线性空间)

线性空间的算法不是特别多,这里是代码:using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyMathLib { /// /// 线性空间 /// public class LinearSpace {

三人行必有我师,手写三行必有所悟 2069

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

MyMathLib系列(订正两个函数)

在行列式消元中的判断条件有问题,这里给出订正后的代码:1)MyMathLib.LinearAlgebra.CalcDeterminant方法/// /// 化三角法行列式计算, /// /// N阶行列式 /// 计算结果 public static double CalcDeterminant(double[,]

三人行必有我师,手写三行必有所悟 2180

一个简单的跨域跨数据库事务处理架构

原来只是有点这个想法,怎么去做这个事务,这次给公司做新架构演示,随带就加进去了,居然还成了,还像那么回事:我的做法很简单:自己写了个事务处理类,提供一个静态的启动事务方法,然后就是Commit,Rollback方法,再利用GUID作为事务ID。有事务处理类管理本地数据库链接和远程跨域服务信息,利用这些信息在Commit或者rollback时进行提交或者回滚,在数据库级上并行执行命令,需要对远程跨域

三人行必有我师,手写三行必有所悟 1万+

腾讯面试题(除掉N个整数中重复数)解题(线性时间,原地置换排序算法)(已修正)

题目:一个大小为N的数组,里面是N个整数,怎样去除重复, 要求时间复杂度为O(n),空间复杂度为O(1).               //下面的思路没问题,但算法有问题,修正后的算法见后面.         ///         /// 需要除掉重复的整数的数组,

三人行必有我师,手写三行必有所悟 1万+

归并排序(MergeSort)的原理及延伸性思考

前面一篇博文写了归并排序的算法实现,虽然做了些注释,但没有写归并排序的原理,这篇就补上,同时对归并所隐含的思想做一个探讨。 1)归并排序的原理      为了便于说明,这里我们提到的已排好序的序列都是指从小到大的升序(对于降序其实原理是一样的。     假设有两个已排好序的

三人行必有我师,手写三行必有所悟 1万+

软件架构风格整理(5 仓库风格 6复制风格) .

1         仓库风格在仓库风格中。有两种不同的构件:中央数据结构说明当前状态.独立构件在中央数据存贮上执行.仓库与外构件问的相互作用在系统中会有大的变化若输入流中某类时间触发进程执行的选择.则仓库是一传统型数据库;另一方面.若中央数据结构的当前状态触发进程执行的选择.则仓库是一黑板系统1.1      数据库系统数据库架构是库风格最常见的形式。构件主要有两大类,一个是中央共享数据源,保存当

三人行必有我师,手写三行必有所悟 1万+

软件架构风格整理(6 CS,BS等)

1.1      CS结构 C/S软件体系结构是基于资源不对等,且为实现共享而提出来的,是20世纪90年代成熟起来的技术, C/S体系结构定义了工作站如何与服务器相连,以实现数据和应用分布到多个处理机上。 C/S体系结构有三个主要组成部分:数据库服务器、客户应用程序和网络。l  服务器 (1)数据库安全性的要求; (2)数据库访问并发性的控制; (3)数据库前端的客户应用程序的全局数据完整性规则;

三人行必有我师,手写三行必有所悟 1万+

最小优先级队列(基于最小二叉堆算法)

在最小生成树Prim算法中,可以利用最小优先级队列来改善时间复杂度,同时在单源最短路径Dijkstra算法中也同样可以利用这种最小优先级队列来改善算法时间复杂度。实现最小优先级队列可以有很多种方式,比如基于二叉最小堆,或者斐波那契堆等。这里是二叉最小堆的C#实现,原理是根据书上的伪代码来的,但有些地方我做了改进,比如书key值改变,原来书上只能变大,这里取掉了这个限制。同时还提供了根据卫星值来选择

三人行必有我师,手写三行必有所悟 9795

软件架构风格整理(1 数据流风格)

1         数据流风格1.1      批处理序列批处理风格的每一步处理都是独立的.并且每一步是顺序执行的.只有当前一步处理完后.后一步处理才能开始.数据传送在步与步之间作为一个整体.(组件为一系列固定顺序的计算单元,组件间只通过数据传递交互。每个处理步骤是一个独立的程序,每一步必须在前一步结束后才能开始,数据必须是完整的,以整体的方式传递)批处理的典型应用:l  经典数据处理;l  程序

三人行必有我师,手写三行必有所悟 9281

建筑行业是时候进行平行建造的应用了

平行建造就是在建筑的建造过程中利用ACP方法,对建造过程进行模拟、实施和校正的方法,平行建造的实施可以更好的降低建造过程中的各种风险,从而保证工期,降低成本,提高建造质量。 对于大型复杂工程的建造过程本身是一个复杂的过程,做平行建造的难度比较大,但由于信息技术的日益发展,建造过程的平行比起社会工程来说还是简单很多,条件成熟很多: 1)BIM的应用解决了建造过程中的人工建筑的基础,BIM不仅提供...

三人行必有我师,手写三行必有所悟 8636

用DotNet做简单的分布式计算的几个关键技术点

hadoop的数据流分布式处理模型,是分布式计算模型的一种实现,hadoop对海量文件数据比较适合,但对于很多公司的应用系统而言,基本都是基于数据库的,并没有多少文件数据需要实时分析,就是日志文件,也可以放在数据库中,特别是用户操作日志(不是系统级日志),当然,就是存成文件,格式和内容也基本是确定的,分析的时候并不需要分拆和Map.其实只要一个简单的分布式分析(reduce)即可。因此模型上没必要

三人行必有我师,手写三行必有所悟 8368

软件架构风格整理(3 独立构件风格 4 虚拟机风格)

1         独立构件风格1.1      进程通讯进程通信架构风格。构件是独立的过程,连接件是消息传递。这种风格的特点是构件通常是命名过程,消息传递的方式可以是点到点、异步和同步方式及远过程调用等。1.2      事件系统事件驱动架构风格。构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中其他构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所

三人行必有我师,手写三行必有所悟 7555
上一篇: MyMathLib系列(向量运算--1)
下一篇: MyMathLib系列(线性空间)
广州接入
广州接入 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄24年 2224粉丝 731原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值