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_DMATRIX_H__ 00021 #define __EG_DMATRIX_H__ 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_numutil.h" 00032 00033 /* ========================================================================= */ 00034 /** @defgroup EGdMatrix Dense Matrices 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-27 00042 * - First implementation. 00043 * */ 00044 /** @{*/ 00045 /** @file 00046 * @brief This file provide the user interface and function definitions for 00047 * Dense Matrices. 00048 * */ 00049 /** @example eg_dmatrix.ex.c */ 00050 /* ========================================================================= */ 00051 /** @brief structure to hold a dense matrix, we choose a row representation 00052 * of the matrix, and we allow row and column permutations. All actual values 00053 * in the matrix are stored in #EGdMatrix_t::matval, and the rows in 00054 * #EGdMatrix_t::matrow. */ 00055 typedef struct EGdMatrix_t 00056 { 00057 size_t col_sz; /**< @brief Number of columns in the matrix. */ 00058 size_t row_sz; /**< @brief Number of rows in the matrix */ 00059 EGlpNum_t **matrow; 00060 /**< @brief Array of size #EGdMatrix_t::row_sz containing 00061 all rows of the matrix */ 00062 EGlpNum_t *matval;/**< @brief Values for all entries */ 00063 int *col_ord; /**< @brief Array of size at least #EGdMatrix_t::col_sz 00064 containing the order ammong all columns i.e. it is a 00065 permutation of {0,....,col_sz-1} which is how the 00066 matrix is treated internally */ 00067 int *row_ord; /**< @brief Array of size at least #EGdMatrix_t::row_sz 00068 containing the order ammong all rows, i.e. it is a 00069 permutation of {0,...,row_sz-1} which is how the 00070 matrix is treated internally */ 00071 } 00072 EGdMatrix_t; 00073 00074 /* ========================================================================= */ 00075 /** @brief Initialize (as a dense matrix of dimension 0x0) an #EGdMatrix_t 00076 * structure. 00077 * @param dmatrix dense matrix structure pointer. 00078 * */ 00079 #define EGdMatrixInit(dmatrix) memset(dmatrix,0,sizeof(EGdMatrix_t)) 00080 00081 /* ========================================================================= */ 00082 /** @brief Clear a dense matrix structure, i.e. free all internally allocated 00083 * data of the structure. Note that no further use of the structure can be made 00084 * unless it is re-initialized and set to a suitable size. 00085 * @param dmatrix dense matrix structure pointer. 00086 * */ 00087 #define EGdMatrixClear(dmatrix) do{\ 00088 EGdMatrix_t*const __EGdm = (dmatrix);\ 00089 EGlpNumFreeArray(__EGdm->matval);\ 00090 EGfree(__EGdm->matrow);\ 00091 int_EGlpNumFreeArray(__EGdm->col_ord);\ 00092 int_EGlpNumFreeArray(__EGdm->row_ord);} while(0) 00093 00094 /* ========================================================================= */ 00095 /** @brief Set new dimensions for a dense matrix structure. 00096 * @param dmatrix dense matrix structure pointer. 00097 * @param new_nrows number of rows in the matrix. 00098 * @param new_ncols number of columns in the matrix. 00099 * @note Take care that the values stored in the matrix are not initialized to 00100 * any particular number. Also the ordering (for both column and row) is reset 00101 * to the standard ordering 0,....,n. 00102 * */ 00103 #define EGdMatrixSetDimension(dmatrix,new_nrows,new_ncols) do{\ 00104 EGdMatrix_t*const __EGdm = (dmatrix);\ 00105 register unsigned __EGdmi;\ 00106 __EGdm->col_sz = (new_ncols);\ 00107 __EGdm->row_sz = (new_nrows);\ 00108 EGlpNumReallocArray(&(__EGdm->matval),__EGdm->col_sz * __EGdm->row_sz);\ 00109 EGrealloc(__EGdm->matrow,__EGdm->row_sz * sizeof(EGlpNum_t*));\ 00110 int_EGlpNumReallocArray(&(__EGdm->col_ord),__EGdm->col_sz);\ 00111 int_EGlpNumReallocArray(&(__EGdm->row_ord),__EGdm->row_sz);\ 00112 __EGdmi = __EGdm->col_sz;\ 00113 while(__EGdmi--) __EGdm->col_ord[__EGdmi] = __EGdmi;\ 00114 __EGdmi = __EGdm->row_sz;\ 00115 while(__EGdmi--) \ 00116 __EGdm->matrow[__EGdmi] = __EGdm->matval + (__EGdmi * __EGdm->col_sz);\ 00117 __EGdmi = __EGdm->row_sz;\ 00118 while(__EGdmi--) __EGdm->row_ord[__EGdmi] = __EGdmi;} while(0) 00119 00120 /* ========================================================================= */ 00121 /** @brief Display a given #EGdMatrix_t structure contents. 00122 * @param dmatrix dense matrix structure pointer. 00123 * @param nat_order if set to one, display the matrix using the natural 00124 * internal order, i.e. we discard the order of columns and rows as defined in 00125 * #EGdMatrix_t::col_ord and #EGdMatrix_t::row_ord. Otherwise, use such orders. 00126 * @param out_file pointer to a FILE structure where we want the output to be 00127 * printed. 00128 * */ 00129 #define EGdMatrixDisplay(dmatrix,nat_order,out_file) do{\ 00130 EGdMatrix_t*const __EGdm = (dmatrix);\ 00131 char* __EGdmstr = 0;\ 00132 size_t __EGdmi, __EGdmj;\ 00133 fprintf(out_file,"Matrix %p\nDimensions: %zd rows, %zd columns\n", (void*)__EGdm, __EGdm->row_sz, __EGdm->col_sz);\ 00134 if(nat_order){\ 00135 for(__EGdmi = 0 ; __EGdmi < __EGdm->row_sz ; __EGdmi++){\ 00136 for(__EGdmj = 0 ; __EGdmj < __EGdm->col_sz ; __EGdmj++){\ 00137 __EGdmstr = EGlpNumGetStr(__EGdm->matrow[__EGdmi][__EGdmj]);\ 00138 fprintf(out_file,"%10s ", __EGdmstr);\ 00139 EGfree(__EGdmstr);\ 00140 }\ 00141 fprintf(out_file,"\n");}\ 00142 } else {\ 00143 for(__EGdmi = 0 ; __EGdmi < __EGdm->row_sz ; __EGdmi++){\ 00144 for(__EGdmj = 0 ; __EGdmj < __EGdm->col_sz ; __EGdmj++){\ 00145 __EGdmstr = EGlpNumGetStr(__EGdm->matrow[__EGdm->row_ord[__EGdmi]][__EGdm->col_ord[__EGdmj]]);\ 00146 fprintf(out_file,"%10s ", __EGdmstr);\ 00147 EGfree(__EGdmstr);\ 00148 }\ 00149 fprintf(out_file,"\n");}\ 00150 }} while(0) 00151 00152 /* ========================================================================= */ 00153 /** @brief Given a number 'num' and a two rows 'ori', 'dest', set rows 00154 * 'dest' to 'dest' + 'ori' * 'num'. Note that the number MUST_NOT be stored 00155 * in row 'dest', and note that rows 'ori' and 'dest' should be different. 00156 * This is needed because of the way GNU_MP interface works. 00157 * @param dmatrix dense matrix structure pointer. 00158 * @param 'ori' index of the row whose multiple will be added to the 'dest' 00159 * row. 00160 * @param 'dest' row to be replaced by 'dest' + 'ori' * 'num'. 00161 * @param 'num' constant to be multiply to the 'ori' and be added to the 00162 * 'dest' row. 00163 * @note The index of the row are taken as internal index, i.e. if we give row 00164 * 'k' we will use the row stored in #EGdMatrix_t::matrow[k], wich does not 00165 * mean that we will access the k-th row in the matrix (wich would need to use 00166 * as index the value #EGdMatrix_t::row_ord[k] instead). Note that we don't 00167 * test wether the given multiple is zero or not. we always perform the 00168 * operation. 00169 * */ 00170 #define EGdMatrixAddRowMultiple(dmatrix,dest,ori,num) do{\ 00171 EGdMatrix_t*const __EGdm = (dmatrix);\ 00172 const size_t __EGdest = (dest);\ 00173 const size_t __EGori = (ori);\ 00174 size_t __EGdmj = __EGdm->col_sz;\ 00175 while(__EGdmj--) \ 00176 EGlpNumAddInnProdTo(__EGdm->matrow[__EGdest][__EGdmj],\ 00177 __EGdm->matrow[__EGori][__EGdmj],num);\ 00178 } while(0) 00179 00180 /* ========================================================================= */ 00181 /** @brief Given a number 'num' and a two rows 'ori', 'dest', set rows 00182 * 'dest' to 'dest' - 'ori' * 'num'. Note that the number MUST_NOT be stored 00183 * in row 'dest', and note that rows 'ori' and 'dest' should be different. 00184 * This is needed because of the way GNU_MP interface works. 00185 * @param dmatrix dense matrix structure pointer. 00186 * @param 'ori' index of the row whose multiple will be added to the 'dest' 00187 * row. 00188 * @param 'dest' row to be replaced by 'dest' - 'ori' * 'num'. 00189 * @param 'num' constant to be multiply to the 'ori' and be added to the 00190 * 'dest' row. 00191 * @note The index of the row are taken as internal index, i.e. if we give row 00192 * 'k' we will use the row stored in #EGdMatrix_t::matrow[k], wich does not 00193 * mean that we will access the k-th row in the matrix (wich would need to use 00194 * as index the value #EGdMatrix_t::row_ord[k] instead). Note that we don't 00195 * test wether the given multiple is zero or not. we always perform the 00196 * operation. 00197 * */ 00198 #define EGdMatrixSubRowMultiple(dmatrix,dest,ori,num) do{\ 00199 EGdMatrix_t*const __EGdm = (dmatrix);\ 00200 const size_t __EGdest = (dest);\ 00201 const size_t __EGori = (ori);\ 00202 size_t __EGdmj = __EGdm->col_sz;\ 00203 while(__EGdmj--) \ 00204 EGlpNumSubInnProdTo(__EGdm->matrow[__EGdest][__EGdmj],\ 00205 __EGdm->matrow[__EGori][__EGdmj],num);\ 00206 } while(0) 00207 /* ========================================================================= */ 00208 /** @brief Given a number and a row, multiply the complete row by the given 00209 * number. Note that the number MUST_NOT be stored in the row being multiplied, 00210 * this is because of the way GNU_MP interface works. 00211 * @param dmatrix dense matrix structure pointer. 00212 * @param row_ind index of the row being multiplied, note that we will multiply 00213 * the row stored in #EGdMatrix_t::matrow[row_ind], wich is different to say 00214 * that we multiply the row in the row_ind-th position in the row ordering (to 00215 * do that, then row_ind should be #EGdMatrix_t::row_ord[k]). 00216 * @param multiple constant to be multiply to the row. 00217 * */ 00218 #define EGdMatrixMultiplyRow(dmatrix,row_ind,multiple) do{\ 00219 EGdMatrix_t*const __EGdm = (dmatrix);\ 00220 const size_t __EGdmi = (row_ind);\ 00221 size_t __EGdmj = __EGdm->col_sz;\ 00222 while(__EGdmj--) EGlpNumMultTo(__EGdm->matrow[__EGdmi][__EGdmj],multiple);\ 00223 } while(0) 00224 00225 /* ========================================================================= */ 00226 /** @brief Given a number 'num' and a two rows 'ori', 'dest', set columns 00227 * 'dest' to 'dest' + 'ori' * 'num'. Note that the number MUST_NOT be stored 00228 * in column 'dest', and note that columns 'ori' and 'dest' should be 00229 * different. This is needed because of the way GNU_MP interface works. 00230 * @param dmatrix dense matrix structure pointer. 00231 * @param 'ori' index of the column whose multiple will be added to the 'dest' 00232 * column. 00233 * @param 'dest' column to be replaced by 'dest' + 'ori' * 'num'. 00234 * @param 'num' constant to be multiply to the 'ori' and be added to the 00235 * 'dest' column. 00236 * @note The index of the column are taken as internal index, i.e. if we give 00237 * column 'k' we will use the column stored in #EGdMatrix_t::matrow[*][k], 00238 * wich does not mean that we will access the k-th column in the matrix (wich 00239 * would need to use as index the value #EGdMatrix_t::row_ord[k] instead). 00240 * Note that we don't test wether the given multiple is zero or not. we 00241 * always perform the operation. 00242 * */ 00243 #define EGdMatrixAddColMultiple(dmatrix,dest,ori,num) do{\ 00244 EGdMatrix_t*const __EGdm = (dmatrix);\ 00245 const size_t __EGdest = (dest);\ 00246 const size_t __EGori = (ori);\ 00247 size_t __EGdmj = __EGdm->row_sz;\ 00248 while(__EGdmj--) \ 00249 EGlpNumAddInnProdTo(__EGdm->matrow[__EGdmj][__EGdest],\ 00250 __EGdm->matrow[__EGdmj][__EGori],num);\ 00251 } while(0) 00252 00253 /* ========================================================================= */ 00254 /** @brief Given a number 'num' and a two rows 'ori', 'dest', set columns 00255 * 'dest' to 'dest' - 'ori' * 'num'. Note that the number MUST_NOT be stored 00256 * in column 'dest', and note that columns 'ori' and 'dest' should be 00257 * different. This is needed because of the way GNU_MP interface works. 00258 * @param dmatrix dense matrix structure pointer. 00259 * @param 'ori' index of the column whose multiple will be added to the 'dest' 00260 * column. 00261 * @param 'dest' column to be replaced by 'dest' - 'ori' * 'num'. 00262 * @param 'num' constant to be multiply to the 'ori' and be added to the 00263 * 'dest' column. 00264 * @note The index of the column are taken as internal index, i.e. if we give 00265 * column 'k' we will use the column stored in #EGdMatrix_t::matrow[*][k], 00266 * wich does not mean that we will access the k-th column in the matrix (wich 00267 * would need to use as index the value #EGdMatrix_t::col_ord[k] instead). 00268 * Note that we don't test wether the given multiple is zero or not. we 00269 * always perform the operation. 00270 * */ 00271 #define EGdMatrixSubColMultiple(dmatrix,dest,ori,num) do{\ 00272 EGdMatrix_t*const __EGdm = (dmatrix);\ 00273 const size_t __EGdest = (dest);\ 00274 const size_t __EGori = (ori);\ 00275 size_t __EGdmj = __EGdm->row_sz;\ 00276 while(__EGdmj--) \ 00277 EGlpNumSubInnProdTo(__EGdm->matrow[__EGdmj][__EGdest],\ 00278 __EGdm->matrow[__EGdmj][__EGori],num);\ 00279 } while(0) 00280 /* ========================================================================= */ 00281 /** @brief Given a number and a column, multiply the complete column by the 00282 * given number. Note that the number MUST_NOT be stored in the column being 00283 * multiplied, this is because of the way GNU_MP interface works. 00284 * @param dmatrix dense matrix structure pointer. 00285 * @param col_ind index of the column being multiplied, note that we will 00286 * multiply the column stored in #EGdMatrix_t::matrow[*][col_ind], wich is 00287 * different to say that we multiply the column in the col_ind-th position in 00288 * the column ordering (to do that, then col_ind should be 00289 * #EGdMatrix_t::col_ord[k]). 00290 * @param multiple constant to be multiply to the column. 00291 * */ 00292 #define EGdMatrixMultiplyCol(dmatrix,col_ind,multiple) do{\ 00293 EGdMatrix_t*const __EGdm = (dmatrix);\ 00294 const size_t __EGdmi = (col_ind);\ 00295 size_t __EGdmj = __EGdm->row_sz;\ 00296 while(__EGdmj--) EGlpNumMultTo(__EGdm->matrow[__EGdmj][__EGdmi],multiple);\ 00297 } while(0) 00298 00299 00300 /* ========================================================================= */ 00301 /** @brief This function performs gaussian elimination to the given matrix, 00302 * depending on the given options it may do row/columns permutations allong the 00303 * way to improve numerical stabillity. 00304 * @param dmatrix dense matrix structure pointer. 00305 * @param do_col_perm if set to one, the try columns permutation to improve 00306 * numericall stabillity, otherwise, not do column permutations at all. 00307 * @param do_row_perm if set to one, try row permutations to improve numericall 00308 * stabillity, otherwise, not do row permutations at all. 00309 * @param status pointer to where return an status, if the procedure finish all 00310 * the way (i.e. the matrix is full rank), then we return #EG_ALGSTAT_SUCCESS, 00311 * if the matrix is found to be partial rank, the status is 00312 * #EG_ALGSTAT_PARTIAL, otherwise, we return #EG_ALGSTAT_NUMERROR, wich means 00313 * that we stoped because a zero pivot was found (after checking for allowed 00314 * row/collumns permmutations). 00315 * @param rank where to return the (proven) rank of the matrix. This number is 00316 * accurate if the status is #EG_ALGSTAT_SUCCESS, or #EG_ALGSTAT_PARTIAL, but 00317 * is just a lower bound if the status is #EG_ALGSTAT_NUMERROR 00318 * @param zero_tol What is the threshold for a value to be considered zero. 00319 * @return if no error happen, we return zero, otherwise a non-zero valued is 00320 * returned. Note that the algorithm status is independent of the return value, 00321 * non zero values araise only if an error happen during execution, wich is 00322 * different to say that the algorithm didn't finish correctly. */ 00323 int EGdMatrixGaussianElimination (EGdMatrix_t * const dmatrix, 00324 const unsigned do_col_perm, 00325 const unsigned do_row_perm, 00326 unsigned *const rank, 00327 EGlpNum_t zero_tol, 00328 int *const status); 00329 00330 /* ========================================================================= */ 00331 /** @}*/ 00332 #endif
1.4.5