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

minimize_lsq_include.c

Go to the documentation of this file.
00001 #include <volume_io/internal_volume_io.h> 00002 #include <bicpl/numerical.h> 00003 #include <bicpl/prog_utils.h> 00004 00005 #define DEFAULT_RATIO 1.0 00006 00007 private Real evaluate_fit( 00008 int n_parameters, 00009 Real constant_term, 00010 LSQ_TYPE *linear_terms, 00011 LSQ_TYPE *square_terms, 00012 int n_cross_terms[], 00013 int *cross_parms[], 00014 LSQ_TYPE *cross_terms[], 00015 Real parm_values[] ) 00016 { 00017 int parm, n; 00018 Real fit, parm_val; 00019 00020 fit = constant_term; 00021 00022 for_less( parm, 0, n_parameters ) 00023 { 00024 parm_val = parm_values[parm]; 00025 fit += parm_val * ((Real) linear_terms[parm] + 00026 parm_val * (Real) square_terms[parm]); 00027 00028 for_less( n, 0, n_cross_terms[parm] ) 00029 fit += parm_val * parm_values[cross_parms[parm][n]] * 00030 (Real) cross_terms[parm][n]; 00031 } 00032 00033 return( fit ); 00034 } 00035 00036 private void evaluate_fit_derivative( 00037 int n_parameters, 00038 Real constant_term, 00039 LSQ_TYPE *linear_terms, 00040 LSQ_TYPE *square_terms, 00041 int n_cross_terms[], 00042 int *cross_parms[], 00043 LSQ_TYPE *cross_terms[], 00044 Real parm_values[], 00045 Real derivatives[] ) 00046 { 00047 int parm, n, neigh_parm, n_terms, *cp; 00048 Real term, parm_val, deriv_p; 00049 LSQ_TYPE *ct; 00050 00051 for_less( parm, 0, n_parameters ) 00052 derivatives[parm] = 0.0; 00053 00054 for_less( parm, 0, n_parameters ) 00055 { 00056 parm_val = parm_values[parm]; 00057 00058 deriv_p = (Real) linear_terms[parm] + 00059 2.0 * parm_val * (Real) square_terms[parm]; 00060 00061 ct = cross_terms[parm]; 00062 cp = cross_parms[parm]; 00063 n_terms = n_cross_terms[parm]; 00064 for_less( n, 0, n_terms ) 00065 { 00066 neigh_parm = *cp++; 00067 term = (Real) (*ct++); 00068 deriv_p += term * parm_values[neigh_parm]; 00069 derivatives[neigh_parm] += term * parm_val; 00070 } 00071 derivatives[parm] += deriv_p; 00072 } 00073 } 00074 00075 private void evaluate_fit_along_line( 00076 int n_parameters, 00077 Real constant_term, 00078 LSQ_TYPE *linear_terms, 00079 LSQ_TYPE *square_terms, 00080 int n_cross_terms[], 00081 int *cross_parms[], 00082 LSQ_TYPE *cross_terms[], 00083 Real parm_values[], 00084 Real negative_gradient[], 00085 Real line_coefs[], 00086 Real *a_ptr, 00087 Real *b_ptr ) 00088 { 00089 int parm, n, n_terms, *cp; 00090 Real a, b, line_coef; 00091 Real a_inc; 00092 LSQ_TYPE *ct; 00093 00094 a = 0.0; 00095 b = 0.0; 00096 00097 for_less( parm, 0, n_parameters ) 00098 { 00099 line_coef = line_coefs[parm]; 00100 a_inc = line_coef * (Real) square_terms[parm]; 00101 00102 ct = cross_terms[parm]; 00103 cp = cross_parms[parm]; 00104 n_terms = n_cross_terms[parm]; 00105 for_less( n, 0, n_terms ) 00106 a_inc += (Real) (*ct++) * line_coefs[*cp++]; 00107 00108 a += line_coef * a_inc; 00109 b += line_coef * (-negative_gradient[parm]); 00110 } 00111 00112 *a_ptr = a; 00113 *b_ptr = b; 00114 } 00115 00116 private void minimize_along_line( 00117 int n_parameters, 00118 Real constant_term, 00119 LSQ_TYPE *linear_terms, 00120 LSQ_TYPE *square_terms, 00121 int n_cross_terms[], 00122 int *cross_parms[], 00123 LSQ_TYPE *cross_terms[], 00124 Real max_step_size, 00125 Real parm_values[], 00126 Real negative_gradient[], 00127 Real line_coefs[] ) 00128 { 00129 int parm; 00130 Real a, b, t, step_size; 00131 static Real ratio; 00132 static BOOLEAN first = TRUE; 00133 00134 if( first ) 00135 { 00136 first = FALSE; 00137 if( getenv( "LSQ_STEP_RATIO" ) == 0 || 00138 sscanf( getenv( "LSQ_STEP_RATIO" ), "%lf", &ratio ) != 1 ) 00139 ratio = DEFAULT_RATIO; 00140 } 00141 00142 evaluate_fit_along_line( n_parameters, constant_term, linear_terms, 00143 square_terms, n_cross_terms, cross_parms, 00144 cross_terms, parm_values, negative_gradient, 00145 line_coefs, &a, &b ); 00146 00147 if( a == 0.0 ) 00148 return; 00149 00150 t = ratio * -b / (2.0 * a); 00151 00152 if( max_step_size >= 0.0 ) 00153 { 00154 step_size = 0.0; 00155 for_less( parm, 0, n_parameters ) 00156 step_size += t * t * line_coefs[parm] * line_coefs[parm]; 00157 00158 step_size = sqrt( step_size ); 00159 if( step_size > max_step_size ) 00160 t *= max_step_size / step_size; 00161 } 00162 00163 for_less( parm, 0, n_parameters ) 00164 parm_values[parm] += t * line_coefs[parm]; 00165 } 00166 00167 private Real private_minimize_lsq( 00168 int n_parameters, 00169 Real constant_term, 00170 LSQ_TYPE *linear_terms, 00171 LSQ_TYPE *square_terms, 00172 int n_cross_terms[], 00173 int *cross_parms[], 00174 LSQ_TYPE *cross_terms[], 00175 Real max_step_size, 00176 int n_iters, 00177 Real parm_values[] ) 00178 { 00179 Real fit, len, gg, dgg, gam; 00180 int iter, p; 00181 int update_rate; 00182 Real *unit_dir, *g, *h, *xi; 00183 Real last_update_time, current_time; 00184 00185 ALLOC( g, n_parameters ); 00186 ALLOC( h, n_parameters ); 00187 ALLOC( xi, n_parameters ); 00188 ALLOC( unit_dir, n_parameters ); 00189 00190 fit = evaluate_fit( n_parameters, constant_term, linear_terms, 00191 square_terms, n_cross_terms, cross_parms, cross_terms, 00192 parm_values ); 00193 00194 print( "Initial %g\n", fit ); 00195 (void) flush_file( stdout ); 00196 00197 evaluate_fit_derivative( n_parameters, constant_term, linear_terms, 00198 square_terms, n_cross_terms, 00199 cross_parms, cross_terms, 00200 parm_values, xi ); 00201 00202 for_less( p, 0, n_parameters ) 00203 { 00204 g[p] = -xi[p]; 00205 h[p] = g[p]; 00206 xi[p] = g[p]; 00207 } 00208 00209 update_rate = 1; 00210 last_update_time = current_cpu_seconds(); 00211 00212 for_less( iter, 0, n_iters ) 00213 { 00214 len = 0.0; 00215 for_less( p, 0, n_parameters ) 00216 len += xi[p] * xi[p]; 00217 00218 if( len != 0.0 ) 00219 { 00220 len = sqrt( len ); 00221 for_less( p, 0, n_parameters ) 00222 unit_dir[p] = xi[p] / len; 00223 00224 minimize_along_line( n_parameters, constant_term, linear_terms, 00225 square_terms, n_cross_terms, cross_parms, 00226 cross_terms, 00227 max_step_size, parm_values, g, unit_dir ); 00228 } 00229 00230 if( ((iter+1) % update_rate) == 0 || iter == n_iters - 1 ) 00231 { 00232 fit = evaluate_fit( n_parameters, constant_term, linear_terms, 00233 square_terms, n_cross_terms, cross_parms, 00234 cross_terms, parm_values ); 00235 00236 print( "%d: %g\n", iter+1, fit ); 00237 (void) flush_file( stdout ); 00238 current_time = current_cpu_seconds(); 00239 if( current_time - last_update_time < 1.0 ) 00240 update_rate *= 10; 00241 last_update_time = current_time; 00242 } 00243 00244 evaluate_fit_derivative( n_parameters, constant_term, linear_terms, 00245 square_terms, n_cross_terms, 00246 cross_parms, cross_terms, 00247 parm_values, xi ); 00248 00249 gg = 0.0; 00250 dgg = 0.0; 00251 for_less( p, 0, n_parameters ) 00252 { 00253 gg += g[p] * g[p]; 00254 dgg += (xi[p] + g[p]) * xi[p]; 00255 /* 00256 dgg += xi[p] * xi[p]; 00257 */ 00258 } 00259 00260 if( gg == 0.0 ) 00261 break; 00262 00263 gam = dgg / gg; 00264 00265 for_less( p, 0, n_parameters ) 00266 { 00267 g[p] = -xi[p]; 00268 h[p] = g[p] + gam * h[p]; 00269 xi[p] = h[p]; 00270 } 00271 } 00272 00273 FREE( g ); 00274 FREE( h ); 00275 FREE( xi ); 00276 FREE( unit_dir ); 00277 00278 return( fit ); 00279 }

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