【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组
本博客所有文章分类的总目录:【总目录】本博客博文总目录-实时更新
开源Math.NET基础数学类库使用总目录:【目录】开源Math.NET基础数学类库使用总目录
前言
在前几篇关于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
【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组的更多相关文章
- 开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解
原文:[原创]开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解 开源Math.NET基础数学类库使用系列文章总目录: 1.开源.NET基础数学计算组件Math.NET(一) ...
- 【目录】开源Math.NET基础数学类库使用总目录
本博客所有文章分类的总目录链接:[总目录]本博客博文总目录-实时更新 1.开源Math.NET数学组件文章 1.开源Math.NET基础数学类库使用(01)综合介绍 2.开源Math.NET ...
- 【原创】开源Math.NET基础数学类库使用(01)综合介绍
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(02)矩阵向量计算
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(03)C#解析Matlab的mat格式
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(05)C#解析Delimited Formats数据格式
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
- 【原创】开源Math.NET基础数学类库使用(07)常用的数学物理常数
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 1.前 ...
- 【原创】开源Math.NET基础数学类库使用(08)C#进行数值积分
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...
随机推荐
- js数组与对象性能比较
js的数组可以看成特殊的对象,获取指定项的行为跟获取对象中指定key对应项的行为是一致的. 一般都是hash map实现的,因而复杂度是常数级的.
- PHP多级联动的学习(一)
我尝试在ThinkCMF中实现多级联动,首先我开始看了dede的联动类别管理前后台的代码以及他的数据库,经过非常多次的尝试,我渐渐有了一点想法,并给予实施. 首先写出前台的界面.如图. 然后在数据库中 ...
- MAC系统设置SSX教程与下载
http://ss.hongxingchajian.com MAC系统设置SSX教程与下载 1.下载客户端并安装,装完后打开 链接: http://pan.baidu.com/s/1o7ypp5g 密 ...
- Linux 下安装中文 ctex 指南
大家在用 $\LaTeX$ 进行中文排版时相信会遇到不少问题,而$\textbf{ctex}$套装的出现则有效的解决了这一问题,只要安装了$\textbf{ctex}$那么在文中不用进行引用设置就可以 ...
- [收藏]C++简单五子棋
#include<iostream> #include<iomanip> using namespace std; ; //棋盘行数 ; //棋盘列数 char p[X][Y] ...
- Think in 递归
网上写递归的文章可以用汗牛充栋来形容了,大多数都非常清晰而又细致的角度上讲解了递归的概念,原理等等.以前学生的时候,递归可以说一直是我的某种死穴,原理,细节我都懂,但是不管是在如何运用或者如何试试算法 ...
- jetty项目中静态文件不能修改问题
修改web.xml 在web.xml中加入如下代码: <servlet> <servlet-name>default</servlet-name> <serv ...
- 大白话讲解Promise(二)理解Promise规范
上一篇我们讲解了ES6中Promise的用法,但是知道了用法还远远不够,作为一名专业的前端工程师,还必须通晓原理.所以,为了补全我们关于Promise的知识树,有必要理解Promise/A+规范,理解 ...
- js动态生成选项之考试系统(一)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...
- 在SqlServer2008R2中,根据分隔符把一列的值切割成多列
近期工作中,有个如上图效果的需求:将一个字段里面的值,以“,"切割成多列 通过思考.搜索,在网上找到了博主Microshaoft的文章: 妙用 T-SQL: PARSENAME 函数 (也可 ...