sparse-matrix.c
Go to the documentation of this file.
00001 /* sparse-matrix.c
00002 
00003 *****
00004 Copyright 1994-1997, Brown University
00005 Copyright 1998, 1999, Anthony R. Cassandra
00006 
00007 All Rights Reserved
00008 
00009 Permission to use, copy, modify, and distribute this software and its
00010 documentation for any purpose other than its incorporation into a
00011 commercial product is hereby granted without fee, provided that the
00012 above copyright notice appear in all copies and that both that
00013 copyright notice and this permission notice appear in supporting
00014 documentation.
00015 
00016 ANTHONY CASSANDRA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00017 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
00018 PARTICULAR PURPOSE.  IN NO EVENT SHALL ANTHONY CASSANDRA BE LIABLE FOR
00019 ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00020 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00021 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00022 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00023 *****
00024 
00025 This module will implementall the routines that pertain to creating and
00026 manipulating a sparse representation of a matrix.
00027 
00028 */
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <assert.h>
00033 
00034 #include "sparse-matrix.h"
00035 
00036 /**********************************************************************/
00037 /********************  Routines for row linked lists  *****************/
00038 /**********************************************************************/
00039 I_Matrix_Row_Node newRowNode( int col, REAL_VALUE value ) {
00040         /*
00041         Just allocates memory and sets the fields.
00042         */
00043         I_Matrix_Row_Node new_node;
00044 
00045         new_node = (I_Matrix_Row_Node ) malloc( sizeof( *new_node ));
00046         checkAllocatedPointer(new_node);
00047 
00048         new_node->column = col;
00049         new_node->value = value;
00050         new_node->next = NULL;
00051 
00052         return( new_node );
00053 
00054 }  /* newRowNode */
00055 /**********************************************************************/
00056 void destroyRow( I_Matrix_Row_Node row ) {
00057         I_Matrix_Row_Node temp;
00058 
00059         while( row != NULL ) {
00060                 temp = row;
00061                 row = row->next;
00062                 free( temp );
00063         } /* while */
00064 }  /* destroyRow */
00065 /**********************************************************************/
00066 I_Matrix_Row_Node removeRowNode( I_Matrix_Row_Node row, 
00067                                                                 int col, int *count ) {
00068                                                                         /*
00069                                                                         Remove the node with column == col, if it exists.  It decrements
00070                                                                         the count if it is removed.  If there is no entry for this in the
00071                                                                         list then we simply igore it and return the original list.
00072                                                                         */
00073                                                                         I_Matrix_Row_Node temp_node, cur_node, trail_node;
00074 
00075                                                                         /* Case if list is empty */
00076                                                                         if( row == NULL )
00077                                                                                 return( NULL );
00078 
00079                                                                         /* Case of removing first item in the list */
00080                                                                         if( row->column == col ) {
00081                                                                                 temp_node = row;
00082                                                                                 row = row->next;
00083                                                                                 free( temp_node );
00084                                                                                 (*count)--;
00085                                                                                 return( row );
00086                                                                         }  /* if we should remove first node */
00087 
00088                                                                         trail_node = row;
00089                                                                         cur_node = row->next;
00090                                                                         while( cur_node != NULL ) {
00091 
00092                                                                                 /* Then bingo!  We found the one to remove */
00093                                                                                 if( cur_node->column == col ) {
00094                                                                                         trail_node->next = cur_node->next;
00095                                                                                         free( cur_node );
00096                                                                                         (*count)--;
00097                                                                                         return( row );
00098                                                                                 }  /* if we found the one to remove */
00099 
00100                                                                                 trail_node = cur_node;
00101                                                                                 cur_node = cur_node->next;
00102                                                                         }  /* while */
00103 
00104                                                                         /* Otherwise we did not find an entry with this column, so just */
00105                                                                         /* return the list and do nothing. */
00106                                                                         return( row );
00107 
00108 }  /* removeRowNode */
00109 /**********************************************************************/
00110 I_Matrix_Row_Node addEntryToRow( I_Matrix_Row_Node row, 
00111                                                                 int col, REAL_VALUE value,
00112                                                                 int *count, int accumulate ) {
00113                                                                         /*
00114                                                                         Will step through the linked list until either the column is found
00115                                                                         or until we see a strictly smaller column number.  It will either
00116                                                                         replace the current value (if the column already exists) or insert a
00117                                                                         new node into the list just before the first column number that is
00118                                                                         highest.  This way, the list always remains sorted by column
00119                                                                         number.  The pointer to the int 'count' will be incremented only if
00120                                                                         we add it to the list, not when we simply replace a value.  *count 
00121                                                                         should be the length of the list sent in, but this routine does not
00122                                                                         check to make sure it is.
00123 
00124                                                                         The accumulate flag will specify whether we should replace the 
00125                                                                         current value (if any) or add the value to the existing value.
00126                                                                         This can be used to build up probabilities in a matrix piecemeal.
00127                                                                         */
00128                                                                         I_Matrix_Row_Node new_node, cur_node, trail_node;
00129                                                                         trail_node = 0; // avoid warning
00130 
00131                                                                         /* Case if we attempt to add a zero entry.  We need to see if there */
00132                                                                         /* is already a non-zero entry for it in the list, and if so remove */
00133                                                                         /* it.  Otherwise we simply ignore this entry request, since we are */
00134                                                                         /* using a sparse representation. */
00135                                                                         if( IS_ZERO( value ) ) {
00136                                                                                 if ( accumulate )
00137                                                                                         return ( row );
00138                                                                                 else
00139                                                                                         return( removeRowNode( row, col, count ));
00140                                                                         }
00141 
00142                                                                         /* Case if the list is empty */
00143                                                                         if( row == NULL ) {
00144                                                                                 new_node = newRowNode( col, value );
00145                                                                                 (*count)++;
00146                                                                                 return( new_node );
00147                                                                         }  /* if row empty */
00148 
00149                                                                         /* Case if it should be inserted into front of list */
00150                                                                         if( row->column > col ) {
00151                                                                                 new_node = newRowNode( col, value );
00152                                                                                 new_node->next = row;
00153                                                                                 (*count)++;
00154                                                                                 return( new_node );
00155                                                                         }  /* if should be inserted in front of list */
00156 
00157                                                                         cur_node = row;
00158                                                                         while( cur_node != NULL ) {
00159 
00160                                                                                 /* Case if we should simply replace (or accumulate) 
00161                                                                                 the current value */
00162                                                                                 if( cur_node->column == col ) {
00163 
00164                                                                                         if( accumulate )
00165                                                                                                 cur_node->value += value;
00166                                                                                         else
00167                                                                                                 cur_node->value = value;
00168 
00169                                                                                         return( row );
00170                                                                                 } /* if we should just replace value */
00171 
00172                                                                                 /* Case if this is the point we should insert it (i.e. between */
00173                                                                                 /* trail_node and cur_node */
00174                                                                                 if( cur_node->column > col ) {
00175                                                                                         new_node = newRowNode( col, value );
00176                                                                                         trail_node->next = new_node;
00177                                                                                         new_node->next = cur_node;
00178                                                                                         (*count)++;
00179                                                                                         return( row );
00180                                                                                 }  /* if we have found place to insert it */
00181 
00182                                                                                 trail_node = cur_node;
00183                                                                                 cur_node = cur_node->next;
00184                                                                         }  /* while */
00185 
00186                                                                         /* Case if it should be inserted at the end of the list.  This */
00187                                                                         /* should be the only case where we exit the bottom of the loop, all */
00188                                                                         /* other cases should exit the routine from within the loop */
00189 
00190                                                                         new_node = newRowNode( col, value );
00191                                                                         trail_node->next = new_node;
00192                                                                         (*count)++;
00193                                                                         return( row );
00194 
00195 }  /* addEntryToRow */
00196 /**********************************************************************/
00197 void displayRow( I_Matrix_Row_Node row ) {
00198 
00199         if( row == NULL )
00200                 printf( "<empty>");
00201 
00202         while( row != NULL ) {
00203                 printf("[%d] %.3f ", row->column, row->value );
00204                 row = row->next;
00205         }  /* while */
00206 
00207         printf( "\n");
00208 }  /* displayRow */
00209 
00210 /**********************************************************************/
00211 /********************  Routines for intermediate matrix    ************/
00212 /**********************************************************************/
00213 I_Matrix newIMatrix( int num_rows ) {
00214         I_Matrix i_matrix;
00215 
00216         i_matrix = (I_Matrix) malloc( sizeof( *i_matrix));
00217         checkAllocatedPointer(i_matrix);
00218 
00219         i_matrix->num_rows = num_rows;
00220 
00221         i_matrix->row = (I_Matrix_Row_Node *)
00222                 calloc( num_rows, sizeof( *(i_matrix->row) ));
00223 
00224         i_matrix->row_length = (int *) calloc( num_rows, sizeof( int ));
00225 
00226         return( i_matrix );
00227 }  /* newIMatrix */
00228 /**********************************************************************/
00229 void destroyIMatrix( I_Matrix i_matrix ) {
00230         int i;
00231 
00232         free( i_matrix->row_length );
00233 
00234         for( i = 0; i < i_matrix->num_rows; i++ )
00235                 destroyRow( i_matrix->row[i] );
00236         free( i_matrix->row );
00237 
00238         free( i_matrix );
00239 
00240 }  /* destroyIMatrix */
00241 /**********************************************************************/
00242 int addEntryToIMatrix( I_Matrix i_matrix, int row, 
00243                                           int col, REAL_VALUE value ) {
00244 
00245                                                   assert(( i_matrix != NULL) 
00246                                                           && (row >=0) && ( row < i_matrix->num_rows ));
00247 
00248                                                   i_matrix->row[row] = addEntryToRow( i_matrix->row[row], col, value, 
00249                                                           &(i_matrix->row_length[row]), 0 );
00250 
00251                                                   return( 1 );
00252 }  /* addEntryToIMatrix */
00253 /**********************************************************************/
00254 int accumulateEntryInIMatrix( I_Matrix i_matrix, int row, 
00255                                                          int col, REAL_VALUE value ) {
00256                                                                  /*
00257                                                                  This routine is the same as addEntryToIMatrix() except it will call 
00258                                                                  the addEntryToRow() routine with the accumulate flag set.  Thus, if
00259                                                                  there is a value already at this row and column, the new value will 
00260                                                                  be the sum of the old and the new value.
00261                                                                  */
00262                                                                  assert(( i_matrix != NULL) 
00263                                                                          && (row >=0) && ( row < i_matrix->num_rows ));
00264 
00265                                                                  i_matrix->row[row] = addEntryToRow( i_matrix->row[row], col, value, 
00266                                                                          &(i_matrix->row_length[row]), 1 );
00267 
00268                                                                  return( 1 );
00269 }  /* addEntryToIMatrix */
00270 /**********************************************************************/
00271 int countEntriesInIMatrix( I_Matrix i_matrix ) {
00272         int i;
00273         int total = 0;
00274 
00275         for( i = 0; i < i_matrix->num_rows; i++ )
00276                 total += i_matrix->row_length[i];
00277 
00278         return( total );
00279 }  /* countEntriesInIMatrix */
00280 /**********************************************************************/
00281 REAL_VALUE sumIMatrixRowValues( I_Matrix i_matrix, int row ) {
00282         REAL_VALUE sum = 0.0;
00283         I_Matrix_Row_Node list;
00284 
00285         list = i_matrix->row[row];
00286 
00287         while( list != NULL ) {
00288                 sum += list->value;
00289                 list = list->next;
00290         }  /* while */
00291         return( sum );
00292 }  /* sumIMatrixRowValues */
00293 /**********************************************************************/
00294 void displayIMatrix( I_Matrix i_matrix ) {
00295         int i;
00296 
00297         for( i = 0; i < i_matrix->num_rows; i++ ) {
00298                 printf( "(len=%d, sum =%.1f)Row=%d: ", i_matrix->row_length[i], 
00299                         sumIMatrixRowValues( i_matrix, i ), i );
00300                 displayRow( i_matrix->row[i] );
00301 
00302         }  /* for i */
00303         
00304 } /* displayIMatrix */
00305 
00306 /**********************************************************************/
00307 /********************  Routines for sparse matrix    ******************/
00308 /**********************************************************************/
00309 Matrix newMatrix( int num_rows, int num_non_zero ) {
00310         Matrix matrix;
00311 
00312         matrix = (Matrix) malloc( sizeof( *matrix ));
00313         checkAllocatedPointer(matrix);
00314 
00315         matrix->num_rows = num_rows;
00316         matrix->num_non_zero = num_non_zero;
00317 
00318         matrix->mat_val = (REAL_VALUE *) 
00319                 calloc( num_non_zero, sizeof( REAL_VALUE ));
00320         matrix->col = (int *) 
00321                 calloc( num_non_zero, sizeof( int ));
00322         matrix->row_start = (int *) 
00323                 calloc( num_rows, sizeof( int ));
00324         matrix->row_length = (int *) 
00325                 calloc( num_rows, sizeof( int ));
00326 
00327         return( matrix );
00328 }  /* newMatrix */
00329 /**********************************************************************/
00330 void destroyMatrix( Matrix matrix ) {
00331 
00332         if(matrix != NULL)
00333         {
00334                 if(matrix->row_length != NULL)
00335                         free( matrix->row_length );
00336                 
00337                 if(matrix->row_start != NULL)
00338                         free( matrix->row_start );
00339                 
00340                 if(matrix->col != NULL)
00341                         free( matrix->col );
00342 
00343                 if(matrix->mat_val != NULL)
00344                         free( matrix->mat_val );
00345 
00346                 free( matrix );
00347         }
00348 }  /* destroyMatrix */
00349 /**********************************************************************/
00350 Matrix transformIMatrix( I_Matrix i_matrix ) {
00351         /*
00352         Will convert a matrix object in intermediate form into a sparse
00353         representation.  It does not free the memory of the intermediate
00354         representation.
00355         */
00356         Matrix matrix;
00357         int row;
00358         I_Matrix_Row_Node cur_node;
00359         int index = 0;  /* holds the position in the mat_val and col arrays */
00360 
00361         /* Allocate the appropriate amount of memory */
00362         matrix = newMatrix( i_matrix->num_rows, 
00363                 countEntriesInIMatrix( i_matrix ));
00364 
00365         /* Now go through and set the values */
00366         for( row = 0; row < i_matrix->num_rows; row++ ) {
00367 
00368                 matrix->row_start[row] = index;
00369                 matrix->row_length[row] = i_matrix->row_length[row];
00370 
00371                 cur_node = i_matrix->row[row];
00372                 while( cur_node != NULL ) {
00373 
00374                         matrix->col[index] = cur_node->column;
00375                         matrix->mat_val[index] = cur_node->value;
00376                         index++;
00377 
00378                         cur_node = cur_node->next;
00379                 }  /* while cur_node */
00380 
00381         }  /* for row */
00382 
00383         assert( index == matrix->num_non_zero );
00384 
00385         return( matrix );
00386 }  /* transformIMatrix */
00387 /**********************************************************************/
00388 REAL_VALUE sumRowValues( Matrix matrix, int row ) {
00389         REAL_VALUE sum = 0.0;
00390         int col;
00391 
00392         for( col = matrix->row_start[row];
00393                 col < matrix->row_start[row] + matrix->row_length[row];
00394                 col++ )
00395                 sum += matrix->mat_val[col];
00396 
00397         return( sum );
00398 }  /* sumRowValues */
00399 /**********************************************************************/
00400 void displayMatrix( Matrix matrix ) {
00401         int i, j;
00402 
00403         for( i = 0; i < matrix->num_rows; i++ ) {
00404                 printf( "(len=%d, sum=%.1f)Row=%d: ", matrix->row_length[i], 
00405                         sumRowValues( matrix, i ), i );
00406 
00407 
00408                 if( matrix->row_length[i] == 0 )
00409                         printf( "<empty>");
00410 
00411                 for( j = matrix->row_start[i];
00412                         j < matrix->row_start[i] + matrix->row_length[i];
00413                         j++ )
00414                         printf("[%d] %.3f ", matrix->col[j], matrix->mat_val[j] );
00415 
00416                 printf( "\n");
00417 
00418         }  /* for i */
00419 
00420 } /* displayMatrix */
00421 /**********************************************************************/
00422 REAL_VALUE getEntryMatrix( Matrix matrix, int row, int col ) {
00423         /*
00424         Returns the value for a particular entry in the matrix.  It looks in
00425         the row for the specified column, and if it is not found it will
00426         return zero, since after all this is a sparse representation.
00427         */
00428         int j;
00429 
00430         for( j = matrix->row_start[row];
00431                 j < matrix->row_start[row] + matrix->row_length[row];
00432                 j++ )
00433 
00434                 if( matrix->col[j] == col )
00435                         return( matrix->mat_val[j] );
00436 
00437         return( 0.0 );
00438 }  /* getEntryMatrix */
00439 /**********************************************************************/
00440 
00441 
00442 


appl
Author(s): petercai
autogenerated on Tue Jan 7 2014 11:02:29