1 /* ========================================================================= */ 2 /* === AMD: approximate minimum degree ordering =========================== */ 3 /* ========================================================================= */ 4 5 /* ------------------------------------------------------------------------- */ 6 /* AMD Version 2.4, Copyright (c) 1996-2013 by Timothy A. Davis, */ 7 /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 /* email: DrTimothyAldenDavis@gmail.com */ 9 /* ------------------------------------------------------------------------- */ 10 11 /* AMD finds a symmetric ordering P of a matrix A so that the Cholesky 12 * factorization of P*A*P' has fewer nonzeros and takes less work than the 13 * Cholesky factorization of A. If A is not symmetric, then it performs its 14 * ordering on the matrix A+A'. Two sets of user-callable routines are 15 * provided, one for int integers and the other for SuiteSparse_long integers. 16 * 17 * The method is based on the approximate minimum degree algorithm, discussed 18 * in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm", 19 * SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp. 20 * 886-905, 1996. This package can perform both the AMD ordering (with 21 * aggressive absorption), and the AMDBAR ordering (without aggressive 22 * absorption) discussed in the above paper. This package differs from the 23 * Fortran codes discussed in the paper: 24 * 25 * (1) it can ignore "dense" rows and columns, leading to faster run times 26 * (2) it computes the ordering of A+A' if A is not symmetric 27 * (3) it is followed by a depth-first post-ordering of the assembly tree 28 * (or supernodal elimination tree) 29 * 30 * For historical reasons, the Fortran versions, amd.f and amdbar.f, have 31 * been left (nearly) unchanged. They compute the identical ordering as 32 * described in the above paper. 33 */ 34 35 module amd; 36 37 nothrow @nogc extern(C): 38 39 import glob_opts; 40 41 import SuiteSparse_config; 42 43 /* get the definition of size_t: */ 44 import core.stdc.stddef; 45 46 enum c_int AMD_CONTROL = 5; /* size of Control array */ 47 enum c_int AMD_INFO = 20; /* size of Info array */ 48 49 /* contents of Control */ 50 enum c_int AMD_DENSE = 0; /* "dense" if degree > Control [0] * sqrt (n) */ 51 enum c_int AMD_AGGRESSIVE = 1; /* do aggressive absorption if Control [1] != 0 */ 52 53 /* default Control settings */ 54 enum c_float AMD_DEFAULT_DENSE = 10.0 ; /* default "dense" degree 10*sqrt(n) */ 55 enum c_int AMD_DEFAULT_AGGRESSIVE = 1; /* do aggressive absorption by default */ 56 57 /* contents of Info */ 58 enum c_int AMD_STATUS = 0; /* return value of amd_order and amd_l_order */ 59 enum c_int AMD_N = 1; /* A is n-by-n */ 60 enum c_int AMD_NZ = 2; /* number of nonzeros in A */ 61 enum c_int AMD_SYMMETRY = 3; /* symmetry of pattern (1 is sym., 0 is unsym.) */ 62 enum c_int AMD_NZDIAG = 4; /* # of entries on diagonal */ 63 enum c_int AMD_NZ_A_PLUS_AT = 5; /* nz in A+A' */ 64 enum c_int AMD_NDENSE = 6; /* number of "dense" rows/columns in A */ 65 enum c_int AMD_MEMORY = 7; /* amount of memory used by AMD */ 66 enum c_int AMD_NCMPA = 8; /* number of garbage collections in AMD */ 67 enum c_int AMD_LNZ = 9; /* approx. nz in L, excluding the diagonal */ 68 enum c_int AMD_NDIV = 10; /* number of fl. point divides for LU and LDL' */ 69 enum c_int AMD_NMULTSUBS_LDL = 11; /* number of fl. point (*,-) pairs for LDL' */ 70 enum c_int AMD_NMULTSUBS_LU = 12; /* number of fl. point (*,-) pairs for LU */ 71 enum c_int AMD_DMAX = 13; /* max nz. in any column of L, incl. diagonal */ 72 73 /* ------------------------------------------------------------------------- */ 74 /* return values of AMD */ 75 /* ------------------------------------------------------------------------- */ 76 77 enum c_int AMD_OK = 0; /* success */ 78 enum c_int AMD_OUT_OF_MEMORY = -1; /* malloc failed, or problem too large */ 79 enum c_int AMD_INVALID = -2; /* input arguments are not valid */ 80 enum c_int AMD_OK_BUT_JUMBLED = 1; /* input matrix is OK for amd_order, but 81 * columns were not sorted, and/or duplicate entries were present. AMD had 82 * to do extra work before ordering the matrix. This is a warning, not an 83 * error. */ 84 85 /* ========================================================================== */ 86 /* === AMD version ========================================================== */ 87 /* ========================================================================== */ 88 89 /* AMD Version 1.2 and later include the following definitions. 90 * As an example, to test if the version you are using is 1.2 or later: 91 * 92 * #ifdef AMD_VERSION 93 * if (AMD_VERSION >= AMD_VERSION_CODE (1,2)) ... 94 * #endif 95 * 96 * This also works during compile-time: 97 * 98 * #if defined(AMD_VERSION) && (AMD_VERSION >= AMD_VERSION_CODE (1,2)) 99 * printf ("This is version 1.2 or later\n") ; 100 * #else 101 * printf ("This is an early version\n") ; 102 * #endif 103 * 104 * Versions 1.1 and earlier of AMD do not include a #define'd version number. 105 */ 106 107 enum string AMD_DATE = "May 4, 2016"; 108 //#define AMD_VERSION_CODE(main,sub) ((main) * 1000 + (sub)) 109 c_int AMD_VERSION_CODE(c_int main, c_int sub) { return (main) * 1000 + (sub); } 110 enum c_int AMD_MAIN_VERSION = 2; 111 enum c_int AMD_SUB_VERSION = 4; 112 enum c_int AMD_SUBSUB_VERSION = 6; 113 //#define AMD_VERSION AMD_VERSION_CODE(AMD_MAIN_VERSION,AMD_SUB_VERSION) 114 enum c_int AMD_VERSION = AMD_VERSION_CODE(AMD_MAIN_VERSION,AMD_SUB_VERSION); // todo : check it 115 116 117 118 /* Input arguments (not modified): 119 * 120 * n: the matrix A is n-by-n. 121 * Ap: an int/SuiteSparse_long array of size n+1, containing column 122 * pointers of A. 123 * Ai: an int/SuiteSparse_long array of size nz, containing the row 124 * indices of A, where nz = Ap [n]. 125 * Control: a c_float array of size AMD_CONTROL, containing control 126 * parameters. Defaults are used if Control is NULL. 127 * 128 * Output arguments (not defined on input): 129 * 130 * P: an int/SuiteSparse_long array of size n, containing the output 131 * permutation. If row i is the kth pivot row, then P [k] = i. In 132 * MATLAB notation, the reordered matrix is A (P,P). 133 * Info: a c_float array of size AMD_INFO, containing statistical 134 * information. Ignored if Info is NULL. 135 * 136 * On input, the matrix A is stored in column-oriented form. The row indices 137 * of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1]. 138 * 139 * If the row indices appear in ascending order in each column, and there 140 * are no duplicate entries, then amd_order is slightly more efficient in 141 * terms of time and memory usage. If this condition does not hold, a copy 142 * of the matrix is created (where these conditions do hold), and the copy is 143 * ordered. This feature is new to v2.0 (v1.2 and earlier required this 144 * condition to hold for the input matrix). 145 * 146 * Row indices must be in the range 0 to 147 * n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros 148 * in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n]. 149 * The matrix does not need to be symmetric, and the diagonal does not need to 150 * be present (if diagonal entries are present, they are ignored except for 151 * the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not 152 * modified. This form of the Ap and Ai arrays to represent the nonzero 153 * pattern of the matrix A is the same as that used internally by MATLAB. 154 * If you wish to use a more flexible input structure, please see the 155 * umfpack_*_triplet_to_col routines in the UMFPACK package, at 156 * http://www.suitesparse.com. 157 * 158 * Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the 159 * range 0 to n-1. nz = Ap [n] >= 0. Ai [0..nz-1] must be in the range 0 160 * to n-1. Finally, Ai, Ap, and P must not be NULL. If any of these 161 * restrictions are not met, AMD returns AMD_INVALID. 162 * 163 * AMD returns: 164 * 165 * AMD_OK if the matrix is valid and sufficient memory can be allocated to 166 * perform the ordering. 167 * 168 * AMD_OUT_OF_MEMORY if not enough memory can be allocated. 169 * 170 * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is 171 * NULL. 172 * 173 * AMD_OK_BUT_JUMBLED if the matrix had unsorted columns, and/or duplicate 174 * entries, but was otherwise valid. 175 * 176 * The AMD routine first forms the pattern of the matrix A+A', and then 177 * computes a fill-reducing ordering, P. If P [k] = i, then row/column i of 178 * the original is the kth pivotal row. In MATLAB notation, the permuted 179 * matrix is A (P,P), except that 0-based indexing is used instead of the 180 * 1-based indexing in MATLAB. 181 * 182 * The Control array is used to set various parameters for AMD. If a NULL 183 * pointer is passed, default values are used. The Control array is not 184 * modified. 185 * 186 * Control [AMD_DENSE]: controls the threshold for "dense" rows/columns. 187 * A dense row/column in A+A' can cause AMD to spend a lot of time in 188 * ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns 189 * with more than Control [AMD_DENSE] * sqrt (n) entries are ignored 190 * during the ordering, and placed last in the output order. The 191 * default value of Control [AMD_DENSE] is 10. If negative, no 192 * rows/columns are treated as "dense". Rows/columns with 16 or 193 * fewer off-diagonal entries are never considered "dense". 194 * 195 * Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive 196 * absorption, in which a prior element is absorbed into the current 197 * element if is a subset of the current element, even if it is not 198 * adjacent to the current pivot element (refer to Amestoy, Davis, 199 * & Duff, 1996, for more details). The default value is nonzero, 200 * which means to perform aggressive absorption. This nearly always 201 * leads to a better ordering (because the approximate degrees are 202 * more accurate) and a lower execution time. There are cases where 203 * it can lead to a slightly worse ordering, however. To turn it off, 204 * set Control [AMD_AGGRESSIVE] to 0. 205 * 206 * Control [2..4] are not used in the current version, but may be used in 207 * future versions. 208 * 209 * The Info array provides statistics about the ordering on output. If it is 210 * not present, the statistics are not returned. This is not an error 211 * condition. 212 * 213 * Info [AMD_STATUS]: the return value of AMD, either AMD_OK, 214 * AMD_OK_BUT_JUMBLED, AMD_OUT_OF_MEMORY, or AMD_INVALID. 215 * 216 * Info [AMD_N]: n, the size of the input matrix 217 * 218 * Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n] 219 * 220 * Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number 221 * of "matched" off-diagonal entries divided by the total number of 222 * off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also 223 * an entry, for any pair (i,j) for which i != j. In MATLAB notation, 224 * S = spones (A) ; 225 * B = tril (S, -1) + triu (S, 1) ; 226 * symmetry = nnz (B & B') / nnz (B) ; 227 * 228 * Info [AMD_NZDIAG]: the number of entries on the diagonal of A. 229 * 230 * Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the 231 * diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1) 232 * with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n 233 * (the smallest possible value). If A is perfectly unsymmetric 234 * (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for 235 * example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz 236 * (the largest possible value). 237 * 238 * Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were 239 * removed from A prior to ordering. These are placed last in the 240 * output order P. 241 * 242 * Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the 243 * current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n 244 * times the size of an integer. This is at most 2.4nz + 9n. This 245 * excludes the size of the input arguments Ai, Ap, and P, which have 246 * a total size of nz + 2*n + 1 integers. 247 * 248 * Info [AMD_NCMPA]: the number of garbage collections performed. 249 * 250 * Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal). 251 * This is a slight upper bound because mass elimination is combined 252 * with the approximate degree update. It is a rough upper bound if 253 * there are many "dense" rows/columns. The rest of the statistics, 254 * below, are also slight or rough upper bounds, for the same reasons. 255 * The post-ordering of the assembly tree might also not exactly 256 * correspond to a true elimination tree postordering. 257 * 258 * Info [AMD_NDIV]: the number of divide operations for a subsequent LDL' 259 * or LU factorization of the permuted matrix A (P,P). 260 * 261 * Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a 262 * subsequent LDL' factorization of A (P,P). 263 * 264 * Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a 265 * subsequent LU factorization of A (P,P), assuming that no numerical 266 * pivoting is required. 267 * 268 * Info [AMD_DMAX]: the maximum number of nonzeros in any column of L, 269 * including the diagonal. 270 * 271 * Info [14..19] are not used in the current version, but may be used in 272 * future versions. 273 */ 274 275 /* ------------------------------------------------------------------------- */ 276 /* direct interface to AMD */ 277 /* ------------------------------------------------------------------------- */ 278 279 version (DLONG){ 280 SuiteSparse_long AMD_order 281 ( 282 SuiteSparse_long n, 283 const SuiteSparse_long * Ap, 284 const SuiteSparse_long * Ai, 285 SuiteSparse_long * P, 286 c_float * Control, 287 c_float * Info 288 ); 289 } 290 else { 291 int AMD_order /* returns AMD_OK, AMD_OK_BUT_JUMBLED, 292 * AMD_INVALID, or AMD_OUT_OF_MEMORY */ 293 ( 294 int n, /* A is n-by-n. n must be >= 0. */ 295 const int * Ap, /* column pointers for A, of size n+1 */ 296 const int * Ai, /* row indices of A, of size nz = Ap [n] */ 297 int * P, /* output permutation, of size n */ 298 c_float * Control, /* input Control settings, of size AMD_CONTROL */ 299 c_float * Info /* output Info statistics, of size AMD_INFO */ 300 ); 301 } 302 303 /* ------------------------------------------------------------------------- */ 304 /* AMD Control and Info arrays */ 305 /* ------------------------------------------------------------------------- */ 306 307 /* amd_defaults: sets the default control settings */ 308 void amd_defaults (c_float * Control) ; 309 void amd_l_defaults (c_float * Control) ; 310 311 /* amd_control: prints the control settings */ 312 void amd_control (c_float * Control) ; 313 void amd_l_control (c_float * Control) ; 314 315 /* amd_info: prints the statistics */ 316 void amd_info (c_float * Info) ; 317 void amd_l_info (c_float * Info) ;