00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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 }