Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

gradient_minimize.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 00013 ---------------------------------------------------------------------------- */ 00014 00015 #include <volume_io/internal_volume_io.h> 00016 #include <bicpl/numerical.h> 00017 00018 #ifndef lint 00019 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Numerical/gradient_minimize.c,v 1.5 2000/02/06 15:30:39 stever Exp $"; 00020 #endif 00021 00022 #define SMALLEST_STEP_SIZE 1.0e-20 00023 00024 #define STEP_RATIO 0.5 00025 00026 private Real take_step( 00027 int n_dims, 00028 Real current[], 00029 Real current_value, 00030 Real (*func) ( Real [], void * ), 00031 void *func_data, 00032 Real step_sizes[], 00033 int n_search_dims, 00034 Real parameters[], 00035 Real best[], 00036 int min_pos[], 00037 int max_pos[], 00038 int pos[] ); 00039 00040 public Real gradient_steps_minimize_function( 00041 int n_dims, 00042 Real initial_parameters[], 00043 Real initial_step_sizes[], 00044 Real (*func) ( Real [], void * ), 00045 void *func_data, 00046 int n_search_dims, 00047 int max_iterations, 00048 Real tolerance, 00049 Real solution[] ) 00050 { 00051 BOOLEAN done; 00052 int iteration, dim, *min_pos, *max_pos, *pos; 00053 Real *step_sizes, *parameters, *best, best_value, next_value; 00054 00055 ALLOC( step_sizes, n_dims ); 00056 00057 for_less( dim, 0, n_dims ) 00058 { 00059 step_sizes[dim] = initial_step_sizes[dim]; 00060 solution[dim] = initial_parameters[dim]; 00061 } 00062 00063 best_value = func( solution, func_data ); 00064 00065 ALLOC( parameters, n_dims ); 00066 ALLOC( best, n_dims ); 00067 ALLOC( min_pos, n_dims ); 00068 ALLOC( max_pos, n_dims ); 00069 ALLOC( pos, n_dims ); 00070 00071 done = FALSE; 00072 iteration = 0; 00073 while( !done && (max_iterations <= 0 || iteration < max_iterations) ) 00074 { 00075 next_value = take_step( n_dims, solution, best_value, func, func_data, 00076 step_sizes, n_search_dims, 00077 parameters, best, min_pos, max_pos, pos ); 00078 00079 if( next_value < best_value && 00080 !numerically_close( next_value, best_value, tolerance ) ) 00081 { 00082 best_value = next_value; 00083 for_less( dim, 0, n_dims ) 00084 { 00085 step_sizes[dim] *= 1.0 / STEP_RATIO; 00086 if( step_sizes[dim] > initial_step_sizes[dim] ) 00087 step_sizes[dim] = initial_step_sizes[dim]; 00088 } 00089 done = FALSE; 00090 } 00091 else 00092 { 00093 done = TRUE; 00094 for_less( dim, 0, n_dims ) 00095 { 00096 if( step_sizes[dim] > SMALLEST_STEP_SIZE ) 00097 done = FALSE; 00098 00099 step_sizes[dim] *= STEP_RATIO; 00100 if( step_sizes[dim] < SMALLEST_STEP_SIZE ) 00101 { 00102 step_sizes[dim] = SMALLEST_STEP_SIZE; 00103 } 00104 } 00105 } 00106 00107 ++iteration; 00108 } 00109 00110 FREE( parameters ); 00111 FREE( best ); 00112 FREE( min_pos ); 00113 FREE( max_pos ); 00114 FREE( pos ); 00115 00116 return( best_value ); 00117 } 00118 00119 private Real take_step( 00120 int n_dims, 00121 Real current[], 00122 Real current_value, 00123 Real (*func) ( Real [], void * ), 00124 void *func_data, 00125 Real step_sizes[], 00126 int n_search_dims, 00127 Real parameters[], 00128 Real best[], 00129 int min_pos[], 00130 int max_pos[], 00131 int pos[] ) 00132 { 00133 int dim, fit_dim, changed_from, n_fit_dims; 00134 Real best_value, value; 00135 00136 for_less( dim, 0, n_dims ) 00137 best[dim] = current[dim]; 00138 best_value = current_value; 00139 00140 if( n_search_dims < 1 ) 00141 n_search_dims = 1; 00142 00143 for( fit_dim = 0; fit_dim < n_dims; fit_dim += n_search_dims ) 00144 { 00145 n_fit_dims = MIN( n_search_dims, n_dims - fit_dim ); 00146 00147 for_less( dim, 0, n_dims ) 00148 { 00149 min_pos[dim] = 0; 00150 max_pos[dim] = 0; 00151 parameters[dim] = best[dim]; 00152 } 00153 00154 for_less( dim, fit_dim, MAX( n_dims, fit_dim + n_fit_dims ) ) 00155 { 00156 min_pos[dim] = -1; 00157 max_pos[dim] = 1; 00158 } 00159 00160 for_less( dim, 0, n_dims ) 00161 pos[dim] = min_pos[dim]; 00162 00163 changed_from = 0; 00164 while( changed_from >= 0 ) 00165 { 00166 for_less( dim, changed_from, n_fit_dims ) 00167 { 00168 parameters[fit_dim+dim] = current[fit_dim+dim] + 00169 step_sizes[fit_dim+dim] * (Real) pos[fit_dim+dim]; 00170 } 00171 00172 value = func( parameters, func_data ); 00173 00174 if( value < best_value ) 00175 { 00176 best_value = value; 00177 for_less( dim, 0, n_dims ) 00178 best[dim] = parameters[dim]; 00179 } 00180 00181 changed_from = n_fit_dims - 1; 00182 00183 do 00184 { 00185 ++pos[fit_dim+changed_from]; 00186 if( pos[fit_dim+changed_from] <= max_pos[fit_dim+changed_from] ) 00187 break; 00188 00189 pos[fit_dim+changed_from] = min_pos[fit_dim+changed_from]; 00190 --changed_from; 00191 } 00192 while( changed_from >= 0 ); 00193 } 00194 } 00195 00196 for_less( dim, 0, n_dims ) 00197 current[dim] = best[dim]; 00198 00199 return( best_value ); 00200 }

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7