balance.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2008-2009 Jaroslav Hajek
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 // Author: A. S. Hodel <scotte@eng.auburn.edu>
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 
00030 #include <string>
00031 
00032 #include "CmplxAEPBAL.h"
00033 #include "fCmplxAEPBAL.h"
00034 #include "dbleAEPBAL.h"
00035 #include "floatAEPBAL.h"
00036 #include "CmplxGEPBAL.h"
00037 #include "fCmplxGEPBAL.h"
00038 #include "dbleGEPBAL.h"
00039 #include "floatGEPBAL.h"
00040 #include "quit.h"
00041 
00042 #include "defun-dld.h"
00043 #include "error.h"
00044 #include "f77-fcn.h"
00045 #include "gripes.h"
00046 #include "oct-obj.h"
00047 #include "utils.h"
00048 
00049 DEFUN_DLD (balance, args, nargout,
00050   "-*- texinfo -*-\n\
00051 @deftypefn  {Loadable Function} {@var{AA} =} balance (@var{A})\n\
00052 @deftypefnx {Loadable Function} {@var{AA} =} balance (@var{A}, @var{opt})\n\
00053 @deftypefnx {Loadable Function} {[@var{DD}, @var{AA}] =} balance (@var{A}, @var{opt})\n\
00054 @deftypefnx {Loadable Function} {[@var{D}, @var{P}, @var{AA}] =} balance (@var{A}, @var{opt})\n\
00055 @deftypefnx {Loadable Function} {[@var{CC}, @var{DD}, @var{AA}, @var{BB}] =} balance (@var{A}, @var{B}, @var{opt})\n\
00056 \n\
00057 Compute @code{@var{AA} = @var{DD} \\ @var{A} * @var{DD}} in which @var{AA}\n\
00058 is a matrix whose row and column norms are roughly equal in magnitude, and\n\
00059 @code{@var{DD} = @var{P} * @var{D}}, in which @var{P} is a permutation\n\
00060 matrix and @var{D} is a diagonal matrix of powers of two.  This allows the\n\
00061 equilibration to be computed without round-off.  Results of eigenvalue\n\
00062 calculation are typically improved by balancing first.\n\
00063 \n\
00064 If two output values are requested, @code{balance} returns\n\
00065 the diagonal @var{D} and the permutation @var{P} separately as vectors.\n\
00066 In this case, @code{@var{DD} = eye(n)(:,@var{P}) * diag (@var{D})}, where\n\
00067 @math{n} is the matrix size.\n\
00068 \n\
00069 If four output values are requested, compute @code{@var{AA} =\n\
00070 @var{CC}*@var{A}*@var{DD}} and @code{@var{BB} = @var{CC}*@var{B}*@var{DD}},\n\
00071 in which @var{AA} and @var{BB} have non-zero elements of approximately the\n\
00072 same magnitude and @var{CC} and @var{DD} are permuted diagonal matrices as\n\
00073 in @var{DD} for the algebraic eigenvalue problem.\n\
00074 \n\
00075 The eigenvalue balancing option @var{opt} may be one of:\n\
00076 \n\
00077 @table @asis\n\
00078 @item \"noperm\", \"S\"\n\
00079 Scale only; do not permute.\n\
00080 \n\
00081 @item \"noscal\", \"P\"\n\
00082 Permute only; do not scale.\n\
00083 @end table\n\
00084 \n\
00085 Algebraic eigenvalue balancing uses standard @sc{lapack} routines.\n\
00086 \n\
00087 Generalized eigenvalue problem balancing uses Ward's algorithm\n\
00088 (SIAM Journal on Scientific and Statistical Computing, 1981).\n\
00089 @end deftypefn")
00090 {
00091   octave_value_list retval;
00092 
00093   int nargin = args.length ();
00094 
00095   if (nargin < 1 || nargin > 3 || nargout < 0 || nargout > 4)
00096     {
00097       print_usage ();
00098       return retval;
00099     }
00100 
00101   // determine if it's AEP or GEP
00102   bool AEPcase = nargin == 1 || args(1).is_string ();
00103 
00104   // problem dimension
00105   octave_idx_type nn = args(0).rows ();
00106 
00107   if (nn != args(0).columns())
00108     {
00109       gripe_square_matrix_required ("balance");
00110       return retval;
00111     }
00112 
00113   bool isfloat = args(0).is_single_type () ||
00114     (! AEPcase && args(1).is_single_type());
00115 
00116   bool complex_case = (args(0).is_complex_type () ||
00117                        (! AEPcase && args(1).is_complex_type ()));
00118 
00119   // Extract argument 1 parameter for both AEP and GEP.
00120   Matrix aa;
00121   ComplexMatrix caa;
00122   FloatMatrix faa;
00123   FloatComplexMatrix fcaa;
00124 
00125   if (isfloat)
00126     {
00127       if (complex_case)
00128         fcaa = args(0).float_complex_matrix_value ();
00129       else
00130         faa = args(0).float_matrix_value ();
00131     }
00132   else
00133     {
00134       if (complex_case)
00135         caa = args(0).complex_matrix_value ();
00136       else
00137         aa = args(0).matrix_value ();
00138     }
00139 
00140   if (error_state)
00141     return retval;
00142 
00143   // Treat AEP/GEP cases.
00144   if (AEPcase)
00145     {
00146       // Algebraic eigenvalue problem.
00147       bool noperm = false, noscal = false;
00148       if (nargin > 1)
00149         {
00150           std::string a1s = args(1).string_value ();
00151           noperm = a1s == "noperm" || a1s == "S";
00152           noscal = a1s == "noscal" || a1s == "P";
00153         }
00154 
00155       // balance the AEP
00156       if (isfloat)
00157         {
00158           if (complex_case)
00159             {
00160               FloatComplexAEPBALANCE result (fcaa, noperm, noscal);
00161 
00162               if (nargout == 0 || nargout == 1)
00163                 retval(0) = result.balanced_matrix ();
00164               else if (nargout == 2)
00165                 {
00166                   retval(1) = result.balanced_matrix ();
00167                   retval(0) = result.balancing_matrix ();
00168                 }
00169               else
00170                 {
00171                   retval(2) = result.balanced_matrix ();
00172                   retval(1) = result.permuting_vector ();
00173                   retval(0) = result.scaling_vector ();
00174                 }
00175 
00176             }
00177           else
00178             {
00179               FloatAEPBALANCE result (faa, noperm, noscal);
00180 
00181               if (nargout == 0 || nargout == 1)
00182                 retval(0) = result.balanced_matrix ();
00183               else if (nargout == 2)
00184                 {
00185                   retval(1) = result.balanced_matrix ();
00186                   retval(0) = result.balancing_matrix ();
00187                 }
00188               else
00189                 {
00190                   retval(2) = result.balanced_matrix ();
00191                   retval(1) = result.permuting_vector ();
00192                   retval(0) = result.scaling_vector ();
00193                 }
00194             }
00195         }
00196       else
00197         {
00198           if (complex_case)
00199             {
00200               ComplexAEPBALANCE result (caa, noperm, noscal);
00201 
00202               if (nargout == 0 || nargout == 1)
00203                 retval(0) = result.balanced_matrix ();
00204               else if (nargout == 2)
00205                 {
00206                   retval(1) = result.balanced_matrix ();
00207                   retval(0) = result.balancing_matrix ();
00208                 }
00209               else
00210                 {
00211                   retval(2) = result.balanced_matrix ();
00212                   retval(1) = result.permuting_vector ();
00213                   retval(0) = result.scaling_vector ();
00214                 }
00215             }
00216           else
00217             {
00218               AEPBALANCE result (aa, noperm, noscal);
00219 
00220               if (nargout == 0 || nargout == 1)
00221                 retval(0) = result.balanced_matrix ();
00222               else if (nargout == 2)
00223                 {
00224                   retval(1) = result.balanced_matrix ();
00225                   retval(0) = result.balancing_matrix ();
00226                 }
00227               else
00228                 {
00229                   retval(2) = result.balanced_matrix ();
00230                   retval(1) = result.permuting_vector ();
00231                   retval(0) = result.scaling_vector ();
00232                 }
00233             }
00234         }
00235     }
00236   else
00237     {
00238       std::string bal_job;
00239       if (nargout == 1)
00240         warning ("balance: used GEP, should have two output arguments");
00241 
00242       // Generalized eigenvalue problem.
00243       if (nargin == 2)
00244         bal_job = "B";
00245       else if (args(2).is_string ())
00246         bal_job = args(2).string_value ();
00247       else
00248         {
00249           error ("balance: OPT argument must be a string");
00250           return retval;
00251         }
00252 
00253       if ((nn != args(1).columns ()) || (nn != args(1).rows ()))
00254         {
00255           gripe_nonconformant ();
00256           return retval;
00257         }
00258 
00259       Matrix bb;
00260       ComplexMatrix cbb;
00261       FloatMatrix fbb;
00262       FloatComplexMatrix fcbb;
00263 
00264       if (isfloat)
00265         {
00266           if (complex_case)
00267             fcbb = args(1).float_complex_matrix_value ();
00268           else
00269             fbb = args(1).float_matrix_value ();
00270         }
00271       else
00272         {
00273           if (complex_case)
00274             cbb = args(1).complex_matrix_value ();
00275           else
00276             bb = args(1).matrix_value ();
00277         }
00278 
00279       // balance the GEP
00280       if (isfloat)
00281         {
00282           if (complex_case)
00283             {
00284               FloatComplexGEPBALANCE result (fcaa, fcbb, bal_job);
00285 
00286               switch (nargout)
00287                 {
00288                 case 4:
00289                   retval(3) = result.balanced_matrix2 ();
00290                   // fall through
00291                 case 3:
00292                   retval(2) = result.balanced_matrix ();
00293                   retval(1) = result.balancing_matrix2 ();
00294                   retval(0) = result.balancing_matrix ();
00295                   break;
00296                 case 2:
00297                   retval(1) = result.balancing_matrix2 ();
00298                   // fall through
00299                 case 1:
00300                   retval(0) = result.balancing_matrix ();
00301                   break;
00302                 default:
00303                   error ("balance: invalid number of output arguments");
00304                   break;
00305                 }
00306             }
00307           else
00308             {
00309               FloatGEPBALANCE result (faa, fbb, bal_job);
00310 
00311               switch (nargout)
00312                 {
00313                 case 4:
00314                   retval(3) = result.balanced_matrix2 ();
00315                   // fall through
00316                 case 3:
00317                   retval(2) = result.balanced_matrix ();
00318                   retval(1) = result.balancing_matrix2 ();
00319                   retval(0) = result.balancing_matrix ();
00320                   break;
00321                 case 2:
00322                   retval(1) = result.balancing_matrix2 ();
00323                   // fall through
00324                 case 1:
00325                   retval(0) = result.balancing_matrix ();
00326                   break;
00327                 default:
00328                   error ("balance: invalid number of output arguments");
00329                   break;
00330                 }
00331             }
00332         }
00333       else
00334         {
00335           if (complex_case)
00336             {
00337               ComplexGEPBALANCE result (caa, cbb, bal_job);
00338 
00339               switch (nargout)
00340                 {
00341                 case 4:
00342                   retval(3) = result.balanced_matrix2 ();
00343                   // fall through
00344                 case 3:
00345                   retval(2) = result.balanced_matrix ();
00346                   retval(1) = result.balancing_matrix2 ();
00347                   retval(0) = result.balancing_matrix ();
00348                   break;
00349                 case 2:
00350                   retval(1) = result.balancing_matrix2 ();
00351                   // fall through
00352                 case 1:
00353                   retval(0) = result.balancing_matrix ();
00354                   break;
00355                 default:
00356                   error ("balance: invalid number of output arguments");
00357                   break;
00358                 }
00359             }
00360           else
00361             {
00362               GEPBALANCE result (aa, bb, bal_job);
00363 
00364               switch (nargout)
00365                 {
00366                 case 4:
00367                   retval(3) = result.balanced_matrix2 ();
00368                   // fall through
00369                 case 3:
00370                   retval(2) = result.balanced_matrix ();
00371                   retval(1) = result.balancing_matrix2 ();
00372                   retval(0) = result.balancing_matrix ();
00373                   break;
00374                 case 2:
00375                   retval(1) = result.balancing_matrix2 ();
00376                   // fall through
00377                 case 1:
00378                   retval(0) = result.balancing_matrix ();
00379                   break;
00380                 default:
00381                   error ("balance: invalid number of output arguments");
00382                   break;
00383                 }
00384             }
00385         }
00386     }
00387 
00388   return retval;
00389 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines