开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解
原文:【原创】开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解
开源Math.NET基础数学类库使用系列文章总目录:
1.开源.NET基础数学计算组件Math.NET(一)综合介绍
2.开源.NET基础数学计算组件Math.NET(二)矩阵向量计算
3.开源.NET基础数学计算组件Math.NET(三)C#解析Matlab的mat格式
4.开源.NET基础数学类库使用Math.NET(四)C#解析Matrix Marke数据格式
5.开源.NET基础数学类库使用Math.NET(五)C#解析Delimited Formats数据格式
6.开源.NET基础数学类库使用Math.NET(六)数值分析之线性方程直接求解
7.开源.NET基础数学类库使用Math.NET(七)常用的一些数学常数
8.开源.NET基础数学类库使用Math.NET(八)C#进行数值积分
9.开源.NET基础数学类库使用Math.NET(九)相关数论函数使用
10.开源.NET基础数学类库使用Math.NET(十)C#进行数据统计
11.开源.NET基础数学类库使用Math.NET(十一)C#计算相关系数
12.开源.NET基础数学类库使用Math.NET(十二)随机数扩展方法
13.开源.NET基础数学类库使用Math.NET(十三)C#实现其他随机数生成器
14.开源.NET基础数学类库使用Math.NET(十四)安全的随机数生成器扩展
后续继续更新中。。如文章链接打开有误,请关注博客,因为文章正在编辑修改中,所有已经列出的目录都将在1个月之内发表。
前言
在前几篇关于Math.NET的博客中(见上面链接),主要是介绍了Math.NET中主要的数值功能,并进行了简单的矩阵向量计算例子,接着使用Math.NET的矩阵等对象,对3种常用的矩阵数据交换格式的读写。一方面可以了解Math.NET的使用,另一方面以后也可以直接读取和保存数据为这两种格式,给大家的科研或者工作带来便利。接下来的文章将继续对Math.NET的功能进行讲解和演示,并附带一些数学方面的基础知识。毕竟很多人没有精力去研究Math.NET,那我就把我的研究心得一一写出来,方便后来人。
1.数值分析与线性方程
数值分析的基本含义与特点:引用
数值分析(numerical analysis)是研究分析用计算机求解数学计算问题的数值计算方法及其理论的学科,是数学的一个分支,它以数字计算机求解数学问题的理论和方法为研究对象。为计算数学的主体部分。数值分析有如下特点:
1·面向计算机
2·有可靠的理论分析
3·要有好的计算复杂性
4·要有数值实验
5.要对算法进行误差分析数值分析的主要内容:插值法,函数逼近,曲线拟和,数值积分,数值微分,解线性方程组的直接方法,解线性方程组的迭代法,非线性方程求根,常微分方程的数值解法。
所以我们今天要解决的就是数值分析的一个很小但又最常接触到的部分,方程(组)的求解。方程(组)的求解有2种方法,一种是直接求解,一种是迭代求解。直接方法比较好理解,相当与使用公式进行直接计算,结果也比较精确。而另外一种是迭代方法。从最初的猜测,迭代方法逐次近似形式收敛只在极限的精确解。
正如上面所说,方程(组)的形式很多,不同的形式以及实际要求的精度都可以使用不同的方法,而本文主要介绍最简单,也是最常见的线性方程的直接求解方法。
2.Math.NET解线性方程源码分析
本文首先对Math.NET中求解线性方程的相关源码进行分析,这样大家碰到了问题,也可以更好的查找源码解决,或者进行扩展,实现自己的一些特殊需求。Math.NET中MathNet.Numerics.LinearAlgebra.Factorization命名空间下有一个泛型接口:ISolver<T>,就是解AX = B类型的线性方程的接口类型。该接口功能很多,看看下面的接口源代码和注释(本人进行了简单的翻译),就很清楚了。
using System; namespace MathNet.Numerics.LinearAlgebra.Factorization
{
/// <summary>形如AX = B的线性方程组求解的接口类型</summary>
/// <typeparam name="T">泛型参数,支持类型有:double, single, <see cref="Complex"/>,
/// 以及 <see cref="Complex32"/>.</typeparam>
public interface ISolver<T> where T : struct, IEquatable<T>, IFormattable
{
/// <summary>求解AX=B的线性方程组</summary>
/// <param name="input">右矩阵<c>B</c>.</param>
/// <returns>返回求解结果矩阵 <c>X</c>.</returns>
Matrix<T> Solve(Matrix<T> input); /// <summary>求解AX=B的线性方程组</summary>
/// <param name="input">右矩阵 <c>B</c>.</param>
/// <param name="result">求解结果矩阵, <c>X</c>.</param>
void Solve(Matrix<T> input, Matrix<T> result); /// <summary>求解AX=b的线性方程组</summary>
/// <param name="input">等式的右边向量 <c>b</c>.</param>
/// <returns>返回求解结果的左边向量 , <c>x</c>.</returns>
Vector<T> Solve(Vector<T> input); /// <summary>求解AX=b的线性方程组</summary>
/// <param name="input">等式的右边向量 <c>b</c>.</param>
/// <param name="result">求解结果矩阵, <c>x</c>.</param>
void Solve(Vector<T> input, Vector<T> result);
}
}
由于求解线性方程组主要用到了矩阵的分解,Math.NET实现了5种矩阵分解的算法:LU,QR,Svd,Evd,Cholesky。而GramSchmidt是继承QR的,每一个都是实现了ISolver<T>接口,因此就可以直接使用矩阵的分解功能,直接进行线性方程组的求解。为了方便,我们举一个LU的源码例子,简单的看看源码的基本情况:
public abstract class LU<T> : ISolver<T> where T : struct, IEquatable<T>, IFormattable
{
static readonly T One = BuilderInstance<T>.Matrix.One; readonly Lazy<Matrix<T>> _lazyL;
readonly Lazy<Matrix<T>> _lazyU;
readonly Lazy<Permutation> _lazyP; protected readonly Matrix<T> Factors;
protected readonly int[] Pivots; protected LU(Matrix<T> factors, int[] pivots)
{
Factors = factors;
Pivots = pivots; _lazyL = new Lazy<Matrix<T>>(ComputeL);
_lazyU = new Lazy<Matrix<T>>(Factors.UpperTriangle);
_lazyP = new Lazy<Permutation>(() => Permutation.FromInversions(Pivots));
} Matrix<T> ComputeL()
{
var result = Factors.LowerTriangle();
for (var i = ; i < result.RowCount; i++)
{
result.At(i, i, One);
}
return result;
} /// <summary>Gets the lower triangular factor.</summary>
public Matrix<T> L
{
get { return _lazyL.Value; }
}
/// <summary>Gets the upper triangular factor.</summary>
public Matrix<T> U
{
get { return _lazyU.Value; }
}
/// <summary>Gets the permutation applied to LU factorization.</summary>
public Permutation P
{
get { return _lazyP.Value; }
}
/// <summary>Gets the determinant of the matrix for which the LU factorization was computed.</summary>
public abstract T Determinant { get; }
public virtual Matrix<T> Solve(Matrix<T> input)
{
var x = Matrix<T>.Build.SameAs(input, input.RowCount, input.ColumnCount);
Solve(input, x);
return x;
}
public abstract void Solve(Matrix<T> input, Matrix<T> result); public virtual Vector<T> Solve(Vector<T> input)
{
var x = Vector<T>.Build.SameAs(input, input.Count);
Solve(input, x);
return x;
}
public abstract void Solve(Vector<T> input, Vector<T> result);
public abstract Matrix<T> Inverse();
}
大家可能会注意到,上面是抽象类,这和Math.NET的实现是有关的。最终都是实现相应版本的Matrix矩阵,然后实现对应版本的类型的分解方法。下面例子会介绍具体使用,大家有疑问,可以拿着源码和例子,调试一番,知道上面的2个实现过程,就比较简单了
3.Math.NET求解线性方程的实例
假设下面是要求解的线性方程组(Ax=b):
5*x + 2*y - 4*z = -7
3*x - 7*y + 6*z = 38
4*x + 1*y + 5*z = 43
测试代码,由于求解的方法很多,只列举了几种,其他的以此类推:
var formatProvider = (CultureInfo) CultureInfo.InvariantCulture.Clone();
formatProvider.TextInfo.ListSeparator = " "; //先创建系数矩阵A
var matrixA = DenseMatrix.OfArray(new[,] {{5.00, 2.00, -4.00}, {3.00, -7.00, 6.00}, {4.00, 1.00, 5.00}}); //创建向量b
var vectorB = new DenseVector(new[] {-7.0, 38.0, 43.0}); // 1.使用LU分解方法求解
var resultX = matrixA.LU().Solve(vectorB);
Console.WriteLine(@"1. Solution using LU decomposition");
Console.WriteLine(resultX.ToString("#0.00\t", formatProvider)); // 2.使用QR分解方法求解
resultX = matrixA.QR().Solve(vectorB);
Console.WriteLine(@"2. Solution using QR decomposition");
Console.WriteLine(resultX.ToString("#0.00\t", formatProvider)); // 3. 使用SVD分解方法求解
matrixA.Svd().Solve(vectorB, resultX);
Console.WriteLine(@"3. Solution using SVD decomposition");
Console.WriteLine(resultX.ToString("#0.00\t", formatProvider)); // 4.使用Gram-Shmidt分解方法求解
matrixA.GramSchmidt().Solve(vectorB, resultX);
Console.WriteLine(@"4. Solution using Gram-Shmidt decomposition");
Console.WriteLine(resultX.ToString("#0.00\t", formatProvider)); // 5.验证结果,就是把结果和A相乘,看看和b是否相等
var reconstructVecorB = matrixA*resultX;
Console.WriteLine(@"5. Multiply coefficient matrix 'A' by result vector 'x'");
Console.WriteLine(reconstructVecorB.ToString("#0.00\t", formatProvider));
结果如下:
. Solution using LU decomposition
DenseVector -Double
3.00
1.00
6.00 . Solution using QR decomposition
DenseVector -Double
3.00
1.00
6.00 . Solution using SVD decomposition
DenseVector -Double
3.00
1.00
6.00 . Solution using Gram-Shmidt decomposition
DenseVector -Double
3.00
1.00
6.00 . Multiply coefficient matrix 'A' by result vector 'x'
DenseVector -Double
-7.00
38.00
43.00
今天的用法就到此为止,请关注博客,后续还有更多的分析和使用文章。
4.资源
源码下载:
如果本文资源或者显示有问题,请参考 本文原文地址:http://www.cnblogs.com/asxinyu/p/4285245.html
本博客还有大量的.NET开源技术文章,您可能感兴趣:
开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解的更多相关文章
- 【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【目录】开源Math.NET基础数学类库使用总目录
本博客所有文章分类的总目录链接:[总目录]本博客博文总目录-实时更新 1.开源Math.NET数学组件文章 1.开源Math.NET基础数学类库使用(01)综合介绍 2.开源Math.NET ...
- 开源Math.NET基础数学类库使用(05)C#解析Delimited Formats数据格式
原文:[原创]开源Math.NET基础数学类库使用(05)C#解析Delimited Formats数据格式 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件 ...
- 开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式
原文:[原创]开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math. ...
- 开源Math.NET基础数学类库使用(03)C#解析Matlab的mat格式
原文:[原创]开源Math.NET基础数学类库使用(03)C#解析Matlab的mat格式 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math.NET( ...
- 开源Math.NET基础数学类库使用(02)矩阵向量计算
原文:[原创]开源Math.NET基础数学类库使用(02)矩阵向量计算 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math.NET(一)综合介绍 ...
- 开源Math.NET基础数学类库使用(01)综合介绍
原文:[原创]开源Math.NET基础数学类库使用(01)综合介绍 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math.NET(一)综合介绍 2. ...
- 【原创】开源Math.NET基础数学类库使用(01)综合介绍
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(02)矩阵向量计算
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
随机推荐
- 完整导出IntelliJ IDEA的快捷键
工欲善其事,必先利其器. 常常和代码打交道的人,熟练使用IDE快捷键那是必须的,由于快捷键能够把你从各种罗嗦事中解放出来.比方,假设没有快捷键,你就须要常常性的暂停快速执行的大脑,右手凭记忆摸到鼠标, ...
- Linux好书、经典书籍推荐
Linux好书.经典书籍推荐 思想篇 <Linux/Unix设计思想> 图书将Unix与Linux的原理有效地结合起来,总结了Unix/Linux软件开发中的原则.在保留了第1版中Unix ...
- 新版SDK自己主动加入PlaceholderFragment的思考
自从Android SDK更新到22.6.3,发现新建Activity的时候,会自己主动生成一个Fragment.这个Fragment是activity的静态内部类.同一时候生成了一个xml叫frag ...
- Learning Cocos2d-x for WP8(2)——深入刨析Hello World
原文:Learning Cocos2d-x for WP8(2)--深入刨析Hello World cocos2d-x框架 在兄弟篇Learning Cocos2d-x for XNA(1)——小窥c ...
- atitit查询表改动表字段没反应--解锁锁定的表
atitit查询表改动表字段没反应--解锁锁定的表 查询表改动表字段没反应 要是使用gui 没反应,最好使用cmd 方式,不卉不个gui 锁上.. ALTER TABLE t_mb_awardweix ...
- org.jsoup.select.Selector
org.jsoup.select.Selector CSS-like element selector, that finds elements matching a query. Selector ...
- vim netrw
我们现在试一下vim文件功能,当你使用vim尝试打开目录时,vim会自动调用netrw.vim插件打开该目录(从操作系统的视角来看,目录其实是一种特殊的文件).例如,我们在vim中执行命令”:e -/ ...
- mysql安装注意
mysql安装教程,网上到处都有,我这里就不细说了. 但是有一点要注意,安装完之后,点击MySql 5.5 Command Line Client时,有可能出现一闪而过,打不开mysql的情况: 首先 ...
- hdu 4107当卡段树
其核心思想是记录最大的节点值和最低值,假设max<p要么min>=p时间,在节点只变化add值,不要子树遍历:否则,就往子树递归. #include<iostream> #in ...
- jdk并发包 CopyOnWriteArrayList源代码分析
CopyOnWriteArrayList是jdk1.5并法包里面用于处理高并发下.读多写少的情况下.减少锁等待的集合类.以下对该类实现做一个简要的分析 1,首先CopyOnWriteArrayList ...