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/amoeba.c,v 1.14 2000/02/06 15:30:39 stever Exp $";
00020
#endif
00021
00022 #define FLIP_RATIO 1.0
00023 #define CONTRACT_RATIO 0.5
00024 #define STRETCH_RATIO 2.0
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 private Real
get_function_value(
00042
amoeba_struct *amoeba,
00043
float parameters[] )
00044 {
00045
return( (*amoeba->
function) ( amoeba->
function_data, parameters ) );
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 public void initialize_amoeba(
00067
amoeba_struct *amoeba,
00068
int n_parameters,
00069 Real initial_parameters[],
00070 Real parameter_deltas[],
00071 amoeba_function function,
00072
void *
function_data,
00073 Real tolerance )
00074 {
00075
int i, j;
00076
00077 amoeba->
n_parameters = n_parameters;
00078 amoeba->
function = function;
00079 amoeba->
function_data = function_data;
00080 amoeba->
tolerance = tolerance;
00081 amoeba->
n_steps_no_improvement = 0;
00082 ALLOC2D( amoeba->
parameters, n_parameters+1, n_parameters );
00083 ALLOC( amoeba->
values, n_parameters+1 );
00084
00085 ALLOC( amoeba->
sum, n_parameters );
00086
00087 for_less( j, 0, n_parameters )
00088 amoeba->
sum[j] = 0.0;
00089
00090 for_less( i, 0, n_parameters+1 )
00091 {
00092 for_less( j, 0, n_parameters )
00093 {
00094 amoeba->
parameters[i][j] = (
float) initial_parameters[j];
00095
if( i > 0 && j == i - 1 )
00096 amoeba->
parameters[i][j] = (
float) parameter_deltas[j];
00097 amoeba->
sum[j] += (Real) amoeba->
parameters[i][j];
00098 }
00099
00100 amoeba->
values[i] =
get_function_value( amoeba, amoeba->
parameters[i] );
00101 }
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 public Real
get_amoeba_parameters(
00119
amoeba_struct *amoeba,
00120 Real parameters[] )
00121 {
00122
int i, j, low;
00123
00124 low = 0;
00125 for_less( i, 1, amoeba->
n_parameters+1 )
00126 {
00127
if( amoeba->
values[i] < amoeba->
values[low] )
00128 low = i;
00129 }
00130
00131 for_less( j, 0, amoeba->
n_parameters )
00132 parameters[j] = (Real) amoeba->
parameters[low][j];
00133
00134
return( amoeba->
values[low] );
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 public void terminate_amoeba(
00151
amoeba_struct *amoeba )
00152 {
00153 FREE2D( amoeba->
parameters );
00154 FREE( amoeba->
values );
00155 FREE( amoeba->
sum );
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 private Real
try_amoeba(
00178
amoeba_struct *amoeba,
00179 Real sum[],
00180
int high,
00181 Real fac )
00182 {
00183
int j;
00184 Real y_try, fac1, fac2;
00185
float *parameters;
00186
00187 ALLOC( parameters, amoeba->
n_parameters );
00188
00189 fac1 = (1.0 - fac) / (Real) amoeba->
n_parameters;
00190 fac2 = fac - fac1;
00191
00192 for_less( j, 0, amoeba->
n_parameters )
00193 parameters[j] = (
float) (sum[j] * fac1 +
00194 (Real) amoeba->
parameters[high][j] * fac2);
00195
00196 y_try =
get_function_value( amoeba, parameters );
00197
00198
if( y_try < amoeba->
values[high] )
00199 {
00200 amoeba->
values[high] = y_try;
00201 for_less( j, 0, amoeba->
n_parameters )
00202 {
00203 sum[j] += (Real) parameters[j] - (Real) amoeba->
parameters[high][j];
00204 amoeba->
parameters[high][j] = parameters[j];
00205 }
00206 }
00207
00208 FREE( parameters );
00209
00210
return( y_try );
00211 }
00212
00213 #define N_STEPS_NO_IMPROVEMENT 20
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 public BOOLEAN
perform_amoeba(
00233
amoeba_struct *amoeba )
00234 {
00235
int i, j, low, high, next_high;
00236 Real y_try, y_save;
00237 BOOLEAN improvement_found;
00238
00239 improvement_found =
TRUE;
00240
00241
if( amoeba->
values[0] > amoeba->
values[1] )
00242 {
00243 high = 0;
00244 next_high = 1;
00245 }
00246
else
00247 {
00248 high = 1;
00249 next_high = 0;
00250 }
00251
00252 low = next_high;
00253
00254 for_less( i, 2, amoeba->
n_parameters+1 )
00255 {
00256
if( amoeba->
values[i] < amoeba->
values[low] )
00257 low = i;
00258
else if( amoeba->
values[i] > amoeba->
values[high] )
00259 {
00260 next_high = high;
00261 high = i;
00262 }
00263
else if( amoeba->
values[i] > amoeba->
values[next_high] )
00264 next_high = i;
00265 }
00266
00267
if(
numerically_close( amoeba->
values[low], amoeba->
values[high],
00268 amoeba->
tolerance ) )
00269 {
00270 ++amoeba->
n_steps_no_improvement;
00271
if( amoeba->
n_steps_no_improvement ==
N_STEPS_NO_IMPROVEMENT )
00272 improvement_found =
FALSE;
00273 }
00274
else
00275 amoeba->
n_steps_no_improvement = 0;
00276
00277 y_try =
try_amoeba( amoeba, amoeba->
sum, high, -
FLIP_RATIO );
00278
00279
if( y_try <= amoeba->
values[low] )
00280 y_try =
try_amoeba( amoeba, amoeba->
sum, high,
STRETCH_RATIO );
00281
else if( y_try >= amoeba->
values[next_high] )
00282 {
00283 y_save = amoeba->
values[high];
00284 y_try =
try_amoeba( amoeba, amoeba->
sum, high,
CONTRACT_RATIO );
00285
00286
if( y_try >= y_save )
00287 {
00288 for_less( i, 0, amoeba->
n_parameters+1 )
00289 {
00290
if( i != low )
00291 {
00292 for_less( j, 0, amoeba->
n_parameters )
00293 {
00294 amoeba->
parameters[i][j] = (amoeba->
parameters[i][j] +
00295 amoeba->
parameters[low][j]) / 2.0f;
00296 }
00297
00298 amoeba->
values[i] =
get_function_value( amoeba,
00299 amoeba->
parameters[i] );
00300 }
00301 }
00302
00303 for_less( j, 0, amoeba->
n_parameters )
00304 {
00305 amoeba->
sum[j] = 0.0;
00306 for_less( i, 0, amoeba->
n_parameters+1 )
00307 amoeba->
sum[j] += (Real) amoeba->
parameters[i][j];
00308 }
00309 }
00310 }
00311
00312
return( improvement_found );
00313 }