Matrix decomposition, a technique that breaks down a square numeric matrix into two different square matrices, is the basis for efficiently solving a system of equations, which in turn is the basis for inverting a matrix. And inverting a matrix is a part of many important algorithms. This article presents and explains C# code that performs matrix decomposition, matrix inversion, a system of equations solution and related operations. Admittedly, matrix decomposition isn’t a flashy topic, but a collection of matrix methods can be an important addition to your personal code library. The methods are explained so you can modify the source code to meet your own needs. Additionally, some of the techniques used in the matrix methods can be reused in other coding scenarios. The best way for you to get a feel for the kind of information presented in this article is to take a look at the screenshot in Figure 1. The demo program begins by creating a 4 x 4 square matrix and displaying its values. Next, the matrix is decomposed into what’s called an LUP matrix. L stands for lower and U stands for upper. The P part (P stands for permutation) is an array with values {3,1,2,0} and indicates that rows 0 and 3 were exchanged during the decomposition process. The decomposition also generated a toggle value of -1, indicating that an odd number of row exchanges occurred. The demo program displays the decomposition in two ways: first as a combined LU matrix and then as separate L and U matrices. Next, the program computes and displays the inverse of the original matrix, using the LUP matrix behind the scenes. The demo program computes the determinant of the original matrix, again using the decomposition. It then uses the inverse of the matrix to solve a system of linear equations and concludes by combining the L and U matrices back into the original matrix. But why go to all the trouble of creating a custom matrix decomposition method and a library of related methods? Although there are many standalone matrix tools available, they can sometimes be difficult to integrate into an application or system. And in spite of the fundamental importance of matrix decomposition, there are few free, non-copyrighted .NET code implementations available; those that do exist are often not explained in enough detail for you to modify the source code to suit your coding scenarios. This article assumes you have intermediate C# programming skills and at least a basic understanding of matrix operations and terminology. All of the key C# code is presented in this article. The code is also available from the MSDN code download site atarchve.msdn.microsoft.com/mag201212matrix. Matrix DefinitionThere are several ways to implement a matrix in C#. The traditional approach, and the one used in this article, is to use an array of arrays, sometimes called a jagged array. For example, this code defines a matrix with three rows and two columns:
Unlike most programming languages, C# has a built-in multidimensional array type, which provides an alternative approach. For example:
A third approach to implementing matrices in C# is to use a single array combined with array index manipulation, like this:
Regardless of the storage scheme used, matrices can be implemented using either an OOP or a static-method approach. For example, an OOP approach could resemble:
There’s no single best choice for matrix design; the best design depends on the particular coding scenario you’re operating in and on your personal coding preferences. This article uses a static-method approach because it’s the easiest to understand and refactor. When using an array-of-arrays design for matrices, because each row must be allocated separately, it’s often convenient to define a helper method to perform memory allocation. For example:
The method can be called like so:
This method demonstrates one advantage of creating your own library of matrix methods: If you want to improve performance, you can omit error-checking the input parameters—at the expense of increasing the risk of the calling code causing an exception. (To keep this article short, most error checking has been removed.) Another advantage is that you can customize your library to optimize for your exact scenario. The main disadvantage of creating your own library is that it can take longer than using an existing library. Another convenient method to add to your matrix library is one that can be used to display a matrix as a string. Here’s one possibility:
You may want to parameterize the number of decimals to display, or the column-width padding, or both. Matrix MultiplicationThe Microsoft .NET Framework 4 and later provide a neat way to significantly improve the performance of a matrix multiplication method. Matrix multiplication is illustrated in Figure 2. Note that the computation of each cell value of the result does not depend on any other cell values in the result, so each computation is independent and they can potentially be performed in parallel on a machine with multiple processors. Here’s a standard approach to matrix multiplication:
Because matrix multiplication is an O(n^3) operation, performance can be an issue. For example, if matrix A has size 300 x 200 and matrix B has size 200 x 400, computing the product of A and B requires 300 * 200 * 400 = 24,000,000 multiplications. The Task Parallel Library (TPL) in the System.Threading.Tasks namespace in the .NET Framework 4 and later makes it easy to code a simple parallelized version of matrix multiplication. One possibility is:
This version chops up the computations by rows. Behind the scenes, the TPL generates all the complex synchronization plumbing code to perform the computations on multiple processors. Consistency TestingAn interesting aspect of a library of methods that are related to each other is that it’s often possible to test them by checking to see if they produce consistent results. For example, suppose you have a method that creates a random matrix:
Additionally, suppose you have a matrix that creates the identity matrix—that is, a square matrix with 1.0s on the main diagonal, 0.0s elsewhere:
And suppose you have a method that compares two matrices for equality:
Notice the MatrixAreEqual method does not compare cell values for exact equality because the values are type double. Instead, the method checks to see if all the cell values are very close (within epsilon) to each other. Because the product of any square matrix m and the identity matrix of the same dimension is equal to the original matrix m, you can test the matrix product method along the lines of this code:
Matrix DecompositionMatrix decomposition takes a square matrix M and computes two new square matrices that when multiplied together give the original matrix M. The idea is similar to ordinary number factoring: the number 6 can be factored into 2 and 3 because 2 * 3 = 6. At first it may seem like there’s little point in decomposing a matrix, but it turns out that matrix decomposition makes the very difficult task of matrix inversion quite a bit simpler. There are many different kinds of matrix decomposition, and each kind can be computed using several different algorithms. The technique presented in this article is called LUP decomposition and uses Doolittle’s method with partial pivoting. To understand LUP decomposition, it’s helpful to first understand the simpler LU decomposition, which was introduced by the famous mathematician Alan Turing. Suppose you have this 4 x 4 matrix M:
One possible LU decomposition of M is L =
And U =
This works because L * U = M. Notice that the lower L matrix has 1.0s on the diagonal and 0.0s in the upper right. In other words, the significant cell values of the lower matrix are in the lower left.Similarly the significant cell values of the upper matrix are on the main diagonal and in the upper right. Notice as well that there’s no overlap of the locations of the significant cell values in L and U. So, instead of generating two results matrices, L and U, matrix decomposition usually stores both the lower and upper results into a single matrix that holds both L and U to save memory space. LUP matrix decomposition is a slight but important variation on LU decomposition. LUP decomposition takes a matrix M and produces L and U matrices but also a P array. The product of L and U in LUP is not exactly the original matrix M but instead is a version of M where some of the rows have been rearranged. The way in which the rows have been rearranged is stored into the P array; this information can be used to reconstruct the original matrix M. A close cousin to the Doolittle decomposition presented in this article is called Crout’s decomposition. The main difference between Doolittle and Crout is that Doolittle places 1.0s on the main diagonal of the L matrix and Crout places 1.0s on the main diagonal of the U matrix. The reason LUP decomposition is used more often than LU decomposition is subtle. As you’ll see shortly, matrix decomposition is used to compute the inverse of a matrix. However, when matrix decomposition is used as a helper for matrix inversion, it turns out that the inversion will fail if there’s a 0.0 value on the main diagonal of the LU matrix. So in LUP decomposition, when a 0.0 value ends up on the main diagonal, the algorithm exchanges two rows to move the 0.0 value off the diagonal and keeps track of which rows were exchanged in the P array. Figure 3 lists a matrix decomposition method. Figure 3 A Matrix Decomposition Method
The method could be called like this:
The MatrixDecompose method accepts as its input a square matrix. The method has three return values. The explicit return is a permuted LU matrix. The method returns two values as out parameters. One is a permutation array that holds information about how the rows were permuted. The second out parameter is a toggle value that’s either +1 or -1 depending on whether the number of row exchanges was even (+1) or odd (-1). The toggle value is not used for matrix inversion but is needed if matrix decomposition is used to compute the determinant of a matrix. The MatrixDecompose method is fairly tricky, but realistically, there are only a few details you need to understand to modify the code. The version presented here allocates new memory for the LU return matrix using a helper method MatrixDuplicate:
An alternative approach is to compute the result into the input matrix in order to save memory.With C# semantics, this would make the matrix parameter a ref parameter because it’s used for both input and output. Using this approach, the method signature would be:
Or, because the explicit return value has been eliminated, you could use it for the permutation array or the exchanges toggle. For example:
You might want to eliminate the toggle parameter to simplify the method signature if you don’t intend to use matrix decomposition to compute a determinant. Another area of MatrixDecompose you might want to modify is this statement:
In words, this code means: “If, even after exchanging two rows because there was a 0.0 value on the main diagonal, there’s still a 0.0 there, then return null.” You may want to modify the arbitrary epsilon value for the equality of zero check from 1.0E-20 to some other value based on the precision characteristics of your system. And instead of returning null, you might want to throw an exception; if the method were to be called as part of matrix inversion, the inversion would fail. Finally, if you’re using matrix decomposition for some purpose other than matrix inversion, you may want to eliminate this statement altogether. Matrix InversionThe key to using matrix decomposition to invert a matrix is to write a helper method that solves a system of equations. This key helper method is presented in Figure 4. Figure 4 The HelperSolve Method
The HelperSolve method finds an array x that when multiplied by an LU matrix gives array b. The method is quite clever, and you can only fully understand it by tracing through a few examples.There are two loops. The first loop uses forward substitution on the lower part of the LU matrix.The second loop uses backward substitution on the upper part of the LU matrix. Some different matrix decomposition implementations call their analogous method something like luBackSub. Although the code is short, it’s tricky, but there shouldn’t be any scenarios where you’d need to modify the code. Notice that HelperSolve accepts an LU matrix from MatrixDecompose but doesn’t use the perm out-parameter. This implies HelperSolve is in fact a helper method and needs additional wrapper code to solve a system of equations. If you refactor the code in this article to an OOP design, you might want to make HelperSolve a private method. With the HelperSolve method in place, the matrix inversion method can be implemented, as shown in Figure 5. Figure 5 The MatrixInverse Method
Again, the code is tricky. The inversion algorithm is based on the idea that the product of a matrix M and its inverse is the identity matrix. Method MatrixInverse essentially solves a system of equations Ax = b where A is an LU matrix decomposition and the b constants are either 1.0 or 0.0 and correspond to the identity matrix. Notice that MatrixInverse uses the perm array from the call to MatrixDecompose. Calling the MatrixInverse method could look like this:
To summarize, an important matrix operation is matrix inversion, which is quite difficult. One approach is to decompose the original matrix, write a helper solve method that performs forward and backward substitution, and then use the decomposition together with the LU permutation array and the helper solve method to find the inverse. This approach may seem complicated, but it’s usually more efficient and easier than computing a matrix inverse directly. Matrix DeterminantWith a matrix decomposition method in hand, it’s easy to code a method to compute the determinant of a matrix:
As it turns out, somewhat surprisingly, the determinant of a matrix is just plus or minus (depending on the toggle value) the product of the values on the main diagonal of the matrix LUP decomposition. Notice that there’s an implicit type conversion of the value of toggle from int to double. In addition to adding error checking to MatrixDeterminant, you might want to add a short-circuit return in situations where the input matrix has size 1 (then return the single value) or size 2 x 2 (then return a*d - b*c). Calling the determinant method could look like this:
Solving Systems of EquationsThe HelperSolve method can be easily adapted to solve a system of linear equations:
Here’s the code that produced the screenshot in Figure 1 to solve the following system:
Notice that SystemSolve rearranges its b input parameter using the perm array from MatrixDecompose before calling HelperSolve. Understanding the Permutation ArrayThe last few lines of output in the screenshot in Figure 1 indicate that it’s possible to multiply the L and U matrices in such a way as to get the original matrix. Knowing how to do this will not enable you to solve practical matrix problems, but it will help you understand the P part of LUP decomposition. Regenerating an original matrix from its L and U components can also be useful for testing your matrix library methods for consistency. One way to regenerate an original matrix after LUP decomposition is to multiply L and U, and then permute the rows of the product using the P array:
The UnPermute method can be coded like this:
A second approach for regenerating an original matrix from its LUP decomposition is to convert the perm array to a perm matrix and then multiply the perm matrix and the combined LU matrix:
A perm matrix is a square matrix with one 1.0 value in each row and each column. The method that creates a perm matrix from a perm array can be coded like so:
Wrapping UpThere are many algorithms that require solving a system of linear equations, finding the inverse of a matrix or finding the determinant of a matrix. Using matrix decomposition is an effective technique for performing all these operations. The code presented here can be used in situations where you want no external dependencies in your code base or you need the ability to customize the operations in order to improve performance or modify functionality. Take the red pill! Dr. James McCaffrey works for Volt Information Sciences Inc., where he manages technical training for software engineers working at the Microsoft Redmond, Wash., campus. He has worked on several Microsoft products including Internet Explorer and MSN Search. McCaffrey is the author of .NET Test Automation Recipes (Apress, 2006). He can be reached at jammc@microsoft.com. Thanks to the following technical experts for reviewing this article: Paul Koch and Dan Liebling
|
矩阵分解,分解成两个不同的方阵,一个方形数字矩阵的一种技术是有效地解决系统的方程,这反过来逆矩阵的基础的基础。 逆矩阵是许多重要算法的一部分。 这篇文章介绍并说明执行矩阵分解、 矩阵求逆、 一个方程的求解和相关的业务系统的 C# 代码。 诚然,矩阵分解并不是一个华而不实的话题,但矩阵方法的集合,可以将您的个人代码库的重要补充。 方法的解释,以便您可以修改的源代码,以满足您自己的需要。 此外,一些在矩阵方法中使用的技术可以在其他编码方案中重用。 您去好好感受一下本文中介绍的信息种类是要看一看的截图中的最佳方法图 1。 该演示程序开始通过创建一个 4 x 4 的方阵和显示其值。 下一步,该矩阵被分解成了所谓的土地矩阵。 L 代表低和 U 站为上限。 P 部分 (P 代表置换) {3,120} 的值的数组,指示行 0 和 3 在分解过程中就被交换了。 分解也生成切换值为-1,指示发生奇数行交流。 该演示程序显示分解两种方式:第一次作为一个组合的 LU 矩阵,然后作为单独的 L 和 U 矩阵。 接下来,程序计算并显示原始矩阵,使用在幕后的土地矩阵的逆。 该演示程序计算行列式的原始矩阵,请再次使用分解。 然后使用矩阵的逆矩阵来解决系统的线性方程组,并通过合并回原始矩阵 L 和 U 矩阵的结论。 但为什么去创建一个自定义矩阵分解方法和相关方法库的所有的麻烦呢? 虽然有许多独立的矩阵工具可用,但他们有时可能很难将集成到应用程序或系统。 矩阵分解的根本重要性,尽管有几个免费、 无版权.NET 代码实现可用 ; 那些确实存在往往不是足够为您要修改的源代码,以适合您的编码方案的详细解释。 本文假定您有中间的 C# 编程技巧和矩阵操作和术语的至少一个基本的了解。 所有关键的 C# 代码是本文中介绍的。 从 MSDN 代码下载站点上的代码是也可用 archve.msdn.microsoft.com/mag201212matrix。 矩阵定义有几种方法在 C# 中执行一个矩阵。 传统的做法和使用在本文中,一是使用一个数组的数组,有时被称为一个交错的数组。 例如,此代码定义了一个具有三行和两列的矩阵:
与大多数编程语言不同,C# 具有内置的多维数组的类型,其中提供了另一种方法。 例如,
在 C# 中执行矩阵的第三种方法是使用单个数组结合数组索引操作,像这样:
无论使用的存储方案,可以使用面向对象或静态方法的方法实现矩阵。 例如,OOP 方法可能类似于:
矩阵设计 ; 没有单一的最佳选择 最好的设计取决于您正在运行中的特定编码方案和个人编码首选项。 这篇文章使用静态方法的方法,因为它是最容易理解和重构。 时使用数组的数组设计矩阵,因为每一行必须单独分配,它通常是一个方便来定义一个帮助器方法来执行内存分配。例如,
可以调用该方法就像这样:
这种方法演示如何创建您自己的库的矩阵方法的一个优点:如果您想要提高性能,您可以省略错误检查输入的参数 — — 而增加导致异常的调用代码的风险。 (要保留这篇简短的文章,大多数错误检查已被移除。)另一个优点是您可以自定义您的库,以优化您确切的方案。 创建您自己的库的主要缺点是它可以采取比使用现有的库长。 另一种方便的方法添加到矩阵库是一个可以用来作为字符串显示矩阵。 这里是一种可能性:
您可能想要参数化的小数位数来显示,和/或列宽度填充,数。 矩阵乘法4 及更高版本的 Microsoft.NET 框架提供了一种巧妙的方法,大大改善性能的矩阵乘法运算方法。 矩阵乘法所示图 2。 请注意每个单元格的结果值的计算方法不依赖任何其他单元格值在结果中,而作的所以每个计算是独立,他们可能可以具有多个处理器的计算机上并行执行。 这里是矩阵乘法的标准方法:
因为矩阵乘法是 O(n^3) 操作,性能可能是一个问题。 例如,如果矩阵 A 具有大小 300 x 200 和矩阵 B 具有大小 200 x 400,计算产品的 A 和 B 要求 300 * 200 * 400 = 24,000,000 乘法运算。 任务并行库 (TPL) System.Threading.Tasks 命名空间在.NET Framework 4 和更高版本中轻松编写一个简单的矩阵乘法的并行化的版本的代码。 一种可能是:
此版本由行印章起计算。 在幕后,TPL 生成所有复杂的同步水暖代码来在多个处理器上执行的计算。 一致性测试图书馆彼此相关的方法的一个有趣的现象是很多时候可能以测试它们通过检查来看是否他们产生一致的结果。 例如,假设您有一个方法,创建一个随机矩阵:
此外,假设您有一个矩阵,创建矩阵的身份 — — 就是一个正方形矩阵与慢速的主对角线,其他地方的 0.0s年上:
并假设您有一个平等的两个矩阵进行比较的方法:
通知的 MatrixAreEqual 方法并不比单元格的值完全相等的因为都是 double 类型的值。 相反,该方法将查看是否所有单元格的值都非常接近 (epsilon) 内彼此。 因为该产品的任何方阵 m 和同一维度的恒等矩阵等于原始矩阵 m,您可以测试矩阵产品方法沿此代码行:
矩阵分解矩阵分解需要方阵 M 和计算两个新方阵的相乘时给原始矩阵 M。 这个想法是类似于普通号码保理业务:6 数可计入 2 和 3,因为 2 * 3 = 6。 起初它可能看起来像有小点中分解矩阵,但它原来矩阵分解使得矩阵求逆的非常困难的任务很简单些。 有许多不同种类的矩阵分解,和每一种可以计算使用几种不同的算法。 本文中介绍的技术被称为土地分解,并使用具有部分回转的杜利特尔的方法。 要了解土地分解,最好先了解更简单的 LU 分解,由著名数学家阿兰 · 图灵介绍。 假设您有此 4 × 4 矩阵 m:
一个可能的 LU 分解,M 的是 L =
U =
这样做是因为 L * U = M。 注意较低的 L 矩阵对角线上的慢速和 0.0s年在右上方。 换句话说,在左下角低矩阵的重要单元格的值。 同样上部矩阵的重要单元格的值是的主对角线上和在右上方。 还注意到有没有重叠的 L 和美国重要的单元格的值的位置 所以,而不是生成两个结果矩阵,L 和 U,矩阵分解通常存储到一个单一的矩阵,持有 L 和 U 以节省内存空间上限和下限结果。 土地矩阵分解是轻微但很重要的变化,对 LU 分解。 土地分解矩阵 M 并生成 L 和 U 的矩阵,但 P 数组。 L 和 U 在图中的产品是不完全的原始矩阵 M,但相反是 M 的版本其中的某些行已经被重新安排。 在这行已经被重新安排的方式存储到 P 的数组 ; 此信息可用于重建原始矩阵 M。 本文中介绍的杜利特尔分解的近亲称为 Crout 的分解。 杜利特尔和 Crout 之间的主要区别是杜利特尔 L 矩阵的主对角线上放置慢速和 Crout U 矩阵的主对角线上放置慢速。 土地分解的原因比 LU 分解是微妙的更频繁的使用。 如您很快就会看到,矩阵分解用于计算矩阵的逆矩阵。 然而,当矩阵分解为佣工用于矩阵求逆,原来反演将失败如果陆矩阵的主对角线上有一个 0.0 的值。 所以在土地分解,当告终的主对角线, 值 0.0 算法会交换移动 0.0 值关闭对角线和跟踪的哪些行被交换 P 数组中的两行。 图 3 列出矩阵分解方法。 图 3 矩阵分解法
像这样,可以调用该方法:
MatrixDecompose 方法接受作为其输入一个方阵。 该方法具有三个返回值。 显式的返回是一个排列后的陆矩阵。该方法作为 out 参数返回两个值。 一个是排列数组,它保存有关 permuted 行是如何的信息。 Out 参数的第二个是 + 1 或-1 根据行交换数量是否甚至 (+ 1) 或 (-1) 为奇数的切换值。 切换值不用于矩阵求逆,但如果用于计算一个矩阵的行列式矩阵分解需要。 MatrixDecompose 方法是相当棘手的事情,但实际上,有只有几个细节,您需要了解修改的代码。 这里提出的版本为陆返回矩阵使用 MatrixDuplicate 的帮助器方法分配新的内存:
另一种方法是进入输入矩阵计算出结果,以节省内存。 用 C# 的语义,这将使该矩阵参数的 ref 参数因为它用于输入和输出。 使用此方法,将方法签名:
或者,因为显式的返回值已被消除,就可以使用它为排列数组或交易所切换。 例如,
您可能想要消除要简化方法签名,如果您不打算使用矩阵分解来计算行列式的切换参数。 您可能想要修改的 MatrixDecompose 的另一个领域是此语句:
话说,此代码的含义:"如果,即使后交换两行,因为有一个 0.0 值的主对角线上,仍然是有 0.0,然后返回空值。"您可能想要修改的任意 epsilon 值为 1.0 e 从零复选的平等-20 到一些其他的值基于您的系统的精度特征。而不是返回 null,您可能想要引发异常 ; 和 如果作为矩阵求逆的一部分被调用的方法,反演将会失败。 最后,如果您使用矩阵分解的一些矩阵求逆以外的目的,您可能想要完全消除这一声明。 矩阵求逆使用矩阵分解反转矩阵的关键是要编写一个 helper 方法,以解决系统的方程。 此关键的帮助器方法提出在图 4。 图 4 HelperSolve 方法
HelperSolve 方法查找数组 x 当乘以陆矩阵赋予数组 b。 方法是很聪明的并可以通过跟踪几个例子只有完全理解它。 有两个循环。 第一个循环使用转发替代关于陆矩阵的下半部分。 第二个循环使用落后的替代上陆矩阵的上半部分。 一些不同的矩阵分解实现调用其类似的方法像 luBackSub 一样的东西。 虽然代码很短,但它是棘手的但就不会有任何情况下,您将需要修改的代码。 通知该帮助器解决接受从 MatrixDecompose LU 矩阵,但不使用该烫发的 out 参数。 这意味着 HelperSolve 其实是要解决系统方程的帮助器方法和需要额外包装代码。 如果您重构到面向对象设计的这篇文章中的代码,您可能想要 HelperSolve 的私有方法。 与地方中的 HelperSolve 方法,矩阵反演方法可以实现,如中所示图 5。 图 5 MatrixInverse 方法
再次,代码是棘手的。 反演算法基于一个矩阵 M 和它的逆产品是恒等矩阵的想法。 方法 MatrixInverse 基本上解决了方程组 Ax = 的 b A 是陆矩阵分解和 b 常量是 1.0 或 0.0 和对应单位矩阵。 请注意 MatrixInverse 使用的烫发数组从对 MatrixDecompose 的调用。 调用 MatrixInverse 方法可能看起来像这样:
概括地说,重要的矩阵操作是矩阵求逆,这是相当难的。 一种方法是将原始矩阵分解、 写一个助手解决执行向前和向后替换的方法和使用的分解与陆排列数组和佣工然后解决方法找到的逆。 这种方法可能看起来很复杂,但它通常是更有效率和更容易比直接计算矩阵的逆。 矩阵行列式与手中的矩阵分解方法,很容易的方法来计算矩阵的行列式的代码:
事实证明,有点令人惊讶,矩阵的行列式是只加上或减去 (根据切换值) 的土地分解矩阵的主对角线上的值的乘积。 请注意没有隐式类型转换价值的切换从 int 将翻一番。 除了添加错误检查至 MatrixDeterminant,您可能要添加短路的输入的矩阵有大小 (然后返回单个值) 1 或 2 x 2 的大小的情况下返回 (然后返回 * d-b * c)。 调用的行列式的方法,象这样:
方程组求解HelperSolve 方法可以轻松地调整,以解决系统的线性方程组:
这里是制作的截图中的代码图 1 来解决以下系统:
SystemSolve 重新排列其 b 输入的参数在调用 HelperSolve 之前使用 MatrixDecompose 中的烫发数组的通知。 理解排列数组输出中的屏幕快照中的最后几行图 1 表示有可能以一种能获取原始矩阵中的 L 和 U 的矩阵相乘。 了解如何执行此操作,不将使您能够解决实际矩阵的问题,但它将帮助您了解土地分解的 P 部分。 再生原始矩阵从其 L 和 U 的组件也可以用于测试您的矩阵库方法的一致性。 土地分解后重新生成原始矩阵的一种方法是将乘以 L 和 U,然后 permute 产品使用 P 数组中的行:
UnPermute 方法可以像这样进行编码:
第二种方法,用于重新生成原始矩阵从其土地分解是向烫发矩阵转换的烫发数组,然后乘以烫发矩阵和组合的陆矩阵:
烫发矩阵是一个正方形矩阵与一个 1.0 中的每一行和每一列的值。 从烫发数组创建一个烫发矩阵的方法可以进行编码就像这样:
总结有很多的算法需要求解线性方程组、 寻找一个矩阵的逆或找到一个矩阵的行列式。 使用矩阵分解是一种有效的执行所有这些操作技术。 这里介绍的代码可以使用您想没有外部依赖项的代码基中或您需要自定义的操作来提高性能或修改功能的能力的情况。 红色药丸 ! 博士。 博士 供职于 Volt Information Sciences, Inc.,在该公司他负责管理对华盛顿州雷蒙德市沃什湾 Microsoft 总部园区的软件工程师进行的技术培训。他参与过多项 Microsoft 产品的研发工作,其中包括 Internet Explorer 和 MSN Search。麦卡弗里是.NET 测试自动化食谱 (Apress,2006年) 的作者。可通过jammc@microsoft.com 与他联系。 衷心感谢以下技术专家对本文的审阅:保罗 · 科赫和 Dan Liebling
|
转自:http://msdn.microsoft.com/zh-cn/magazine/jj863137.aspx