dmperm.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2012 David Bateman
00004 Copyright (C) 1998-2005 Andy Adler
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include "defun-dld.h"
00029 #include "error.h"
00030 #include "gripes.h"
00031 #include "oct-obj.h"
00032 #include "utils.h"
00033 
00034 #include "oct-sparse.h"
00035 #include "ov-re-sparse.h"
00036 #include "ov-cx-sparse.h"
00037 #include "SparseQR.h"
00038 #include "SparseCmplxQR.h"
00039 
00040 #ifdef IDX_TYPE_LONG
00041 #define CXSPARSE_NAME(name) cs_dl ## name
00042 #else
00043 #define CXSPARSE_NAME(name) cs_di ## name
00044 #endif
00045 
00046 static RowVector
00047 put_int (octave_idx_type *p, octave_idx_type n)
00048 {
00049   RowVector ret (n);
00050   for (octave_idx_type i = 0; i < n; i++)
00051     ret.xelem(i) = p[i] + 1;
00052   return ret;
00053 }
00054 
00055 #if HAVE_CXSPARSE
00056 static octave_value_list
00057 dmperm_internal (bool rank, const octave_value arg, int nargout)
00058 {
00059   octave_value_list retval;
00060   octave_idx_type nr = arg.rows ();
00061   octave_idx_type nc = arg.columns ();
00062   SparseMatrix m;
00063   SparseComplexMatrix cm;
00064   CXSPARSE_NAME () csm;
00065   csm.m = nr;
00066   csm.n = nc;
00067   csm.x = 0;
00068   csm.nz = -1;
00069 
00070   if (arg.is_real_type ())
00071     {
00072       m = arg.sparse_matrix_value ();
00073       csm.nzmax = m.nnz();
00074       csm.p = m.xcidx ();
00075       csm.i = m.xridx ();
00076     }
00077   else
00078     {
00079       cm = arg.sparse_complex_matrix_value ();
00080       csm.nzmax = cm.nnz();
00081       csm.p = cm.xcidx ();
00082       csm.i = cm.xridx ();
00083     }
00084 
00085   if (!error_state)
00086     {
00087       if (nargout <= 1 || rank)
00088         {
00089 #if defined(CS_VER) && (CS_VER >= 2)
00090           octave_idx_type *jmatch = CXSPARSE_NAME (_maxtrans) (&csm, 0);
00091 #else
00092           octave_idx_type *jmatch = CXSPARSE_NAME (_maxtrans) (&csm);
00093 #endif
00094           if (rank)
00095             {
00096               octave_idx_type r = 0;
00097               for (octave_idx_type i = 0; i < nc; i++)
00098                 if (jmatch[nr+i] >= 0)
00099                   r++;
00100               retval(0) = static_cast<double>(r);
00101             }
00102           else
00103             retval(0) = put_int (jmatch + nr, nc);
00104           CXSPARSE_NAME (_free) (jmatch);
00105         }
00106       else
00107         {
00108 #if defined(CS_VER) && (CS_VER >= 2)
00109           CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm, 0);
00110 #else
00111           CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm);
00112 #endif
00113 
00114           //retval(5) = put_int (dm->rr, 5);
00115           //retval(4) = put_int (dm->cc, 5);
00116 #if defined(CS_VER) && (CS_VER >= 2)
00117           retval(3) = put_int (dm->s, dm->nb+1);
00118           retval(2) = put_int (dm->r, dm->nb+1);
00119           retval(1) = put_int (dm->q, nc);
00120           retval(0) = put_int (dm->p, nr);
00121 #else
00122           retval(3) = put_int (dm->S, dm->nb+1);
00123           retval(2) = put_int (dm->R, dm->nb+1);
00124           retval(1) = put_int (dm->Q, nc);
00125           retval(0) = put_int (dm->P, nr);
00126 #endif
00127           CXSPARSE_NAME (_dfree) (dm);
00128         }
00129     }
00130   return retval;
00131 }
00132 #endif
00133 
00134 DEFUN_DLD (dmperm, args, nargout,
00135   "-*- texinfo -*-\n\
00136 @deftypefn  {Loadable Function} {@var{p} =} dmperm (@var{S})\n\
00137 @deftypefnx {Loadable Function} {[@var{p}, @var{q}, @var{r}, @var{S}] =} dmperm (@var{S})\n\
00138 \n\
00139 @cindex Dulmage-Mendelsohn decomposition\n\
00140 Perform a Dulmage-Mendelsohn permutation of the sparse matrix @var{S}.\n\
00141 With a single output argument @code{dmperm} performs the row permutations\n\
00142 @var{p} such that @code{@var{S}(@var{p},:)} has no zero elements on the\n\
00143 diagonal.\n\
00144 \n\
00145 Called with two or more output arguments, returns the row and column\n\
00146 permutations, such that @code{@var{S}(@var{p}, @var{q})} is in block\n\
00147 triangular form.  The values of @var{r} and @var{S} define the boundaries\n\
00148 of the blocks.  If @var{S} is square then @code{@var{r} == @var{S}}.\n\
00149 \n\
00150 The method used is described in: A. Pothen & C.-J. Fan. @cite{Computing the\n\
00151 Block Triangular Form of a Sparse Matrix}. ACM Trans. Math. Software,\n\
00152 16(4):303-324, 1990.\n\
00153 @seealso{colamd, ccolamd}\n\
00154 @end deftypefn")
00155 {
00156   int nargin = args.length();
00157   octave_value_list retval;
00158 
00159   if (nargin != 1)
00160     {
00161       print_usage ();
00162       return retval;
00163     }
00164 
00165 #if HAVE_CXSPARSE
00166   retval = dmperm_internal (false, args(0), nargout);
00167 #else
00168   error ("dmperm: not available in this version of Octave");
00169 #endif
00170 
00171   return retval;
00172 }
00173 
00174 /*
00175 
00176 %!testif HAVE_CXSPARSE
00177 %! n=20;
00178 %! a=speye(n,n);a=a(randperm(n),:);
00179 %! assert(a(dmperm(a),:),speye(n))
00180 
00181 %!testif HAVE_CXSPARSE
00182 %! n=20;
00183 %! d=0.2;
00184 %! a=tril(sprandn(n,n,d),-1)+speye(n,n);
00185 %! a=a(randperm(n),randperm(n));
00186 %! [p,q,r,s]=dmperm(a);
00187 %! assert(tril(a(p,q),-1),sparse(n,n))
00188 
00189 */
00190 
00191 DEFUN_DLD (sprank, args, nargout,
00192   "-*- texinfo -*-\n\
00193 @deftypefn {Loadable Function} {@var{p} =} sprank (@var{S})\n\
00194 @cindex structural rank\n\
00195 \n\
00196 Calculate the structural rank of the sparse matrix @var{S}.  Note that\n\
00197 only the structure of the matrix is used in this calculation based on\n\
00198 a Dulmage-Mendelsohn permutation to block triangular form.  As such the\n\
00199 numerical rank of the matrix @var{S} is bounded by\n\
00200 @code{sprank (@var{S}) >= rank (@var{S})}.  Ignoring floating point errors\n\
00201 @code{sprank (@var{S}) == rank (@var{S})}.\n\
00202 @seealso{dmperm}\n\
00203 @end deftypefn")
00204 {
00205   int nargin = args.length();
00206   octave_value_list retval;
00207 
00208   if (nargin != 1)
00209     {
00210       print_usage ();
00211       return retval;
00212     }
00213 
00214 #if HAVE_CXSPARSE
00215   retval = dmperm_internal (true, args(0), nargout);
00216 #else
00217   error ("sprank: not available in this version of Octave");
00218 #endif
00219 
00220   return retval;
00221 }
00222 
00223 /*
00224 
00225 %!error(sprank(1,2));
00226 %!testif HAVE_CXSPARSE
00227 %! assert(sprank(speye(20)), 20)
00228 %!testif HAVE_CXSPARSE
00229 %! assert(sprank([1,0,2,0;2,0,4,0]),2)
00230 
00231 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines