• C#,数值计算(Numerical Recipes in C#),线性代数方程的求解,LU分解(LU Decomposition)源程序


     

    《Numerical Recipes in C++》原文摘要:

     

     

     

    凑字数的狗屁不通的译文:

    在线性代数中, LU分解(LU Factorization)是矩阵分解的一种,可以将一个矩阵分解为一个下三角矩阵和一个上三角矩阵的乘积(有时是它们和一个置换矩阵的乘积)。LU分解主要应用在数值分析中,用来解线性方程、求反矩阵或计算行列式。
    将系数矩阵A转变成等价两个矩阵L和U的乘积 ,其中L和U分别是单位下三角矩阵和上三角矩阵。当A的所有顺序主子式都不为0时,矩阵A可以唯一地分解为A=LU。其中L是下三角矩阵,U是上三角矩阵。
    LU分解在本质上是高斯消元法的一种表达形式。实质上是将A通过初等行变换变成一个上三角矩阵,其变换矩阵就是一个单位下三角矩阵。这正是所谓的杜尔里特算法(Doolittle algorithm):从下至上地对矩阵A做初等行变换,将对角线左下方的元素变成零,然后再证明这些行变换的效果等同于左乘一系列单位下三角矩阵,这一系列单位下三角矩阵的乘积的逆就是L矩阵,它也是一个单位下三角矩阵。这类算法的复杂度一般在(三分之二的n三次方) 左右。

    算法改进


    (i)Doolittle分解
    对于非奇异矩阵(任n阶顺序主子式不全为0)的方阵A,都可以进行Doolittle分解,得到A=LU,其中L为单位下三角矩阵,U为上三角矩阵;这里的Doolittle分解实际就是Gauss变换;
    (ii)Crout分解
    对于非奇异矩阵(任n阶顺序主子式不全为0)的方阵A,都可以进行Crout分解,得到A=LU,其中L为下三角矩阵,U为单位上三角矩阵;
    (iii)列主元三角分解
    对于非奇异矩阵的方阵A,采用列主元三角分解,得到PA=LU,其中P为一个置换矩阵,L,U与Doolittle分解的规定相同;
    (iv)全主元三角分解
    对于非奇异矩阵的方阵A,采用全主元三角分解,得到PAQ=LU,其中P,Q为置换矩阵,L,U与Doolittle分解的规定相同;
    (v)直接三角分解
    对于非奇异矩阵的方阵A,利用直接三角分解推导得到的公式(Doolittle分解公式或者Crout分解公式),可以进行递归操作,以便于计算机编程实现;
    (vi)“追赶法”
    追赶法是针对带状矩阵(尤其是三对角矩阵)这一大稀疏矩阵的特殊结构,得出的一种保带性分解的公式推导,实质结果也是LU分解;因为大稀疏矩阵在工程领域应用较多,所以这部分内容需要特别掌握。
    (vii)Cholesky分解法(平方根法)和改进的平方根法
    Cholesky分解法是是针对正定矩阵的分解,其结果是 A=LDLT=LD(1/2)D(1/2)LT=L1L1T。如何得到L1,实际也是给出了递归公式。
    改进的平方根法是Cholesky分解的一种改进。为避免公式中开平方,得到的结果是A=LDLT=TLT, 同样给出了求T,L的公式。
    小结:
    (1) 从(i)~(iv)是用手工计算的基础方法,(v)~(vi)是用计算机辅助计算的算法公式指导;
    (2) 这些方法产生的目的是为了得到线性方程组的解,本质是高斯消元法。
     

     

    源程序(POWER BY 315SOFT.COM

    1. using System;
    2. namespace Legalsoft.Truffer
    3. {
    4. /// <summary>
    5. /// LU decomposition - PTC
    6. /// Iterative Improvement of a Solution to Linear Equations
    7. /// </summary>
    8. public class LUdcmp
    9. {
    10. private int n { get; set; }
    11. /// <summary>
    12. /// Stores the decomposition
    13. /// </summary>
    14. private double[,] lu { get; set; }
    15. /// <summary>
    16. /// Stores the permutation.
    17. /// </summary>
    18. private int[] indx { get; set; }
    19. /// <summary>
    20. /// Used by det.
    21. /// </summary>
    22. private double d { get; set; }
    23. private double[,] aref { get; set; }
    24. /// <summary>
    25. /// Given a matrix a[0..n - 1][0..n-1], this routine replaces it by the LU decomposition of a
    26. /// rowwise permutation of itself.a is input.On output, it is arranged as in equation(2.3.14)
    27. /// above; indx[0..n - 1] is an output vector that records the row permutation effected by the
    28. /// partial pivoting; d is output as +/-1 depending on whether the number of row interchanges
    29. /// was even or odd, respectively. This routine is used in combination with solve to solve linear
    30. /// equations or invert a matrix.
    31. /// </summary>
    32. /// <param name="a"></param>
    33. /// <exception cref="Exception"></exception>
    34. public LUdcmp(double[,] a)
    35. {
    36. this.n = a.GetLength(0);
    37. this.lu = a;
    38. this.aref = a;
    39. this.indx = new int[n];
    40. const double TINY = 1.0e-40;
    41. double[] vv = new double[n];
    42. d = 1.0;
    43. for (int i = 0; i < n; i++)
    44. {
    45. double big = 0.0;
    46. for (int j = 0; j < n; j++)
    47. {
    48. double temp = Math.Abs(lu[i, j]);
    49. if ((temp) > big)
    50. {
    51. big = temp;
    52. }
    53. }
    54. //if (big == 0.0)
    55. if (Math.Abs(big) <= float.Epsilon)
    56. {
    57. throw new Exception("Singular matrix in LUdcmp");
    58. }
    59. vv[i] = 1.0 / big;
    60. }
    61. for (int k = 0; k < n; k++)
    62. {
    63. double big = 0.0;
    64. int imax = k;
    65. for (int i = k; i < n; i++)
    66. {
    67. double temp = vv[i] * Math.Abs(lu[i, k]);
    68. if (temp > big)
    69. {
    70. big = temp;
    71. imax = i;
    72. }
    73. }
    74. if (k != imax)
    75. {
    76. for (int j = 0; j < n; j++)
    77. {
    78. double temp = lu[imax, j];
    79. lu[imax, j] = lu[k, j];
    80. lu[k, j] = temp;
    81. }
    82. d = -d;
    83. vv[imax] = vv[k];
    84. }
    85. indx[k] = imax;
    86. //if (lu[k, k] == 0.0)
    87. if (Math.Abs(lu[k, k]) <= float.Epsilon)
    88. {
    89. lu[k, k] = TINY;
    90. }
    91. for (int i = k + 1; i < n; i++)
    92. {
    93. double temp = lu[i, k] /= lu[k, k];
    94. for (int j = k + 1; j < n; j++)
    95. {
    96. lu[i, j] -= temp * lu[k, j];
    97. }
    98. }
    99. }
    100. }
    101. /// <summary>
    102. /// Solves the set of n linear equations A*x = b using the stored LU decomposition of A.
    103. /// b[0..n - 1] is input as the right-hand side vector b, while x returns the solution vector x; b and
    104. /// x may reference the same vector, in which case the solution overwrites the input.This routine
    105. /// takes into account the possibility that b will begin with many zero elements, so it is efficient for
    106. /// use in matrix inversion.
    107. /// </summary>
    108. /// <param name="b"></param>
    109. /// <param name="x"></param>
    110. /// <exception cref="Exception"></exception>
    111. public void solve(double[] b, double[] x)
    112. {
    113. int ii = 0;
    114. if (b.Length != n || x.Length != n)
    115. {
    116. throw new Exception("LUdcmp::solve bad sizes");
    117. }
    118. for (int i = 0; i < n; i++)
    119. {
    120. x[i] = b[i];
    121. }
    122. for (int i = 0; i < n; i++)
    123. {
    124. int ip = indx[i];
    125. double sum = x[ip];
    126. x[ip] = x[i];
    127. if (ii != 0)
    128. {
    129. for (int j = ii - 1; j < i; j++)
    130. {
    131. sum -= lu[i, j] * x[j];
    132. }
    133. }
    134. else if (sum != 0.0)
    135. {
    136. ii = i + 1;
    137. }
    138. x[i] = sum;
    139. }
    140. for (int i = n - 1; i >= 0; i--)
    141. {
    142. double sum = x[i];
    143. for (int j = i + 1; j < n; j++)
    144. {
    145. sum -= lu[i, j] * x[j];
    146. }
    147. x[i] = sum / lu[i, i];
    148. }
    149. }
    150. /// <summary>
    151. /// Solves m sets of n linear equations A*X = B using the stored LU decomposition of A.The
    152. /// matrix b[0..n - 1][0..m - 1] inputs the right-hand sides, while x[0..n - 1][0..m - 1] returns the
    153. /// solution A^-1* B.b and x may reference the same matrix, in which case the solution overwrites
    154. /// the input.
    155. /// </summary>
    156. /// <param name="b"></param>
    157. /// <param name="x"></param>
    158. /// <exception cref="Exception"></exception>
    159. public void solve(double[,] b, double[,] x)
    160. {
    161. int m = b.GetLength(1);
    162. if (b.GetLength(0) != n || x.GetLength(0) != n || b.GetLength(1) != x.GetLength(1))
    163. {
    164. throw new Exception("LUdcmp::solve bad sizes");
    165. }
    166. double[] xx = new double[n];
    167. for (int j = 0; j < m; j++)
    168. {
    169. for (int i = 0; i < n; i++)
    170. {
    171. xx[i] = b[i, j];
    172. }
    173. solve( xx, xx);
    174. for (int i = 0; i < n; i++)
    175. {
    176. x[i, j] = xx[i];
    177. }
    178. }
    179. }
    180. /// <summary>
    181. /// Using the stored LU decomposition,
    182. /// return in ainv the matrix inverse
    183. /// </summary>
    184. /// <param name="ainv"></param>
    185. public void inverse(double[,] ainv)
    186. {
    187. //ainv.resize(n, n);
    188. for (int i = 0; i < n; i++)
    189. {
    190. for (int j = 0; j < n; j++)
    191. {
    192. ainv[i, j] = 0.0;
    193. }
    194. ainv[i, i] = 1.0;
    195. }
    196. solve( ainv, ainv);
    197. }
    198. /// <summary>
    199. /// Using the stored LU decomposition,
    200. /// return the determinant of the matrix A.
    201. /// </summary>
    202. /// <returns></returns>
    203. public double det()
    204. {
    205. double dd = d;
    206. for (int i = 0; i < n; i++)
    207. {
    208. dd *= lu[i, i];
    209. }
    210. return dd;
    211. }
    212. /// <summary>
    213. /// Improves a solution vector x[0..n - 1] of the linear set of equations A*x= b.
    214. /// The vectors b[0..n - 1] and x[0..n - 1] are input.On output, x[0..n - 1] is
    215. /// modified, to an improved set of values.
    216. /// </summary>
    217. /// <param name="b"></param>
    218. /// <param name="x"></param>
    219. public void mprove(double[] b, double[] x)
    220. {
    221. double[] r = new double[n];
    222. for (int i = 0; i < n; i++)
    223. {
    224. double sdp = -b[i];
    225. for (int j = 0; j < n; j++)
    226. {
    227. sdp += (double)aref[i, j] * (double)x[j];
    228. }
    229. r[i] = sdp;
    230. }
    231. solve( r, r);
    232. for (int i = 0; i < n; i++)
    233. {
    234. x[i] -= r[i];
    235. }
    236. }
    237. }
    238. }

  • 相关阅读:
    英语写作中“展示”、“表明”demonstrate、show、indicate、illustrate的用法
    预处理,编译,汇编,链接,全过程。
    ++ Reference: Standard C++ Library reference: C Library: cmath: lround
    神经网络仿真软件是什么,神经网络仿真软件下载
    Day46:项目-购物车案例
    c++基础(自用)
    植物大战僵尸杂交版全平台 PC MAC 安卓手机下载安装详细图文教程
    position sticky与overflow冲突失效无作用,解决办法
    JSON.parse 和 JSON.stringify 详解
    拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话
  • 原文地址:https://blog.csdn.net/beijinghorn/article/details/125580733