Changeset 1188
- Timestamp:
- Jul 6, 2004, 6:05:29 PM (22 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 2 edited
-
dataManip/psMinimize.c (modified) (26 diffs)
-
math/psMinimize.c (modified) (26 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/dataManip/psMinimize.c
r1185 r1188 25 25 #include <math.h> 26 26 27 #define MAX_LMM_NUM_ITERATIONS 500 27 #define MAX_LMM_ITERATIONS 100 28 #define MAX_MINIMIZE_ITERATIONS 100 28 29 typedef struct 29 30 { … … 38 39 float (*d_evalModel) (const psVector *, const psVector *, int); 39 40 } 40 psModelData; 41 // The first argument to evalModel() and 42 // d_evalModel() specifies the data point. 43 // It must have the same size as the second 44 // dimension of *domain. 45 // The second argument must have the same size 46 // as *initialGuess and *paramMask. 47 41 psMinChi2Data; 48 42 49 43 typedef struct … … 56 50 float (*d_evalModel) (const psVector *, const psVector *, int); 57 51 } 58 psM odelData2;52 psMinimizeData; 59 53 60 54 61 55 /****************************************************************************** 62 p_psMinFunc(*v, *params): This routine calls the user supplied function to 63 be minimized. The "v" argument of this function corresponds to the 64 parameters of the function to be minimized. 65 66 56 p_psMinFunc(*params, *funcData): We use the GSL-supplied function 57 gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied 58 by the user. The GSL function requires the user-supplied function to be in 59 a different format than the psLib format. The purpose of this procedure is 60 to serve as a GSL-format wrapper for the psLib user-supplied function which 61 is to be minimized. 62 *params: The parameters of the function to be minimized. These will be 63 varied by GSL in order to minimize the function. 64 *funcData: a psLib struct which contains the data point to be minimized, 65 the function and derivative function pointers, an initial guess at 66 the parameters, an option parameter mask, etc. 67 67 *****************************************************************************/ 68 double p_psMinFunc(const gsl_vector * v,69 void * params)68 double p_psMinFunc(const gsl_vector *params, 69 void *funcData) 70 70 { 71 71 int i; // Loop index variable. 72 72 int j; // Loop index variable. 73 73 float tmpf; // Temporary floating point variable. 74 const psVector *restrict coord = ((psM odelData2 *) params)->coord;75 const psVector *restrict mask = ((psM odelData2 *) params)->paramMask;76 psVector *restrict initialGuess = ((psM odelData2 *)params)->initialGuess;74 const psVector *restrict coord = ((psMinimizeData *) funcData)->coord; 75 const psVector *restrict mask = ((psMinimizeData *) funcData)->paramMask; 76 psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess; 77 77 float (*evalModel)(const psVector *, const psVector *) = 78 ((psM odelData2 *) params)->evalModel;78 ((psMinimizeData *) funcData)->evalModel; 79 79 psVector *inputParameterList = NULL; 80 80 81 // The GSL routines will call this function with the masked parameters 82 // removed. However, the user-supplied function (to be modified) does not 83 // have those parameters removed. Here will create a new parameter list 84 // with the masked parameters added (we expand initialGuess). 81 85 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 82 83 86 if (mask != NULL) { 84 87 j = 0; … … 87 90 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 88 91 } else { 89 inputParameterList->data.F32[i] = gsl_vector_get(v, j++); 90 } 91 } 92 } else { 93 for (i=0;i<initialGuess->n;i++) { 94 inputParameterList->data.F32[i] = gsl_vector_get(v, i); 95 } 96 } 97 //printf("HMMM: (%.1f %.1f %.1f %.1f)\n", 98 // inputParameterList->data.F32[0], 99 // inputParameterList->data.F32[1], 100 // coord->data.F32[0], 101 // coord->data.F32[1]); 102 92 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 93 } 94 } 95 } else { 96 for (i=0;i<initialGuess->n;i++) { 97 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 98 } 99 } 100 101 // Call the user-supplied function. 103 102 tmpf = evalModel(inputParameterList, coord); 103 104 // Free allocated memory and return the value of the function. 104 105 psFree(inputParameterList); 105 //printf("Called p_psMinFunc()\n");106 106 return(tmpf); 107 107 } 108 108 109 void p_psMinFuncDeriv(const gsl_vector *v, 110 void *params, 109 /****************************************************************************** 110 p_psMinFuncDeriv(*params, *funcData): We use the GSL-supplied function 111 gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied 112 by the user. The GSL function requires the user-supplied function to be in 113 a different format than the psLib format. The purpose of this procedure is 114 to serve as a GSL-format wrapper for the psLib user-supplied function which 115 is to be minimized. 116 *params: The parameters of the function to be minimized. These will be 117 varied by GSL in order to minimize the function. 118 *funcData: a psLib struct which contains the data point to be minimized, 119 the function and derivative function pointers, an initial guess at 120 the parameters, an option parameter mask, etc. 121 *df: we calculate the derivative of the function w.r.t. to each parameter 122 in "params" and return those derivatives in this psVector. 123 *****************************************************************************/ 124 void p_psMinFuncDeriv(const gsl_vector *params, 125 void *funcData, 111 126 gsl_vector *df) 112 127 { … … 114 129 int j; // Loop index variable. 115 130 float tmpf; // Temporary floating point variable. 116 const psVector *restrict coord = ((psM odelData2 *) params)->coord;117 const psVector *restrict mask = ((psM odelData2 *) params)->paramMask;118 psVector *restrict initialGuess = ((psM odelData2 *)params)->initialGuess;131 const psVector *restrict coord = ((psMinimizeData *) funcData)->coord; 132 const psVector *restrict mask = ((psMinimizeData *) funcData)->paramMask; 133 psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess; 119 134 float (*d_evalModel)(const psVector *, const psVector *, int) = 120 ((psM odelData2 *) params)->d_evalModel;135 ((psMinimizeData *) funcData)->d_evalModel; 121 136 psVector *inputParameterList = NULL; 122 137 138 // The GSL routines will call this function with the masked parameters 139 // removed. However, the user-supplied function (to be modified) does not 140 // have those parameters removed. Here will create a new parameter list 141 // with the masked parameters added (we expand initialGuess). 123 142 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 124 125 143 if (mask != NULL) { 126 144 j = 0; … … 129 147 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 130 148 } else { 131 inputParameterList->data.F32[i] = gsl_vector_get(v, j++); 132 } 133 } 134 } else { 135 for (i=0;i<initialGuess->n;i++) { 136 inputParameterList->data.F32[i] = gsl_vector_get(v, i); 137 } 138 } 139 149 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 150 } 151 } 152 } else { 153 for (i=0;i<initialGuess->n;i++) { 154 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 155 } 156 } 157 158 // Evaluate the derivative w.r.t. each parameter. 159 // NOTE: we can probably remove the calls for masked parameters. 140 160 for (i=0;i<initialGuess->n;i++) { 141 161 tmpf = d_evalModel(inputParameterList, coord, i); 142 162 gsl_vector_set(df, i, tmpf); 143 163 } 164 165 // Free allocated memory. 144 166 psFree(inputParameterList); 145 167 } 146 168 147 /* Compute both f and df together. */ 148 void p_psMinFuncFuncDeriv(const gsl_vector *x, 149 void *params, 169 /****************************************************************************** 170 Compute both p_psMinFunc and p_psMinFuncDeriv together. 171 *****************************************************************************/ 172 void p_psMinFuncFuncDeriv(const gsl_vector *params, 173 void *funcData, 150 174 double *f, 151 175 gsl_vector *df) 152 176 { 153 *f = p_psMinFunc( x, params);154 p_psMinFuncDeriv( x, params, df);177 *f = p_psMinFunc(params, funcData); 178 p_psMinFuncDeriv(params, funcData, df); 155 179 } 156 180 … … 161 185 This routine must minimize an arbitrary function; it must determine the set 162 186 of parameters of that function such that the 163 164 187 *****************************************************************************/ 165 188 psVector * … … 175 198 int iter = 0; 176 199 gsl_multimin_function_fdf f; 177 double *xInit = NULL;178 200 const gsl_multimin_fdfminimizer_type *T; 179 201 gsl_multimin_fdfminimizer *s; 180 psM odelData2inputData;202 psMinimizeData inputData; 181 203 gsl_vector *x; 182 204 … … 188 210 inputData.paramCount = 0; 189 211 190 printf("psMinimize(): initialGuess->n is %d\n", initialGuess->n); 191 printf("psMinimize(): coord->n is %d\n", coord->n); 192 printf("psMinimize(): coord is (%.1f, %.1f)\n", coord->data.F32[0], 193 coord->data.F32[1]); 194 212 // If the user supplied a parameter mask, then count the number of 213 // non-masked elements. This will be used later in allocating a vector 214 // for the parameters. 195 215 if (paramMask != NULL) { 196 216 for (i=0;i<paramMask->n;i++) { … … 204 224 205 225 // The initial guess at the parameters for the function are written into 206 // the vector inputParameterList. If the paramMask is not NULL, then those 207 // parameters are masked out. 208 209 xInit = (double *) psAlloc(inputData.paramCount * sizeof(double)); 226 // the vector inputParameterList. If the paramMask is not NULL, then 227 // masked parameters are masked out. 228 x = gsl_vector_alloc(inputData.paramCount); 210 229 if (paramMask != NULL) { 211 230 j = 0; 212 231 for (i=0;i<initialGuess->n;i++) { 213 232 if (paramMask->data.U8[i] == 0) { 214 xInit[j++] = initialGuess->data.F32[i];215 } 216 } 217 } else { 218 for (i=0;i<initialGuess->n;i++) { 219 xInit[i] = initialGuess->data.F32[i];233 gsl_vector_set(x, j++, initialGuess->data.F32[i]); 234 } 235 } 236 } else { 237 for (i=0;i<initialGuess->n;i++) { 238 gsl_vector_set(x, i, initialGuess->data.F32[i]); 220 239 } 221 240 } … … 224 243 f.fdf = &p_psMinFuncFuncDeriv; 225 244 f.n = inputData.paramCount; 226 // GUS: is this correct?227 //f.params = xInit;228 245 f.params = &inputData; 229 246 230 231 printf("inputData.paramCount is %d\n", inputData.paramCount);232 x = gsl_vector_alloc(inputData.paramCount);233 for (i=0;i<inputData.paramCount;i++) {234 gsl_vector_set(x, i, xInit[i]);235 }236 247 T = gsl_multimin_fdfminimizer_conjugate_fr; 237 248 s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount); 238 239 249 gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4); 240 241 250 do { 242 251 iter++; … … 251 260 printf ("Minimum found at:\n"); 252 261 253 } while (status == GSL_CONTINUE && iter < 100);262 } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS); 254 263 255 264 // In the above steps we had removed the masked elements from the … … 270 279 } 271 280 } 272 psFree(xInit);273 281 return(initialGuess); 274 282 } … … 278 286 279 287 280 // The first argument to evalModel() and 281 // d_evalModel() specifies the data point. 282 // It must have the same size as the second 283 // dimension of *domain. 284 // The second argument must have the same size 285 // as *initialGuess and *paramMask. 288 // The first argument to evalModel() and d_evalModel() specifies the data 289 // point. It must have the same size as the second dimension of *domain. 290 // The second argument must have the same size as *initialGuess and 291 // *paramMask. 286 292 287 293 /****************************************************************************** 288 ****************************************************************************** 289 gsl_function_f(x, params, f): This function serves as a standardized wrapper 290 for the user supplied function which is to be minimized. The GSL 291 minimization routines have no knowledge of the user-supplied function. They 292 only call this routine, which then calls the user-supplied function. The 293 arguments are: 294 294 p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL-supplied function 295 gsl_multifit_fdfsolver_iterate() to determine the function parameters that 296 best fit the supllied set of data points. That GSL function requires the 297 user-supplied function to be in a different format than the psLib format. 298 The purpose of this procedure is to serve as a GSL-format wrapper for the 299 psLib user-supplied function which is to be minimized. 295 300 x: These are the parameters which are to be varied by GSL in order to 296 301 minimized chi2 over the data set. 297 params: this data structure contains the input values over which the302 funcData: this data structure contains the input values over which the 298 303 function will be evaluated, the expected value of the function at 299 304 those points, the amount of error tolerable at those points, a mask … … 302 307 outData: The function is evaluated at each point, then subtract the 303 308 expected value and divide by the error. 304 ******************************************************************************305 309 *****************************************************************************/ 306 int gsl_function_f(const gsl_vector *x,307 void *params,308 gsl_vector *outData)310 int p_psMinChi2Func(const gsl_vector *params, 311 void *funcData, 312 gsl_vector *outData) 309 313 { 310 314 int i; // Loop index variable. 311 315 int j; // Loop index variable. 312 316 float tmpf; // Temporary floating point variable. 313 const psImage *restrict domain = ((psM odelData *)params)->domain;314 const psVector *restrict data = ((psM odelData *)params)->data;315 const psVector *restrict errors = ((psM odelData *) params)->errors;316 const psVector *restrict mask = ((psM odelData *) params)->paramMask;317 psVector *restrict initialGuess = ((psM odelData *)params)->initialGuess;318 float (*evalModel)(const psVector *, const psVector *) = ((psM odelData *) params)->evalModel;317 const psImage *restrict domain = ((psMinChi2Data *)funcData)->domain; 318 const psVector *restrict data = ((psMinChi2Data *)funcData)->data; 319 const psVector *restrict errors = ((psMinChi2Data *) funcData)->errors; 320 const psVector *restrict mask = ((psMinChi2Data *) funcData)->paramMask; 321 psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess; 322 float (*evalModel)(const psVector *, const psVector *) = ((psMinChi2Data *) funcData)->evalModel; 319 323 psVector *inputParameterList = NULL; 320 324 psVector *tmpVecPtr = NULL; … … 326 330 // have those parameters removed. Here will create a new parameter list 327 331 // with the masked parameters added (we expand initialGuess). 332 328 333 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 329 330 334 if (mask != NULL) { 331 335 j = 0; … … 334 338 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 335 339 } else { 336 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 337 } 338 } 339 } else { 340 for (i=0;i<initialGuess->n;i++) { 341 inputParameterList->data.F32[i] = gsl_vector_get(x, i); 342 } 343 } 344 340 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 341 } 342 } 343 } else { 344 for (i=0;i<initialGuess->n;i++) { 345 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 346 } 347 } 348 349 // Evaluate the function at each data point. 345 350 for (i=0;i<domain->numRows;i++) { 346 351 for (j=0;j<domain->numCols;j++) { … … 353 358 } 354 359 360 // Free allocated memory. 355 361 psFree(inputParameterList); 356 362 psFree(tmpVecPtr); 363 357 364 return GSL_SUCCESS; 358 365 } 359 366 360 int gsl_function_df(const gsl_vector *x,361 void *params,362 gsl_matrix *J)363 { 364 const psImage *restrict domain = ((psM odelData *)params)->domain;365 const psVector *restrict errors = ((psM odelData *) params)->errors;366 const psVector *restrict mask = ((psM odelData *) params)->paramMask;367 psVector *restrict initialGuess = ((psM odelData *)params)->initialGuess;367 int p_psMinChi2FuncDeriv(const gsl_vector *params, 368 void *funcData, 369 gsl_matrix *J) 370 { 371 const psImage *restrict domain = ((psMinChi2Data *)funcData)->domain; 372 const psVector *restrict errors = ((psMinChi2Data *) funcData)->errors; 373 const psVector *restrict mask = ((psMinChi2Data *) funcData)->paramMask; 374 psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess; 368 375 psVector *inputParameterList = NULL; 369 376 psVector *tmpVecPtr = NULL; 370 float (*d_evalModel)(const psVector *, const psVector *, int) = ((psM odelData *) params)->d_evalModel;377 float (*d_evalModel)(const psVector *, const psVector *, int) = ((psMinChi2Data *) funcData)->d_evalModel; 371 378 372 379 size_t i; … … 380 387 // have those parameters removed. Here will create a new parameter list 381 388 // with the masked parameters added (we expand initialGuess). 389 382 390 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 383 384 391 if (mask != NULL) { 385 392 j = 0; … … 388 395 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 389 396 } else { 390 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 391 } 392 } 393 } else { 394 for (i=0;i<initialGuess->n;i++) { 395 inputParameterList->data.F32[i] = gsl_vector_get(x, i); 396 } 397 } 398 397 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 398 } 399 } 400 } else { 401 for (i=0;i<initialGuess->n;i++) { 402 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 403 } 404 } 405 406 // Evaluate the derivtaive at each data point, and w.r.t. each parameter. 399 407 for (i=0;i<domain->numRows;i++) { 400 408 for (j=0;j<tmpVecPtr->n;j++) { … … 413 421 } 414 422 415 int gsl_my_function_fdf(const gsl_vector *x, 416 void *params, 417 gsl_vector *f, 418 gsl_matrix *J) 419 { 420 gsl_function_f(x, params, f); 421 gsl_function_df(x, params, J); 423 424 int p_psMinChi2FuncFuncDeriv(const gsl_vector *params, 425 void *funcData, 426 gsl_vector *f, 427 gsl_matrix *J) 428 { 429 p_psMinChi2Func(params, funcData, f); 430 p_psMinChi2FuncDeriv(params, funcData, J); 422 431 423 432 return GSL_SUCCESS; … … 451 460 // minimization. 452 461 gsl_multifit_fdfsolver *s; // GSL data structure. 453 psM odelData inputData;462 psMinChi2Data inputData; 454 463 float chiSqOld = 0.0; 455 464 … … 464 473 inputData.d_evalModel = DevalModel; 465 474 475 // If the user supplied a parameter mask, then count the number of 476 // non-masked elements. This will be used later in allocating a vector 477 // for the parameters. 466 478 if (paramMask != NULL) { 467 479 for (i=0;i<paramMask->n;i++) { … … 477 489 // the vector inputParameterList. If the paramMask is not NULL, then those 478 490 // parameters are masked out. 479 480 491 xInit = (double *) psAlloc(inputData.paramCount * sizeof(double)); 481 492 if (paramMask != NULL) { … … 504 515 // and the data structures those functions use. 505 516 506 f.f = & gsl_function_f;507 f.df = & gsl_function_df;508 f.fdf = & gsl_my_function_fdf;517 f.f = &p_psMinChi2Func; 518 f.df = &p_psMinChi2FuncDeriv; 519 f.fdf = &p_psMinChi2FuncFuncDeriv; 509 520 f.n = numData; 510 521 f.p = inputData.paramCount; … … 542 553 chiSqOld = *chiSq; 543 554 544 } while (status == GSL_CONTINUE && iter < MAX_LMM_ NUM_ITERATIONS);555 } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS); 545 556 546 557 -
trunk/psLib/src/math/psMinimize.c
r1185 r1188 25 25 #include <math.h> 26 26 27 #define MAX_LMM_NUM_ITERATIONS 500 27 #define MAX_LMM_ITERATIONS 100 28 #define MAX_MINIMIZE_ITERATIONS 100 28 29 typedef struct 29 30 { … … 38 39 float (*d_evalModel) (const psVector *, const psVector *, int); 39 40 } 40 psModelData; 41 // The first argument to evalModel() and 42 // d_evalModel() specifies the data point. 43 // It must have the same size as the second 44 // dimension of *domain. 45 // The second argument must have the same size 46 // as *initialGuess and *paramMask. 47 41 psMinChi2Data; 48 42 49 43 typedef struct … … 56 50 float (*d_evalModel) (const psVector *, const psVector *, int); 57 51 } 58 psM odelData2;52 psMinimizeData; 59 53 60 54 61 55 /****************************************************************************** 62 p_psMinFunc(*v, *params): This routine calls the user supplied function to 63 be minimized. The "v" argument of this function corresponds to the 64 parameters of the function to be minimized. 65 66 56 p_psMinFunc(*params, *funcData): We use the GSL-supplied function 57 gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied 58 by the user. The GSL function requires the user-supplied function to be in 59 a different format than the psLib format. The purpose of this procedure is 60 to serve as a GSL-format wrapper for the psLib user-supplied function which 61 is to be minimized. 62 *params: The parameters of the function to be minimized. These will be 63 varied by GSL in order to minimize the function. 64 *funcData: a psLib struct which contains the data point to be minimized, 65 the function and derivative function pointers, an initial guess at 66 the parameters, an option parameter mask, etc. 67 67 *****************************************************************************/ 68 double p_psMinFunc(const gsl_vector * v,69 void * params)68 double p_psMinFunc(const gsl_vector *params, 69 void *funcData) 70 70 { 71 71 int i; // Loop index variable. 72 72 int j; // Loop index variable. 73 73 float tmpf; // Temporary floating point variable. 74 const psVector *restrict coord = ((psM odelData2 *) params)->coord;75 const psVector *restrict mask = ((psM odelData2 *) params)->paramMask;76 psVector *restrict initialGuess = ((psM odelData2 *)params)->initialGuess;74 const psVector *restrict coord = ((psMinimizeData *) funcData)->coord; 75 const psVector *restrict mask = ((psMinimizeData *) funcData)->paramMask; 76 psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess; 77 77 float (*evalModel)(const psVector *, const psVector *) = 78 ((psM odelData2 *) params)->evalModel;78 ((psMinimizeData *) funcData)->evalModel; 79 79 psVector *inputParameterList = NULL; 80 80 81 // The GSL routines will call this function with the masked parameters 82 // removed. However, the user-supplied function (to be modified) does not 83 // have those parameters removed. Here will create a new parameter list 84 // with the masked parameters added (we expand initialGuess). 81 85 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 82 83 86 if (mask != NULL) { 84 87 j = 0; … … 87 90 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 88 91 } else { 89 inputParameterList->data.F32[i] = gsl_vector_get(v, j++); 90 } 91 } 92 } else { 93 for (i=0;i<initialGuess->n;i++) { 94 inputParameterList->data.F32[i] = gsl_vector_get(v, i); 95 } 96 } 97 //printf("HMMM: (%.1f %.1f %.1f %.1f)\n", 98 // inputParameterList->data.F32[0], 99 // inputParameterList->data.F32[1], 100 // coord->data.F32[0], 101 // coord->data.F32[1]); 102 92 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 93 } 94 } 95 } else { 96 for (i=0;i<initialGuess->n;i++) { 97 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 98 } 99 } 100 101 // Call the user-supplied function. 103 102 tmpf = evalModel(inputParameterList, coord); 103 104 // Free allocated memory and return the value of the function. 104 105 psFree(inputParameterList); 105 //printf("Called p_psMinFunc()\n");106 106 return(tmpf); 107 107 } 108 108 109 void p_psMinFuncDeriv(const gsl_vector *v, 110 void *params, 109 /****************************************************************************** 110 p_psMinFuncDeriv(*params, *funcData): We use the GSL-supplied function 111 gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied 112 by the user. The GSL function requires the user-supplied function to be in 113 a different format than the psLib format. The purpose of this procedure is 114 to serve as a GSL-format wrapper for the psLib user-supplied function which 115 is to be minimized. 116 *params: The parameters of the function to be minimized. These will be 117 varied by GSL in order to minimize the function. 118 *funcData: a psLib struct which contains the data point to be minimized, 119 the function and derivative function pointers, an initial guess at 120 the parameters, an option parameter mask, etc. 121 *df: we calculate the derivative of the function w.r.t. to each parameter 122 in "params" and return those derivatives in this psVector. 123 *****************************************************************************/ 124 void p_psMinFuncDeriv(const gsl_vector *params, 125 void *funcData, 111 126 gsl_vector *df) 112 127 { … … 114 129 int j; // Loop index variable. 115 130 float tmpf; // Temporary floating point variable. 116 const psVector *restrict coord = ((psM odelData2 *) params)->coord;117 const psVector *restrict mask = ((psM odelData2 *) params)->paramMask;118 psVector *restrict initialGuess = ((psM odelData2 *)params)->initialGuess;131 const psVector *restrict coord = ((psMinimizeData *) funcData)->coord; 132 const psVector *restrict mask = ((psMinimizeData *) funcData)->paramMask; 133 psVector *restrict initialGuess = ((psMinimizeData *)funcData)->initialGuess; 119 134 float (*d_evalModel)(const psVector *, const psVector *, int) = 120 ((psM odelData2 *) params)->d_evalModel;135 ((psMinimizeData *) funcData)->d_evalModel; 121 136 psVector *inputParameterList = NULL; 122 137 138 // The GSL routines will call this function with the masked parameters 139 // removed. However, the user-supplied function (to be modified) does not 140 // have those parameters removed. Here will create a new parameter list 141 // with the masked parameters added (we expand initialGuess). 123 142 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 124 125 143 if (mask != NULL) { 126 144 j = 0; … … 129 147 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 130 148 } else { 131 inputParameterList->data.F32[i] = gsl_vector_get(v, j++); 132 } 133 } 134 } else { 135 for (i=0;i<initialGuess->n;i++) { 136 inputParameterList->data.F32[i] = gsl_vector_get(v, i); 137 } 138 } 139 149 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 150 } 151 } 152 } else { 153 for (i=0;i<initialGuess->n;i++) { 154 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 155 } 156 } 157 158 // Evaluate the derivative w.r.t. each parameter. 159 // NOTE: we can probably remove the calls for masked parameters. 140 160 for (i=0;i<initialGuess->n;i++) { 141 161 tmpf = d_evalModel(inputParameterList, coord, i); 142 162 gsl_vector_set(df, i, tmpf); 143 163 } 164 165 // Free allocated memory. 144 166 psFree(inputParameterList); 145 167 } 146 168 147 /* Compute both f and df together. */ 148 void p_psMinFuncFuncDeriv(const gsl_vector *x, 149 void *params, 169 /****************************************************************************** 170 Compute both p_psMinFunc and p_psMinFuncDeriv together. 171 *****************************************************************************/ 172 void p_psMinFuncFuncDeriv(const gsl_vector *params, 173 void *funcData, 150 174 double *f, 151 175 gsl_vector *df) 152 176 { 153 *f = p_psMinFunc( x, params);154 p_psMinFuncDeriv( x, params, df);177 *f = p_psMinFunc(params, funcData); 178 p_psMinFuncDeriv(params, funcData, df); 155 179 } 156 180 … … 161 185 This routine must minimize an arbitrary function; it must determine the set 162 186 of parameters of that function such that the 163 164 187 *****************************************************************************/ 165 188 psVector * … … 175 198 int iter = 0; 176 199 gsl_multimin_function_fdf f; 177 double *xInit = NULL;178 200 const gsl_multimin_fdfminimizer_type *T; 179 201 gsl_multimin_fdfminimizer *s; 180 psM odelData2inputData;202 psMinimizeData inputData; 181 203 gsl_vector *x; 182 204 … … 188 210 inputData.paramCount = 0; 189 211 190 printf("psMinimize(): initialGuess->n is %d\n", initialGuess->n); 191 printf("psMinimize(): coord->n is %d\n", coord->n); 192 printf("psMinimize(): coord is (%.1f, %.1f)\n", coord->data.F32[0], 193 coord->data.F32[1]); 194 212 // If the user supplied a parameter mask, then count the number of 213 // non-masked elements. This will be used later in allocating a vector 214 // for the parameters. 195 215 if (paramMask != NULL) { 196 216 for (i=0;i<paramMask->n;i++) { … … 204 224 205 225 // The initial guess at the parameters for the function are written into 206 // the vector inputParameterList. If the paramMask is not NULL, then those 207 // parameters are masked out. 208 209 xInit = (double *) psAlloc(inputData.paramCount * sizeof(double)); 226 // the vector inputParameterList. If the paramMask is not NULL, then 227 // masked parameters are masked out. 228 x = gsl_vector_alloc(inputData.paramCount); 210 229 if (paramMask != NULL) { 211 230 j = 0; 212 231 for (i=0;i<initialGuess->n;i++) { 213 232 if (paramMask->data.U8[i] == 0) { 214 xInit[j++] = initialGuess->data.F32[i];215 } 216 } 217 } else { 218 for (i=0;i<initialGuess->n;i++) { 219 xInit[i] = initialGuess->data.F32[i];233 gsl_vector_set(x, j++, initialGuess->data.F32[i]); 234 } 235 } 236 } else { 237 for (i=0;i<initialGuess->n;i++) { 238 gsl_vector_set(x, i, initialGuess->data.F32[i]); 220 239 } 221 240 } … … 224 243 f.fdf = &p_psMinFuncFuncDeriv; 225 244 f.n = inputData.paramCount; 226 // GUS: is this correct?227 //f.params = xInit;228 245 f.params = &inputData; 229 246 230 231 printf("inputData.paramCount is %d\n", inputData.paramCount);232 x = gsl_vector_alloc(inputData.paramCount);233 for (i=0;i<inputData.paramCount;i++) {234 gsl_vector_set(x, i, xInit[i]);235 }236 247 T = gsl_multimin_fdfminimizer_conjugate_fr; 237 248 s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount); 238 239 249 gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4); 240 241 250 do { 242 251 iter++; … … 251 260 printf ("Minimum found at:\n"); 252 261 253 } while (status == GSL_CONTINUE && iter < 100);262 } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS); 254 263 255 264 // In the above steps we had removed the masked elements from the … … 270 279 } 271 280 } 272 psFree(xInit);273 281 return(initialGuess); 274 282 } … … 278 286 279 287 280 // The first argument to evalModel() and 281 // d_evalModel() specifies the data point. 282 // It must have the same size as the second 283 // dimension of *domain. 284 // The second argument must have the same size 285 // as *initialGuess and *paramMask. 288 // The first argument to evalModel() and d_evalModel() specifies the data 289 // point. It must have the same size as the second dimension of *domain. 290 // The second argument must have the same size as *initialGuess and 291 // *paramMask. 286 292 287 293 /****************************************************************************** 288 ****************************************************************************** 289 gsl_function_f(x, params, f): This function serves as a standardized wrapper 290 for the user supplied function which is to be minimized. The GSL 291 minimization routines have no knowledge of the user-supplied function. They 292 only call this routine, which then calls the user-supplied function. The 293 arguments are: 294 294 p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL-supplied function 295 gsl_multifit_fdfsolver_iterate() to determine the function parameters that 296 best fit the supllied set of data points. That GSL function requires the 297 user-supplied function to be in a different format than the psLib format. 298 The purpose of this procedure is to serve as a GSL-format wrapper for the 299 psLib user-supplied function which is to be minimized. 295 300 x: These are the parameters which are to be varied by GSL in order to 296 301 minimized chi2 over the data set. 297 params: this data structure contains the input values over which the302 funcData: this data structure contains the input values over which the 298 303 function will be evaluated, the expected value of the function at 299 304 those points, the amount of error tolerable at those points, a mask … … 302 307 outData: The function is evaluated at each point, then subtract the 303 308 expected value and divide by the error. 304 ******************************************************************************305 309 *****************************************************************************/ 306 int gsl_function_f(const gsl_vector *x,307 void *params,308 gsl_vector *outData)310 int p_psMinChi2Func(const gsl_vector *params, 311 void *funcData, 312 gsl_vector *outData) 309 313 { 310 314 int i; // Loop index variable. 311 315 int j; // Loop index variable. 312 316 float tmpf; // Temporary floating point variable. 313 const psImage *restrict domain = ((psM odelData *)params)->domain;314 const psVector *restrict data = ((psM odelData *)params)->data;315 const psVector *restrict errors = ((psM odelData *) params)->errors;316 const psVector *restrict mask = ((psM odelData *) params)->paramMask;317 psVector *restrict initialGuess = ((psM odelData *)params)->initialGuess;318 float (*evalModel)(const psVector *, const psVector *) = ((psM odelData *) params)->evalModel;317 const psImage *restrict domain = ((psMinChi2Data *)funcData)->domain; 318 const psVector *restrict data = ((psMinChi2Data *)funcData)->data; 319 const psVector *restrict errors = ((psMinChi2Data *) funcData)->errors; 320 const psVector *restrict mask = ((psMinChi2Data *) funcData)->paramMask; 321 psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess; 322 float (*evalModel)(const psVector *, const psVector *) = ((psMinChi2Data *) funcData)->evalModel; 319 323 psVector *inputParameterList = NULL; 320 324 psVector *tmpVecPtr = NULL; … … 326 330 // have those parameters removed. Here will create a new parameter list 327 331 // with the masked parameters added (we expand initialGuess). 332 328 333 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 329 330 334 if (mask != NULL) { 331 335 j = 0; … … 334 338 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 335 339 } else { 336 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 337 } 338 } 339 } else { 340 for (i=0;i<initialGuess->n;i++) { 341 inputParameterList->data.F32[i] = gsl_vector_get(x, i); 342 } 343 } 344 340 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 341 } 342 } 343 } else { 344 for (i=0;i<initialGuess->n;i++) { 345 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 346 } 347 } 348 349 // Evaluate the function at each data point. 345 350 for (i=0;i<domain->numRows;i++) { 346 351 for (j=0;j<domain->numCols;j++) { … … 353 358 } 354 359 360 // Free allocated memory. 355 361 psFree(inputParameterList); 356 362 psFree(tmpVecPtr); 363 357 364 return GSL_SUCCESS; 358 365 } 359 366 360 int gsl_function_df(const gsl_vector *x,361 void *params,362 gsl_matrix *J)363 { 364 const psImage *restrict domain = ((psM odelData *)params)->domain;365 const psVector *restrict errors = ((psM odelData *) params)->errors;366 const psVector *restrict mask = ((psM odelData *) params)->paramMask;367 psVector *restrict initialGuess = ((psM odelData *)params)->initialGuess;367 int p_psMinChi2FuncDeriv(const gsl_vector *params, 368 void *funcData, 369 gsl_matrix *J) 370 { 371 const psImage *restrict domain = ((psMinChi2Data *)funcData)->domain; 372 const psVector *restrict errors = ((psMinChi2Data *) funcData)->errors; 373 const psVector *restrict mask = ((psMinChi2Data *) funcData)->paramMask; 374 psVector *restrict initialGuess = ((psMinChi2Data *)funcData)->initialGuess; 368 375 psVector *inputParameterList = NULL; 369 376 psVector *tmpVecPtr = NULL; 370 float (*d_evalModel)(const psVector *, const psVector *, int) = ((psM odelData *) params)->d_evalModel;377 float (*d_evalModel)(const psVector *, const psVector *, int) = ((psMinChi2Data *) funcData)->d_evalModel; 371 378 372 379 size_t i; … … 380 387 // have those parameters removed. Here will create a new parameter list 381 388 // with the masked parameters added (we expand initialGuess). 389 382 390 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 383 384 391 if (mask != NULL) { 385 392 j = 0; … … 388 395 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 389 396 } else { 390 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 391 } 392 } 393 } else { 394 for (i=0;i<initialGuess->n;i++) { 395 inputParameterList->data.F32[i] = gsl_vector_get(x, i); 396 } 397 } 398 397 inputParameterList->data.F32[i] = gsl_vector_get(params, j++); 398 } 399 } 400 } else { 401 for (i=0;i<initialGuess->n;i++) { 402 inputParameterList->data.F32[i] = gsl_vector_get(params, i); 403 } 404 } 405 406 // Evaluate the derivtaive at each data point, and w.r.t. each parameter. 399 407 for (i=0;i<domain->numRows;i++) { 400 408 for (j=0;j<tmpVecPtr->n;j++) { … … 413 421 } 414 422 415 int gsl_my_function_fdf(const gsl_vector *x, 416 void *params, 417 gsl_vector *f, 418 gsl_matrix *J) 419 { 420 gsl_function_f(x, params, f); 421 gsl_function_df(x, params, J); 423 424 int p_psMinChi2FuncFuncDeriv(const gsl_vector *params, 425 void *funcData, 426 gsl_vector *f, 427 gsl_matrix *J) 428 { 429 p_psMinChi2Func(params, funcData, f); 430 p_psMinChi2FuncDeriv(params, funcData, J); 422 431 423 432 return GSL_SUCCESS; … … 451 460 // minimization. 452 461 gsl_multifit_fdfsolver *s; // GSL data structure. 453 psM odelData inputData;462 psMinChi2Data inputData; 454 463 float chiSqOld = 0.0; 455 464 … … 464 473 inputData.d_evalModel = DevalModel; 465 474 475 // If the user supplied a parameter mask, then count the number of 476 // non-masked elements. This will be used later in allocating a vector 477 // for the parameters. 466 478 if (paramMask != NULL) { 467 479 for (i=0;i<paramMask->n;i++) { … … 477 489 // the vector inputParameterList. If the paramMask is not NULL, then those 478 490 // parameters are masked out. 479 480 491 xInit = (double *) psAlloc(inputData.paramCount * sizeof(double)); 481 492 if (paramMask != NULL) { … … 504 515 // and the data structures those functions use. 505 516 506 f.f = & gsl_function_f;507 f.df = & gsl_function_df;508 f.fdf = & gsl_my_function_fdf;517 f.f = &p_psMinChi2Func; 518 f.df = &p_psMinChi2FuncDeriv; 519 f.fdf = &p_psMinChi2FuncFuncDeriv; 509 520 f.n = numData; 510 521 f.p = inputData.paramCount; … … 542 553 chiSqOld = *chiSq; 543 554 544 } while (status == GSL_CONTINUE && iter < MAX_LMM_ NUM_ITERATIONS);555 } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS); 545 556 546 557
Note:
See TracChangeset
for help on using the changeset viewer.
