1 #include <../src/tao/matrix/lmvmmat.h> 2 #include <../src/tao/unconstrained/impls/ntr/ntrimpl.h> 3 4 #include <petscksp.h> 5 6 #define NTR_PC_NONE 0 7 #define NTR_PC_AHESS 1 8 #define NTR_PC_BFGS 2 9 #define NTR_PC_PETSC 3 10 #define NTR_PC_TYPES 4 11 12 #define BFGS_SCALE_AHESS 0 13 #define BFGS_SCALE_BFGS 1 14 #define BFGS_SCALE_TYPES 2 15 16 #define NTR_INIT_CONSTANT 0 17 #define NTR_INIT_DIRECTION 1 18 #define NTR_INIT_INTERPOLATION 2 19 #define NTR_INIT_TYPES 3 20 21 #define NTR_UPDATE_REDUCTION 0 22 #define NTR_UPDATE_INTERPOLATION 1 23 #define NTR_UPDATE_TYPES 2 24 25 static const char *NTR_PC[64] = {"none","ahess","bfgs","petsc"}; 26 27 static const char *BFGS_SCALE[64] = {"ahess","bfgs"}; 28 29 static const char *NTR_INIT[64] = {"constant","direction","interpolation"}; 30 31 static const char *NTR_UPDATE[64] = {"reduction","interpolation"}; 32 33 /* Routine for BFGS preconditioner */ 34 #undef __FUNCT__ 35 #define __FUNCT__ "MatLMVMSolveShell" 36 static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) 37 { 38 PetscErrorCode ierr; 39 Mat M; 40 PetscFunctionBegin; 41 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 42 PetscValidHeaderSpecific(b,VEC_CLASSID,2); 43 PetscValidHeaderSpecific(x,VEC_CLASSID,3); 44 ierr = PCShellGetContext(pc,(void**)&M);CHKERRQ(ierr); 45 ierr = MatLMVMSolve(M, b, x);CHKERRQ(ierr); 46 PetscFunctionReturn(0); 47 } 48 49 /* 50 TaoSolve_NTR - Implements Newton's Method with a trust region approach 51 for solving unconstrained minimization problems. 52 53 The basic algorithm is taken from MINPACK-2 (dstrn). 54 55 TaoSolve_NTR computes a local minimizer of a twice differentiable function 56 f by applying a trust region variant of Newton's method. At each stage 57 of the algorithm, we use the prconditioned conjugate gradient method to 58 determine an approximate minimizer of the quadratic equation 59 60 q(s) = <s, Hs + g> 61 62 subject to the trust region constraint 63 64 || s ||_M <= radius, 65 66 where radius is the trust region radius and M is a symmetric positive 67 definite matrix (the preconditioner). Here g is the gradient and H 68 is the Hessian matrix. 69 70 Note: TaoSolve_NTR MUST use the iterative solver KSPCGNASH, KSPCGSTCG, 71 or KSPCGGLTR. Thus, we set KSPCGNASH, KSPCGSTCG, or KSPCGGLTR in this 72 routine regardless of what the user may have previously specified. 73 */ 74 #undef __FUNCT__ 75 #define __FUNCT__ "TaoSolve_NTR" 76 static PetscErrorCode TaoSolve_NTR(Tao tao) 77 { 78 TAO_NTR *tr = (TAO_NTR *)tao->data; 79 KSPType ksp_type; 80 PetscBool is_nash,is_stcg,is_gltr; 81 KSPConvergedReason ksp_reason; 82 PC pc; 83 TaoConvergedReason reason; 84 PetscReal fmin, ftrial, prered, actred, kappa, sigma, beta; 85 PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; 86 PetscReal f, gnorm; 87 88 PetscReal delta; 89 PetscReal norm_d; 90 PetscErrorCode ierr; 91 PetscInt bfgsUpdates = 0; 92 PetscInt needH; 93 94 PetscInt i_max = 5; 95 PetscInt j_max = 1; 96 PetscInt i, j, N, n, its; 97 98 PetscFunctionBegin; 99 if (tao->XL || tao->XU || tao->ops->computebounds) { 100 ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by ntr algorithm\n");CHKERRQ(ierr); 101 } 102 103 ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr); 104 ierr = PetscStrcmp(ksp_type,KSPCGNASH,&is_nash);CHKERRQ(ierr); 105 ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&is_stcg);CHKERRQ(ierr); 106 ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&is_gltr);CHKERRQ(ierr); 107 if (!is_nash && !is_stcg && !is_gltr) { 108 SETERRQ(PETSC_COMM_SELF,1,"TAO_NTR requires nash, stcg, or gltr for the KSP"); 109 } 110 111 /* Initialize the radius and modify if it is too large or small */ 112 tao->trust = tao->trust0; 113 tao->trust = PetscMax(tao->trust, tr->min_radius); 114 tao->trust = PetscMin(tao->trust, tr->max_radius); 115 116 if (NTR_PC_BFGS == tr->pc_type && !tr->M) { 117 ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); 118 ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); 119 ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&tr->M);CHKERRQ(ierr); 120 ierr = MatLMVMAllocateVectors(tr->M,tao->solution);CHKERRQ(ierr); 121 } 122 123 /* Check convergence criteria */ 124 ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient);CHKERRQ(ierr); 125 ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 126 if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Inf or NaN"); 127 needH = 1; 128 129 ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); 130 if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 131 132 /* Create vectors for the limited memory preconditioner */ 133 if ((NTR_PC_BFGS == tr->pc_type) && (BFGS_SCALE_BFGS != tr->bfgs_scale_type)) { 134 if (!tr->Diag) { 135 ierr = VecDuplicate(tao->solution, &tr->Diag);CHKERRQ(ierr); 136 } 137 } 138 139 /* Modify the preconditioner to use the bfgs approximation */ 140 ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); 141 switch(tr->pc_type) { 142 case NTR_PC_NONE: 143 ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); 144 ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 145 break; 146 147 case NTR_PC_AHESS: 148 ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr); 149 ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 150 ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr); 151 break; 152 153 case NTR_PC_BFGS: 154 ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr); 155 ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 156 ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr); 157 ierr = PCShellSetContext(pc, tr->M);CHKERRQ(ierr); 158 ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr); 159 break; 160 161 default: 162 /* Use the pc method set by pc_type */ 163 break; 164 } 165 166 /* Initialize trust-region radius */ 167 switch(tr->init_type) { 168 case NTR_INIT_CONSTANT: 169 /* Use the initial radius specified */ 170 break; 171 172 case NTR_INIT_INTERPOLATION: 173 /* Use the initial radius specified */ 174 max_radius = 0.0; 175 176 for (j = 0; j < j_max; ++j) { 177 fmin = f; 178 sigma = 0.0; 179 180 if (needH) { 181 ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 182 needH = 0; 183 } 184 185 for (i = 0; i < i_max; ++i) { 186 187 ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); 188 ierr = VecAXPY(tr->W, -tao->trust/gnorm, tao->gradient);CHKERRQ(ierr); 189 ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); 190 191 if (PetscIsInfOrNanReal(ftrial)) { 192 tau = tr->gamma1_i; 193 } 194 else { 195 if (ftrial < fmin) { 196 fmin = ftrial; 197 sigma = -tao->trust / gnorm; 198 } 199 200 ierr = MatMult(tao->hessian, tao->gradient, tao->stepdirection);CHKERRQ(ierr); 201 ierr = VecDot(tao->gradient, tao->stepdirection, &prered);CHKERRQ(ierr); 202 203 prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm)); 204 actred = f - ftrial; 205 if ((PetscAbsScalar(actred) <= tr->epsilon) && 206 (PetscAbsScalar(prered) <= tr->epsilon)) { 207 kappa = 1.0; 208 } 209 else { 210 kappa = actred / prered; 211 } 212 213 tau_1 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust + (1.0 - tr->theta_i) * prered - actred); 214 tau_2 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust - (1.0 + tr->theta_i) * prered + actred); 215 tau_min = PetscMin(tau_1, tau_2); 216 tau_max = PetscMax(tau_1, tau_2); 217 218 if (PetscAbsScalar(kappa - 1.0) <= tr->mu1_i) { 219 /* Great agreement */ 220 max_radius = PetscMax(max_radius, tao->trust); 221 222 if (tau_max < 1.0) { 223 tau = tr->gamma3_i; 224 } 225 else if (tau_max > tr->gamma4_i) { 226 tau = tr->gamma4_i; 227 } 228 else { 229 tau = tau_max; 230 } 231 } 232 else if (PetscAbsScalar(kappa - 1.0) <= tr->mu2_i) { 233 /* Good agreement */ 234 max_radius = PetscMax(max_radius, tao->trust); 235 236 if (tau_max < tr->gamma2_i) { 237 tau = tr->gamma2_i; 238 } 239 else if (tau_max > tr->gamma3_i) { 240 tau = tr->gamma3_i; 241 } 242 else { 243 tau = tau_max; 244 } 245 } 246 else { 247 /* Not good agreement */ 248 if (tau_min > 1.0) { 249 tau = tr->gamma2_i; 250 } 251 else if (tau_max < tr->gamma1_i) { 252 tau = tr->gamma1_i; 253 } 254 else if ((tau_min < tr->gamma1_i) && (tau_max >= 1.0)) { 255 tau = tr->gamma1_i; 256 } 257 else if ((tau_1 >= tr->gamma1_i) && (tau_1 < 1.0) && 258 ((tau_2 < tr->gamma1_i) || (tau_2 >= 1.0))) { 259 tau = tau_1; 260 } 261 else if ((tau_2 >= tr->gamma1_i) && (tau_2 < 1.0) && 262 ((tau_1 < tr->gamma1_i) || (tau_2 >= 1.0))) { 263 tau = tau_2; 264 } 265 else { 266 tau = tau_max; 267 } 268 } 269 } 270 tao->trust = tau * tao->trust; 271 } 272 273 if (fmin < f) { 274 f = fmin; 275 ierr = VecAXPY(tao->solution, sigma, tao->gradient);CHKERRQ(ierr); 276 ierr = TaoComputeGradient(tao,tao->solution, tao->gradient);CHKERRQ(ierr); 277 278 ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 279 280 if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 281 needH = 1; 282 283 ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); 284 if (reason != TAO_CONTINUE_ITERATING) { 285 PetscFunctionReturn(0); 286 } 287 } 288 } 289 tao->trust = PetscMax(tao->trust, max_radius); 290 291 /* Modify the radius if it is too large or small */ 292 tao->trust = PetscMax(tao->trust, tr->min_radius); 293 tao->trust = PetscMin(tao->trust, tr->max_radius); 294 break; 295 296 default: 297 /* Norm of the first direction will initialize radius */ 298 tao->trust = 0.0; 299 break; 300 } 301 302 /* Set initial scaling for the BFGS preconditioner 303 This step is done after computing the initial trust-region radius 304 since the function value may have decreased */ 305 if (NTR_PC_BFGS == tr->pc_type) { 306 if (f != 0.0) { 307 delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 308 } 309 else { 310 delta = 2.0 / (gnorm*gnorm); 311 } 312 ierr = MatLMVMSetDelta(tr->M,delta);CHKERRQ(ierr); 313 } 314 315 /* Have not converged; continue with Newton method */ 316 while (reason == TAO_CONTINUE_ITERATING) { 317 ++tao->niter; 318 tao->ksp_its=0; 319 /* Compute the Hessian */ 320 if (needH) { 321 ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 322 needH = 0; 323 } 324 325 if (NTR_PC_BFGS == tr->pc_type) { 326 if (BFGS_SCALE_AHESS == tr->bfgs_scale_type) { 327 /* Obtain diagonal for the bfgs preconditioner */ 328 ierr = MatGetDiagonal(tao->hessian, tr->Diag);CHKERRQ(ierr); 329 ierr = VecAbs(tr->Diag);CHKERRQ(ierr); 330 ierr = VecReciprocal(tr->Diag);CHKERRQ(ierr); 331 ierr = MatLMVMSetScale(tr->M,tr->Diag);CHKERRQ(ierr); 332 } 333 334 /* Update the limited memory preconditioner */ 335 ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); 336 ++bfgsUpdates; 337 } 338 339 while (reason == TAO_CONTINUE_ITERATING) { 340 ierr = KSPSetOperators(tao->ksp, tao->hessian, tao->hessian_pre);CHKERRQ(ierr); 341 342 /* Solve the trust region subproblem */ 343 ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 344 ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); 345 ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); 346 tao->ksp_its+=its; 347 tao->ksp_tot_its+=its; 348 ierr = KSPCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); 349 350 if (0.0 == tao->trust) { 351 /* Radius was uninitialized; use the norm of the direction */ 352 if (norm_d > 0.0) { 353 tao->trust = norm_d; 354 355 /* Modify the radius if it is too large or small */ 356 tao->trust = PetscMax(tao->trust, tr->min_radius); 357 tao->trust = PetscMin(tao->trust, tr->max_radius); 358 } 359 else { 360 /* The direction was bad; set radius to default value and re-solve 361 the trust-region subproblem to get a direction */ 362 tao->trust = tao->trust0; 363 364 /* Modify the radius if it is too large or small */ 365 tao->trust = PetscMax(tao->trust, tr->min_radius); 366 tao->trust = PetscMin(tao->trust, tr->max_radius); 367 368 ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 369 ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); 370 ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); 371 tao->ksp_its+=its; 372 tao->ksp_tot_its+=its; 373 ierr = KSPCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); 374 375 if (norm_d == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); 376 } 377 } 378 ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 379 ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason);CHKERRQ(ierr); 380 if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && 381 (NTR_PC_BFGS == tr->pc_type) && (bfgsUpdates > 1)) { 382 /* Preconditioner is numerically indefinite; reset the 383 approximate if using BFGS preconditioning. */ 384 385 if (f != 0.0) { 386 delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 387 } 388 else { 389 delta = 2.0 / (gnorm*gnorm); 390 } 391 ierr = MatLMVMSetDelta(tr->M, delta);CHKERRQ(ierr); 392 ierr = MatLMVMReset(tr->M);CHKERRQ(ierr); 393 ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); 394 bfgsUpdates = 1; 395 } 396 397 if (NTR_UPDATE_REDUCTION == tr->update_type) { 398 /* Get predicted reduction */ 399 ierr = KSPCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); 400 if (prered >= 0.0) { 401 /* The predicted reduction has the wrong sign. This cannot 402 happen in infinite precision arithmetic. Step should 403 be rejected! */ 404 tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 405 } 406 else { 407 /* Compute trial step and function value */ 408 ierr = VecCopy(tao->solution,tr->W);CHKERRQ(ierr); 409 ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); 410 ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); 411 412 if (PetscIsInfOrNanReal(ftrial)) { 413 tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 414 } else { 415 /* Compute and actual reduction */ 416 actred = f - ftrial; 417 prered = -prered; 418 if ((PetscAbsScalar(actred) <= tr->epsilon) && 419 (PetscAbsScalar(prered) <= tr->epsilon)) { 420 kappa = 1.0; 421 } 422 else { 423 kappa = actred / prered; 424 } 425 426 /* Accept or reject the step and update radius */ 427 if (kappa < tr->eta1) { 428 /* Reject the step */ 429 tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 430 } 431 else { 432 /* Accept the step */ 433 if (kappa < tr->eta2) { 434 /* Marginal bad step */ 435 tao->trust = tr->alpha2 * PetscMin(tao->trust, norm_d); 436 } 437 else if (kappa < tr->eta3) { 438 /* Reasonable step */ 439 tao->trust = tr->alpha3 * tao->trust; 440 } 441 else if (kappa < tr->eta4) { 442 /* Good step */ 443 tao->trust = PetscMax(tr->alpha4 * norm_d, tao->trust); 444 } 445 else { 446 /* Very good step */ 447 tao->trust = PetscMax(tr->alpha5 * norm_d, tao->trust); 448 } 449 break; 450 } 451 } 452 } 453 } 454 else { 455 /* Get predicted reduction */ 456 ierr = KSPCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); 457 if (prered >= 0.0) { 458 /* The predicted reduction has the wrong sign. This cannot 459 happen in infinite precision arithmetic. Step should 460 be rejected! */ 461 tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 462 } 463 else { 464 ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); 465 ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); 466 ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); 467 if (PetscIsInfOrNanReal(ftrial)) { 468 tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 469 } 470 else { 471 ierr = VecDot(tao->gradient, tao->stepdirection, &beta);CHKERRQ(ierr); 472 actred = f - ftrial; 473 prered = -prered; 474 if ((PetscAbsScalar(actred) <= tr->epsilon) && 475 (PetscAbsScalar(prered) <= tr->epsilon)) { 476 kappa = 1.0; 477 } 478 else { 479 kappa = actred / prered; 480 } 481 482 tau_1 = tr->theta * beta / (tr->theta * beta - (1.0 - tr->theta) * prered + actred); 483 tau_2 = tr->theta * beta / (tr->theta * beta + (1.0 + tr->theta) * prered - actred); 484 tau_min = PetscMin(tau_1, tau_2); 485 tau_max = PetscMax(tau_1, tau_2); 486 487 if (kappa >= 1.0 - tr->mu1) { 488 /* Great agreement; accept step and update radius */ 489 if (tau_max < 1.0) { 490 tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); 491 } 492 else if (tau_max > tr->gamma4) { 493 tao->trust = PetscMax(tao->trust, tr->gamma4 * norm_d); 494 } 495 else { 496 tao->trust = PetscMax(tao->trust, tau_max * norm_d); 497 } 498 break; 499 } 500 else if (kappa >= 1.0 - tr->mu2) { 501 /* Good agreement */ 502 503 if (tau_max < tr->gamma2) { 504 tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); 505 } 506 else if (tau_max > tr->gamma3) { 507 tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); 508 } 509 else if (tau_max < 1.0) { 510 tao->trust = tau_max * PetscMin(tao->trust, norm_d); 511 } 512 else { 513 tao->trust = PetscMax(tao->trust, tau_max * norm_d); 514 } 515 break; 516 } 517 else { 518 /* Not good agreement */ 519 if (tau_min > 1.0) { 520 tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); 521 } 522 else if (tau_max < tr->gamma1) { 523 tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 524 } 525 else if ((tau_min < tr->gamma1) && (tau_max >= 1.0)) { 526 tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 527 } 528 else if ((tau_1 >= tr->gamma1) && (tau_1 < 1.0) && 529 ((tau_2 < tr->gamma1) || (tau_2 >= 1.0))) { 530 tao->trust = tau_1 * PetscMin(tao->trust, norm_d); 531 } 532 else if ((tau_2 >= tr->gamma1) && (tau_2 < 1.0) && 533 ((tau_1 < tr->gamma1) || (tau_2 >= 1.0))) { 534 tao->trust = tau_2 * PetscMin(tao->trust, norm_d); 535 } 536 else { 537 tao->trust = tau_max * PetscMin(tao->trust, norm_d); 538 } 539 } 540 } 541 } 542 } 543 544 /* The step computed was not good and the radius was decreased. 545 Monitor the radius to terminate. */ 546 ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); 547 } 548 549 /* The radius may have been increased; modify if it is too large */ 550 tao->trust = PetscMin(tao->trust, tr->max_radius); 551 552 if (reason == TAO_CONTINUE_ITERATING) { 553 ierr = VecCopy(tr->W, tao->solution);CHKERRQ(ierr); 554 f = ftrial; 555 ierr = TaoComputeGradient(tao, tao->solution, tao->gradient);CHKERRQ(ierr); 556 ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 557 if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 558 needH = 1; 559 ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); 560 } 561 } 562 PetscFunctionReturn(0); 563 } 564 565 /*------------------------------------------------------------*/ 566 #undef __FUNCT__ 567 #define __FUNCT__ "TaoSetUp_NTR" 568 static PetscErrorCode TaoSetUp_NTR(Tao tao) 569 { 570 TAO_NTR *tr = (TAO_NTR *)tao->data; 571 PetscErrorCode ierr; 572 573 PetscFunctionBegin; 574 if (!tao->gradient) {ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr);} 575 if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution, &tao->stepdirection);CHKERRQ(ierr);} 576 if (!tr->W) {ierr = VecDuplicate(tao->solution, &tr->W);CHKERRQ(ierr);} 577 578 tr->Diag = 0; 579 tr->M = 0; 580 PetscFunctionReturn(0); 581 } 582 583 /*------------------------------------------------------------*/ 584 #undef __FUNCT__ 585 #define __FUNCT__ "TaoDestroy_NTR" 586 static PetscErrorCode TaoDestroy_NTR(Tao tao) 587 { 588 TAO_NTR *tr = (TAO_NTR *)tao->data; 589 PetscErrorCode ierr; 590 591 PetscFunctionBegin; 592 if (tao->setupcalled) { 593 ierr = VecDestroy(&tr->W);CHKERRQ(ierr); 594 } 595 ierr = MatDestroy(&tr->M);CHKERRQ(ierr); 596 ierr = VecDestroy(&tr->Diag);CHKERRQ(ierr); 597 ierr = PetscFree(tao->data);CHKERRQ(ierr); 598 PetscFunctionReturn(0); 599 } 600 601 /*------------------------------------------------------------*/ 602 #undef __FUNCT__ 603 #define __FUNCT__ "TaoSetFromOptions_NTR" 604 static PetscErrorCode TaoSetFromOptions_NTR(PetscOptionItems *PetscOptionsObject,Tao tao) 605 { 606 TAO_NTR *tr = (TAO_NTR *)tao->data; 607 PetscErrorCode ierr; 608 609 PetscFunctionBegin; 610 ierr = PetscOptionsHead(PetscOptionsObject,"Newton trust region method for unconstrained optimization");CHKERRQ(ierr); 611 ierr = PetscOptionsEList("-tao_ntr_pc_type", "pc type", "", NTR_PC, NTR_PC_TYPES, NTR_PC[tr->pc_type], &tr->pc_type,NULL);CHKERRQ(ierr); 612 ierr = PetscOptionsEList("-tao_ntr_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[tr->bfgs_scale_type], &tr->bfgs_scale_type,NULL);CHKERRQ(ierr); 613 ierr = PetscOptionsEList("-tao_ntr_init_type", "tao->trust initialization type", "", NTR_INIT, NTR_INIT_TYPES, NTR_INIT[tr->init_type], &tr->init_type,NULL);CHKERRQ(ierr); 614 ierr = PetscOptionsEList("-tao_ntr_update_type", "radius update type", "", NTR_UPDATE, NTR_UPDATE_TYPES, NTR_UPDATE[tr->update_type], &tr->update_type,NULL);CHKERRQ(ierr); 615 ierr = PetscOptionsReal("-tao_ntr_eta1", "step is unsuccessful if actual reduction < eta1 * predicted reduction", "", tr->eta1, &tr->eta1,NULL);CHKERRQ(ierr); 616 ierr = PetscOptionsReal("-tao_ntr_eta2", "", "", tr->eta2, &tr->eta2,NULL);CHKERRQ(ierr); 617 ierr = PetscOptionsReal("-tao_ntr_eta3", "", "", tr->eta3, &tr->eta3,NULL);CHKERRQ(ierr); 618 ierr = PetscOptionsReal("-tao_ntr_eta4", "", "", tr->eta4, &tr->eta4,NULL);CHKERRQ(ierr); 619 ierr = PetscOptionsReal("-tao_ntr_alpha1", "", "", tr->alpha1, &tr->alpha1,NULL);CHKERRQ(ierr); 620 ierr = PetscOptionsReal("-tao_ntr_alpha2", "", "", tr->alpha2, &tr->alpha2,NULL);CHKERRQ(ierr); 621 ierr = PetscOptionsReal("-tao_ntr_alpha3", "", "", tr->alpha3, &tr->alpha3,NULL);CHKERRQ(ierr); 622 ierr = PetscOptionsReal("-tao_ntr_alpha4", "", "", tr->alpha4, &tr->alpha4,NULL);CHKERRQ(ierr); 623 ierr = PetscOptionsReal("-tao_ntr_alpha5", "", "", tr->alpha5, &tr->alpha5,NULL);CHKERRQ(ierr); 624 ierr = PetscOptionsReal("-tao_ntr_mu1", "", "", tr->mu1, &tr->mu1,NULL);CHKERRQ(ierr); 625 ierr = PetscOptionsReal("-tao_ntr_mu2", "", "", tr->mu2, &tr->mu2,NULL);CHKERRQ(ierr); 626 ierr = PetscOptionsReal("-tao_ntr_gamma1", "", "", tr->gamma1, &tr->gamma1,NULL);CHKERRQ(ierr); 627 ierr = PetscOptionsReal("-tao_ntr_gamma2", "", "", tr->gamma2, &tr->gamma2,NULL);CHKERRQ(ierr); 628 ierr = PetscOptionsReal("-tao_ntr_gamma3", "", "", tr->gamma3, &tr->gamma3,NULL);CHKERRQ(ierr); 629 ierr = PetscOptionsReal("-tao_ntr_gamma4", "", "", tr->gamma4, &tr->gamma4,NULL);CHKERRQ(ierr); 630 ierr = PetscOptionsReal("-tao_ntr_theta", "", "", tr->theta, &tr->theta,NULL);CHKERRQ(ierr); 631 ierr = PetscOptionsReal("-tao_ntr_mu1_i", "", "", tr->mu1_i, &tr->mu1_i,NULL);CHKERRQ(ierr); 632 ierr = PetscOptionsReal("-tao_ntr_mu2_i", "", "", tr->mu2_i, &tr->mu2_i,NULL);CHKERRQ(ierr); 633 ierr = PetscOptionsReal("-tao_ntr_gamma1_i", "", "", tr->gamma1_i, &tr->gamma1_i,NULL);CHKERRQ(ierr); 634 ierr = PetscOptionsReal("-tao_ntr_gamma2_i", "", "", tr->gamma2_i, &tr->gamma2_i,NULL);CHKERRQ(ierr); 635 ierr = PetscOptionsReal("-tao_ntr_gamma3_i", "", "", tr->gamma3_i, &tr->gamma3_i,NULL);CHKERRQ(ierr); 636 ierr = PetscOptionsReal("-tao_ntr_gamma4_i", "", "", tr->gamma4_i, &tr->gamma4_i,NULL);CHKERRQ(ierr); 637 ierr = PetscOptionsReal("-tao_ntr_theta_i", "", "", tr->theta_i, &tr->theta_i,NULL);CHKERRQ(ierr); 638 ierr = PetscOptionsReal("-tao_ntr_min_radius", "lower bound on initial trust-region radius", "", tr->min_radius, &tr->min_radius,NULL);CHKERRQ(ierr); 639 ierr = PetscOptionsReal("-tao_ntr_max_radius", "upper bound on trust-region radius", "", tr->max_radius, &tr->max_radius,NULL);CHKERRQ(ierr); 640 ierr = PetscOptionsReal("-tao_ntr_epsilon", "tolerance used when computing actual and predicted reduction", "", tr->epsilon, &tr->epsilon,NULL);CHKERRQ(ierr); 641 ierr = PetscOptionsTail();CHKERRQ(ierr); 642 ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr); 643 PetscFunctionReturn(0); 644 } 645 646 /*------------------------------------------------------------*/ 647 #undef __FUNCT__ 648 #define __FUNCT__ "TaoView_NTR" 649 static PetscErrorCode TaoView_NTR(Tao tao, PetscViewer viewer) 650 { 651 TAO_NTR *tr = (TAO_NTR *)tao->data; 652 PetscErrorCode ierr; 653 PetscInt nrejects; 654 PetscBool isascii; 655 656 PetscFunctionBegin; 657 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 658 if (isascii) { 659 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 660 if (NTR_PC_BFGS == tr->pc_type && tr->M) { 661 ierr = MatLMVMGetRejects(tr->M, &nrejects);CHKERRQ(ierr); 662 ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n", nrejects);CHKERRQ(ierr); 663 } 664 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 665 } 666 PetscFunctionReturn(0); 667 } 668 669 /*------------------------------------------------------------*/ 670 /*MC 671 TAONTR - Newton's method with trust region for unconstrained minimization. 672 At each iteration, the Newton trust region method solves the system. 673 NTR expects a KSP solver with a trust region radius. 674 min_d .5 dT Hk d + gkT d, s.t. ||d|| < Delta_k 675 676 Options Database Keys: 677 + -tao_ntr_pc_type - "none","ahess","bfgs","petsc" 678 . -tao_ntr_bfgs_scale_type - type of scaling with bfgs pc, "ahess" or "bfgs" 679 . -tao_ntr_init_type - "constant","direction","interpolation" 680 . -tao_ntr_update_type - "reduction","interpolation" 681 . -tao_ntr_min_radius - lower bound on trust region radius 682 . -tao_ntr_max_radius - upper bound on trust region radius 683 . -tao_ntr_epsilon - tolerance for accepting actual / predicted reduction 684 . -tao_ntr_mu1_i - mu1 interpolation init factor 685 . -tao_ntr_mu2_i - mu2 interpolation init factor 686 . -tao_ntr_gamma1_i - gamma1 interpolation init factor 687 . -tao_ntr_gamma2_i - gamma2 interpolation init factor 688 . -tao_ntr_gamma3_i - gamma3 interpolation init factor 689 . -tao_ntr_gamma4_i - gamma4 interpolation init factor 690 . -tao_ntr_theta_i - thetha1 interpolation init factor 691 . -tao_ntr_eta1 - eta1 reduction update factor 692 . -tao_ntr_eta2 - eta2 reduction update factor 693 . -tao_ntr_eta3 - eta3 reduction update factor 694 . -tao_ntr_eta4 - eta4 reduction update factor 695 . -tao_ntr_alpha1 - alpha1 reduction update factor 696 . -tao_ntr_alpha2 - alpha2 reduction update factor 697 . -tao_ntr_alpha3 - alpha3 reduction update factor 698 . -tao_ntr_alpha4 - alpha4 reduction update factor 699 . -tao_ntr_alpha4 - alpha4 reduction update factor 700 . -tao_ntr_mu1 - mu1 interpolation update 701 . -tao_ntr_mu2 - mu2 interpolation update 702 . -tao_ntr_gamma1 - gamma1 interpolcation update 703 . -tao_ntr_gamma2 - gamma2 interpolcation update 704 . -tao_ntr_gamma3 - gamma3 interpolcation update 705 . -tao_ntr_gamma4 - gamma4 interpolation update 706 - -tao_ntr_theta - theta interpolation update 707 708 Level: beginner 709 M*/ 710 711 #undef __FUNCT__ 712 #define __FUNCT__ "TaoCreate_NTR" 713 PETSC_EXTERN PetscErrorCode TaoCreate_NTR(Tao tao) 714 { 715 TAO_NTR *tr; 716 PetscErrorCode ierr; 717 718 PetscFunctionBegin; 719 720 ierr = PetscNewLog(tao,&tr);CHKERRQ(ierr); 721 722 tao->ops->setup = TaoSetUp_NTR; 723 tao->ops->solve = TaoSolve_NTR; 724 tao->ops->view = TaoView_NTR; 725 tao->ops->setfromoptions = TaoSetFromOptions_NTR; 726 tao->ops->destroy = TaoDestroy_NTR; 727 728 /* Override default settings (unless already changed) */ 729 if (!tao->max_it_changed) tao->max_it = 50; 730 if (!tao->trust0_changed) tao->trust0 = 100.0; 731 tao->data = (void*)tr; 732 733 /* Standard trust region update parameters */ 734 tr->eta1 = 1.0e-4; 735 tr->eta2 = 0.25; 736 tr->eta3 = 0.50; 737 tr->eta4 = 0.90; 738 739 tr->alpha1 = 0.25; 740 tr->alpha2 = 0.50; 741 tr->alpha3 = 1.00; 742 tr->alpha4 = 2.00; 743 tr->alpha5 = 4.00; 744 745 /* Interpolation trust region update parameters */ 746 tr->mu1 = 0.10; 747 tr->mu2 = 0.50; 748 749 tr->gamma1 = 0.25; 750 tr->gamma2 = 0.50; 751 tr->gamma3 = 2.00; 752 tr->gamma4 = 4.00; 753 754 tr->theta = 0.05; 755 756 /* Interpolation parameters for initialization */ 757 tr->mu1_i = 0.35; 758 tr->mu2_i = 0.50; 759 760 tr->gamma1_i = 0.0625; 761 tr->gamma2_i = 0.50; 762 tr->gamma3_i = 2.00; 763 tr->gamma4_i = 5.00; 764 765 tr->theta_i = 0.25; 766 767 tr->min_radius = 1.0e-10; 768 tr->max_radius = 1.0e10; 769 tr->epsilon = 1.0e-6; 770 771 tr->pc_type = NTR_PC_BFGS; 772 tr->bfgs_scale_type = BFGS_SCALE_AHESS; 773 tr->init_type = NTR_INIT_INTERPOLATION; 774 tr->update_type = NTR_UPDATE_REDUCTION; 775 776 /* Set linear solver to default for trust region */ 777 ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr); 778 ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr); 779 ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr); 780 PetscFunctionReturn(0); 781 } 782 783