00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "SparseCmplxCHOL.h"
00029 #include "SparsedbleCHOL.h"
00030 #include "oct-spparms.h"
00031 #include "sparse-util.h"
00032 #include "oct-locbuf.h"
00033
00034 #include "ov-re-sparse.h"
00035 #include "ov-cx-sparse.h"
00036 #include "defun-dld.h"
00037 #include "error.h"
00038 #include "gripes.h"
00039 #include "oct-obj.h"
00040 #include "utils.h"
00041
00042 DEFUN_DLD (symbfact, args, nargout,
00043 "-*- texinfo -*-\n\
00044 @deftypefn {Loadable Function} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{r}] =} symbfact (@var{S})\n\
00045 @deftypefnx {Loadable Function} {[@dots{}] =} symbfact (@var{S}, @var{typ})\n\
00046 @deftypefnx {Loadable Function} {[@dots{}] =} symbfact (@var{S}, @var{typ}, @var{mode})\n\
00047 \n\
00048 Perform a symbolic factorization analysis on the sparse matrix @var{S}.\n\
00049 Where\n\
00050 \n\
00051 @table @var\n\
00052 @item S\n\
00053 @var{S} is a complex or real sparse matrix.\n\
00054 \n\
00055 @item typ\n\
00056 Is the type of the factorization and can be one of\n\
00057 \n\
00058 @table @samp\n\
00059 @item sym\n\
00060 Factorize @var{S}. This is the default.\n\
00061 \n\
00062 @item col\n\
00063 Factorize @code{@var{S}' * @var{S}}.\n\
00064 \n\
00065 @item row\n\
00066 Factorize @xcode{@var{S} * @var{S}'}.\n\
00067 \n\
00068 @item lo\n\
00069 Factorize @xcode{@var{S}'}\n\
00070 @end table\n\
00071 \n\
00072 @item mode\n\
00073 The default is to return the Cholesky@tie{}factorization for @var{r}, and if\n\
00074 @var{mode} is 'L', the conjugate transpose of the Cholesky@tie{}factorization\n\
00075 is returned. The conjugate transpose version is faster and uses less\n\
00076 memory, but returns the same values for @var{count}, @var{h}, @var{parent}\n\
00077 and @var{post} outputs.\n\
00078 @end table\n\
00079 \n\
00080 The output variables are\n\
00081 \n\
00082 @table @var\n\
00083 @item count\n\
00084 The row counts of the Cholesky@tie{}factorization as determined by @var{typ}.\n\
00085 \n\
00086 @item h\n\
00087 The height of the elimination tree.\n\
00088 \n\
00089 @item parent\n\
00090 The elimination tree itself.\n\
00091 \n\
00092 @item post\n\
00093 A sparse boolean matrix whose structure is that of the Cholesky\n\
00094 factorization as determined by @var{typ}.\n\
00095 @end table\n\
00096 @end deftypefn")
00097 {
00098 octave_value_list retval;
00099 int nargin = args.length ();
00100
00101 if (nargin < 1 || nargin > 3 || nargout > 5)
00102 {
00103 print_usage ();
00104 return retval;
00105 }
00106
00107 #ifdef HAVE_CHOLMOD
00108
00109 cholmod_common Common;
00110 cholmod_common *cm = &Common;
00111 CHOLMOD_NAME(start) (cm);
00112
00113 double spu = octave_sparse_params::get_key ("spumoni");
00114 if (spu == 0.)
00115 {
00116 cm->print = -1;
00117 cm->print_function = 0;
00118 }
00119 else
00120 {
00121 cm->print = static_cast<int> (spu) + 2;
00122 cm->print_function =&SparseCholPrint;
00123 }
00124
00125 cm->error_handler = &SparseCholError;
00126 cm->complex_divide = CHOLMOD_NAME(divcomplex);
00127 cm->hypotenuse = CHOLMOD_NAME(hypot);
00128
00129 double dummy;
00130 cholmod_sparse Astore;
00131 cholmod_sparse *A = &Astore;
00132 A->packed = true;
00133 A->sorted = true;
00134 A->nz = 0;
00135 #ifdef IDX_TYPE_LONG
00136 A->itype = CHOLMOD_LONG;
00137 #else
00138 A->itype = CHOLMOD_INT;
00139 #endif
00140 A->dtype = CHOLMOD_DOUBLE;
00141 A->stype = 1;
00142 A->x = &dummy;
00143
00144 if (args(0).is_real_type ())
00145 {
00146 const SparseMatrix a = args(0).sparse_matrix_value();
00147 A->nrow = a.rows();
00148 A->ncol = a.cols();
00149 A->p = a.cidx();
00150 A->i = a.ridx();
00151 A->nzmax = a.nnz();
00152 A->xtype = CHOLMOD_REAL;
00153
00154 if (a.rows() > 0 && a.cols() > 0)
00155 A->x = a.data();
00156 }
00157 else if (args(0).is_complex_type ())
00158 {
00159 const SparseComplexMatrix a = args(0).sparse_complex_matrix_value();
00160 A->nrow = a.rows();
00161 A->ncol = a.cols();
00162 A->p = a.cidx();
00163 A->i = a.ridx();
00164 A->nzmax = a.nnz();
00165 A->xtype = CHOLMOD_COMPLEX;
00166
00167 if (a.rows() > 0 && a.cols() > 0)
00168 A->x = a.data();
00169 }
00170 else
00171 gripe_wrong_type_arg ("symbfact", args(0));
00172
00173 octave_idx_type coletree = false;
00174 octave_idx_type n = A->nrow;
00175
00176 if (nargin > 1)
00177 {
00178 char ch;
00179 std::string str = args(1).string_value();
00180 ch = tolower (str.c_str()[0]);
00181 if (ch == 'r')
00182 A->stype = 0;
00183 else if (ch == 'c')
00184 {
00185 n = A->ncol;
00186 coletree = true;
00187 A->stype = 0;
00188 }
00189 else if (ch == 's')
00190 A->stype = 1;
00191 else if (ch == 's')
00192 A->stype = -1;
00193 else
00194 error ("symbfact: unrecognized TYP in symbolic factorization");
00195 }
00196
00197 if (A->stype && A->nrow != A->ncol)
00198 error ("symbfact: S must be a square matrix");
00199
00200 if (!error_state)
00201 {
00202 OCTAVE_LOCAL_BUFFER (octave_idx_type, Parent, n);
00203 OCTAVE_LOCAL_BUFFER (octave_idx_type, Post, n);
00204 OCTAVE_LOCAL_BUFFER (octave_idx_type, ColCount, n);
00205 OCTAVE_LOCAL_BUFFER (octave_idx_type, First, n);
00206 OCTAVE_LOCAL_BUFFER (octave_idx_type, Level, n);
00207
00208 cholmod_sparse *F = CHOLMOD_NAME(transpose) (A, 0, cm);
00209 cholmod_sparse *Aup, *Alo;
00210
00211 if (A->stype == 1 || coletree)
00212 {
00213 Aup = A ;
00214 Alo = F ;
00215 }
00216 else
00217 {
00218 Aup = F ;
00219 Alo = A ;
00220 }
00221
00222 CHOLMOD_NAME(etree) (Aup, Parent, cm);
00223
00224 if (cm->status < CHOLMOD_OK)
00225 {
00226 error("matrix corrupted");
00227 goto symbfact_error;
00228 }
00229
00230 if (CHOLMOD_NAME(postorder) (Parent, n, 0, Post, cm) != n)
00231 {
00232 error("postorder failed");
00233 goto symbfact_error;
00234 }
00235
00236 CHOLMOD_NAME(rowcolcounts) (Alo, 0, 0, Parent, Post, 0,
00237 ColCount, First, Level, cm);
00238
00239 if (cm->status < CHOLMOD_OK)
00240 {
00241 error("matrix corrupted");
00242 goto symbfact_error;
00243 }
00244
00245 if (nargout > 4)
00246 {
00247 cholmod_sparse *A1, *A2;
00248
00249 if (A->stype == 1)
00250 {
00251 A1 = A;
00252 A2 = 0;
00253 }
00254 else if (A->stype == -1)
00255 {
00256 A1 = F;
00257 A2 = 0;
00258 }
00259 else if (coletree)
00260 {
00261 A1 = F;
00262 A2 = A;
00263 }
00264 else
00265 {
00266 A1 = A;
00267 A2 = F;
00268 }
00269
00270
00271 octave_idx_type lnz = 0 ;
00272 for (octave_idx_type j = 0 ; j < n ; j++)
00273 lnz += ColCount [j] ;
00274
00275
00276
00277 SparseBoolMatrix L (n, n, lnz);
00278
00279
00280 lnz = 0;
00281 for (octave_idx_type j = 0 ; j < n ; j++)
00282 {
00283 L.xcidx(j) = lnz;
00284 lnz += ColCount [j];
00285 }
00286 L.xcidx(n) = lnz;
00287
00288
00289
00290 octave_idx_type *W = First;
00291 for (octave_idx_type j = 0 ; j < n ; j++)
00292 W [j] = L.xcidx(j);
00293
00294
00295 cholmod_sparse *R = cholmod_allocate_sparse (n, 1, n, false, true,
00296 0, CHOLMOD_PATTERN, cm);
00297 octave_idx_type *Rp = static_cast<octave_idx_type *>(R->p);
00298 octave_idx_type *Ri = static_cast<octave_idx_type *>(R->i);
00299
00300
00301 for (octave_idx_type k = 0 ; k < n ; k++)
00302 {
00303
00304 CHOLMOD_NAME (row_subtree) (A1, A2, k, Parent, R, cm) ;
00305 for (octave_idx_type p = 0 ; p < Rp [1] ; p++)
00306 L.xridx (W [Ri [p]]++) = k ;
00307
00308
00309 L.xridx (W [k]++) = k ;
00310 }
00311
00312
00313 cholmod_free_sparse (&R, cm) ;
00314
00315
00316
00317 if (nargin < 3)
00318 L = L.transpose ();
00319
00320
00321 for (octave_idx_type p = 0 ; p < lnz ; p++)
00322 L.xdata(p) = true;
00323
00324 retval(4) = L;
00325 }
00326
00327 ColumnVector tmp (n);
00328 if (nargout > 3)
00329 {
00330 for (octave_idx_type i = 0; i < n; i++)
00331 tmp(i) = Post[i] + 1;
00332 retval(3) = tmp;
00333 }
00334
00335 if (nargout > 2)
00336 {
00337 for (octave_idx_type i = 0; i < n; i++)
00338 tmp(i) = Parent[i] + 1;
00339 retval(2) = tmp;
00340 }
00341
00342 if (nargout > 1)
00343 {
00344
00345 octave_idx_type height = 0 ;
00346 for (int i = 0 ; i < n ; i++)
00347 height = (height > Level[i] ? height : Level[i]);
00348 height++ ;
00349 retval(1) = static_cast<double> (height);
00350 }
00351
00352 for (octave_idx_type i = 0; i < n; i++)
00353 tmp(i) = ColCount[i];
00354 retval(0) = tmp;
00355 }
00356
00357 symbfact_error:
00358 #else
00359 error ("symbfact: not available in this version of Octave");
00360 #endif
00361
00362 return retval;
00363 }