logo资料库

MathNet笔记.pdf

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
⚫ 安装 C# 科学计算库 Math.NET Numerics 在 Visual Studio 2015 中,打开 Tools -> Nuget Package Manager -> Package Manager Console。然后在 Package Manager Console 中输入如下命令: Install-Package MathNet.Numerics 然后会自动安装 Math.NET Numerics。安装成功后,Package Manager Console 会有如下提示 ⚫ 在 C#中使用 mathnet,需要利用 using 引入相关类 矩阵运算的相关类: using MathNet.Numerics.LinearAlgebra.Double; using MathNet.Numerics.LinearAlgebra.Generic; ⚫ // 格式设置 var formatProvider=(CultureInfo)CultureInfo.InvariantCulture.Clone(); formatProvider.TextInfo.ListSeparator=" "; ⚫ 利用 C#中的 double[,]直接创建矩阵 var mb = Matrix.Build; double[,] d_matrix = new double[2,3]; var matrix2 = mb.DenseOfArray(d_matrix);//2×3 矩阵 我 曾 做过 测试 , 将 double[,] 先转 成 Math 矩阵 , 然后 进行 矩 阵运 算, 再 利用 matrix2.ToArray()将 Math 矩阵转换成 double[,],其运算时间和直接利用 C#编写 的矩阵运算相差很小。但如果是利用 for 循环将 double 数组的数值赋值给 Math 矩阵进 行矩阵运算,然后再利用 for 循环将 Math 矩阵赋值给某个 double[,]数组,其运算时间 可以减少 1/3。在开发效率和运算效率上,使用的时候可以根据需要进行取舍。 ⚫ 矩阵操作 矩阵操作最常用的莫过于从一个矩阵中取值 //取从第二行开始的 2 行,第三列开始的三列子矩阵 var submatrix = matrix.SubMatrix(2, 2, 3, 3); //取从第 5 行第 3 列开始的 4 个行元素 var row = matrix.Row(5, 3, 4); //取从第 2 列第 6 行开始的 3 个列元素 var column = matrix.Column(2, 6, 3); //取从第 2 列开始的 4 列 matrix.ColumnEnumerator(2, 4) //取从第 4 行开始的 3 行 matrix.RowEnumerator(4, 3) //矩阵变为行向量或者列向量 matrix.ToRowWiseArray()/matrix.ToColumnWiseArray() //取矩阵的对角线元素向量 matrix.Diagonal() ⚫ 向矩阵中插值
//将向量 vector 插入到指定的行/列,原有的行列顺延 var result = matrix.InsertColumn(3,vector)/matrix.InsertRow(3,vector); //用 vector 替换指定的行/列 matrix.SetColumn(2,(Vector)vector);/matrix.SetRow(3,(double[])vector); //用矩阵替换指定位置的块矩阵 matrix.SetSubMatrix(1,3,1,3,DenseMatrix.Identity(3)); //替换矩阵的对角线元素 matrix.SetDiagonal(new[]{5.0,4.0,3.0,2.0,1.0}); //将 matrixB 扩展到 matrixA 的右方/上方,将结果保存在 result 中 matrixA.Append(matrixB,result)/matrixA.Stack(matrixB,result) ⚫ //创建一个随机的矩阵 var matrix = new DenseMatrix(5); var rnd = new Random(1); for (var i=0; i < matrix.RowCount; i++) { for (var j=0; j < matrix.ColumnCount; j++) { matrix[i,j] = rnd.NextDouble(); } } ⚫ 矩阵相乘 var mb = Matrix.Build; var A = mb.Dense(3, 5, 2.0);//3×5 矩阵,所有值为 2.0 var B = mb.Dense(5, 4, 3.0);//5×4 矩阵,所有值为 3.0 var y = A * B;//或 var y=A.Multiply(B); Console.WriteLine("A:\n{0}\nB:\n{1}\ny:\n{2}",A,B,y); A: 2,2,2,2,2 2,2,2,2,2 2,2,2,2,2 B: 3,3,3,3 3,3,3,3 3,3,3,3 3,3,3,3 3,3,3,3 y: 30,30,30,30 30,30,30,30 30,30,30,30 ⚫ 矩阵相减
var mb = Matrix.Build; var A = mb.Dense(3,3,2.0); var B = mb.Dense(3,3,1.2); var C = A.Subtract(B); ⚫ 矩阵相加 var mb = Matrix.Build; var A = mb.Dense(3,3,2.0); var B = mb.Dense(3,3,1.2); var C = A.Add(B); ⚫ 矩阵转置 var mb = Matrix.Build; var A = mb.DenseOfArray(new double[,]{ {1,2,3,4},{5,6,7,8}, {9,10,11,12},{13,14,15,16} var B = A.Transpose(); }); ⚫ 矩阵求逆 var mb = Matrix.Build; var A = mb.DenseOfArray (new double[,]{ {1,1,2}, {-1,2,0}, {1,1,3} var B = A.Inverse(); }); A: 1,1,2 -1,2,0 1,1,3 B: 2,-0.3,-1.33 1,0.33,-0.67 -1,0,1 ⚫ 矩阵行列式的值 var mb = Matrix.Build; var A = mb.DenseOfArray(new double[,]{ {1,1,2}, {-1,2,0}, {1,1,3} var B = A.Determinant(); });
⚫ 矩阵的秩 var mb = Matrix.Build; var A = mb.DenseOfArray(new double[,]{ {1,2,3,4},{5,6,7,8}, {9,10,11,12},{13,14,15,16} }); var B =A.Rank(); ⚫ 矩阵左乘向量:y=b*A var mb = Matrix.Build; var vb = DenseVector.Build; var A = mb.Dense(3,5,2.0); var b = vb.Dense(3,3); var y = A.LeftMultiply(b); Console.WriteLine("A:\n{0}\nB:\n{1}\ny:\n{2}",A,b,y); A: 2,2,2,2,2 2,2,2,2,2 2,2,2,2,2 B: 3,3,3 y: 18,18,18,18,18 ⚫ 矩阵分解 LU 分解 var mb = Matrix.Build; var A = mb.Dense(3, 3, 2.0); var l=A.LU().L; var u = A.LU().U; Console.WriteLine("A:\n{0}\nl:\n{1}\nu:\n{2}",A,l,u); A: 2,2,2 2,2,2 2,2,2 l: 1,0,0 1,1,0 1,0,1 u: 2,2,2 0,0,0 0,0,0
类似的还有 Cholesky 分解,Evd 分解,GramSchmidt 分解,QR 分解,Svd 分解 ⚫ 求解线性方程组 对于一阶线性方程组 5*x+2*y-4*z=-7 3*x-7*y+6*z=38 4*x+1*y+5*z=43 可以如下求解: //先创建系数矩阵 A var matrixA = DenseMatrix.OfArray(new[,] { {5.00, 2.00, -4.00}, {3.00, -7.00, 6.00}, {4.00, 1.00, 5.00} }); 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)); ---------------------------------------------------------- 矩阵定义和初始化 常用矩阵初始化函数: var matrix2 = new DenseMatrix(3);//3 维方阵 var matrix3 = new DenseMatrix(2, 3);//2×3 矩阵 var matrixI = DenseMatrix.Identity(5);//5 维单位矩阵 矩阵操作和 C#中的数组操作一致,matrix2[m,n]取其 m 行 n 列上的值或对其赋值
MathNet 中重载了.ToString()函数,可以直接用 matrix.ToString()输出整个数组, 大大方便了调试和保存数据。 矩阵转换: var permutations = new Permutation(new[] { 0, 1, 3, 2, 4 }); matrix.PermuteRows(permutations); //互换矩阵的 3,4 行 permutations = new Permutation(new[] { 1, 0, 4, 3, 2 }); matrix.PermuteColumns(permutations); //互换矩阵的 1,2 列,3,5 列。 可以看出,互换是由 Permutation 中的数字序号决定的。 1.矩阵运算 matrixA = 3.0 * matrixB//数乘 matrixA = vector*matrixB/matrixA=matrixB*vector//向量乘 matrixC = matrixA+/-/*matrixB//矩阵加、减、乘 resultM = (DenseMatrix)matrixA.PointwiseDivide(matrixB); //点乘 上述所有运算符都有对应的函数,也可是利用函数进行运算,如“+”可以写成 matrixC=(DenseMatrix)matrixA.Add(matrixB); 或者 matrixA.Add(matrixB,matrixC); matrixB = matrixA.Inverse()/Transpose() //求逆和转置 2.求解线性方程组 对于一阶线性方程组 5*x+2*y-4*z=-7 3*x-7*y+6*z=38 4*x+1*y+5*z=43 可以如下求解: var matrixA =new DenseMatrix(new[,] { { 5.00, 2.00, -4.00 }, { 3.00, -7.00, 6.00 },{ 4.00, 1.00, 5.00 } }); var vectorB = new DenseVector(new[] { -7.0, 38.0, 43.0 }); var resultX = matrixA.LU().Solve(vectorB); 或者 resultX = matrixA.QR().Solve(vectorB); 或者 matrixA.Svd(true).Solve(vectorB, resultX); 或者 matrixA.GramSchmidt().Solve(vectorB, resultX); 3.矩阵秩、行列式、trace 和范数 matrix.Determinant()/Rank()/ConditionNumber()/Trace() //行列式/秩 /条件数/trace matrix.L1Norm()/L2Norm()/FrobeniusNorm()/InfinityNorm() //范数 矩阵和向量 Math.Net Numberics 程序集中包含了矩阵和向量的丰富类型。他们都支持单精度和双 精度类型。 像在 dotnet 中所有的数据类型一样,他们都是基于 0 索引的,例如,左上 位置的索引值是(0,0),在矩阵中第一个索引值指的是行,第二个索引值指的是列,空 矩阵和向量不支持,例如,每个维数的长度至少是一。
存储布局 1.向量 • 密集向量 使用一个与向量相同长度数组。 • 稀疏向量 用两个通常比向量小的数组,一个数组存储非零值,另一个数组存储他们的索引值,向上排序. 2.矩阵 • 密集矩阵 用一个数组存储 • 对角矩阵 只存储对角值,在一个数组存储。 • 稀疏矩阵 用了三个数组存储,第一个数组存储非零值,第二个数组存储非零值对应列号,第三个数组存储行偏 移值,并且最后一个元素存储矩阵中非零值的个数。 第一个数组 values 存储非零值,顺序是每行从左往右扫,扫完依次扫下一行,即 1,7,2,8,5,3,9,6,4 第二个数组 column indices 存储非零值的对应列号,即 0,1,1,2,0,2,3,1,3。 第三个数组 row offsets 存储行偏移值,首先数组大小为行数+1(该例为 4+1),第 i 个 元素值存储第 i 行首个非零值前面非零值的个数(第 0 个数肯定为 0),例如该数组第 1(基 于 0 索引)个值存储的是第 1 行第一个非零值(该例为 2)前面非零值的个数(该例为 2, 非零值为 1,7)。在例如该数组第 3 个值存储的是第 3 行第一个非零值(6)前面非零值的 个数(该例为 7,非零值为 1,7,2,8,5,3,9)。第三个数组最后一个值存储矩阵中所有非 零值的个数(该例为 9)。 创建矩阵和向量 Matrix和 Vector类型定义在 MathNet.Numerics.LinearAlgebra 命名空 间中。从技术和性能上考虑,可以对每种数据类型进行明确的实现,例如,双精度类型可以 使用 DenseMatrix 类,这个类在 MathNet.Numerics.LinearAlgebra.Double 命 名空间中。你一般不需要考虑这个,而是使用通常意义的 Matrix 的抽象类型,我们 需要其他的方法来创建矩阵和向量实例。 Matrix m = Matrix.Build.Random(2, 2); Vector v = Vector.Build.Random(4); Console.WriteLine(m.ToString()); Console.WriteLine(m.ToString());
由于在一个应用程序中,你通常指需要用到一个特定的数据类型,通常用来来减少代码的小 技巧是定义这个组建器的快捷方式。 var M = Matrix.Build; var V = Vector.Build; Matrix m1 = M.Dense(2, 2); Matrix m2 = M.Dense(2, 2,(i,j)=>i+j); Vector v1 = V.Dense(4); Vector v2 = V.Dense(4, (i) => i % 2); Console.WriteLine("{0}\n{1}\n{2}\n{3}", m1.ToString(), m2.ToString(), v1.ToString(), v2.ToString()); 这个组建器通常确定数据的存储方式,因此如果你想构建一个稀疏矩阵,intelligense 将会列出所有的选项,一旦你敲入 M.Sparse. [lang=csharp] // 3x4 dense matrix filled with zeros M.Dense(3, 4); // 3x4 dense matrix filled with 1.0. M.Dense(3, 4, 1.0); // 3x4 dense matrix where each field is initialized using a function M.Dense(3, 4, (i,j) => 100*i + j); // 3x4 square dense matrix with each diagonal value set to 2.0 M.DenseDiagonal(3, 4, 2.0);
分享到:
收藏