Changeset 5175
- Timestamp:
- Sep 28, 2005, 4:13:54 PM (21 years ago)
- Location:
- trunk/psLib
- Files:
-
- 3 edited
-
src/math/psMinimize.c (modified) (15 diffs)
-
src/math/psMinimize.h (modified) (3 diffs)
-
test/math/tst_psMinimize06.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimize.c
r5113 r5175 10 10 * @author EAM, IfA 11 11 * 12 * @version $Revision: 1.14 0$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-09-2 3 23:01:30$12 * @version $Revision: 1.141 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-09-29 02:13:54 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 16 16 * 17 17 * XXX: must follow coding name standards on local functions. 18 * 18 * XXX: put local functions in front. 19 * 19 20 */ 20 21 /*****************************************************************************/ … … 33 34 /*****************************************************************************/ 34 35 /* DEFINE STATEMENTS */ 35 /* What are the following macros for? */36 36 /*****************************************************************************/ 37 #define PS_SEG psLib 38 #define PS_PWD dataManip 39 #define PS_FILE psMinimize 37 40 38 /*****************************************************************************/ 41 39 /* TYPE DEFINITIONS */ … … 44 42 /*****************************************************************************/ 45 43 /* GLOBAL VARIABLES */ 44 /* XXX: Do these conform to code standard? */ 46 45 /*****************************************************************************/ 47 46 static psMinimizeChi2PowellFunc Chi2PowellFunc = NULL; 48 47 static psVector *myValue; 49 48 static psVector *myError; 50 51 49 /*****************************************************************************/ 52 50 /* FILE STATIC VARIABLES */ … … 64 62 ****************************************************************************** 65 63 *****************************************************************************/ 66 // measure the distance to the minimum assuming a linear model 67 // XXX: Move this to the pub area. 68 bool psMinimizeGaussNewtonDelta (psVector *delta, 69 const psVector *params, 70 const psVector *paramMask, 71 const psArray *x, 72 const psVector *y, 73 const psVector *yErr, 74 psMinimizeLMChi2Func func) 64 // XXX EAM : can we use static copies of LUv, LUm, A? 65 psBool p_psMinLM_GuessABP( 66 psImage *Alpha, 67 psVector *Beta, 68 psVector *Params, 69 const psImage *alpha, 70 const psVector *beta, 71 const psVector *params, 72 const psVector *paramMask, 73 const psVector *beta_lim, 74 const psVector *params_min, 75 const psVector *params_max, 76 psF64 lambda) 77 { 78 # define USE_LU_DECOMP 1 79 # if (USE_LU_DECOMP) 80 psVector *LUv = NULL; 81 psImage *LUm = NULL; 82 psImage *A = NULL; 83 psF32 det; 84 85 // LU decomposition version 86 psTrace(__func__, 5, "using LUD version\n"); 87 88 // set new guess values (creates matrix A) 89 A = psImageCopy(NULL, alpha, PS_TYPE_F64); 90 for (int j = 0; j < params->n; j++) { 91 if ((paramMask != NULL) && (paramMask->data.U8[j])) 92 continue; 93 A->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 94 } 95 96 // solve A*beta = Beta (Alpha = 1/A) 97 // these operations do not modify the input values (creates LUm, LUv) 98 LUm = psMatrixLUD(NULL, &LUv, A); 99 Beta = psMatrixLUSolve(Beta, LUm, beta, LUv); 100 Alpha = psMatrixInvert(Alpha, A, &det); 101 102 # else 103 // gauss-jordan version 104 psTrace(__func__, 5, "using Gauss-J version"); 105 106 // set new guess values (creates matrix A) 107 Beta = psVectorCopy(Beta, beta, PS_TYPE_F64); 108 Alpha = psImageCopy(Alpha, alpha, PS_TYPE_F64); 109 for (int j = 0; j < params->n; j++) { 110 if ((paramMask != NULL) && (paramMask->data.U8[j])) 111 continue; 112 Alpha->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 113 } 114 115 psGaussJordan(Alpha, Beta); 116 psFree(A); 117 psFree(LUm); 118 psFree(LUv); 119 # endif 120 121 // apply Beta to get new Params values 122 for (int j = 0; j < params->n; j++) { 123 if ((paramMask != NULL) && (paramMask->data.U8[j])) 124 continue; 125 // Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 126 // compare Beta to beta limits 127 if (beta_lim != NULL) { 128 if (fabs(Beta->data.F64[j]) > fabs(beta_lim->data.F32[j])) { 129 Beta->data.F64[j] = (Beta->data.F64[j] > 0) ? fabs(beta_lim->data.F32[j]) : -fabs(beta_lim->data.F32[j]); 130 } 131 } 132 Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 133 // compare new params to param limits 134 if (params_max != NULL) { 135 Params->data.F32[j] = PS_MIN (Params->data.F32[j], params_max->data.F32[j]); 136 } 137 if (params_min != NULL) { 138 Params->data.F32[j] = PS_MAX (Params->data.F32[j], params_min->data.F32[j]); 139 } 140 } 141 # if (USE_LU_DECOMP) 142 psFree(A); 143 psFree(LUm); 144 psFree(LUv); 145 # endif 146 147 return(true); 148 } 149 150 151 bool psMinimizeGaussNewtonDelta( 152 psVector *delta, 153 const psVector *params, 154 const psVector *paramMask, 155 const psArray *x, 156 const psVector *y, 157 const psVector *yWt, 158 psMinimizeLMChi2Func func) 75 159 { 76 160 77 161 // allocate internal arrays (current vs Guess) 78 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64);79 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64);80 psVector *beta = psVectorAlloc (params->n, PS_TYPE_F64);81 psVector *Params = psVectorAlloc (params->n, PS_TYPE_F64);82 psVector *dy = psVectorAlloc (y->n, PS_TYPE_F32);162 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64); 163 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64); 164 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F64); 165 psVector *Params = psVectorAlloc(params->n, PS_TYPE_F64); 166 psVector *dy = NULL; 83 167 84 168 // the user provides the error or NULL. we need to convert 85 169 // to appropriate weights 86 if (yErr != NULL) { 87 for (int i = 0; i < dy->n; i++) { 88 dy->data.F32[i] = 1.0 / PS_SQR (yErr->data.F32[i]); 89 } 170 if (yWt != NULL) { 171 dy = (psVector *) yWt; 90 172 } else { 91 for (int i = 0; i < dy->n; i++) { 92 dy->data.F32[i] = 1.0; 93 } 94 } 95 96 p_psMinLM_SetABX (alpha, beta, params, paramMask, x, y, dy, func); 97 p_psMinLM_GuessABP (Alpha, delta, Params, alpha, beta, params, paramMask, 0.0); 98 99 psFree (alpha); 100 psFree (Alpha); 101 psFree (beta); 102 psFree (Params); 103 psFree (dy); 173 dy = psVectorAlloc(y->n, PS_TYPE_F32); 174 psVectorInit(dy, 1.0); 175 } 176 177 p_psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func); 178 p_psMinLM_GuessABP(Alpha, delta, Params, alpha, beta, params, paramMask, NULL, NULL, NULL, 0.0); 179 180 psFree(alpha); 181 psFree(Alpha); 182 psFree(beta); 183 psFree(Params); 184 if (yWt == NULL) { 185 psFree(dy); 186 } 104 187 return (true); 105 188 } 106 189 107 108 190 // measure linear model prediction 109 psF64 p_psMinLM_dLinear (const psVector *Beta, const psVector *beta, psF64 lambda) 191 psF64 p_psMinLM_dLinear( 192 const psVector *Beta, 193 const psVector *beta, 194 psF64 lambda) 110 195 { 111 196 … … 117 202 dLinear += lambda*PS_SQR(B[i]) + B[i]*b[i]; 118 203 } 119 return (0.5*dLinear); 120 } 204 return(0.5*dLinear); 205 } 206 207 // XXX EAM: this needs to respect the mask on params 208 // alpha, beta, params are already allocated 209 psF64 p_psMinLM_SetABX( 210 psImage *alpha, 211 psVector *beta, 212 const psVector *params, 213 const psVector *paramMask, 214 const psArray *x, 215 const psVector *y, 216 const psVector *dy, 217 psMinimizeLMChi2Func func) 218 { 219 PS_ASSERT_IMAGE_NON_NULL(alpha, NAN); 220 PS_ASSERT_VECTOR_NON_NULL(beta, NAN); 221 PS_ASSERT_VECTOR_NON_NULL(params, NAN); 222 PS_ASSERT_PTR_NON_NULL(x, NAN); 223 PS_ASSERT_VECTOR_NON_NULL(y, NAN); 224 PS_ASSERT_VECTOR_NON_NULL(dy, NAN); 225 226 psF64 chisq; 227 psF64 delta; 228 psF64 weight; 229 psF64 ymodel; 230 psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32); 231 232 // zero alpha and beta for summing below 233 for (int j = 0; j < params->n; j++) { 234 for (int k = 0; k < params->n; k++) { 235 alpha->data.F64[j][k] = 0; 236 } 237 beta->data.F64[j] = 0; 238 } 239 chisq = 0.0; 240 241 // calculate chisq, alpha, beta 242 for (int i = 0; i < y->n; i++) { 243 ymodel = func(deriv, params, (psVector *) x->data[i]); 244 245 delta = ymodel - y->data.F32[i]; 246 chisq += PS_SQR(delta) * dy->data.F32[i]; 247 248 for (int j = 0; j < params->n; j++) { 249 if ((paramMask != NULL) && (paramMask->data.U8[j])) 250 continue; 251 weight = deriv->data.F32[j] * dy->data.F32[i]; 252 for (int k = 0; k <= j; k++) { 253 if ((paramMask != NULL) && (paramMask->data.U8[k])) 254 continue; 255 alpha->data.F64[j][k] += weight * deriv->data.F32[k]; 256 } 257 beta->data.F64[j] += weight * delta; 258 } 259 } 260 261 // calculate lower-left half of alpha 262 for (int j = 1; j < params->n; j++) { 263 for (int k = 0; k < j; k++) { 264 alpha->data.F64[k][j] = alpha->data.F64[j][k]; 265 } 266 } 267 268 // fill in pivots if we apply a mask 269 if (paramMask != NULL) { 270 for (int j = 0; j < params->n; j++) { 271 if (paramMask->data.U8[j]) { 272 alpha->data.F64[j][j] = 1; 273 beta->data.F64[j] = 1; 274 } 275 } 276 } 277 278 psFree(deriv); 279 return(chisq); 280 } 281 121 282 122 283 /****************************************************************************** 123 psMinimizeLMChi2(): This routine will take an procedure which calculates 124 an arbitrary function and it's derivative and minimize the chi-squared match 125 between that function at the specified coords and the specified value at 126 those coords. 284 psMinimizeLMChi2(): This routine will take an procedure which calculates an 285 arbitrary function and it's derivative and minimize the chi-squared match 286 between that function at the specified coords and the specified value at those 287 coords. 288 289 XXX: Put the ASSERTS in. 127 290 128 291 XXX EAM this is my re-implementation of MinLM … … 135 298 XXX: Change the whole thing to F64, if input data is F32, convert it. 136 299 *****************************************************************************/ 137 psBool psMinimizeLMChi2(psMinimization *min, 138 psImage *covar, 139 psVector *params, 140 const psVector *paramMask, 141 const psArray *x, 142 const psVector *y, 143 const psVector *yErr, 144 psMinimizeLMChi2Func func) 145 { 300 psBool psMinimizeLMChi2( 301 psMinimization *min, 302 psImage *covar, 303 psVector *params, 304 const psVector *paramMask, 305 const psArray *x, 306 const psVector *y, 307 const psVector *yWt, 308 psMinimizeLMChi2Func func) 309 { 310 psTrace(__func__, 3, "---- %s() begin ----\n", __func__); 146 311 PS_ASSERT_PTR_NON_NULL(min, false); 312 // XXX: If covar not NULL, do asserts... 147 313 PS_ASSERT_VECTOR_NON_NULL(params, false); 148 314 PS_ASSERT_VECTOR_NON_EMPTY(params, false); … … 162 328 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, false); 163 329 PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, false); 164 if (y Err!= NULL) {165 PS_ASSERT_VECTOR_TYPE(y Err, PS_TYPE_F32, false);166 PS_ASSERT_VECTORS_SIZE_EQUAL(y, y Err, false);330 if (yWt != NULL) { 331 PS_ASSERT_VECTOR_TYPE(yWt, PS_TYPE_F32, false); 332 PS_ASSERT_VECTORS_SIZE_EQUAL(y, yWt, false); 167 333 } 168 334 PS_ASSERT_PTR_NON_NULL(func, false); … … 173 339 174 340 // allocate internal arrays (current vs Guess) 175 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64);176 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F64);177 psVector *beta = psVectorAlloc (params->n, PS_TYPE_F64);178 psVector *Beta = psVectorAlloc (params->n, PS_TYPE_F64);179 psVector *Params = psVectorAlloc (params->n, PS_TYPE_F32);341 psImage *alpha = psImageAlloc(params->n, params->n, PS_TYPE_F64); 342 psImage *Alpha = psImageAlloc(params->n, params->n, PS_TYPE_F64); 343 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F64); 344 psVector *Beta = psVectorAlloc(params->n, PS_TYPE_F64); 345 psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32); 180 346 psVector *dy = NULL; 181 347 psF64 Chisq = 0.0; 182 348 psF64 lambda = 0.001; 183 184 // XXX EAM: why is this needed here? the value is not used, and the memory 185 // is allocated above. However, if I drop it, I get weird answers or 186 // crashes. 187 Params = psVectorCopy (Params, params, PS_TYPE_F32); 349 // XXX: Code this properly. Don't use mustFree00. 350 psBool mustFree00 = false; 351 psVector *beta_lim = NULL; 352 psVector *param_min = NULL; 353 psVector *param_max = NULL; 354 355 // if we are provided a covar image, we expect to find these three vectors in first three rows 356 if (covar != NULL) { 357 mustFree00 = true; 358 beta_lim = psVectorAlloc(params->n, PS_TYPE_F32); 359 param_min = psVectorAlloc(params->n, PS_TYPE_F32); 360 param_max = psVectorAlloc(params->n, PS_TYPE_F32); 361 for (int i = 0; i < params->n; i++) { 362 beta_lim->data.F32[i] = covar->data.F64[0][i]; 363 param_min->data.F32[i] = covar->data.F64[1][i]; 364 param_max->data.F32[i] = covar->data.F64[2][i]; 365 } 366 psImageRecycle(covar, params->n, params->n, PS_TYPE_F64); 367 } 368 369 // why is this needed here??? the initial guess on params is provided by the user 370 Params = psVectorCopy(Params, params, PS_TYPE_F32); 188 371 189 372 // the user provides the error or NULL. we need to convert 190 373 // to appropriate weights 191 dy = psVectorAlloc (y->n, PS_TYPE_F32); 192 if (yErr != NULL) { 193 for (int i = 0; i < dy->n; i++) { 194 dy->data.F32[i] = 1.0 / PS_SQR (yErr->data.F32[i]); 195 } 374 if (yWt != NULL) { 375 dy = (psVector *) yWt; 196 376 } else { 197 for (int i = 0; i < dy->n; i++) { 198 dy->data.F32[i] = 1.0; 199 } 377 dy = psVectorAlloc(y->n, PS_TYPE_F32); 378 psVectorInit(dy, 1.0); 200 379 } 201 380 202 381 // calculate initial alpha and beta, set chisq (min->value) 203 min->value = p_psMinLM_SetABX (alpha, beta, params, paramMask, x, y, dy, func); 204 # ifndef PS_NO_TRACE 382 min->value = p_psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func); 383 if (isnan(min->value)) { 384 min->iter = min->maxIter; 385 return(false); 386 } 205 387 // dump some useful info if trace is defined 206 /* XXX: This code is seg faulting. 207 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 208 p_psImagePrint (psTraceGetDestination(), alpha, "alpha guess"); 209 p_psVectorPrint (psTraceGetDestination(), beta, "beta guess"); 210 p_psVectorPrint (psTraceGetDestination(), params, "params guess"); 211 } 212 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 4) { 213 // XXX: Where is this? 214 // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess"); 215 } 216 */ 217 # endif /* PS_NO_TRACE */ 218 219 min->lastDelta = min->tol + 1.0; 388 if (psTraceGetLevel(__func__) >= 6) { 389 p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)"); 390 p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)"); 391 p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)"); 392 } 393 if (psTraceGetLevel (__func__) >= 6) { 394 //XXX: p_psVectorPrintRow(psTraceGetDestination(), Params, "params guess"); 395 } 396 220 397 // iterate until the tolerance is reached, or give up 221 while ((min->lastDelta > min->tol) && (min->iter < min->maxIter)) { 398 while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) { 399 psTrace(__func__, 5, "Iteration number %d. (max iterations is %d).\n", min->iter, min->maxIter); 400 psTrace(__func__, 5, "Last delta is %f. Min->tol is %f.\n", min->lastDelta, min->tol); 401 222 402 // set a new guess for Alpha, Beta, Params 223 p_psMinLM_GuessABP (Alpha, Beta, Params, alpha, beta, params, paramMask, lambda); 403 p_psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, 404 beta_lim, param_min, param_max, lambda); 224 405 225 406 // measure linear model prediction 226 psF64 dLinear = p_psMinLM_dLinear (Beta, beta, lambda); 227 228 # ifndef PS_NO_TRACE 407 psF64 dLinear = p_psMinLM_dLinear(Beta, beta, lambda); 408 229 409 // dump some useful info if trace is defined 230 /* XXX: This code is seg faulting. 231 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 232 p_psImagePrint (psTraceGetDestination(), Alpha, "alpha guess"); 233 p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess"); 234 p_psVectorPrint (psTraceGetDestination(), Params, "params guess"); 235 } 236 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 4) { 237 // XXX: Where is this? 238 // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess"); 239 } 240 */ 241 # endif /* PS_NO_TRACE */ 410 if (psTraceGetLevel(__func__) >= 6) { 411 p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (1)"); 412 p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (1)"); 413 p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)"); 414 } 415 if (psTraceGetLevel(__func__) >= 6) { 416 //XXX: p_psVectorPrintRow(psTraceGetDestination(), Params, "params guess"); 417 } 242 418 243 419 // calculate Chisq for new guess, update Alpha & Beta 244 Chisq = p_psMinLM_SetABX (Alpha, Beta, Params, paramMask, x, y, dy, func);420 Chisq = p_psMinLM_SetABX(Alpha, Beta, Params, paramMask, x, y, dy, func); 245 421 246 422 // XXX EAM alternate convergence criterion: … … 250 426 psF64 rho = (min->value - Chisq) / dLinear; 251 427 252 psTrace (".psLib.dataManip.psMinimizeLMChi2", 4, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, Chisq, min->lastDelta, rho); 253 # ifndef PS_NO_TRACE 428 psTrace(__func__, 5, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, 429 Chisq, min->lastDelta, rho); 430 254 431 // dump some useful info if trace is defined 255 /* XXX: This code is seg faulting. 256 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) { 257 p_psImagePrint (psTraceGetDestination(), Alpha, "alpha guess"); 258 p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess"); 259 p_psVectorPrint (psTraceGetDestination(), Params, "params guess"); 260 } 261 */ 262 # endif /* PS_NO_TRACE */ 432 if (psTraceGetLevel(__func__) >= 6) { 433 p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)"); 434 p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)"); 435 p_psVectorPrint(psTraceGetDestination(), Params, "params guess (2)"); 436 } 263 437 264 438 /* if (Chisq < min->value) { */ … … 266 440 min->lastDelta = (min->value - Chisq) / (dy->n - params->n); 267 441 min->value = Chisq; 268 alpha = psImageCopy (alpha, Alpha, PS_TYPE_F64);269 beta = psVectorCopy (beta, Beta, PS_TYPE_F64);270 params = psVectorCopy (params, Params, PS_TYPE_F32);442 alpha = psImageCopy(alpha, Alpha, PS_TYPE_F64); 443 beta = psVectorCopy(beta, Beta, PS_TYPE_F64); 444 params = psVectorCopy(params, Params, PS_TYPE_F32); 271 445 lambda *= 0.1; 272 446 } else { 273 447 lambda *= 10.0; 274 448 } 275 min->iter ++; 276 277 // printf("CONDITIONS: (%f > %f) && (%d < %d)\n", min->lastDelta, min->tol, min->iter, min->maxIter); 278 } 279 psTrace (".psLib.dataManip.psMinimizeLMChi2", 4, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter); 449 min->iter++; 450 } 451 psTrace(__func__, 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter); 280 452 281 453 // construct & return the covariance matrix (if requested) 282 454 if (covar != NULL) { 283 p_psMinLM_GuessABP (covar, Beta, Params, alpha, beta, params, paramMask, 0.0); 455 p_psMinLM_GuessABP(covar, Beta, Params, alpha, beta, params, paramMask, 456 beta_lim, param_min, param_max, 0.0); 284 457 } 285 458 286 459 // free the internal temporary data 287 psFree (alpha); 288 psFree (Alpha); 289 psFree (beta); 290 psFree (Beta); 291 psFree (Params); 292 psFree (dy); 293 460 psFree(alpha); 461 psFree(Alpha); 462 psFree(beta); 463 psFree(Beta); 464 psFree(Params); 465 if (yWt == NULL) { 466 psFree(dy); 467 } 468 if (mustFree00 == true) { 469 psFree(beta_lim); 470 psFree(param_min); 471 psFree(param_max); 472 } 294 473 if (min->iter == min->maxIter) { 295 return (false); 296 } 297 return (true); 298 } 299 300 // XXX EAM: this needs to respect the mask on params 301 // alpha, beta, params are already allocated 302 psF64 p_psMinLM_SetABX (psImage *alpha, 303 psVector *beta, 304 const psVector *params, 305 const psVector *paramMask, 306 const psArray *x, 307 const psVector *y, 308 const psVector *dy, 309 psMinimizeLMChi2Func func) 310 { 311 PS_ASSERT_IMAGE_NON_NULL(alpha, NAN); 312 PS_ASSERT_VECTOR_NON_NULL(beta, NAN); 313 PS_ASSERT_VECTOR_NON_NULL(params, NAN); 314 PS_ASSERT_PTR_NON_NULL(x, NAN); 315 PS_ASSERT_VECTOR_NON_NULL(y, NAN); 316 PS_ASSERT_VECTOR_NON_NULL(dy, NAN); 317 318 psF64 chisq; 319 psF64 delta; 320 psF64 weight; 321 psF64 ymodel; 322 psVector *deriv = psVectorAlloc (params->n, PS_TYPE_F32); 323 324 // zero alpha and beta for summing below 325 for (int j = 0; j < params->n; j++) { 326 for (int k = 0; k < params->n; k++) { 327 alpha->data.F64[j][k] = 0; 328 } 329 beta->data.F64[j] = 0; 330 } 331 chisq = 0.0; 332 333 // calculate chisq, alpha, beta 334 for (int i = 0; i < y->n; i++) { 335 ymodel = func (deriv, params, (psVector *) x->data[i]); 336 337 delta = ymodel - y->data.F32[i]; 338 chisq += PS_SQR (delta) * dy->data.F32[i]; 339 340 for (int j = 0; j < params->n; j++) { 341 if ((paramMask != NULL) && (paramMask->data.U8[j])) 342 continue; 343 weight = deriv->data.F32[j] * dy->data.F32[i]; 344 for (int k = 0; k <= j; k++) { 345 if ((paramMask != NULL) && (paramMask->data.U8[k])) 346 continue; 347 alpha->data.F64[j][k] += weight * deriv->data.F32[k]; 348 } 349 beta->data.F64[j] += weight * delta; 350 } 351 } 352 353 // calculate lower-left half of alpha 354 for (int j = 1; j < params->n; j++) { 355 for (int k = 0; k < j; k++) { 356 alpha->data.F64[k][j] = alpha->data.F64[j][k]; 357 } 358 } 359 360 // fill in pivots if we apply a mask 361 if (paramMask != NULL) { 362 for (int j = 0; j < params->n; j++) { 363 if (paramMask->data.U8[j]) { 364 alpha->data.F64[j][j] = 1; 365 beta->data.F64[j] = 1; 366 } 367 } 368 } 369 370 psFree (deriv); 371 return (chisq); 372 } 373 374 // XXX EAM : can we use static copies of LUv, LUm, A? 375 psBool p_psMinLM_GuessABP (psImage *Alpha, 376 psVector *Beta, 377 psVector *Params, 378 const psImage *alpha, 379 const psVector *beta, 380 const psVector *params, 381 const psVector *paramMask, 382 psF64 lambda) 383 { 384 385 # define USE_LU_DECOMP 1 386 # if (USE_LU_DECOMP) 387 psVector *LUv = NULL; 388 psImage *LUm = NULL; 389 psImage *A = NULL; 390 psF32 det; 391 392 // LU decomposition version 393 psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using LUD version\n"); 394 395 // set new guess values (creates matrix A) 396 A = psImageCopy (NULL, alpha, PS_TYPE_F64); 397 for (int j = 0; j < params->n; j++) { 398 if ((paramMask != NULL) && (paramMask->data.U8[j])) 399 continue; 400 A->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 401 } 402 403 // solve A*beta = Beta (Alpha = 1/A) 404 // these operations do not modify the input values (creates LUm, LUv) 405 LUm = psMatrixLUD (NULL, &LUv, A); 406 Beta = psMatrixLUSolve (Beta, LUm, beta, LUv); 407 Alpha = psMatrixInvert (Alpha, A, &det); 408 409 # else 410 // gauss-jordan version 411 psTrace (".psLib.dataManip.psMinLM_GuessABP", 5, "using Gauss-J version"); 412 413 // set new guess values (creates matrix A) 414 Beta = psVectorCopy (Beta, beta, PS_TYPE_F64); 415 Alpha = psImageCopy (Alpha, alpha, PS_TYPE_F64); 416 for (int j = 0; j < params->n; j++) { 417 if ((paramMask != NULL) && (paramMask->data.U8[j])) 418 continue; 419 Alpha->data.F64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda); 420 } 421 422 psGaussJordan (Alpha, Beta); 423 # endif 424 425 // apply Beta to get new Params values 426 for (int j = 0; j < params->n; j++) { 427 if ((paramMask != NULL) && (paramMask->data.U8[j])) 428 continue; 429 Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 430 } 431 432 # if (USE_LU_DECOMP) 433 psFree (A); 434 psFree (LUm); 435 psFree (LUv); 436 # endif 437 438 return true; 474 psTrace(__func__, 3, "---- %s(false) end ----\n", __func__); 475 return(false); 476 } 477 psTrace(__func__, 3, "---- %s(true) end ----\n", __func__); 478 return(true); 439 479 } 440 480 441 481 // XXX EAM : temporary gauss-jordan solver based on gene's 442 482 // version based on the Numerical Recipes version 443 bool psGaussJordan (psImage *a, psVector *b) 483 bool psGaussJordan( 484 psImage *a, 485 psVector *b) 444 486 { 445 487 … … 455 497 vector = b->data.F64; 456 498 457 indxc = psAlloc (Nx*sizeof(int));458 indxr = psAlloc (Nx*sizeof(int));459 ipiv = psAlloc (Nx*sizeof(int));499 indxc = psAlloc(Nx*sizeof(int)); 500 indxr = psAlloc(Nx*sizeof(int)); 501 ipiv = psAlloc(Nx*sizeof(int)); 460 502 for (j = 0; j < Nx; j++) { 461 503 ipiv[j] = 0; … … 476 518 if (ipiv[k] == 0) { 477 519 if (fabs (matrix[j][k]) >= big) { 478 big = fabs (matrix[j][k]);520 big = fabs(matrix[j][k]); 479 521 irow = j; 480 522 icol = k; … … 492 534 if (irow != icol) { 493 535 for (l = 0; l < Nx; l++) { 494 PS_SWAP (matrix[irow][l], matrix[icol][l]);495 } 496 PS_SWAP (vector[irow], vector[icol]);536 PS_SWAP(matrix[irow][l], matrix[icol][l]); 537 } 538 PS_SWAP(vector[irow], vector[icol]); 497 539 } 498 540 indxr[i] = irow; … … 524 566 if (indxr[l] != indxc[l]) { 525 567 for (k = 0; k < Nx; k++) { 526 PS_SWAP (matrix[k][indxr[l]], matrix[k][indxc[l]]);527 } 528 } 529 } 530 psFree (ipiv);531 psFree (indxr);532 psFree (indxc);533 return (true);568 PS_SWAP(matrix[k][indxr[l]], matrix[k][indxc[l]]); 569 } 570 } 571 } 572 psFree(ipiv); 573 psFree(indxr); 574 psFree(indxc); 575 return(true); 534 576 535 577 fescape: 536 psFree (ipiv);537 psFree (indxr);538 psFree (indxc);539 return (false);578 psFree(ipiv); 579 psFree(indxr); 580 psFree(indxc); 581 return(false); 540 582 } 541 583 … … 565 607 bool psMemCheckMinimization(psPtr ptr) 566 608 { 567 return ( psMemGetDeallocator(ptr) == (psFreeFunc)minimizationFree );609 return( psMemGetDeallocator(ptr) == (psFreeFunc)minimizationFree ); 568 610 } 569 611 -
trunk/psLib/src/math/psMinimize.h
r4991 r5175 8 8 * @author GLG, MHPCC 9 9 * 10 * @version $Revision: 1.5 7$ $Name: not supported by cvs2svn $11 * @date $Date: 2005-09- 11 22:18:40$10 * @version $Revision: 1.58 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2005-09-29 02:13:54 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 202 202 psMinimizeLMChi2Func func ///< Specified function 203 203 ); 204 bool psMinimizeLMChi2_OLD( 205 psMinimization *min, ///< Minimization specification 206 psImage *covar, ///< Covariance matrix 207 psVector *params, ///< "Best Guess" for the parameters that minimize func 208 const psVector *paramMask, ///< Parameters to be held fixed by the minimizer 209 const psArray *x, ///< Measurement ordinates of multiple vectors 210 const psVector *y, ///< Measurement coordinates 211 const psVector *yErr, ///< Errors in the measurement coordinates 212 psMinimizeLMChi2Func func ///< Specified function 213 ); 204 214 205 215 bool psMinimizeGaussNewtonDelta ( … … 217 227 * @return psBool: True if successful. 218 228 */ 219 psBool p_psMinLM_GuessABP (229 psBool p_psMinLM_GuessABP_OLD( 220 230 psImage *Alpha, ///< New Alpha guess 221 231 psVector *Beta, ///< New Beta guess -
trunk/psLib/test/math/tst_psMinimize06.c
r4859 r5175 7 7 #include <math.h> 8 8 #define NUM_ITERATIONS 100 9 #define ERR_TOL 0. 09 #define ERR_TOL 0.1 10 10 #define NUM_DATA_POINTS 20 11 11 #define NUM_PARAMS 5 … … 45 45 } 46 46 47 48 47 psS32 t01() 49 48 { … … 63 62 ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10); 64 63 ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3); 65 /* 66 printf("x[%d] is vector (%f, %f)\n", i, ((psVector *) (myCoords->data[i]))->data.F32[0], 67 ((psVector *) (myCoords->data[i]))->data.F32[1]); 68 */ 64 psTrace(__func__, 5, "x[%d] is vector (%f, %f)\n", i, ((psVector *) (myCoords->data[i]))->data.F32[0], 65 ((psVector *) (myCoords->data[i]))->data.F32[1]); 69 66 y->data.F32[i] = (float) i; 70 67 } … … 74 71 } 75 72 76 psMinimizeLMChi2(min, 77 myCovar, 78 myParams, 79 NULL, 80 myCoords, 81 y, 82 NULL, 83 (psMinimizeLMChi2Func) myFunc); 73 psBool rc = psMinimizeLMChi2(min, 74 NULL, 75 myParams, 76 NULL, 77 myCoords, 78 y, 79 NULL, 80 (psMinimizeLMChi2Func) myFunc); 81 if (rc == false) { 82 printf("TEST ERROR: psMinimizeLMChi2() returned FALSE.\n"); 83 fflush(stdout); 84 testStatus = false; 85 } else { 86 printf("\nThe value of the function at the minimum is %f\n", min->value); 87 for (psS32 i=0;i<NUM_DATA_POINTS;i++) { 88 printf("The minimum for data point %d: %f\n", i, myFunc(myDerivs, myParams, (psVector *) myCoords->data[i])); 89 fflush(stdout); 90 } 84 91 85 printf("\nThe value of the function at the minimum is %f\n", min->value); 86 for (psS32 i=0;i<NUM_DATA_POINTS;i++) { 87 printf("The minimum for data point %d: %f\n", i, myFunc(myDerivs, myParams, (psVector *) myCoords->data[i])); 88 } 89 90 for (psS32 i=0;i<NUM_PARAMS;i++) { 91 printf("Parameter %d at the minimum is %f (expected: %f)\n", i, 92 myParams->data.F32[i], expectedParm[i]); 92 for (psS32 i=0;i<NUM_PARAMS;i++) { 93 printf("Parameter %d at the minimum is %f (expected: %f)\n", i, 94 myParams->data.F32[i], expectedParm[i]); 95 fflush(stdout); 96 } 93 97 } 94 98 … … 99 103 psFree(myCoords); 100 104 psFree(y); 101 102 105 psMemCheckCorruption(1); 103 psS32 memLeaks = psMemCheckLeaks(currentId, NULL,NULL,false);106 psS32 memLeaks = psMemCheckLeaks(currentId, NULL, NULL, false); 104 107 if (0 != memLeaks) { 108 printf("TEST ERROR: Memory Leaks! (%d leaks).\n", memLeaks); 109 fflush(stdout); 110 // XXX: This is causing a seg fault 105 111 psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks); 106 112 } … … 108 114 } 109 115 116 117 110 118 psS32 main() 111 119 { 112 120 psLogSetFormat("HLNM"); 121 psTraceSetDestination(1); 122 psTraceSetLevel(".", 0); 123 psTraceSetLevel(__func__, 10); 124 psTraceSetLevel("t01", 10); 125 psTraceSetLevel("psMinimizeLMChi2_OLD", 10); 126 psTraceSetLevel("psMinimizeLMChi2", 10); 127 psTraceSetLevel("psMinimizeGaussNewtonDelta", 0); 128 psTraceSetLevel("psMinimizeGaussNewtonDelta_EAM", 0); 129 psTraceSetLevel("p_psMinLM_GuessABP", 0); 130 psTraceSetLevel("p_psMinLM_GuessABP_EAM", 0); 131 psTraceSetLevel("p_psMinLM_SetABX", 0); 132 psTraceSetLevel("psGaussJordan", 0); 133 psTraceSetLevel("psMinimizationAlloc", 0); 134 psTraceSetLevel("psMemCheckMinimization", 0); 135 psTraceSetLevel("p_psDetermineBracket", 0); 136 psTraceSetLevel("p_psDetermineBracket2", 0); 137 psTraceSetLevel("p_psLineMin", 0); 138 psTraceSetLevel("psMinimizePowell", 0); 139 psTraceSetLevel("myPowellChi2Func", 0); 140 psTraceSetLevel("psMinimizeChi2Powell", 0); 141 psTraceSetLevel("BuildSums1D", 0); 142 psTraceSetLevel("BuildSums2D", 0); 143 psTraceSetLevel("Polynomial2DEvalVectorD", 0); 144 psTraceSetLevel("vectorFitPolynomial1DCheby", 0); 145 psTraceSetLevel("VectorFitPolynomial1DOrd", 0); 146 psTraceSetLevel("psVectorFitPolynomial1D", 0); 147 psTraceSetLevel("psVectorClipFitPolynomial1D", 0); 148 149 psTrace(__func__, 2, "Calling new psMinimize().\n"); 113 150 t01(); 151 printf("DONE\n"); 152 fflush(stdout); 114 153 } 154 //is the way 155
Note:
See TracChangeset
for help on using the changeset viewer.
