eg_dbasis_red.c

Go to the documentation of this file.
00001 /* EGlib "Efficient General Library" provides some basic structures and
00002  * algorithms commons in many optimization algorithms.
00003  *
00004  * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation; either version 2.1 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but 
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00013  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00014  * License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00019  * */
00020 #include "eg_dbasis_red.h"
00021 /** @file
00022  * @ingroup EGdBasisRed */
00023 /** @addtogroup EGdBasisRed */
00024 /** @{ */
00025 /* ========================================================================= */
00026 uintmax_t EGdBsRedStats[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00027 
00028 /* ========================================================================= */
00029 /** @brief, build (from scratch) the GM matrix */
00030 static void EGdBsRedBuildGM (EGdMatrix_t * const GM,
00031                              const unsigned full_dim,
00032                              const unsigned length,
00033                              EGlpNum_t ** const basis,
00034                              EGlpNum_t orilen,
00035                              EGlpNum_t tmpval)
00036 {
00037   register unsigned i,
00038     j;
00039   /* compute all norms and store them in the first row and in the diagonal. */
00040   EGlpNumOne (orilen);
00041   for (i = full_dim; i--;)
00042   {
00043     EGlpNumInnProd (tmpval, basis[i], basis[i], length);
00044     EGlpNumCopy (GM->matrow[0][i], tmpval);
00045     EGlpNumCopy (GM->matrow[i][i], tmpval);
00046     EGlpNumMultTo (orilen, tmpval);
00047   }
00048   /* sort the vectors in increasing order according to norm, we do this because
00049    * one of the conditions for the algorithm to stop is that the norms are in
00050    * increasing order. */
00051   EGutilPermSort (full_dim, GM->col_ord, GM->matrow[0]);
00052   memcpy (GM->row_ord, GM->col_ord, sizeof (int) * full_dim);
00053   /* fill-up the GM matrix with the inner products of the vectors */
00054   for (i = full_dim; i--;)
00055   {
00056     for (j = i + 1; j < full_dim; j++)
00057     {
00058       EGlpNumInnProd (tmpval, basis[i], basis[j], length);
00059       EGlpNumCopy (GM->matrow[i][j], tmpval);
00060       EGlpNumCopy (GM->matrow[j][i], tmpval);
00061     }
00062   }
00063 }
00064 
00065 /* ========================================================================= */
00066 int EGdBsRed (EGdBsRed_t * const bsred,
00067               unsigned *const ext_dim,
00068               EGlpNum_t zero_tol,
00069               int *const ext_status)
00070 {
00071   EGdMatrix_t *const GM = &(bsred->GM);
00072   const unsigned full_dim = bsred->dim;
00073   const unsigned length = bsred->length;
00074   EGlpNum_t **const basis = bsred->basis;
00075   int rval = 0;
00076   EGlpNum_t tmpval,
00077     tmpval2,
00078     orilen,
00079     endlen;
00080   unsigned dim = 1;
00081   unsigned rank = 0;
00082   int status = EG_ALGSTAT_SUCCESS;
00083   int ge_status = 0;
00084   int tmpint;
00085   register unsigned i,
00086     j,
00087     k;
00088   MESSAGE (EG_DBSRED_VERBOSE, "Entering with dimension %u length %u", full_dim,
00089            length);
00090   EGdBsRedStats[EG_BSRED_CALLS]++;
00091   EGlpNumInitVar (tmpval);
00092   EGlpNumInitVar (tmpval2);
00093   EGlpNumInitVar (orilen);
00094   EGlpNumInitVar (endlen);
00095   TESTG ((rval = (full_dim > length)), CLEANUP, "the length of the vectors "
00096          "(%u) is smaller than the number of vectors (%u) being considered!",
00097          length, full_dim);
00098   /* check that we do have at least two vectors in the basis, otherwise we are
00099    * done. */
00100   if (full_dim < 2)
00101   {
00102     dim = full_dim;
00103     goto CLEANUP;
00104   }
00105   /* otherwise we have a non-trivial problem in our hands and we have to re-set
00106    * everithing */
00107   EGdMatrixSetDimension (GM, full_dim, full_dim);
00108   EGlpNumOne (orilen);
00109   /* compute GM and sort the matrix according to the norms of the basis vectors
00110    * */
00111   EGdBsRedBuildGM (GM, full_dim, length, basis, orilen, tmpval);
00112 #if EG_DBSRED_VERBOSE +100<= DEBUG
00113   fprintf (stderr, "Order ");
00114   for (i = 0; i < full_dim; i++)
00115     fprintf (stderr, "%d ", GM->row_ord[i]);
00116   fprintf (stderr, "\nGM ");
00117   EGdMatrixDisplay (GM, 0, stderr);
00118 #endif
00119   /* main loop */
00120   while (dim < full_dim)
00121   {
00122     EGdBsRedStats[EG_BSRED_ITT]++;
00123     /* do gaussian elimination to compute the Gram-Smith multipliers */
00124     rval = EGdMatrixGaussianElimination (GM, 0, 0, &rank, zero_tol, &ge_status);
00125     CHECKRVALG (rval, CLEANUP);
00126 #if EG_DBSRED_VERBOSE+100 <= DEBUG
00127     fprintf (stderr, "Order ");
00128     for (i = 0; i < full_dim; i++)
00129       fprintf (stderr, "%d ", GM->row_ord[i]);
00130     fprintf (stderr, "\nafter Gausian Elimination GM ");
00131     EGdMatrixDisplay (GM, 0, stderr);
00132 #endif
00133     /* if the gaussian elimination procedure does not fully finish, then we
00134      * stop right now with status EG_ALGSTAT_PARTIAL or EG_ALGSTAT_NUMERROR */
00135     if (ge_status != EG_ALGSTAT_SUCCESS)
00136     {
00137       status = ge_status;
00138       break;
00139     }
00140     /* now we first try to find a \mu_ij > 1/2, if we do find such an element,
00141      * we must do the reduction step of the algorithm */
00142     j = dim;
00143     for (; j < full_dim; j++)
00144     {
00145       for (i = j; i--;)
00146       {
00147         EGlpNumCopy (tmpval, GM->matrow[GM->col_ord[i]][GM->col_ord[j]]);
00148         EGlpNumDivTo (tmpval, GM->matrow[GM->col_ord[i]][GM->col_ord[i]]);
00149         EGlpNumCopyAbs (tmpval2, tmpval);
00150         /* do the reduction step if needed */
00151         if (EGlpNumIsGreaDbl (tmpval2, 0x1p-1))
00152         {
00153           EGdBsRedStats[EG_BSRED_SZRED]++;
00154           /* bset tmpval2 = round(tmpval) */
00155           EGlpNumFloor (tmpval2, tmpval);
00156           EGlpNumSubTo (tmpval, tmpval2);
00157           if (EGlpNumIsGreaDbl (tmpval, 0x1p-1))
00158             EGlpNumAddTo (tmpval2, oneLpNum);
00159           MESSAGE (EG_DBSRED_VERBOSE + 100, "Doing reduction for mu(%u,%u)=%lf,"
00160                    " multiple %lf", j, i, EGlpNumToLf (tmpval),
00161                    EGlpNumToLf (tmpval2));
00162           /* now we replace b_j by b_j - tmpval2 b_i */
00163           EGdMatrixSubColMultiple (GM, GM->col_ord[j], GM->col_ord[i], tmpval2);
00164           for (k = length; k--;)
00165             EGlpNumSubInnProdTo (basis[GM->col_ord[j]][k],
00166                                  basis[GM->col_ord[i]][k], tmpval2);
00167         }                       /* done with the reduction */
00168       }                         /* end checking column j of GM */
00169     }
00170 #if EG_DBSRED_VERBOSE+100 <= DEBUG
00171     fprintf (stderr, "Order ");
00172     for (i = 0; i < full_dim; i++)
00173       fprintf (stderr, "%d ", GM->row_ord[i]);
00174     fprintf (stderr, "\nafter Step I GM ");
00175     EGdMatrixDisplay (GM, 0, stderr);
00176 #endif
00177     /* now we are done with step I of the algorithm, now we check step 2, wich
00178      * check for condition 
00179      * | b^*_j + \mu_{j,j-1} b^*_{j-1}|^2 \geq \alpha |b^*_{j-1}|^2, where
00180      * \alpha must be in (1/4,1). */
00181     for (i = 1; i < full_dim; i++)
00182     {
00183       EGlpNumCopy (tmpval, GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i]]);
00184       EGlpNumMultTo (tmpval, tmpval);
00185       EGlpNumDivTo (tmpval, GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i - 1]]);
00186       EGlpNumAddTo (tmpval, GM->matrow[GM->col_ord[i]][GM->col_ord[i]]);
00187       EGlpNumDivTo (tmpval, GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i - 1]]);
00188       /* check that we have to interchange b_j and b_{j-1}, we use lambda equal
00189        * to 1048575/1048576 = (2^20-1)/2^20 */
00190       if (EGlpNumIsLessDbl (tmpval, EG_DBSRED_ALPHA))
00191       {
00192         EGdBsRedStats[EG_BSRED_INTR]++;
00193         MESSAGE (EG_DBSRED_VERBOSE + 100, "Doing swap between columns %u,%u",
00194                  i - 1, i);
00195         EGlpNumCopy (tmpval2, GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i]]);
00196         EGlpNumCopy (tmpval, tmpval2);
00197         EGlpNumMultTo (tmpval, tmpval);
00198         EGlpNumDivTo (tmpval2,
00199                       GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i - 1]]);
00200         EGlpNumDivTo (tmpval,
00201                       GM->matrow[GM->col_ord[i - 1]][GM->col_ord[i - 1]]);
00202         EGlpNumAddTo (tmpval, GM->matrow[GM->col_ord[i]][GM->col_ord[i]]);
00203         EGdMatrixAddRowMultiple (GM, GM->col_ord[i], GM->col_ord[i - 1],
00204                                  tmpval2);
00205         EGlpNumCopy (GM->matrow[GM->col_ord[i]][GM->col_ord[i]], tmpval);
00206         EGswap (GM->col_ord[i], GM->col_ord[i - 1], tmpint);
00207         EGswap (GM->row_ord[i], GM->row_ord[i - 1], tmpint);
00208         break;
00209       }                         /* done doing the interchange of rows */
00210     }
00211     dim = i;
00212 #if EG_DBSRED_VERBOSE+100 <= DEBUG
00213     fprintf (stderr, "Order ");
00214     for (i = 0; i < full_dim; i++)
00215       fprintf (stderr, "%d ", GM->row_ord[i]);
00216     fprintf (stderr, "\nafter Step II GM ");
00217     EGdMatrixDisplay (GM, 0, stderr);
00218 #endif
00219     MESSAGE (EG_DBSRED_VERBOSE + 100, "Current Dimension %u", dim);
00220   }
00221   /* compute final length */
00222   EGlpNumOne (endlen);
00223   for (i = full_dim; i--;)
00224     EGlpNumMultTo (endlen, GM->matrow[i][i]);
00225   /* ending */
00226 CLEANUP:
00227   *ext_dim = dim;
00228   *ext_status = status;
00229   MESSAGE (EG_DBSRED_VERBOSE, "Ending with dimmension %u, status %d\nOriginal "
00230            "Basis Length %lg, Final Length %lg, gain %lg", dim, status,
00231            EGlpNumToLf (orilen), EGlpNumToLf (endlen),
00232            EGlpNumToLf (orilen) / EGlpNumToLf (endlen));
00233   EGlpNumClearVar (endlen);
00234   EGlpNumClearVar (orilen);
00235   EGlpNumClearVar (tmpval2);
00236   EGlpNumClearVar (tmpval);
00237   return rval;
00238 }
00239 
00240 /* ========================================================================= */
00241 /** @} */

Generated on Mon Jan 30 08:48:52 2006 for EGlib by  doxygen 1.4.5