• 【原创】开源Math.NET基础数学类库使用(15)C#计算矩阵行列式


                   本博客所有文章分类的总目录:【总目录】本博客博文总目录-实时更新 

    开源Math.NET基础数学类库使用总目录:【目录】开源Math.NET基础数学类库使用总目录

      上个月对Math.NET的基本使用进行了介绍,主要内容有矩阵,向量的相关操作,解析数据格式,数值积分,数据统计,相关函数,求解线性方程组以及随机数发生器的相关内容。这个月接着深入发掘Math.NET的各种功能,并对源代码进行分析,使得大家可以尽可能的使用Math.NET在.NET平台下轻易的开发数学计算相关的,或者可以将其中的源码快速移植到自己的系统中去(有时候并不需要所有的功能,只需要其中的部分功能代码),今天要介绍的是Math.NET中利用C#计算矩阵行列式的功能。

    本文原文地址:http://www.cnblogs.com/asxinyu/p/4304289.html

    1.行列式概念与性质

      行列式是关于方阵的元素所定义的一种运算,其运算的结果是一个数,称为方阵的行列式值,简称为方阵的行列式。

         

      行列式的概念最初是伴随着方程组的求解而发展起来的。行列式的提出可以追溯到十七世纪,最初的雏形由日本数学家关孝和与德国数学家戈特弗里德·莱布尼茨各自独立得出,时间大致相同。日本数学家关孝和提出来的,他在1683年写了一部名为解伏题之法的著作,意思是“解行列式问题的方法”,书中对行列式的概念和它的展开已经有了清楚的叙述。欧洲第一个提出行列式概念的是德国数学家,微积分学奠基人之一莱布尼茨

      行列式是线性代数里面的一个基本概念,我们可以从其定义和性质中了解一下其作用:

    1.行列式与它的转置行列式相等;

    2.互换行列式的两行(列),行列式变号;

    3.行列式的某一行(列)的所有的元素都乘以同一数k,等于用数k乘此行列式;

    4.行列式如果有两行(列)元素成比例,则此行列式等于零;

    5.若行列式的某一列(行)的元素都是两数之和,则这个行列式是对应两个行列式的和;

    6.把行列式的某一列(行)的各元素乘以同一数然后加到另一列(行)对应的元素上去,行列式不变

    2.Math.NET计算行列式的实现

      Math.NET在对行列式的计算过程中,只是把其作为矩阵计算的一个小部分功能,作为属性添加在各个矩阵分解算法的抽象和实现类中。因为Math.NET中矩阵的泛型类型的相关实现主要是支持Double和Float类型,所以基本上与泛型相关的类都实现了2个版本,在实际使用时再进行调用。而矩阵分解算法如:Cholesky,LU,QR,Svd等都有一个抽象泛型基类。在这些抽象类中都定义好了矩阵分解相关的计算,如行列式,方程求解等功能,然后对类进行继承,如Cholesky分解算法,的抽象 基类:

     1 internal abstract class Cholesky : Cholesky<double>
     2 {
     3     protected Cholesky(Matrix<double> factor)
     4         : base(factor)
     5     {
     6     }
     7 
     8     /// <summary>
     9     /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
    10     /// </summary>
    11     public override double Determinant
    12     {
    13         get
    14         {
    15             var det = 1.0;
    16             for (var j = 0; j < Factor.RowCount; j++)
    17             {
    18                 var d = Factor.At(j, j);
    19                 det *= d*d;
    20             }
    21 
    22             return det;
    23         }
    24     }
    25 
    26     /// <summary>
    27     /// Gets the log determinant of the matrix for which the Cholesky matrix was computed.
    28     /// </summary>
    29     public override double DeterminantLn
    30     {
    31         get
    32         {
    33             var det = 0.0;
    34             for (var j = 0; j < Factor.RowCount; j++)
    35             {
    36                 det += 2*Math.Log(Factor.At(j, j));
    37             }
    38 
    39             return det;
    40         }
    41     }
    42 }

    这个基类就是继承实现的Doule类型的版本,然后DenseCholesky继承该类,实现更多的计算功能:

     1 internal sealed class DenseCholesky : Cholesky
     2 {       
     3     public static DenseCholesky Create(DenseMatrix matrix)
     4     {
     5         if (matrix.RowCount != matrix.ColumnCount)
     6         {
     7             throw new ArgumentException(Resources.ArgumentMatrixSquare);
     8         }
     9         var factor = (DenseMatrix) matrix.Clone();
    10         Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
    11         return new DenseCholesky(factor);
    12     }
    13 
    14     DenseCholesky(Matrix<double> factor): base(factor)  {      }
    15     
    16     public override void Solve(Matrix<double> input, Matrix<double> result)
    17     {
    18         if (result.RowCount != input.RowCount)
    19         {
    20             throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
    21         }
    22 
    23         if (result.ColumnCount != input.ColumnCount)
    24         {
    25             throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
    26         }
    27 
    28         if (input.RowCount != Factor.RowCount)
    29         {
    30             throw Matrix.DimensionsDontMatch<ArgumentException>(input, Factor);
    31         }
    32 
    33         var dinput = input as DenseMatrix;
    34         if (dinput == null)
    35         {
    36             throw new NotSupportedException("Can only do Cholesky factorization for dense matrices at the moment.");
    37         }
    38 
    39         var dresult = result as DenseMatrix;
    40         if (dresult == null)
    41         {
    42             throw new NotSupportedException("Can only do Cholesky factorization for dense matrices at the moment.");
    43         }
    44         Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfDouble);
    45         var dfactor = (DenseMatrix) Factor;
    46         Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount);
    47     }
    48 
    49     public override void Solve(Vector<double> input, Vector<double> result)
    50     {
    51         if (input.Count != result.Count)
    52         {
    53             throw new ArgumentException(Resources.ArgumentVectorsSameLength);
    54         }
    55 
    56         if (input.Count != Factor.RowCount)
    57         {
    58             throw Matrix.DimensionsDontMatch<ArgumentException>(input, Factor);
    59         }
    60 
    61         var dinput = input as DenseVector;
    62         if (dinput == null)
    63         {
    64             throw new NotSupportedException("Can only do Cholesky factorization for dense vectors at the moment.");
    65         }
    66         var dresult = result as DenseVector;
    67         if (dresult == null)
    68         {
    69             throw new NotSupportedException("Can only do Cholesky factorization for dense vectors at the moment.");
    70         }
    71 
    72         Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfDouble);
    73 
    74         var dfactor = (DenseMatrix) Factor;
    75         Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1);
    76     }
    77 }

    这里只是介绍了具体行列式计算的实现,其实在Math.NET中这种实现只要在调试的时候搞懂了其中一个,其他相关的都好懂了。调用的时候,由于矩阵的类型里面都有相关的属性,可以直接继续计算,下面就演示一下如何调用计算行列式。

    3.矩阵行列式计算的调用代码

       在矩阵类Martix中,已经有一个属性Determinant可以直接获取矩阵的行列式,所以计算也非常简单:

     1 // 格式设置
     2 var formatProvider = (CultureInfo)CultureInfo.InvariantCulture.Clone();
     3 formatProvider.TextInfo.ListSeparator = " ";
     4 
     5 //创建一个随机的矩阵
     6 var matrix = new DenseMatrix(5);
     7 var rnd = new Random(1); 
     8 for (var i = 0; i < matrix.RowCount; i++)
     9 {
    10     for (var j = 0; j < matrix.ColumnCount; j++)
    11     {
    12         matrix[i, j] = rnd.NextDouble();
    13     }
    14 }
    15 // 计算行列式
    16 Console.WriteLine(@"1. 行列式 结果为");
    17 Console.WriteLine(matrix.Determinant());
    18 Console.WriteLine();

      输出结果为:

    1. 行列式 结果为
    0.0349730711309253

      如果要使用特殊的分解算法类计算行列式,也可以单独计算,例如下面的代码,先利用matrix对象生成一个Cholesky分解算法的对象,然后用它来计算行列式:

     1 var formatProvider = (CultureInfo)CultureInfo.InvariantCulture.Clone();
     2 formatProvider.TextInfo.ListSeparator = " ";
     3 
     4 //创建矩阵
     5 var matrix = DenseMatrix.OfArray(new[,] { { 2.0, 1.0 }, { 1.0, 2.0 } });
     6 Console.WriteLine(@"原始矩阵");
     7 Console.WriteLine(matrix.ToString("#0.00	", formatProvider));
     8 Console.WriteLine();
     9 
    10 //cholesky分解对象
    11 var cholesky = matrix.Cholesky();
    12 
    13 //计算行列式
    14 Console.WriteLine(@"矩阵行列式");
    15 Console.WriteLine(cholesky.Determinant);
    16 Console.WriteLine();

    结果如下:

    1 原始矩阵
    2 DenseMatrix 2x2-Double
    3 2.00      1.00
    4 1.00      2.00
    5 
    6 矩阵行列式
    7 3

    4.资源

      资源包括源代码以及案例都可以去官网下载,下载地址本系列文章的目录中第一篇文章:http://www.cnblogs.com/asxinyu/p/4264638.html,有介绍。由于源码很大,如果找不到相应的案例,可以进行搜索,可以比较快的找到相应的代码。

  • 相关阅读:
    枚举类型的应用
    动手动脑
    四则运算和验证码--源码
    ATM源码
    javabean+jsp+servlet+jdbc
    四则运算改良
    Java异常
    课后总结
    包装类Integre
    对象验证
  • 原文地址:https://www.cnblogs.com/asxinyu/p/Dotnet_Opensource_MathNet_Determinant_15.html
Copyright © 2020-2023  润新知