Changeset 10253 for trunk/psLib/src/math/psMinimizeLMM.c
- Timestamp:
- Nov 28, 2006, 4:25:14 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMinimizeLMM.c (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimizeLMM.c
r10192 r10253 10 10 * @author EAM, IfA 11 11 * 12 * @version $Revision: 1.2 6$ $Name: not supported by cvs2svn $13 * @date $Date: 2006-11-2 6 21:53:57$12 * @version $Revision: 1.27 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2006-11-29 02:25:14 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 49 49 /*****************************************************************************/ 50 50 51 // XXX EAM : can we use static copies of LUv, LUm, A?52 51 psBool p_psMinLM_GuessABP( 53 52 psImage *Alpha, … … 58 57 const psVector *params, 59 58 const psVector *paramMask, 60 const psVector *beta_lim, 61 const psVector *params_min, 62 const psVector *params_max, 63 psF64 lambda) 64 { 65 PS_ASSERT_VECTOR_TYPE(Alpha, PS_TYPE_F64, false); 66 PS_ASSERT_VECTOR_TYPE(Beta, PS_TYPE_F64, false); 59 psMinimizeLMLimitFunc checkLimits, 60 psF32 lambda) 61 { 62 PS_ASSERT_VECTOR_TYPE(Alpha, PS_TYPE_F32, false); 63 PS_ASSERT_VECTOR_TYPE(Beta, PS_TYPE_F32, false); 67 64 PS_ASSERT_VECTOR_TYPE(Params, PS_TYPE_F32, false); 68 PS_ASSERT_VECTOR_TYPE(alpha, PS_TYPE_F 64, false);69 PS_ASSERT_VECTOR_TYPE(beta, PS_TYPE_F 64, false);65 PS_ASSERT_VECTOR_TYPE(alpha, PS_TYPE_F32, false); 66 PS_ASSERT_VECTOR_TYPE(beta, PS_TYPE_F32, false); 70 67 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false); 71 68 if (paramMask) { … … 73 70 } 74 71 72 // XXX the LU Decomposition code requires F64. this is now incompatible 73 // with the rest of this code. drop this segment when the changes are tested. 75 74 # define USE_LU_DECOMP 0 76 75 # if (USE_LU_DECOMP) … … 115 114 116 115 // set new guess values (creates matrix A) 117 Beta = psVectorCopy(Beta, beta, PS_TYPE_F 64);118 Alpha = psImageCopy(Alpha, alpha, PS_TYPE_F 64);116 Beta = psVectorCopy(Beta, beta, PS_TYPE_F32); 117 Alpha = psImageCopy(Alpha, alpha, PS_TYPE_F32); 119 118 for (int j = 0; j < params->n; j++) { 120 119 if ((paramMask != NULL) && (paramMask->data.U8[j])) { 121 120 continue; 122 121 } 123 Alpha->data.F 64[j][j] = alpha->data.F64[j][j] * (1.0 + lambda);124 } 125 126 if (false == psMatrixGJSolve (Alpha, Beta)) {122 Alpha->data.F32[j][j] = alpha->data.F32[j][j] * (1.0 + lambda); 123 } 124 125 if (false == psMatrixGJSolveF32(Alpha, Beta)) { 127 126 // psError(PS_ERR_UNKNOWN, false, "singular matrix in Guess ABP\n"); 128 127 psTrace ("psLib.math", 4, "singular matrix in Guess ABP\n"); … … 137 136 continue; 138 137 } 139 // Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 140 // compare Beta to beta limits 141 if (beta_lim != NULL) { 142 if (fabs(Beta->data.F64[j]) > fabs(beta_lim->data.F32[j])) { 143 Beta->data.F64[j] = (Beta->data.F64[j] > 0) ? fabs(beta_lim->data.F32[j]) : -fabs(beta_lim->data.F32[j]); 144 } 145 } 146 Params->data.F32[j] = params->data.F32[j] - Beta->data.F64[j]; 138 // apply beta limits 139 if (checkLimits) 140 checkLimits (PS_MINIMIZE_BETA_LIMIT, j, Params->data.F32, Beta->data.F32); 141 Params->data.F32[j] = params->data.F32[j] - Beta->data.F32[j]; 142 147 143 // compare new params to param limits 148 if (params_max != NULL) { 149 Params->data.F32[j] = PS_MIN (Params->data.F32[j], params_max->data.F32[j]); 150 } 151 if (params_min != NULL) { 152 Params->data.F32[j] = PS_MAX (Params->data.F32[j], params_min->data.F32[j]); 153 } 154 } 155 156 144 if (checkLimits) 145 checkLimits (PS_MINIMIZE_PARAM_MIN, j, Params->data.F32, Beta->data.F32); 146 if (checkLimits) 147 checkLimits (PS_MINIMIZE_PARAM_MAX, j, Params->data.F32, Beta->data.F32); 148 } 157 149 return(true); 158 150 } 159 160 151 161 152 bool psMinimizeGaussNewtonDelta( … … 170 161 psTrace("psLib.math", 3, "---- begin ----\n"); 171 162 // allocate internal arrays (current vs Guess) 172 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F 64);173 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F 64);174 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F 64);163 psImage *alpha = psImageAlloc (params->n, params->n, PS_TYPE_F32); 164 psImage *Alpha = psImageAlloc (params->n, params->n, PS_TYPE_F32); 165 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F32); 175 166 psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32); 176 167 psVector *dy = NULL; … … 186 177 } 187 178 188 psF64 rcF64 = p_psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func); 189 if (isnan(rcF64)) { 179 // XXX should we give up if chisq is nan? 180 psF32 rcF32 = p_psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func); 181 if (isnan(rcF32)) { 190 182 psTrace ("psLib.math", 5, "p_psMinLM_SetABX() returned a NAN.\n"); 191 183 rc = false; … … 199 191 } 200 192 201 psBool rcBool = p_psMinLM_GuessABP(Alpha, delta, Params, alpha, beta, params, paramMask, NULL, NULL, NULL,0.0);193 psBool rcBool = p_psMinLM_GuessABP(Alpha, delta, Params, alpha, beta, params, paramMask, NULL, 0.0); 202 194 if (rcBool == false) { 203 195 psTrace ("psLib.math", 5, "p_psMinLM_GuessABP() returned FALSE.\n"); … … 223 215 224 216 // measure linear model prediction 225 psF 64p_psMinLM_dLinear(217 psF32 p_psMinLM_dLinear( 226 218 const psVector *Beta, 227 219 const psVector *beta, 228 psF 64lambda)220 psF32 lambda) 229 221 { 230 222 231 223 /* get linear model prediction */ 232 psF 64dLinear = 0;233 psF 64 *B = Beta->data.F64;234 psF 64 *b = beta->data.F64;224 psF32 dLinear = 0; 225 psF32 *B = Beta->data.F32; 226 psF32 *b = beta->data.F32; 235 227 for (int i = 0; i < beta->n; i++) { 236 228 dLinear += lambda*PS_SQR(B[i]) + B[i]*b[i]; … … 239 231 } 240 232 241 // XXX EAM: this needs to respect the mask on params242 233 // alpha, beta, params are already allocated 243 psF 64p_psMinLM_SetABX(234 psF32 p_psMinLM_SetABX( 244 235 psImage *alpha, 245 236 psVector *beta, … … 259 250 PS_ASSERT_VECTOR_NON_NULL(dy, NAN); 260 251 261 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32,false);252 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false); 262 253 if (paramMask) { 263 254 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false); 264 255 } 265 256 266 psF 64chisq;267 psF 64delta;268 psF 64weight;269 psF 64ymodel;257 psF32 chisq; 258 psF32 delta; 259 psF32 weight; 260 psF32 ymodel; 270 261 psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32); 271 262 … … 273 264 for (psS32 j = 0; j < params->n; j++) { 274 265 for (psS32 k = 0; k < params->n; k++) { 275 alpha->data.F 64[j][k] = 0;276 } 277 beta->data.F 64[j] = 0;266 alpha->data.F32[j][k] = 0; 267 } 268 beta->data.F32[j] = 0; 278 269 } 279 270 chisq = 0.0; … … 301 292 continue; 302 293 } 303 alpha->data.F 64[j][k] += weight * deriv->data.F32[k];294 alpha->data.F32[j][k] += weight * deriv->data.F32[k]; 304 295 } 305 beta->data.F 64[j] += weight * delta;296 beta->data.F32[j] += weight * delta; 306 297 } 307 298 } … … 310 301 for (psS32 j = 1; j < params->n; j++) { 311 302 for (psS32 k = 0; k < j; k++) { 312 alpha->data.F 64[k][j] = alpha->data.F64[j][k];303 alpha->data.F32[k][j] = alpha->data.F32[j][k]; 313 304 } 314 305 } … … 318 309 for (psS32 j = 0; j < params->n; j++) { 319 310 if (paramMask->data.U8[j]) { 320 alpha->data.F 64[j][j] = 1;321 beta->data.F 64[j] = 1;311 alpha->data.F32[j][j] = 1; 312 beta->data.F32[j] = 1; 322 313 } 323 314 } … … 335 326 coords. 336 327 337 XXX: This must work for both F32 and F64. F32 is currently implemented. 338 Note: since the LUD routines are only implemented in F64, then we 339 will have to convert all F32 input vectors to F64 regardless. So, 340 the F64 port might be an optimization. 341 328 This requires F32 input data; all internal calls use F32. 329 XXX Make an F64 version? 342 330 *****************************************************************************/ 343 331 psBool psMinimizeLMChi2( … … 345 333 psImage *covar, 346 334 psVector *params, 347 psMinConstrain *constrain,335 psMinConstraint *constraint, 348 336 const psArray *x, 349 337 const psVector *y, … … 357 345 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false); 358 346 psVector *paramMask = NULL; 359 psVector *paramDelta = NULL; 360 psVector *paramMin = NULL; 361 psVector *paramMax = NULL; 362 if (constrain != NULL) { 363 paramDelta = constrain->paramDelta; 364 paramMin = constrain->paramMin; 365 paramMax = constrain->paramMax; 366 paramMask = constrain->paramMask; 367 PS_ASSERT_VECTOR_TYPE(paramDelta, PS_TYPE_F32, false); 368 PS_ASSERT_VECTOR_TYPE(paramMin, PS_TYPE_F32, false); 369 PS_ASSERT_VECTOR_TYPE(paramMax, PS_TYPE_F32, false); 370 PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramDelta, false); 371 PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMin, false); 372 PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMax, false); 347 if (constraint != NULL) { 348 paramMask = constraint->paramMask; 373 349 if (paramMask != NULL) { 374 350 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false); … … 392 368 PS_ASSERT_PTR_NON_NULL(func, false); 393 369 370 psMinimizeLMLimitFunc checkLimits = NULL; 371 if (constraint) { 372 checkLimits = constraint->checkLimits; 373 } 374 394 375 // this function has test and current values for several things 395 376 // the current best value is in lower case … … 397 378 398 379 // allocate internal arrays (current vs Guess) 399 psImage *alpha = psImageAlloc(params->n, params->n, PS_TYPE_F 64);400 psImage *Alpha = psImageAlloc(params->n, params->n, PS_TYPE_F 64);401 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F 64);402 psVector *Beta = psVectorAlloc(params->n, PS_TYPE_F 64);380 psImage *alpha = psImageAlloc(params->n, params->n, PS_TYPE_F32); 381 psImage *Alpha = psImageAlloc(params->n, params->n, PS_TYPE_F32); 382 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F32); 383 psVector *Beta = psVectorAlloc(params->n, PS_TYPE_F32); 403 384 psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32); 404 385 psVector *dy = NULL; 405 psF 64Chisq = 0.0;406 psF 64lambda = 0.001;386 psF32 Chisq = 0.0; 387 psF32 lambda = 0.001; 407 388 408 389 // the user provides the error or NULL. we need to convert … … 436 417 437 418 // set a new guess for Alpha, Beta, Params 438 if (!p_psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, 439 paramDelta, paramMin, paramMax, lambda)) { 419 if (!p_psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda)) { 440 420 min->iter ++; 441 421 lambda *= 10.0; … … 444 424 445 425 // measure linear model prediction 446 psF 64dLinear = p_psMinLM_dLinear(Beta, beta, lambda);426 psF32 dLinear = p_psMinLM_dLinear(Beta, beta, lambda); 447 427 448 428 // dump some useful info if trace is defined … … 467 447 // expected delta from the linear model (dLinear) 468 448 // accept new guess if it is an improvement (rho > 0), or else increase lambda 469 psF 64rho = (min->value - Chisq) / dLinear;449 psF32 rho = (min->value - Chisq) / dLinear; 470 450 471 451 psTrace("psLib.math", 5, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, … … 482 462 min->lastDelta = (min->value - Chisq) / (dy->n - params->n); 483 463 min->value = Chisq; 484 alpha = psImageCopy(alpha, Alpha, PS_TYPE_F 64);485 beta = psVectorCopy(beta, Beta, PS_TYPE_F 64);464 alpha = psImageCopy(alpha, Alpha, PS_TYPE_F32); 465 beta = psVectorCopy(beta, Beta, PS_TYPE_F32); 486 466 params = psVectorCopy(params, Params, PS_TYPE_F32); 487 467 lambda *= 0.1; … … 495 475 // construct & return the covariance matrix (if requested) 496 476 if (covar != NULL) { 497 if (!p_psMinLM_GuessABP(covar, Beta, Params, alpha, beta, params, paramMask, 498 paramDelta, paramMin, paramMax, 0.0)) { 477 if (!p_psMinLM_GuessABP(covar, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0)) { 499 478 psTrace ("psLib.math", 5, "failure to calculate covariance matrix\n"); 500 479 } … … 546 525 547 526 548 static void constrainFree(psMinConstrain *tmp) 549 { 550 // There are no dynamically allocated items 551 } 552 553 psMinConstrain* psMinConstrainAlloc() 554 { 555 psMinConstrain *tmp = psAlloc(sizeof(psMinConstrain)); 527 static void constraintFree(psMinConstraint *tmp) 528 { 529 if (tmp == NULL) 530 return; 531 532 psFree (tmp->paramMask); 533 } 534 535 psMinConstraint* psMinConstraintAlloc() 536 { 537 psMinConstraint *tmp = psAlloc(sizeof(psMinConstraint)); 538 psMemSetDeallocator(tmp, (psFreeFunc)constraintFree); 556 539 tmp->paramMask = NULL; 557 tmp->paramMax = NULL; 558 tmp->paramMin = NULL; 559 tmp->paramDelta = NULL; 540 tmp->checkLimits = NULL; 560 541 561 542 return(tmp); 562 543 } 563 544 564 bool psMemCheckConstrain (psPtr tmp)565 { 566 return(psMemGetDeallocator(tmp) == (psFreeFunc) constrain Free);567 } 545 bool psMemCheckConstraint(psPtr tmp) 546 { 547 return(psMemGetDeallocator(tmp) == (psFreeFunc) constraintFree); 548 }
Note:
See TracChangeset
for help on using the changeset viewer.
