eg_dmatrix.h

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 #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

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