矩陣和向量
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<T>
和Vector<T>
類型定義在MathNet.Numerics.LinearAlgebra
命名空間中。從技術和性能上考慮,可以對每種數據類型進行明確的實現,例如,雙精度類型可以使用DenseMatrix
類,這個類在MathNet.Numerics.LinearAlgebra.Double
命名空間中。你一般不需要考慮這個,而是使用通常意義的Matrix<T>
的抽象類型,我們需要其他的方法來創建矩陣和向量實例。
Matrix<double> m = Matrix<double>.Build.Random(2, 2); Vector<double> v = Vector<double>.Build.Random(4); Console.WriteLine(m.ToString()); Console.WriteLine(m.ToString());
由於在一個應用程序中,你通常指需要用到一個特定的數據類型,通常用來來減少代碼的小技巧是定義這個組建器的快捷方式。
var M = Matrix<double>.Build; var V = Vector<double>.Build; Matrix<double> m1 = M.Dense(2, 2); Matrix<double> m2 = M.Dense(2, 2,(i,j)=>i+j); Vector<double> v1 = V.Dense(4); Vector<double> 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); // 3x3 dense identity matrix M.DenseIdentity(3); // 3x4 dense random matrix sampled from a Gamma distribution M.Random(3, 4, new Gamma(1.0, 5.0));
但是大多數情況下,我們已經其他格式的數據,需要轉換到矩陣形式,當函數中有一個of的函數他是用來創建原始數據副本的。
[lang=csharp] // Copy of an existing matrix (can also be sparse or diagonal) Matrix<double> x = ... M.DenseOfMatrix(x); // Directly bind to an existing column-major array without copying (note: no "Of") double[] x = existing... M.Dense(3, 4, x); // From a 2D-array double[,] x = {{ 1.0, 2.0 }, { 3.0, 4.0 }}; M.DenseOfArray(x); // From an enumerable of values and their coordinates Tuple<int,int,double>[] x = {Tuple.Create(0,0,2.0), Tuple.Create(0,1,-3.0)}; M.DenseOfIndexed(3,4,x); // From an enumerable in column major order (column by column) double[] x = {1.0, 2.0, 3.0, 4.0}; M.DenseOfColumnMajor(2, 2, x); // From an enumerable of enumerable-columns (optional with explicit size) IEnumerable<IEnumerable<double>> x = ... M.DenseOfColumns(x); // From a params-array of array-columns (or an enumerable of them) M.DenseOfColumnArrays(new[] {2.0, 3.0}, new[] {4.0, 5.0}); // From a params-array of column vectors (or an enumerable of them) M.DenseOfColumnVectors(V.Random(3), V.Random(3)); // Equivalent variants also for rows or diagonals: M.DenseOfRowArrays(new[] {2.0, 3.0}, new[] {4.0, 5.0}); M.DenseOfDiagonalArray(new[] {2.0, 3.0, 4.0}); // if you already have existing matrices and want to concatenate them Matrix<double>[,] x = ... M.DenseOfMatrixArray(x);
矩陣運算
可以直接加減乘除操作,也可以使用方法進行運算。
var M = Matrix<double>.Build; var V = Vector<double>.Build; Matrix<double> m1 = M.Dense(2, 2, 1); Matrix<double> m2 = M.Dense(2, 2, (i, j) => i + j); Matrix<double> m3 = m1 * m2; //or //Matrix<double> m3 = m1.Multiply(m2);//m1 * m2 note that order Matrix<double> m4 = m3.Transpose(); Console.WriteLine("{0}\n{1}\nmultiply:\n{2}\ntranpose\n{3}", m1.ToString(), m2.ToString(), m3.ToString(), m4.ToString());
這些方法也重載一個方法,它賦值給第三個參數,允許避免為每單個操作分配新的變量,提供了維數匹配。
Matrix<double> m1 = M.Diagonal(3, 2, 1); Matrix<double> m2 = M.Dense(2, 2, (i, j) => i + j); Matrix<double> m3 = M.Random(3,2); m1.Multiply(m2, m3);// m3 <= m1 * m2