ldl.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /* ========================================================================== */
  2. /* === ldl.c: sparse LDL' factorization and solve package =================== */
  3. /* ========================================================================== */
  4. /* LDL: a simple set of routines for sparse LDL' factorization. These routines
  5. * are not terrifically fast (they do not use dense matrix kernels), but the
  6. * code is very short. The purpose is to illustrate the algorithms in a very
  7. * concise manner, primarily for educational purposes. Although the code is
  8. * very concise, this package is slightly faster than the built-in sparse
  9. * Cholesky factorization in MATLAB 7.0 (chol), when using the same input
  10. * permutation.
  11. *
  12. * The routines compute the LDL' factorization of a real sparse symmetric
  13. * matrix A (or PAP' if a permutation P is supplied), and solve upper
  14. * and lower triangular systems with the resulting L and D factors. If A is
  15. * positive definite then the factorization will be accurate. A can be
  16. * indefinite (with negative values on the diagonal D), but in this case no
  17. * guarantee of accuracy is provided, since no numeric pivoting is performed.
  18. *
  19. * The n-by-n sparse matrix A is in compressed-column form. The nonzero values
  20. * in column j are stored in Ax [Ap [j] ... Ap [j+1]-1], with corresponding row
  21. * indices in Ai [Ap [j] ... Ap [j+1]-1]. Ap [0] = 0 is required, and thus
  22. * nz = Ap [n] is the number of nonzeros in A. Ap is an int array of size n+1.
  23. * The int array Ai and the double array Ax are of size nz. This data structure
  24. * is identical to the one used by MATLAB, except for the following
  25. * generalizations. The row indices in each column of A need not be in any
  26. * particular order, although they must be in the range 0 to n-1. Duplicate
  27. * entries can be present; any duplicates are summed. That is, if row index i
  28. * appears twice in a column j, then the value of A (i,j) is the sum of the two
  29. * entries. The data structure used here for the input matrix A is more
  30. * flexible than MATLAB's, which requires sorted columns with no duplicate
  31. * entries.
  32. *
  33. * Only the diagonal and upper triangular part of A (or PAP' if a permutation
  34. * P is provided) is accessed. The lower triangular parts of the matrix A or
  35. * PAP' can be present, but they are ignored.
  36. *
  37. * The optional input permutation is provided as an array P of length n. If
  38. * P [k] = j, the row and column j of A is the kth row and column of PAP'.
  39. * If P is present then the factorization is LDL' = PAP' or L*D*L' = A(P,P) in
  40. * 0-based MATLAB notation. If P is not present (a null pointer) then no
  41. * permutation is performed, and the factorization is LDL' = A.
  42. *
  43. * The lower triangular matrix L is stored in the same compressed-column
  44. * form (an int Lp array of size n+1, an int Li array of size Lp [n], and a
  45. * double array Lx of the same size as Li). It has a unit diagonal, which is
  46. * not stored. The row indices in each column of L are always returned in
  47. * ascending order, with no duplicate entries. This format is compatible with
  48. * MATLAB, except that it would be more convenient for MATLAB to include the
  49. * unit diagonal of L. Doing so here would add additional complexity to the
  50. * code, and is thus omitted in the interest of keeping this code short and
  51. * readable.
  52. *
  53. * The elimination tree is held in the Parent [0..n-1] array. It is normally
  54. * not required by the user, but it is required by ldl_numeric. The diagonal
  55. * matrix D is held as an array D [0..n-1] of size n.
  56. *
  57. * --------------------
  58. * C-callable routines:
  59. * --------------------
  60. *
  61. * ldl_symbolic: Given the pattern of A, computes the Lp and Parent arrays
  62. * required by ldl_numeric. Takes time proportional to the number of
  63. * nonzeros in L. Computes the inverse Pinv of P if P is provided.
  64. * Also returns Lnz, the count of nonzeros in each column of L below
  65. * the diagonal (this is not required by ldl_numeric).
  66. * ldl_numeric: Given the pattern and numerical values of A, the Lp array,
  67. * the Parent array, and P and Pinv if applicable, computes the
  68. * pattern and numerical values of L and D.
  69. * ldl_lsolve: Solves Lx=b for a dense vector b.
  70. * ldl_dsolve: Solves Dx=b for a dense vector b.
  71. * ldl_ltsolve: Solves L'x=b for a dense vector b.
  72. * ldl_perm: Computes x=Pb for a dense vector b.
  73. * ldl_permt: Computes x=P'b for a dense vector b.
  74. * ldl_valid_perm: checks the validity of a permutation vector
  75. * ldl_valid_matrix: checks the validity of the sparse matrix A
  76. *
  77. * ----------------------------
  78. * Limitations of this package:
  79. * ----------------------------
  80. *
  81. * In the interest of keeping this code simple and readable, ldl_symbolic and
  82. * ldl_numeric assume their inputs are valid. You can check your own inputs
  83. * prior to calling these routines with the ldl_valid_perm and ldl_valid_matrix
  84. * routines. Except for the two ldl_valid_* routines, no routine checks to see
  85. * if the array arguments are present (non-NULL). Like all C routines, no
  86. * routine can determine if the arrays are long enough and don't overlap.
  87. *
  88. * The ldl_numeric does check the numerical factorization, however. It returns
  89. * n if the factorization is successful. If D (k,k) is zero, then k is
  90. * returned, and L is only partially computed.
  91. *
  92. * No pivoting to control fill-in is performed, which is often critical for
  93. * obtaining good performance. I recommend that you compute the permutation P
  94. * using AMD or SYMAMD (approximate minimum degree ordering routines), or an
  95. * appropriate graph-partitioning based ordering. See the ldldemo.m routine for
  96. * an example in MATLAB, and the ldlmain.c stand-alone C program for examples of
  97. * how to find P. Routines for manipulating compressed-column matrices are
  98. * available in UMFPACK. AMD, SYMAMD, UMFPACK, and this LDL package are all
  99. * available at http://www.suitesparse.com.
  100. *
  101. * -------------------------
  102. * Possible simplifications:
  103. * -------------------------
  104. *
  105. * These routines could be made even simpler with a few additional assumptions.
  106. * If no input permutation were performed, the caller would have to permute the
  107. * matrix first, but the computation of Pinv, and the use of P and Pinv could be
  108. * removed. If only the diagonal and upper triangular part of A or PAP' are
  109. * present, then the tests in the "if (i < k)" statement in ldl_symbolic and
  110. * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can
  111. * equal k in ldl_symbolic, but then the body of the if statement would
  112. * correctly do no work since Flag [k] == k). If we could assume that no
  113. * duplicate entries are present, then the statement Y [i] += Ax [p] could be
  114. * replaced with Y [i] = Ax [p] in ldl_numeric.
  115. *
  116. * --------------------------
  117. * Description of the method:
  118. * --------------------------
  119. *
  120. * LDL computes the symbolic factorization by finding the pattern of L one row
  121. * at a time. It does this based on the following theory. Consider a sparse
  122. * system Lx=b, where L, x, and b, are all sparse, and where L comes from a
  123. * Cholesky (or LDL') factorization. The elimination tree (etree) of L is
  124. * defined as follows. The parent of node j is the smallest k > j such that
  125. * L (k,j) is nonzero. Node j has no parent if column j of L is completely zero
  126. * below the diagonal (j is a root of the etree in this case). The nonzero
  127. * pattern of x is the union of the paths from each node i to the root, for
  128. * each nonzero b (i). To compute the numerical solution to Lx=b, we can
  129. * traverse the columns of L corresponding to nonzero values of x. This
  130. * traversal does not need to be done in the order 0 to n-1. It can be done in
  131. * any "topological" order, such that x (i) is computed before x (j) if i is a
  132. * descendant of j in the elimination tree.
  133. *
  134. * The row-form of the LDL' factorization is shown in the MATLAB function
  135. * ldlrow.m in this LDL package. Note that row k of L is found via a sparse
  136. * triangular solve of L (1:k-1, 1:k-1) \ A (1:k-1, k), to use 1-based MATLAB
  137. * notation. Thus, we can start with the nonzero pattern of the kth column of
  138. * A (above the diagonal), follow the paths up to the root of the etree of the
  139. * (k-1)-by-(k-1) leading submatrix of L, and obtain the pattern of the kth row
  140. * of L. Note that we only need the leading (k-1)-by-(k-1) submatrix of L to
  141. * do this. The elimination tree can be constructed as we go.
  142. *
  143. * The symbolic factorization does the same thing, except that it discards the
  144. * pattern of L as it is computed. It simply counts the number of nonzeros in
  145. * each column of L and then constructs the Lp index array when it's done. The
  146. * symbolic factorization does not need to do this in topological order.
  147. * Compare ldl_symbolic with the first part of ldl_numeric, and note that the
  148. * while (len > 0) loop is not present in ldl_symbolic.
  149. *
  150. * Copyright (c) 2006 by Timothy A Davis, http://www.suitesparse.com.
  151. * All Rights Reserved. Developed while on sabbatical
  152. * at Stanford University and Lawrence Berkeley National Laboratory. Refer to
  153. * the README file for the License.
  154. */
  155. #include "ldl.h"
  156. //#include "../../../include/glblopts.h"
  157. //#include "../../../include/ecos.h"
  158. /* ========================================================================== */
  159. /* === ldl_symbolic2 ======================================================== */
  160. /* ========================================================================== */
  161. /* The input to this routine is a sparse matrix A, stored in column form, and
  162. * an optional permutation P. The output is the elimination tree
  163. * and the number of nonzeros in each column of L. Parent [i] = k if k is the
  164. * parent of i in the tree. The Parent array is required by ldl_numeric.
  165. * Lnz [k] gives the number of nonzeros in the kth column of L, excluding the
  166. * diagonal.
  167. *
  168. * One workspace vector (Flag) of size n is required.
  169. *
  170. * If P is NULL, then it is ignored. The factorization will be LDL' = A.
  171. * Pinv is not computed. In this case, neither P nor Pinv are required by
  172. * ldl_numeric.
  173. *
  174. * If P is not NULL, then it is assumed to be a valid permutation. If
  175. * row and column j of A is the kth pivot, the P [k] = j. The factorization
  176. * will be LDL' = PAP', or A (p,p) in MATLAB notation. The inverse permutation
  177. * Pinv is computed, where Pinv [j] = k if P [k] = j. In this case, both P
  178. * and Pinv are required as inputs to ldl_numeric.
  179. *
  180. * The floating-point operation count of the subsequent call to ldl_numeric
  181. * is not returned, but could be computed after ldl_symbolic is done. It is
  182. * the sum of (Lnz [k]) * (Lnz [k] + 2) for k = 0 to n-1.
  183. *
  184. * This is essentially ldl_symbolic, but with the following simplifications
  185. * implemented (as stated above) by A. Domahidi:
  186. *
  187. * These routines could be made even simpler with a few additional assumptions.
  188. * If no input permutation were performed, the caller would have to permute the
  189. * matrix first, but the computation of Pinv, and the use of P and Pinv could be
  190. * removed. If only the diagonal and upper triangular part of A or PAP' are
  191. * present, then the tests in the "if (i < k)" statement in ldl_symbolic and
  192. * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can
  193. * equal k in ldl_symbolic, but then the body of the if statement would
  194. * correctly do no work since Flag [k] == k).
  195. */
  196. void LDL_symbolic2
  197. (
  198. LDL_int n, /* A and L are n-by-n, where n >= 0 */
  199. LDL_int Ap [ ], /* input of size n+1, not modified */
  200. LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */
  201. LDL_int Lp [ ], /* output of size n+1, not defined on input */
  202. LDL_int Parent [ ], /* output of size n, not defined on input */
  203. LDL_int Lnz [ ], /* output of size n, not defined on input */
  204. LDL_int Flag [ ] /* workspace of size n, not defn. on input or output */
  205. )
  206. {
  207. LDL_int i, k, p, p2 ;
  208. for (k = 0 ; k < n ; k++){
  209. /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
  210. Parent [k] = -1 ; /* parent of k is not yet known */
  211. Flag [k] = k ; /* mark node k as visited */
  212. Lnz [k] = 0 ; /* count of nonzeros in column k of L */
  213. p2 = Ap [k+1] ;
  214. for (p = Ap [k] ; p < p2 ; p++) {
  215. /* A (i,k) is nonzero (original or permuted A) */
  216. i = Ai [p];
  217. /* follow path from i to root of etree, stop at flagged node */
  218. for ( ; Flag [i] != k ; i = Parent [i]){
  219. /* find parent of i if not yet determined */
  220. if (Parent [i] == -1) Parent [i] = k ;
  221. Lnz [i]++ ; /* L (k,i) is nonzero */
  222. Flag [i] = k ; /* mark i as visited */
  223. }
  224. }
  225. }
  226. /* construct Lp index array from Lnz column counts */
  227. Lp [0] = 0 ;
  228. for (k = 0 ; k < n ; k++){
  229. Lp [k+1] = Lp [k] + Lnz [k] ;
  230. }
  231. }
  232. /* ========================================================================== */
  233. /* === ldl_numeric2 ========================================================== */
  234. /* ========================================================================== */
  235. /* Given a sparse matrix A (the arguments n, Ap, Ai, and Ax) and its symbolic
  236. * analysis (Lp and Parent, and optionally P and Pinv), compute the numeric LDL'
  237. * factorization of A or PAP'. The outputs of this routine are arguments Li,
  238. * Lx, and D. It also requires three size-n workspaces (Y, Pattern, and Flag).
  239. *
  240. * This is essentially ldl_numeric, but with the following simplifications
  241. * implemented (as stated above) by A. Domahidi:
  242. *
  243. * These routines could be made even simpler with a few additional assumptions.
  244. * If no input permutation were performed, the caller would have to permute the
  245. * matrix first, but the computation of Pinv, and the use of P and Pinv could be
  246. * removed. If only the diagonal and upper triangular part of A or PAP' are
  247. * present, then the tests in the "if (i < k)" statement in ldl_symbolic and
  248. * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can
  249. * equal k in ldl_symbolic, but then the body of the if statement would
  250. * correctly do no work since Flag [k] == k). If we could assume that no
  251. * duplicate entries are present, then the statement Y [i] += Ax [p] could be
  252. * replaced with Y [i] = Ax [p] in ldl_numeric.
  253. */
  254. LDL_int LDL_numeric2 /* returns n if successful, k if D (k,k) is zero */
  255. (
  256. LDL_int n, /* A and L are n-by-n, where n >= 0 */
  257. LDL_int Ap [ ], /* input of size n+1, not modified */
  258. LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */
  259. double Ax [ ], /* input of size nz=Ap[n], not modified */
  260. LDL_int Lp [ ], /* input of size n+1, not modified */
  261. LDL_int Parent [ ], /* input of size n, not modified */
  262. LDL_int Sign[ ], /* input of size n, sign vector of diagonal entries for regularization */
  263. double eps, /* input, regularization threshold */
  264. double delta, /* input, regularization parameter */
  265. LDL_int Lnz [ ], /* output of size n, not defn. on input */
  266. LDL_int Li [ ], /* output of size lnz=Lp[n], not defined on input */
  267. double Lx [ ], /* output of size lnz=Lp[n], not defined on input */
  268. double D [ ], /* output of size n, not defined on input */
  269. double Y [ ], /* workspace of size n, not defn. on input or output */
  270. LDL_int Pattern [ ], /* workspace of size n, not defn. on input or output */
  271. LDL_int Flag [ ] /* workspace of size n, not defn. on input or output */
  272. #if PROFILING > 1
  273. ,double *t1, /* time for non-zero pattern computation */
  274. double *t2 /* time for back-solves */
  275. #endif
  276. )
  277. {
  278. double yi, l_ki;
  279. LDL_int i, k, p, p2, len, top;
  280. #if PROFILING > 1
  281. timer clock;
  282. #endif
  283. /* go row-wise about this */
  284. for (k = 0 ; k < n ; k++){
  285. #if PROFILING > 1
  286. tic(&clock);
  287. #endif
  288. /* compute nonzero Pattern of kth row of L, in topological order */
  289. Y [k] = 0.0 ; /* Y(0:k) is now all zero */
  290. top = n ; /* stack for pattern is empty */
  291. Flag [k] = k ; /* mark node k as visited */
  292. Lnz [k] = 0 ; /* count of nonzeros in column k of L */
  293. p2 = Ap [k+1] ;
  294. for (p = Ap [k] ; p < p2 ; p++){
  295. i = Ai [p]; /* get A(i,k) */
  296. Y [i] = Ax [p] ;
  297. for (len = 0 ; Flag [i] != k ; i = Parent [i]){
  298. Pattern [len++] = i ; /* L(k,i) is nonzero */
  299. Flag [i] = k ; /* mark i as visited */
  300. }
  301. while (len > 0) Pattern [--top] = Pattern [--len] ;
  302. }
  303. #if PROFILING > 1
  304. *t1 += toc(&clock);
  305. tic(&clock);
  306. #endif
  307. /* compute numerical values kth row of L (a sparse triangular solve) */
  308. D [k] = Y [k] ; /* get D(k,k) and clear Y(k) */
  309. Y [k] = 0.0 ;
  310. for ( ; top < n ; top++){
  311. i = Pattern [top] ; /* Pattern [top:n-1] is pattern of L(:,k) */
  312. yi = Y [i] ; /* get and clear Y(i) */
  313. Y [i] = 0.0 ;
  314. p2 = Lp [i] + Lnz [i] ;
  315. for (p = Lp [i] ; p < p2 ; p++){
  316. Y [Li [p]] -= Lx [p] * yi ;
  317. }
  318. l_ki = yi / D [i] ; /* the nonzero entry L(k,i) */
  319. D [k] -= l_ki * yi ;
  320. Li [p] = k ; /* store L(k,i) in column form of L */
  321. Lx [p] = l_ki ;
  322. Lnz [i]++ ; /* increment count of nonzeros in col i */
  323. }
  324. /* Dynamic regularization */
  325. D[k] = Sign[k]*D[k] <= eps ? Sign[k]*delta : D[k];
  326. #if PROFILING > 1
  327. *t2 += toc(&clock);
  328. #endif
  329. /* FOR DEBUG
  330. if( Sign[k]*D[k] <= eps )
  331. {
  332. PRINTTEXT( "Sign[%d]=%d, D[%d] = %6.4e, regularizing to %4.2e\n", (int)k, (int)Sign[k], (int)k, D[k], Sign[k]*delta);
  333. D[k] = Sign[k]*delta;
  334. }
  335. */
  336. }
  337. return (n) ; /* success, diagonal of D is all nonzero */
  338. }
  339. /* ========================================================================== */
  340. /* === ldl_lsolve: solve Lx=b ============================================== */
  341. /* ========================================================================== */
  342. void LDL_lsolve
  343. (
  344. LDL_int n, /* L is n-by-n, where n >= 0 */
  345. double X [ ], /* size n. right-hand-side on input, soln. on output */
  346. LDL_int Lp [ ], /* input of size n+1, not modified */
  347. LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */
  348. double Lx [ ] /* input of size lnz=Lp[n], not modified */
  349. ){
  350. LDL_int j, p, p2 ;
  351. for (j = 0 ; j < n ; j++){
  352. p2 = Lp [j+1] ;
  353. for (p = Lp [j] ; p < p2 ; p++){
  354. X [Li [p]] -= Lx [p] * X [j] ;
  355. }
  356. }
  357. }
  358. /* MODIFIED BY ALEXANDER DOMAHIDI */
  359. /* ========================================================================== */
  360. /* === ldl_lsolve2: solve Lx=b ============================================= */
  361. /* ========================================================================== */
  362. void LDL_lsolve2
  363. (
  364. LDL_int n, /* L is n-by-n, where n >= 0 */
  365. double b [ ], /* size n. input. right-hand-side */
  366. LDL_int Lp [ ], /* input of size n+1, not modified */
  367. LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */
  368. double Lx [ ], /* input of size lnz=Lp[n], not modified */
  369. double x [ ] /* size n. output. solution to Lx=b */
  370. )
  371. {
  372. LDL_int j, p, p2 ;
  373. for( j=0; j < n; j++ ){ x[j] = b[j]; }
  374. for (j = 0 ; j < n ; j++){
  375. p2 = Lp [j+1] ;
  376. for (p = Lp [j] ; p < p2 ; p++){
  377. x [Li [p]] -= Lx [p] * x [j];
  378. }
  379. }
  380. }
  381. /* ========================================================================== */
  382. /* === ldl_dsolve: solve Dx=b ============================================== */
  383. /* ========================================================================== */
  384. void LDL_dsolve
  385. (
  386. LDL_int n, /* D is n-by-n, where n >= 0 */
  387. double X [ ], /* size n. right-hand-side on input, soln. on output */
  388. double D [ ] /* input of size n, not modified */
  389. )
  390. {
  391. LDL_int j ;
  392. for (j = 0 ; j < n ; j++){ X [j] /= D [j]; }
  393. }
  394. /* ========================================================================== */
  395. /* === ldl_ltsolve: solve L'x=b ============================================ */
  396. /* ========================================================================== */
  397. void LDL_ltsolve
  398. (
  399. LDL_int n, /* L is n-by-n, where n >= 0 */
  400. double X [ ], /* size n. right-hand-side on input, soln. on output */
  401. LDL_int Lp [ ], /* input of size n+1, not modified */
  402. LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */
  403. double Lx [ ] /* input of size lnz=Lp[n], not modified */
  404. )
  405. {
  406. LDL_int j, p, p2 ;
  407. for (j = n-1 ; j >= 0 ; j--){
  408. p2 = Lp [j+1] ;
  409. for (p = Lp [j] ; p < p2 ; p++){
  410. X [j] -= Lx [p] * X [Li [p]] ;
  411. }
  412. }
  413. }