comparison liboctave/UMFPACK/AMD/Source/amd_aat.c @ 5164:57077d0ddc8e

[project @ 2005-02-25 19:55:24 by jwe]
author jwe
date Fri, 25 Feb 2005 19:55:28 +0000
parents
children
comparison
equal deleted inserted replaced
5163:9f3299378193 5164:57077d0ddc8e
1 /* ========================================================================= */
2 /* === AMD_aat ============================================================= */
3 /* ========================================================================= */
4
5 /* ------------------------------------------------------------------------- */
6 /* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */
7 /* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */
8 /* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */
9 /* web: http://www.cise.ufl.edu/research/sparse/amd */
10 /* ------------------------------------------------------------------------- */
11
12 /* AMD_aat: compute the symmetry of the pattern of A, and count the number of
13 * nonzeros each column of A+A' (excluding the diagonal). Assume the input
14 * matrix has no errors.
15 */
16
17 #include "amd_internal.h"
18
19 GLOBAL Int AMD_aat /* returns nz in A+A' */
20 (
21 Int n,
22 const Int Ap [ ],
23 const Int Ai [ ],
24 Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/
25 Int Tp [ ], /* workspace of size n */
26 double Info [ ]
27 )
28 {
29 Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz, nzaat ;
30 double sym ;
31
32 #ifndef NDEBUG
33 AMD_debug_init ("AMD AAT") ;
34 for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ;
35 ASSERT (AMD_valid (n, n, Ap, Ai)) ;
36 #endif
37
38 if (Info != (double *) NULL)
39 {
40 /* clear the Info array, if it exists */
41 for (i = 0 ; i < AMD_INFO ; i++)
42 {
43 Info [i] = EMPTY ;
44 }
45 Info [AMD_STATUS] = AMD_OK ;
46 }
47
48 for (k = 0 ; k < n ; k++)
49 {
50 Len [k] = 0 ;
51 }
52
53 nzdiag = 0 ;
54 nzboth = 0 ;
55 nz = Ap [n] ;
56
57 for (k = 0 ; k < n ; k++)
58 {
59 p1 = Ap [k] ;
60 p2 = Ap [k+1] ;
61 AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ;
62
63 /* construct A+A' */
64 for (p = p1 ; p < p2 ; )
65 {
66 /* scan the upper triangular part of A */
67 j = Ai [p] ;
68 if (j < k)
69 {
70 /* entry A (j,k) is in the strictly upper triangular part,
71 * add both A (j,k) and A (k,j) to the matrix A+A' */
72 Len [j]++ ;
73 Len [k]++ ;
74 AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j));
75 p++ ;
76 }
77 else if (j == k)
78 {
79 /* skip the diagonal */
80 p++ ;
81 nzdiag++ ;
82 break ;
83 }
84 else /* j > k */
85 {
86 /* first entry below the diagonal */
87 break ;
88 }
89 /* scan lower triangular part of A, in column j until reaching
90 * row k. Start where last scan left off. */
91 ASSERT (Tp [j] != EMPTY) ;
92 ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ;
93 pj2 = Ap [j+1] ;
94 for (pj = Tp [j] ; pj < pj2 ; )
95 {
96 i = Ai [pj] ;
97 if (i < k)
98 {
99 /* A (i,j) is only in the lower part, not in upper.
100 * add both A (i,j) and A (j,i) to the matrix A+A' */
101 Len [i]++ ;
102 Len [j]++ ;
103 AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n",
104 i,j, j,i)) ;
105 pj++ ;
106 }
107 else if (i == k)
108 {
109 /* entry A (k,j) in lower part and A (j,k) in upper */
110 pj++ ;
111 nzboth++ ;
112 break ;
113 }
114 else /* i > k */
115 {
116 /* consider this entry later, when k advances to i */
117 break ;
118 }
119 }
120 Tp [j] = pj ;
121 }
122 /* Tp [k] points to the entry just below the diagonal in column k */
123 Tp [k] = p ;
124 }
125
126 /* clean up, for remaining mismatched entries */
127 for (j = 0 ; j < n ; j++)
128 {
129 for (pj = Tp [j] ; pj < Ap [j+1] ; pj++)
130 {
131 i = Ai [pj] ;
132 /* A (i,j) is only in the lower part, not in upper.
133 * add both A (i,j) and A (j,i) to the matrix A+A' */
134 Len [i]++ ;
135 Len [j]++ ;
136 AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n",
137 i,j, j,i)) ;
138 }
139 }
140
141 /* --------------------------------------------------------------------- */
142 /* compute the symmetry of the nonzero pattern of A */
143 /* --------------------------------------------------------------------- */
144
145 /* Given a matrix A, the symmetry of A is:
146 * B = tril (spones (A), -1) + triu (spones (A), 1) ;
147 * sym = nnz (B & B') / nnz (B) ;
148 * or 1 if nnz (B) is zero.
149 */
150
151 if (nz == nzdiag)
152 {
153 sym = 1 ;
154 }
155 else
156 {
157 sym = ((double) (2 * nzboth)) / ((double) (nz - nzdiag)) ;
158 }
159
160 nzaat = 0 ;
161 for (k = 0 ; k < n ; k++)
162 {
163 nzaat += Len [k] ;
164 }
165 AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = "ID"\n",nzaat));
166 AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n",
167 nzboth, nz, nzdiag, sym)) ;
168
169 if (Info != (double *) NULL)
170 {
171 Info [AMD_STATUS] = AMD_OK ;
172 Info [AMD_N] = n ;
173 Info [AMD_NZ] = nz ;
174 Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */
175 Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */
176 Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */
177 }
178
179 return (nzaat) ;
180 }