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 #ifndef __EG_DBASIS_REDUCTION__ 00021 #define __EG_DBASIS_REDUCTION__ 00022 #include <stdlib.h> 00023 #include <stdio.h> 00024 #include <string.h> 00025 #include <limits.h> 00026 #include <math.h> 00027 #include <float.h> 00028 #include "eg_macros.h" 00029 #include "eg_mem.h" 00030 #include "eg_lpnum.h" 00031 #include "eg_dmatrix.h" 00032 #include "eg_numutil.h" 00033 /* ========================================================================= */ 00034 /** @defgroup EGdBasisRed LLL Basis Reduction 00035 * Here we define a common interface for dense matrices (i.e. a structure), and 00036 * some common operations over dense matrices. The definition uses EGlpNum as 00037 * reference number type, this allow for template initializations. 00038 * 00039 * @par History: 00040 * Revision 0.0.2 00041 * - 2005-10-28 00042 * - First implementation. 00043 * */ 00044 /** @{*/ 00045 /** @file 00046 * @brief This file provide the user interface and function definitions for 00047 * the so-called LLL Basis Reduction Algorithm. This algorithm was first 00048 * presented in the paper "Factoring polynomials with rational coefficients", 00049 * Mathematische Annalen 261 (1981), p515-534. and has been extensivelly 00050 * studied elsewere. for more details just Google-it. 00051 * */ 00052 /** @example eg_dmatrix.ex.c */ 00053 /* ========================================================================= */ 00054 /** @brief verbosity level */ 00055 #define EG_DBSRED_VERBOSE 0 00056 00057 /* ========================================================================= */ 00058 /** @name Profiling structures and functions for the basis reduction algorithm. 00059 * */ 00060 /*@{*/ 00061 /* ========================================================================= */ 00062 /** @brief where to hold the profile information */ 00063 extern uintmax_t EGdBsRedStats[10]; 00064 00065 /* ========================================================================= */ 00066 /** @brief where we store the number of calls to #EGdBsRed */ 00067 #define EG_BSRED_CALLS 0 00068 00069 /* ========================================================================= */ 00070 /** @brief where we store the total number of size reductions performed in 00071 * #EGdBsRed */ 00072 #define EG_BSRED_SZRED 1 00073 00074 /* ========================================================================= */ 00075 /** @brief where we store the total number of interchanges performed in 00076 * #EGdBsRed */ 00077 #define EG_BSRED_INTR 2 00078 00079 /* ========================================================================= */ 00080 /** @brief where we store the total number of innermost loops performed in 00081 * #EGdBsRed */ 00082 #define EG_BSRED_ITT 3 00083 00084 /* ========================================================================= */ 00085 /** @brief Print into the given file stream, the current statistics related 00086 * to the #EGdBsRed algorithm. And reset all counters to zero. 00087 * @param ofile where we want to print the profile information. */ 00088 #define EGdBsRedProfile(ofile) do{\ 00089 fprintf(ofile,"LLL Basis Reduction Statistics:\n");\ 00090 fprintf(ofile,"\tNumber Calls : %ju\n", EGdBsRedStats[EG_BSRED_CALLS]);\ 00091 fprintf(ofile,"\tLoops : %ju\n", EGdBsRedStats[EG_BSRED_ITT]);\ 00092 fprintf(ofile,"\tSize Reductions : %ju\n", EGdBsRedStats[EG_BSRED_SZRED]);\ 00093 fprintf(ofile,"\tInterchanges : %ju\n", EGdBsRedStats[EG_BSRED_INTR]);\ 00094 memset(EGdBsRedStats,0,sizeof(EGdBsRedStats));} while(0) 00095 00096 /*@}*/ 00097 00098 /* ========================================================================= */ 00099 /** @brief Value used in condition two of the LLL algorithm, remember that this 00100 * number should be between \f$(1/4,1)\f$. By default we choose \f$\lambda = 00101 * \frac{2^{20}-1}{2^{20}} \approx .99999904632568359375 \f$. */ 00102 #define EG_DBSRED_ALPHA 0x3ffp-10 00103 00104 /* ========================================================================= */ 00105 /** @brief structure to hold all necesary data to perform the LLL's basis 00106 * reduction algorithm. */ 00107 typedef struct EGdBsRed_t 00108 { 00109 size_t dim; /**< @brief Number of elements in the basis */ 00110 size_t length; /**< @brief Length of the vectors in the basis, note that 00111 it should be that length >= dim */ 00112 size_t basis_sz; /**< @brief Actual length of the #EGdBsRed_t::basis 00113 array */ 00114 EGlpNum_t **basis;/**< @brief array of pointers to arrays containing the 00115 vector basis in extended (including zero coef) form. 00116 The vectors themselves are considered as allocated 00117 outside. everything else is considered as internally 00118 allocated. */ 00119 EGdMatrix_t GM; /**< @brief Here we store and compute the Gram-Schmidt 00120 needed for the LLL basis reduction algorithm */ 00121 } 00122 EGdBsRed_t; 00123 00124 /* ========================================================================= */ 00125 /** @brief Initialize an #EGdBsRed_t structure, as a basis with zero elements 00126 * of dimension zero. 00127 * @param bsred pointer to an #EGdBsRed_t structure. 00128 * */ 00129 #define EGdBsRedInit(bsred) do{\ 00130 EGdBsRed_t*const __EGdbs = (bsred);\ 00131 memset(__EGdbs,0,sizeof(EGdBsRed_t));\ 00132 EGdMatrixInit(&(__EGdbs->GM));} while(0) 00133 00134 /* ========================================================================= */ 00135 /** @brief Free any internally allocated memory in a #EGdBsRed_t structure. 00136 * @param bsred pointer to an #EGdBsRed_t structure. 00137 * */ 00138 #define EGdBsRedClear(bsred) do{\ 00139 EGdBsRed_t*const __EGdbs = (bsred);\ 00140 if(__EGdbs->basis) EGfree(__EGdbs->basis);\ 00141 EGdMatrixClear(&(__EGdbs->GM));} while(0) 00142 00143 /* ========================================================================= */ 00144 /** @brief reset an #EGdBsRed_t structure as a basis without elements (note 00145 * that we do not reset the length of the vectors, just the number of vectors 00146 * in the basis). 00147 * @param bsred pointer to an #EGdBsRed_t structure. 00148 * */ 00149 #define EGdBsRedReset(bsred) ((bsred)->dim = 0) 00150 00151 /* ========================================================================= */ 00152 /** @brief set the length of the vectors used in the basis for an #EGdBsRed_t 00153 * structure. 00154 * @param bsred pointer to an #EGdBsRed_t structure. 00155 * @param new_length length of the vectors in the basis. 00156 * */ 00157 #define EGdBsRedSetLength(bsred,new_length) ((bsred)->length = (new_length)) 00158 00159 /* ========================================================================= */ 00160 /** @brief add a new vector to the basis. 00161 * @param bsred pointer to an #EGdBsRed_t structure. 00162 * @param new_elem new vector to add to the basis. 00163 * */ 00164 #define EGdBsRedAddElement(bsred,new_elem) do{\ 00165 EGdBsRed_t*const __EGdbs = (bsred);\ 00166 if(__EGdbs->basis_sz <= __EGdbs->dim){\ 00167 __EGdbs->basis_sz += 10U;\ 00168 EGrealloc(__EGdbs->basis,sizeof(EGlpNum_t*)*__EGdbs->basis_sz);}\ 00169 __EGdbs->basis[__EGdbs->dim++] = (new_elem);} while(0) 00170 00171 /* ========================================================================= */ 00172 /** @brief This function performs the so-called LLL basis reduction algorithm. 00173 * @param bsred pointer to an #EGdBsRed_t structure. 00174 * @param status where we return the status of the algorithm, if the algorithm 00175 * finish with non-zero reduced elements, the status is #EG_ALGSTAT_SUCCESS. if 00176 * the algorithm finish with some zero reduced vector, the status is 00177 * #EG_ALGSTAT_PARTIAL. if the algorithm stop because of numerical problems, 00178 * the status is #EG_ALGSTAT_NUMERROR. 00179 * @param zero_tol threshold for a number to be considered as zero. 00180 * @param dim pointer to a number where we return the dimension of the basis 00181 * that the algorithm could prove before running in any numerical problem. If 00182 * the algorithm stop with status #EG_ALGSTAT_SUCCESS, then this number should 00183 * be equal to #EGdBsRed_t::dim. The vectors that we finish reducing are stored 00184 * in #EGdMatrix_t::row_ord[0], ... , #EGdMatrix_t::row_ord[dim], in the 00185 * #EGdBsRed_t::GM matrix. 00186 * @return zero if the algorithm finish, non-zero if an unforeseen error occure 00187 * during execution. 00188 * @par Details: 00189 * The implementation that we use introduce (as an heuristic step) the sorting 00190 * of the original basis vectors in increasing order according to their norms, 00191 * this simple step reduced the total running time of the algorithm, but does 00192 * not improve the theoretical running time. A second detail is that we only 00193 * compute the Gram-Schmidth coefficients only once (at the beggining of the 00194 * program), and then, we only update the changed entries for both operations 00195 * \a size \a reduction and \a interchange. The advantage of the approach is 00196 * that we save most Gram-Schmidth computations and also all the recomputations 00197 * of the inner products of the elements currently in the basis. Again, this 00198 * are improvements form the practical point of view, but not in practice. The 00199 * dissadvantage of this approach is that we do accumulate rounding errors in 00200 * the Gram-Schmidth coefficients allong the way, but if all original vectors 00201 * coefficients where integer (and not too big), then the error should not grow 00202 * too much. Still this may happen if the input basis is ill conditioned. 00203 * */ 00204 int EGdBsRed (EGdBsRed_t * const bsred, 00205 unsigned *const dim, 00206 EGlpNum_t zero_tol, 00207 int *const status); 00208 00209 /* ========================================================================= */ 00210 /** @}*/ 00211 #endif
1.4.5