~logan/ubuntu/trusty/suitesparse/4.2.1-3ubuntu1

« back to all changes in this revision

Viewing changes to LDL/ldl_userguide.tex

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Prud'homme
  • Date: 2007-05-29 09:36:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070529093629-zowquo0b7slkk6nc
Tags: 3.0.0-2
* suitesparse builds properly twice in a row
* Bug fix: "suitesparse - FTBFS: Broken build depens: libgfortran1-dev",
  thanks to Bastian Blank (Closes: #426349).
* Bug fix: "suitesparse_3.0.0-1: FTBFS: build-depends on
  libgfortran1-dev", thanks to Steve Langasek (Closes: #426354).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
\documentclass[12pt]{article}
2
 
 
3
 
\newcommand{\m}[1]{{\bf{#1}}}       % for matrices and vectors
4
 
\newcommand{\tr}{^{\sf T}}          % transpose
5
 
 
6
 
\topmargin 0in
7
 
\textheight 9in
8
 
\oddsidemargin 0pt
9
 
\evensidemargin 0pt
10
 
\textwidth 6.5in
11
 
 
12
 
%-------------------------------------------------------------------------------
13
 
\begin{document}
14
 
%-------------------------------------------------------------------------------
15
 
 
16
 
\title{User Guide for LDL, a concise sparse Cholesky package}
17
 
\author{Timothy A. Davis\thanks{
18
 
Dept.~of Computer and Information Science and Engineering,
19
 
Univ.~of Florida, Gainesville, FL, USA.
20
 
email: davis@cise.ufl.edu.
21
 
http://www.cise.ufl.edu/$\sim$davis.
22
 
This work was supported by the National
23
 
Science Foundation, under grant CCR-0203270.
24
 
Portions of the work were done while on sabbatical at Stanford University
25
 
and Lawrence Berkeley National Laboratory (with funding from Stanford
26
 
University and the SciDAC program).
27
 
}}
28
 
 
29
 
\date{Apr. 30, 2006}
30
 
 
31
 
\maketitle
32
 
 
33
 
%-------------------------------------------------------------------------------
34
 
\begin{abstract}
35
 
The {\tt LDL} software package is a set of short, concise routines for
36
 
factorizing symmetric positive-definite sparse matrices, with some
37
 
applicability to symmetric indefinite matrices.  Its primary purpose is
38
 
to illustrate much of the basic theory of sparse matrix algorithms in as
39
 
concise a code as possible, including an elegant method
40
 
of sparse symmetric factorization that computes the factorization row-by-row
41
 
but stores it column-by-column.  The entire symbolic and numeric factorization
42
 
consists of less than 50 lines of code.  The package is written in C,
43
 
and includes a MATLAB interface.
44
 
\end{abstract}
45
 
%-------------------------------------------------------------------------------
46
 
 
47
 
%-------------------------------------------------------------------------------
48
 
\section{Overview}
49
 
%-------------------------------------------------------------------------------
50
 
 
51
 
{\tt LDL} is a set of short, concise routines that compute the $\m{LDL}\tr$
52
 
factorization of a sparse symmetric matrix $\m{A}$.  Its primary purpose is
53
 
to illustrate much of the basic theory of sparse matrix algorithms in as
54
 
compact a code as possible, including an elegant method of
55
 
sparse symmetric factorization (related to \cite{Liu86c,Liu91}).
56
 
The lower triangular factor $\m{L}$ is computed row-by-row, in contrast to the
57
 
conventional column-by-column method.
58
 
Although it does not achieve the same level of performance
59
 
as methods based on dense matrix kernels
60
 
(such as \cite{NgPeyton93,RothbergGupta91}),
61
 
its performance is competitive with column-by-column methods that do not
62
 
use dense kernels \cite{GeorgeLiu79, GeorgeLiu, GilbertMolerSchreiber}.
63
 
 
64
 
Section~\ref{Algorithm} gives a brief description of the algorithm
65
 
used in the symbolic and numeric factorization.  A more detailed tutorial-level
66
 
discussion may be found in \cite{Stewart03}.  Details
67
 
of the concise implementation of this method are given in
68
 
Section~\ref{Implementation}.  Sections~\ref{MATLAB}~and~\ref{C} give an
69
 
overview of how to use the package in MATLAB and in a stand-alone C program.
70
 
 
71
 
%-------------------------------------------------------------------------------
72
 
\section{Algorithm}
73
 
\label{Algorithm}
74
 
%-------------------------------------------------------------------------------
75
 
 
76
 
The underlying numerical algorithm is described below.  The $k$th
77
 
step solves a lower triangular system of dimension $k-1$ to compute the
78
 
$k$th row of $\m{L}$ and the $d_{kk}$ entry of the diagonal matrix $\m{D}$.
79
 
Colon notation is used for submatrices.  For example,
80
 
$\m{L}_{k,1:k-1}$ refers to the first $k-1$ columns of
81
 
the $k$th row of $\m{L}$.  Similarly, $\m{L}_{1:k-1,1:k-1}$ refers to
82
 
the leading $(k-1)$-by-$(k-1)$ submatrix of $\m{L}$.
83
 
%---------------
84
 
\vspace{-0.2in}
85
 
\begin{tabbing}
86
 
\hspace{2em} \= \hspace{2em} \= \hspace{2em} \= \\
87
 
{\bf Algorithm~1
88
 
($\m{LDL}\tr$ factorization of a $n$-by-$n$ symmetric matrix $\m{A}$)} \\
89
 
\> {\bf for} $k = 1$ {\bf to} $n$ \\
90
 
\>\> (step 1) Solve $\m{L}_{1:k-1,1:k-1}\m{y} = \m{A}_{1:k-1,k}$ for $\m{y}$ \\
91
 
\>\> (step 2) $\m{L}_{k,1:k-1} = (\m{D}_{1:k-1,1:k-1}^{-1} \m{y})\tr$ \\
92
 
\>\> (step 3) $l_{kk} = 1$ \\
93
 
\>\> (step 4) $d_{kk} = a_{kk} - \m{L}_{k,1:k-1}\m{y}$ \\
94
 
\> {\bf end for}
95
 
\end{tabbing}
96
 
%---------------
97
 
 
98
 
The algorithm computes an $\m{LDL}\tr$ factorization without numerical pivoting.
99
 
It can thus factorize any symmetric positive definite matrix, and any
100
 
symmetric indefinite matrix whose leading minors are all well-conditioned.
101
 
 
102
 
When $\m{A}$ and $\m{L}$ are sparse, step 1 of Algorithm~1 requires a
103
 
triangular solve of the form $\m{Lx}=\m{b}$, where all three terms in
104
 
the equation are sparse.  This is the most costly step of the Algorithm.
105
 
Steps 2 through 4 are fairly straightforward.
106
 
 
107
 
Let ${\cal X}$ and ${\cal B}$ refer to the set of indices of nonzero entries
108
 
in $\m{x}$ and $\m{b}$, respectively, in the lower triangular system
109
 
$\m{Lx}=\m{b}$.  To compute $\m{x}$ efficiently
110
 
the nonzero pattern ${\cal X}$ must be found first.
111
 
In the general case when $\m{L}$ is arbitrary \cite{GilbertPeierls88},
112
 
the nonzero
113
 
pattern ${\cal X}$ is the set of nodes reachable via paths in the graph $G_L$
114
 
from all nodes in the set ${\cal B}$, and where the graph $G_L$ has
115
 
$n$ nodes and a directed edge $(j,i)$ if and only if $l_{ij}$ is nonzero.
116
 
To compute the numerical solution to $\m{Lx}=\m{b}$ by accessing the columns of
117
 
$\m{L}$ one at a time, ${\cal X}$ can be traversed
118
 
in any topological order of the subgraph of $G_L$ consisting of nodes in
119
 
${\cal X}$.  That is, $x_j$ must be computed before $x_i$ if there is a path
120
 
from $j$ to $i$ in $G_L$.  The natural order ($1, 2, \ldots, n$) is one such
121
 
ordering, but that requires a costly sort of ${\cal X}$.
122
 
With a graph traversal and topological sort, the solution of $\m{Lx}=\m{b}$
123
 
can be computed using Algorithm~2 below.
124
 
The computation of ${\cal X}$ and $\m{x}$ both take
125
 
time proportional to the floating-point operation count.
126
 
%---------------
127
 
\vspace{-0.2in}
128
 
\begin{tabbing}
129
 
\hspace{2em} \= \hspace{2em} \= \hspace{2em} \= \\
130
 
{\bf Algorithm~2
131
 
(Solve $\m{Lx}=\m{b}$, where $\m{L}$ is lower triangular with unit diagonal)} \\
132
 
\> ${\cal X} = \mbox{Reach}_{G_L} ({\cal B})$ \\
133
 
\> $\m{x} = \m{b}$ \\
134
 
\> {\bf for} $i \in {\cal X}$ in any topological order \\
135
 
\>\> $\m{x}_{i+1:n} = \m{x}_{i+1:n} - \m{L}_{i+1:n,i} x_i$ \\
136
 
\> {\bf end for}
137
 
\end{tabbing}
138
 
%---------------
139
 
 
140
 
The general result also governs the pattern of $\m{y}$ in Algorithm~1.
141
 
However, in this case $\m{L}$ arises from a sparse Cholesky factorization,
142
 
and is governed by the elimination tree \cite{Liu90a}.
143
 
A general graph traversal is not required.
144
 
In the elimination tree, the parent of node $i$ is the smallest $j > i$
145
 
such that $l_{ji}$ is nonzero.  Node $i$ has no parent if column $i$ of
146
 
$\m{L}$ is completely zero below the diagonal; $i$ is a root of the
147
 
elimination tree in this case.  The nonzero pattern of $\m{x}$ is the
148
 
union of all the nodes on the paths from any node $i$ (where $b_i$ is nonzero) to the
149
 
root of the elimination tree \cite[Thm 2.4]{Liu86c}.  It is referred to here as a tree,
150
 
but in general it can be a forest.
151
 
 
152
 
Rather than a general topological sort of the subgraph of $G_L$ consisting
153
 
nodes reachable from nodes in ${\cal B}$, a simpler
154
 
tree traversal can be used.  First, select any nonzero entry $b_i$
155
 
and follow the path from $i$ to the root of tree.
156
 
Nodes along this path are marked and placed in a stack,
157
 
with $i$ at the top of the
158
 
stack and the root at the bottom.
159
 
Repeat for every other nonzero entry in $b_i$, in arbitrary order, but stop
160
 
just before reaching a marked node (the result can be empty if $i$ is already
161
 
in the stack).  The stack now contains ${\cal X}$, a topological ordering of
162
 
the nonzero pattern of $\m{x}$, which can be used in Algorithm~2 to solve
163
 
$\m{Lx}=\m{b}$.  The time to compute ${\cal X}$
164
 
using an elimination tree traversal is much faster than the general graph
165
 
traversal, taking time proportional to the size of ${\cal X}$ rather than the
166
 
number of floating-point operations required to compute $\m{x}$.
167
 
 
168
 
In the $k$th step of the factorization, the set ${\cal X}$ becomes the
169
 
nonzero pattern of row $k$ of $\m{L}$.  This step requires the elimination
170
 
tree of $\m{L}_{1:k-1,1:k-1}$, and must construct the elimination tree of
171
 
$\m{L}_{1:k,1:k}$ for step $k+1$.  Recall that the parent of $i$ in the
172
 
tree is the smallest $j$ such that $i < j$ and $l_{ji} \ne 0$.
173
 
Thus, if any node $i$ already has a parent $j$, then $j$ will remain the
174
 
parent of $i$ in the elimination trees of all other larger leading submatrices
175
 
of $\m{L}$, and in the elimination tree of $\m{L}$ itself.
176
 
If $l_{ki} \ne 0$ and $i$ does not have a parent in the elimination tree of
177
 
$\m{L}_{1:k-1,1:k-1}$, then the parent of $i$ is $k$
178
 
in the elimination tree of $\m{L}_{1:k,1:k}$.
179
 
Node $k$ becomes the parent of any node $i \in {\cal X}$ that does not yet
180
 
have a parent.
181
 
 
182
 
Since Algorithm~2 traverses $\m{L}$ in column order, $\m{L}$ is stored in a
183
 
conventional sparse column representation.  Each column $j$ is stored as a list
184
 
of nonzero values and their corresponding row indices.  When row $k$ is
185
 
computed, the new entries can be placed at the end of each list.  As
186
 
a by-product of computing $\m{L}$ one row at a time,
187
 
the columns of $\m{L}$ are computed in a sorted manner.  This is a convenient
188
 
form of the output.
189
 
MATLAB requires the columns of its sparse matrices to be sorted, for example.
190
 
Sorted columns improve the speed of Algorithm~2, since the memory access
191
 
pattern is more regular.  The conventional column-by-column algorithm
192
 
\cite{GeorgeLiu79,GeorgeLiu} does not produce columns of $\m{L}$ with
193
 
sorted row indices.
194
 
 
195
 
A simple symbolic pre-analysis can be obtained by repeating the subtree traversals.
196
 
All that is required to compute the nonzero pattern of
197
 
the $k$th row of $\m{L}$ is the partially constructed elimination tree
198
 
and the nonzero pattern of the $k$th column of $\m{A}$.  This is computed
199
 
in time proportional to the size of this set, using the elimination tree
200
 
traversal.  Once constructed, the number of nonzeros in each column of
201
 
$\m{L}$ is incremented, for each entry in ${\cal X}$, and then ${\cal X}$
202
 
is discarded.  The set ${\cal X}$ need not be constructed in topological
203
 
order, so no stack is required.  The run time of the symbolic analysis
204
 
algorithm is thus proportional to the number of nonzeros in $\m{L}$.
205
 
This is more costly than the optimal algorithm \cite{GilbertNgPeyton94},
206
 
which takes time essentially proportional to the number of nonzeros in $\m{A}$.
207
 
The memory requirements are just the matrix $\m{A}$ and a few size-$n$ integer
208
 
arrays.  The result of the algorithm is the elimination tree, a count
209
 
of the number of nonzeros in each column of $\m{L}$, and
210
 
the cumulative sum of the column counts.
211
 
 
212
 
%-------------------------------------------------------------------------------
213
 
\section{Implementation}
214
 
\label{Implementation}
215
 
%-------------------------------------------------------------------------------
216
 
 
217
 
Because of its simplicity, the implementation of this algorithm leads to
218
 
a very short, concise code.  The symbolic analysis routine {\tt ldl\_symbolic}
219
 
shown in Figure~\ref{ldlsymbolic}
220
 
consists of only 18 lines of executable C code.
221
 
This includes 5 lines of code to allow for a
222
 
sparsity-preserving ordering $\m{P}$ so that either $\m{A}$ or $\m{PAP}\tr$
223
 
can be analyzed, 3 lines of code to compute the cumulative sum of
224
 
the column counts, and one line of code to speed up a {\tt for} loop.
225
 
An additional line of code allows for a more general form of the input
226
 
sparse matrix $\m{A}$.
227
 
 
228
 
The {\tt n}-by-{\tt n} sparse matrix $\m{A}$ is provided in compressed column
229
 
form as an {\tt int} array {\tt Ap} of length {\tt n+1},
230
 
an {\tt int} array {\tt Ai} of length {\tt nz},
231
 
and a {\tt double} array {\tt Ax} also of length {\tt nz},
232
 
where {\tt nz} is the number of entries in the matrix.
233
 
The numerical values of entries in column $j$ are stored in
234
 
{\tt Ax[Ap[j]} $\ldots$ {\tt Ap[j+1]-1]}
235
 
and the corresponding row indices are in
236
 
{\tt Ai[Ap[j]} $\ldots$ {\tt Ap[j+1]-1]}.
237
 
With {\tt Ap[0] = 0}, the number of entries in the matrix is {\tt nz = Ap[n]}.
238
 
If no fill-reducing ordering {\tt P} is provided,
239
 
only entries in the upper triangular part of $\m{A}$ are considered.
240
 
If {\tt P} is provided and row/column {\tt i} of the
241
 
matrix $\m{A}$ is the {\tt k}-th row/column of $\m{PAP}\tr$, then {\tt P[k]=i}.
242
 
Only entries in the upper
243
 
triangular part of $\m{PAP}\tr$ are considered.  These entries may be
244
 
in the lower triangular part of $\m{A}$, so to ensure that the correct matrix
245
 
is factorized, all entries of $\m{A}$ should be provided when using the
246
 
permutation input {\tt P}.
247
 
 
248
 
The outputs of {\tt ldl\_symbolic} are three size-{\tt n} arrays:
249
 
{\tt Parent} holds the elimination tree,
250
 
{\tt Lnz} holds the counts of the number of entries in each column of
251
 
$\m{L}$, and
252
 
{\tt Lp} holds the cumulative sum of {\tt Lnz}.
253
 
The size-{\tt n} array {\tt Flag} is used as workspace.
254
 
None of the output or workspace arrays need to be initialized.
255
 
 
256
 
\begin{figure}
257
 
\caption{{\tt ldl\_symbolic:} finding the elimination tree and column counts}
258
 
\label{ldlsymbolic}
259
 
{\scriptsize
260
 
\begin{verbatim}
261
 
void ldl_symbolic
262
 
(
263
 
    int n,              /* A and L are n-by-n, where n >= 0 */
264
 
    int Ap [ ],         /* input of size n+1, not modified */
265
 
    int Ai [ ],         /* input of size nz=Ap[n], not modified */
266
 
    int Lp [ ],         /* output of size n+1, not defined on input */
267
 
    int Parent [ ],     /* output of size n, not defined on input */
268
 
    int Lnz [ ],        /* output of size n, not defined on input */
269
 
    int Flag [ ],       /* workspace of size n, not defn. on input or output */
270
 
    int P [ ],          /* optional input of size n */
271
 
    int Pinv [ ]        /* optional output of size n (used if P is not NULL) */
272
 
)
273
 
{
274
 
    int i, k, p, kk, p2 ;
275
 
    if (P)
276
 
    {
277
 
        /* If P is present then compute Pinv, the inverse of P */
278
 
        for (k = 0 ; k < n ; k++)
279
 
        {
280
 
            Pinv [P [k]] = k ;
281
 
        }
282
 
    }
283
 
    for (k = 0 ; k < n ; k++)
284
 
    {
285
 
        /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
286
 
        Parent [k] = -1 ;           /* parent of k is not yet known */
287
 
        Flag [k] = k ;              /* mark node k as visited */
288
 
        Lnz [k] = 0 ;               /* count of nonzeros in column k of L */
289
 
        kk = (P) ? (P [k]) : (k) ;  /* kth original, or permuted, column */
290
 
        p2 = Ap [kk+1] ;
291
 
        for (p = Ap [kk] ; p < p2 ; p++)
292
 
        {
293
 
            /* A (i,k) is nonzero (original or permuted A) */
294
 
            i = (Pinv) ? (Pinv [Ai [p]]) : (Ai [p]) ;
295
 
            if (i < k)
296
 
            {
297
 
                /* follow path from i to root of etree, stop at flagged node */
298
 
                for ( ; Flag [i] != k ; i = Parent [i])
299
 
                {
300
 
                    /* find parent of i if not yet determined */
301
 
                    if (Parent [i] == -1) Parent [i] = k ;
302
 
                    Lnz [i]++ ;                         /* L (k,i) is nonzero */
303
 
                    Flag [i] = k ;                      /* mark i as visited */
304
 
                }
305
 
            }
306
 
        }
307
 
    }
308
 
    /* construct Lp index array from Lnz column counts */
309
 
    Lp [0] = 0 ;
310
 
    for (k = 0 ; k < n ; k++)
311
 
    {
312
 
        Lp [k+1] = Lp [k] + Lnz [k] ;
313
 
    }
314
 
}
315
 
\end{verbatim}
316
 
}
317
 
\end{figure}
318
 
 
319
 
The {\tt ldl\_numeric} numeric factorization routine shown
320
 
in Figure~\ref{ldlnumeric} consists of only 31 lines of
321
 
executable code.  It includes this same subtree traversal algorithm
322
 
as {\tt ldl\_symbolic},
323
 
except that each path is placed on a stack that holds
324
 
nonzero pattern of the $k$th row of $\m{L}$.
325
 
This traversal is followed by a sparse forward solve
326
 
using this pattern, and all of the nonzero entries in
327
 
the resulting $k$th row of $\m{L}$ are appended to their respective columns
328
 
in the data structure of $\m{L}$.
329
 
 
330
 
\begin{figure}
331
 
\caption{{\tt ldl\_numeric:} numeric factorization}
332
 
\label{ldlnumeric}
333
 
{\scriptsize
334
 
\begin{verbatim}
335
 
int ldl_numeric         /* returns n if successful, k if D (k,k) is zero */
336
 
(
337
 
    int n,              /* A and L are n-by-n, where n >= 0 */
338
 
    int Ap [ ],         /* input of size n+1, not modified */
339
 
    int Ai [ ],         /* input of size nz=Ap[n], not modified */
340
 
    double Ax [ ],      /* input of size nz=Ap[n], not modified */
341
 
    int Lp [ ],         /* input of size n+1, not modified */
342
 
    int Parent [ ],     /* input of size n, not modified */
343
 
    int Lnz [ ],        /* output of size n, not defn. on input */
344
 
    int Li [ ],         /* output of size lnz=Lp[n], not defined on input */
345
 
    double Lx [ ],      /* output of size lnz=Lp[n], not defined on input */
346
 
    double D [ ],       /* output of size n, not defined on input */
347
 
    double Y [ ],       /* workspace of size n, not defn. on input or output */
348
 
    int Pattern [ ],    /* workspace of size n, not defn. on input or output */
349
 
    int Flag [ ],       /* workspace of size n, not defn. on input or output */
350
 
    int P [ ],          /* optional input of size n */
351
 
    int Pinv [ ]        /* optional input of size n */
352
 
)
353
 
{
354
 
    double yi, l_ki ;
355
 
    int i, k, p, kk, p2, len, top ;
356
 
    for (k = 0 ; k < n ; k++)
357
 
    {
358
 
        /* compute nonzero Pattern of kth row of L, in topological order */
359
 
        Y [k] = 0.0 ;               /* Y(0:k) is now all zero */
360
 
        top = n ;                   /* stack for pattern is empty */
361
 
        Flag [k] = k ;              /* mark node k as visited */
362
 
        Lnz [k] = 0 ;               /* count of nonzeros in column k of L */
363
 
        kk = (P) ? (P [k]) : (k) ;  /* kth original, or permuted, column */
364
 
        p2 = Ap [kk+1] ;
365
 
        for (p = Ap [kk] ; p < p2 ; p++)
366
 
        {
367
 
            i = (Pinv) ? (Pinv [Ai [p]]) : (Ai [p]) ;   /* get A(i,k) */
368
 
            if (i <= k)
369
 
            {
370
 
                Y [i] += Ax [p] ;  /* scatter A(i,k) into Y (sum duplicates) */
371
 
                for (len = 0 ; Flag [i] != k ; i = Parent [i])
372
 
                {
373
 
                    Pattern [len++] = i ;   /* L(k,i) is nonzero */
374
 
                    Flag [i] = k ;          /* mark i as visited */
375
 
                }
376
 
                while (len > 0) Pattern [--top] = Pattern [--len] ;
377
 
            }
378
 
        }
379
 
        /* compute numerical values kth row of L (a sparse triangular solve) */
380
 
        D [k] = Y [k] ;             /* get D(k,k) and clear Y(k) */
381
 
        Y [k] = 0.0 ;
382
 
        for ( ; top < n ; top++)
383
 
        {
384
 
            i = Pattern [top] ;     /* Pattern [top:n-1] is pattern of L(:,k) */
385
 
            yi = Y [i] ;            /* get and clear Y(i) */
386
 
            Y [i] = 0.0 ;
387
 
            p2 = Lp [i] + Lnz [i] ;
388
 
            for (p = Lp [i] ; p < p2 ; p++)
389
 
            {
390
 
                Y [Li [p]] -= Lx [p] * yi ;
391
 
            }
392
 
            l_ki = yi / D [i] ;     /* the nonzero entry L(k,i) */
393
 
            D [k] -= l_ki * yi ;
394
 
            Li [p] = k ;            /* store L(k,i) in column form of L */
395
 
            Lx [p] = l_ki ;
396
 
            Lnz [i]++ ;             /* increment count of nonzeros in col i */
397
 
        }
398
 
        if (D [k] == 0.0) return (k) ;      /* failure, D(k,k) is zero */
399
 
    }
400
 
    return (n) ;        /* success, diagonal of D is all nonzero */
401
 
}
402
 
\end{verbatim}
403
 
}
404
 
\end{figure}
405
 
 
406
 
After the matrix is factorized, the {\tt ldl\_lsolve}, {\tt ldl\_dsolve},
407
 
and {\tt ldl\_ltsolve} routines shown in Figure~\ref{ldlsolve}
408
 
are provided to solve
409
 
$\m{Lx}=\m{b}$, $\m{Dx}=\m{b}$, and $\m{L}\tr\m{x}=\m{b}$, respectively.
410
 
Together, they solve $\m{Ax}=\m{b}$, and consist of only 10 lines of executable
411
 
code.  If a fill-reducing permutation is used,
412
 
{\tt ldl\_perm} and {\tt ldl\_permt} must be used to permute $\m{b}$ and
413
 
$\m{x}$ accordingly.
414
 
 
415
 
\begin{figure}
416
 
\caption{Solve routines}
417
 
\label{ldlsolve}
418
 
{\scriptsize
419
 
\begin{verbatim}
420
 
void ldl_lsolve
421
 
(
422
 
    int n,              /* L is n-by-n, where n >= 0 */
423
 
    double X [ ],       /* size n.  right-hand-side on input, soln. on output */
424
 
    int Lp [ ],         /* input of size n+1, not modified */
425
 
    int Li [ ],         /* input of size lnz=Lp[n], not modified */
426
 
    double Lx [ ]       /* input of size lnz=Lp[n], not modified */
427
 
)
428
 
{
429
 
    int j, p, p2 ;
430
 
    for (j = 0 ; j < n ; j++)
431
 
    {
432
 
        p2 = Lp [j+1] ;
433
 
        for (p = Lp [j] ; p < p2 ; p++)
434
 
        {
435
 
            X [Li [p]] -= Lx [p] * X [j] ;
436
 
        }
437
 
    }
438
 
}
439
 
 
440
 
void ldl_dsolve
441
 
(
442
 
    int n,              /* D is n-by-n, where n >= 0 */
443
 
    double X [ ],       /* size n.  right-hand-side on input, soln. on output */
444
 
    double D [ ]        /* input of size n, not modified */
445
 
)
446
 
{
447
 
    int j ;
448
 
    for (j = 0 ; j < n ; j++)
449
 
    {
450
 
        X [j] /= D [j] ;
451
 
    }
452
 
}
453
 
 
454
 
void ldl_ltsolve
455
 
(
456
 
    int n,              /* L is n-by-n, where n >= 0 */
457
 
    double X [ ],       /* size n.  right-hand-side on input, soln. on output */
458
 
    int Lp [ ],         /* input of size n+1, not modified */
459
 
    int Li [ ],         /* input of size lnz=Lp[n], not modified */
460
 
    double Lx [ ]       /* input of size lnz=Lp[n], not modified */
461
 
)
462
 
{
463
 
    int j, p, p2 ;
464
 
    for (j = n-1 ; j >= 0 ; j--)
465
 
    {
466
 
        p2 = Lp [j+1] ;
467
 
        for (p = Lp [j] ; p < p2 ; p++)
468
 
        {
469
 
            X [j] -= Lx [p] * X [Li [p]] ;
470
 
        }
471
 
    }
472
 
}
473
 
\end{verbatim}
474
 
}
475
 
\end{figure}
476
 
 
477
 
In addition to appearing as a Collected Algorithm of the ACM \cite{Davis05},
478
 
{\tt LDL} is available at http://www.cise.ufl.edu/research/sparse.
479
 
 
480
 
%-------------------------------------------------------------------------------
481
 
\section{Using LDL in MATLAB}
482
 
\label{MATLAB}
483
 
%-------------------------------------------------------------------------------
484
 
 
485
 
The simplest way to use {\tt LDL} is within MATLAB.  Once the {\tt LDL}
486
 
mexFunction is compiled and installed, the MATLAB statement
487
 
{\tt [L, D, Parent, fl] = ldl (A)} returns the sparse factorization
488
 
{\tt A = (L+I)*D*(L+I)'}, where {\tt L} is lower triangular, {\tt D} is a
489
 
diagonal matrix, and {\tt I} is the {\tt n}-by-{\tt n}
490
 
identity matrix ({\tt LDL} does not return the unit diagonal of {\tt L}).
491
 
The elimination tree is returned in {\tt Parent}.
492
 
If no zero on the diagonal of {\tt D} is encountered, {\tt fl} is the
493
 
floating-point operation count.  Otherwise, {\tt D(-fl,-fl)} is the first
494
 
zero entry encountered.  Let {\tt d=-fl}.  The function returns the
495
 
factorization of {\tt A (1:d,1:d)}, where rows {\tt d+1} to {\tt n} of {\tt L}
496
 
and {\tt D} are all zero.  If a sparsity preserving permutation {\tt P} is
497
 
passed, {\tt [L, D, Parent, fl] = ldl (A,P)} operates on {\tt A(P,P)} without
498
 
forming it explicitly.
499
 
 
500
 
The statement {\tt x = ldl (A, [ ], b)} is roughly equivalent to
501
 
{\tt x = A}$\backslash${\tt b}, when {\tt A} is sparse, real, and symmetric.
502
 
The $\m{LDL}\tr$ factorization of {\tt A} is performed.  If {\tt P} is
503
 
provided, {\tt x = ldl (A, P, b)} still performs
504
 
{\tt x = A}$\backslash${\tt b}, except that {\tt A(P,P)} is factorized
505
 
instead.
506
 
 
507
 
%-------------------------------------------------------------------------------
508
 
\section{Using LDL in a C program}
509
 
\label{C}
510
 
%-------------------------------------------------------------------------------
511
 
 
512
 
The C-callable {\tt LDL} library consists of nine user-callable routines
513
 
and one include file.
514
 
 
515
 
\begin{itemize}
516
 
\item {\tt ldl\_symbolic}:  given the nonzero pattern of a sparse symmetric
517
 
    matrix $\m{A}$ and an optional permutation $\m{P}$, analyzes either
518
 
    $\m{A}$ or $\m{PAP}\tr$, and returns the elimination tree, the
519
 
    number of nonzeros in each column of $\m{L}$, and the {\tt Lp} array
520
 
    for the sparse matrix data structure for $\m{L}$.
521
 
    Duplicate entries are allowed in the columns of $\m{A}$, and the
522
 
    row indices in each column need not be sorted.
523
 
    Providing a sparsity-preserving ordering is critical for obtaining
524
 
    good performance.  A minimum degree ordering
525
 
    (such as AMD \cite{AmestoyDavisDuff96,AmestoyDavisDuff03})
526
 
    or a graph-partitioning based ordering are appropriate.
527
 
\item {\tt ldl\_numeric}:  given {\tt Lp} and the elimination tree computed
528
 
    by {\tt ldl\_symbolic}, and an optional permutation $\m{P}$,
529
 
    returns the numerical factorization of $\m{A}$ or $\m{PAP}\tr$.
530
 
    Duplicate entries are allowed in the columns of $\m{A}$
531
 
    (any duplicate entries are summed), and the
532
 
    row indices in each column need not be sorted.
533
 
    The data structure for $\m{L}$ is the same as $\m{A}$, except that
534
 
    no duplicates appear, and each column has sorted row indices.
535
 
\item {\tt ldl\_lsolve}:  given the factor $\m{L}$ computed by
536
 
    {\tt ldl\_numeric}, solves the linear system $\m{Lx}=\m{b}$, where
537
 
    $\m{x}$ and $\m{b}$ are full $n$-by-1 vectors.
538
 
\item {\tt ldl\_dsolve}:  given the factor $\m{D}$ computed by
539
 
    {\tt ldl\_numeric}, solves the linear system $\m{Dx}=\m{b}$.
540
 
\item {\tt ldl\_ltsolve}:  given the factor $\m{L}$ computed by
541
 
    {\tt ldl\_numeric}, solves the linear system $\m{L}\tr\m{x}=\m{b}$.
542
 
\item {\tt ldl\_perm}: given a vector $\m{b}$ and a permutation $\m{P}$,
543
 
    returns $\m{x}=\m{Pb}$.
544
 
\item {\tt ldl\_permt}: given a vector $\m{b}$ and a permutation $\m{P}$,
545
 
    returns $\m{x}=\m{P}\tr\m{b}$.
546
 
\item {\tt ldl\_valid\_perm}:  Except for checking if the diagonal of
547
 
    $\m{D}$ is zero, none of the above routines check their inputs for errors.
548
 
    This routine checks the validity of a permutation $\m{P}$.
549
 
\item {\tt ldl\_valid\_matrix}:  checks if a matrix $\m{A}$ is valid as input
550
 
    to {\tt ldl\_symbolic} and {\tt ldl\_numeric}.
551
 
\end{itemize}
552
 
 
553
 
Note that the primary input to the {\tt ldl\_symbolic} and
554
 
{\tt ldl\_numeric} is the sparse matrix $\m{A}$.  It is provided in
555
 
column-oriented form, and only the upper triangular part is accessed.
556
 
This is slightly different than the primary output: the matrix $\m{L}$, 
557
 
which is lower triangular in column-oriented form.
558
 
If you wish to factorize a symmetric matrix $\m{A}$ for which only the lower
559
 
triangular part is supplied, you would need to transpose $\m{A}$ before
560
 
passing it {\tt ldl\_symbolic} and {\tt ldl\_numeric}.
561
 
 
562
 
\begin{figure}
563
 
\caption{Example of use}
564
 
\label{ldlsimple}
565
 
{\scriptsize
566
 
\begin{verbatim}
567
 
#include <stdio.h>
568
 
#include "ldl.h"
569
 
#define N 10    /* A is 10-by-10 */
570
 
#define ANZ 19  /* # of nonzeros on diagonal and upper triangular part of A */
571
 
#define LNZ 13  /* # of nonzeros below the diagonal of L */
572
 
 
573
 
int main (int argc, int **argv)
574
 
{
575
 
    /* only the upper triangular part of A is required */
576
 
    int    Ap [N+1] = {0, 1, 2, 3, 4,   6, 7,   9,   11,      15,     ANZ},
577
 
           Ai [ANZ] = {0, 1, 2, 3, 1,4, 5, 4,6, 4,7, 0,4,7,8, 1,4,6,9 } ;
578
 
    double Ax [ANZ] = {1.7, 1., 1.5, 1.1, .02,2.6, 1.2, .16,1.3, .09,1.6,
579
 
                     .13,.52,.11,1.4, .01,.53,.56,3.1},
580
 
           b [N] = {.287, .22, .45, .44, 2.486, .72, 1.55, 1.424, 1.621, 3.759};
581
 
    double Lx [LNZ], D [N], Y [N] ;
582
 
    int Li [LNZ], Lp [N+1], Parent [N], Lnz [N], Flag [N], Pattern [N], d, i ;
583
 
 
584
 
    /* factorize A into LDL' (P and Pinv not used) */
585
 
    ldl_symbolic (N, Ap, Ai, Lp, Parent, Lnz, Flag, NULL, NULL) ;
586
 
    printf ("Nonzeros in L, excluding diagonal: %d\n", Lp [N]) ;
587
 
    d = ldl_numeric (N, Ap, Ai, Ax, Lp, Parent, Lnz, Li, Lx, D, Y, Pattern,
588
 
        Flag, NULL, NULL) ;
589
 
 
590
 
    if (d == N)
591
 
    {
592
 
        /* solve Ax=b, overwriting b with the solution x */
593
 
        ldl_lsolve (N, b, Lp, Li, Lx) ;
594
 
        ldl_dsolve (N, b, D) ;
595
 
        ldl_ltsolve (N, b, Lp, Li, Lx) ;
596
 
        for (i = 0 ; i < N ; i++) printf ("x [%d] = %g\n", i, b [i]) ;
597
 
    }
598
 
    else
599
 
    {
600
 
        printf ("ldl_numeric failed, D (%d,%d) is zero\n", d, d) ;
601
 
    }
602
 
    return (0) ;
603
 
}
604
 
\end{verbatim}
605
 
}
606
 
\end{figure}
607
 
 
608
 
The program in Figure~\ref{ldlsimple}
609
 
illustrates the basic usage of the {\tt LDL} routines.
610
 
It analyzes and factorizes the sparse symmetric positive-definite matrix
611
 
{\small
612
 
\[
613
 
\m{A} = \left[
614
 
\begin{array}{cccccccccc}
615
 
      1.7 &   0 &   0 &   0 &   0 &   0 &   0 &   0 & .13 &   0 \\
616
 
        0 &  1. &   0 &   0 & .02 &   0 &   0 &   0 &   0 & .01 \\
617
 
        0 &   0 & 1.5 &   0 &   0 &   0 &   0 &   0 &   0 &   0 \\
618
 
        0 &   0 &   0 & 1.1 &   0 &   0 &   0 &   0 &   0 &   0 \\
619
 
        0 & .02 &   0 &   0 & 2.6 &   0 & .16 & .09 & .52 & .53 \\
620
 
        0 &   0 &   0 &   0 &   0 & 1.2 &   0 &   0 &   0 &   0 \\
621
 
        0 &   0 &   0 &   0 & .16 &   0 & 1.3 &   0 &   0 & .56 \\
622
 
        0 &   0 &   0 &   0 & .09 &   0 &   0 & 1.6 & .11 &   0 \\
623
 
      .13 &   0 &   0 &   0 & .52 &   0 &   0 & .11 & 1.4 &   0 \\
624
 
        0 & .01 &   0 &   0 & .53 &   0 & .56 &   0 &   0 & 3.1 \\
625
 
\end{array}
626
 
\right]
627
 
\]
628
 
}
629
 
and then solves a system $\m{Ax}=\m{b}$ whose true solution is
630
 
$x_i = i/10$.  Note that {\tt Li} and {\tt Lx} are statically allocated.
631
 
Normally they would be allocated after their size, {\tt Lp[n]},
632
 
is determined by {\tt ldl\_symbolic}.
633
 
More example programs are included with the {\tt LDL} package.
634
 
 
635
 
\section{Acknowledgments}
636
 
 
637
 
I would like to thank Pete Stewart for his comments on an earlier draft
638
 
of this software and its accompanying paper.
639
 
 
640
 
\newpage
641
 
\bibliographystyle{plain}
642
 
\bibliography{ldl}
643
 
 
644
 
\end{document}