1c14b763aSAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h> 2c14b763aSAlp Dener #include <petscksp.h> 3c14b763aSAlp Dener 4c14b763aSAlp Dener /* 5c14b763aSAlp Dener Implements Newton's Method with a trust region approach for solving 6c14b763aSAlp Dener bound constrained minimization problems. This version includes a 7c14b763aSAlp Dener line search fall-back in the event of a trust region failure. 8c14b763aSAlp Dener 9df278d8fSAlp Dener The linear system solve has to be done with a conjugate gradient method. 10c14b763aSAlp Dener */ 11c14b763aSAlp Dener 12c14b763aSAlp Dener static PetscErrorCode TaoSolve_BNTL(Tao tao) 13c14b763aSAlp Dener { 14c14b763aSAlp Dener PetscErrorCode ierr; 15c14b763aSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 16e465cd6fSAlp Dener KSPConvergedReason ksp_reason; 17c14b763aSAlp Dener TaoLineSearchConvergedReason ls_reason; 18c14b763aSAlp Dener 19e465cd6fSAlp Dener PetscReal oldTrust, prered, actred, stepNorm, steplen; 20c14b763aSAlp Dener PetscBool stepAccepted = PETSC_TRUE; 21*28017e9fSAlp Dener PetscInt stepType; 22c14b763aSAlp Dener 23c14b763aSAlp Dener PetscFunctionBegin; 24*28017e9fSAlp Dener /* Initialize the preconditioner, KSP solver and trust radius/line search */ 25c14b763aSAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 26c14b763aSAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 27*28017e9fSAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 28c14b763aSAlp Dener 29c14b763aSAlp Dener /* Have not converged; continue with Newton method */ 30c14b763aSAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 31c14b763aSAlp Dener tao->niter++; 32c14b763aSAlp Dener tao->ksp_its=0; 33c14b763aSAlp Dener /* Compute the Hessian */ 34c14b763aSAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 35c14b763aSAlp Dener /* Update the BFGS preconditioner */ 36c14b763aSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 37c14b763aSAlp Dener if (BFGS_SCALE_PHESS == bnk->bfgs_scale_type) { 38c14b763aSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 39c14b763aSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 40c14b763aSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 41c14b763aSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 42c14b763aSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 43c14b763aSAlp Dener } 44c14b763aSAlp Dener /* Update the limited memory preconditioner and get existing # of updates */ 45c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 46c14b763aSAlp Dener } 47c14b763aSAlp Dener 488d5ead36SAlp Dener /* Use the common BNK kernel to compute the Newton step (for inactive variables only) */ 49e465cd6fSAlp Dener ierr = TaoBNKComputeStep(tao, &ksp_reason);CHKERRQ(ierr); 50c14b763aSAlp Dener 51c14b763aSAlp Dener /* Store current solution before it changes */ 52c14b763aSAlp Dener oldTrust = tao->trust; 53c14b763aSAlp Dener bnk->fold = bnk->f; 54c14b763aSAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 55c14b763aSAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 56c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->unprojected_gradient_old);CHKERRQ(ierr); 57c14b763aSAlp Dener 58c14b763aSAlp Dener /* Temporarily accept the step and project it into the bounds */ 59c14b763aSAlp Dener ierr = VecAXPY(tao->solution, 1.0, tao->stepdirection);CHKERRQ(ierr); 60c14b763aSAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 61c14b763aSAlp Dener 62c14b763aSAlp Dener /* Check if the projection changed the step direction */ 63c14b763aSAlp Dener ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr); 648d5ead36SAlp Dener ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr); 65c14b763aSAlp Dener ierr = VecNorm(tao->stepdirection, NORM_2, &stepNorm);CHKERRQ(ierr); 66c14b763aSAlp Dener if (stepNorm != bnk->dnorm) { 678d5ead36SAlp Dener /* Projection changed the step, so we have to recompute predicted reduction. 688d5ead36SAlp Dener However, we deliberately do not change the step norm and the trust radius 698d5ead36SAlp Dener in order for the safeguard to more closely mimic a piece-wise linesearch 708d5ead36SAlp Dener along the bounds. */ 71*28017e9fSAlp Dener ierr = MatMult(bnk->H_inactive, tao->stepdirection, bnk->Xwork);CHKERRQ(ierr); 72c14b763aSAlp Dener ierr = VecAYPX(bnk->Xwork, -0.5, tao->gradient);CHKERRQ(ierr); 73c14b763aSAlp Dener ierr = VecDot(bnk->Xwork, tao->stepdirection, &prered); 74c14b763aSAlp Dener } else { 75c14b763aSAlp Dener /* Step did not change, so we can just recover the pre-computed prediction */ 76c14b763aSAlp Dener ierr = KSPCGGetObjFcn(tao->ksp, &prered);CHKERRQ(ierr); 77c14b763aSAlp Dener } 78c14b763aSAlp Dener prered = -prered; 79c14b763aSAlp Dener 80c14b763aSAlp Dener /* Compute the actual reduction and update the trust radius */ 81c14b763aSAlp Dener ierr = TaoComputeObjective(tao, tao->solution, &bnk->f);CHKERRQ(ierr); 82c14b763aSAlp Dener actred = bnk->fold - bnk->f; 83*28017e9fSAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, bnk->update_type, stepType, &stepAccepted);CHKERRQ(ierr); 84c14b763aSAlp Dener 85c14b763aSAlp Dener if (stepAccepted) { 86c14b763aSAlp Dener /* Step is good, evaluate the gradient and the hessian */ 878d5ead36SAlp Dener steplen = 1.0; 88e465cd6fSAlp Dener ++bnk->newt; 89c14b763aSAlp Dener ierr = TaoComputeGradient(tao, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 90c14b763aSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 91c14b763aSAlp Dener } else { 92c14b763aSAlp Dener /* Trust-region rejected the step. Revert the solution. */ 93c14b763aSAlp Dener bnk->f = bnk->fold; 94c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 95c14b763aSAlp Dener 96c14b763aSAlp Dener /* Trigger the line search */ 97e465cd6fSAlp Dener ierr = TaoBNKSafeguardStep(tao, ksp_reason, &stepType);CHKERRQ(ierr); 98c14b763aSAlp Dener ierr = TaoBNKPerformLineSearch(tao, stepType, &steplen, &ls_reason);CHKERRQ(ierr); 99c14b763aSAlp Dener if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) { 100c14b763aSAlp Dener /* Line search failed, revert solution and terminate */ 101c14b763aSAlp Dener bnk->f = bnk->fold; 102c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 103c14b763aSAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 104c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 105c14b763aSAlp Dener tao->trust = 0.0; 106c14b763aSAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 107c14b763aSAlp Dener } else { 108c14b763aSAlp Dener /* Line search succeeded so we should update the trust radius based on the LS step length */ 109770b7498SAlp Dener tao->trust = oldTrust; 110*28017e9fSAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, BNK_UPDATE_STEP, stepType, &stepAccepted);CHKERRQ(ierr); 111e465cd6fSAlp Dener /* count the accepted step types */ 112e465cd6fSAlp Dener switch (stepType) { 113e465cd6fSAlp Dener case BNK_NEWTON: 114e465cd6fSAlp Dener ++bnk->newt; 115e465cd6fSAlp Dener break; 116e465cd6fSAlp Dener case BNK_BFGS: 117e465cd6fSAlp Dener ++bnk->bfgs; 118e465cd6fSAlp Dener break; 119e465cd6fSAlp Dener case BNK_SCALED_GRADIENT: 120e465cd6fSAlp Dener ++bnk->sgrad; 121e465cd6fSAlp Dener break; 122e465cd6fSAlp Dener case BNK_GRADIENT: 123e465cd6fSAlp Dener ++bnk->grad; 124e465cd6fSAlp Dener break; 125e465cd6fSAlp Dener default: 126e465cd6fSAlp Dener break; 127e465cd6fSAlp Dener } 128c14b763aSAlp Dener } 129c14b763aSAlp Dener } 130c14b763aSAlp Dener 131c14b763aSAlp Dener /* Check for termination */ 132c14b763aSAlp Dener ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr); 133c14b763aSAlp Dener if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 134c14b763aSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 1358d5ead36SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 136c14b763aSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 137c14b763aSAlp Dener } 138c14b763aSAlp Dener PetscFunctionReturn(0); 139c14b763aSAlp Dener } 140c14b763aSAlp Dener 141df278d8fSAlp Dener /*------------------------------------------------------------*/ 142df278d8fSAlp Dener 143c14b763aSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNTL(Tao tao) 144c14b763aSAlp Dener { 145c14b763aSAlp Dener TAO_BNK *bnk; 146c14b763aSAlp Dener PetscErrorCode ierr; 147c14b763aSAlp Dener 148c14b763aSAlp Dener PetscFunctionBegin; 149c14b763aSAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 150c14b763aSAlp Dener tao->ops->solve=TaoSolve_BNTL; 151c14b763aSAlp Dener 152c14b763aSAlp Dener bnk = (TAO_BNK *)tao->data; 153c14b763aSAlp Dener bnk->update_type = BNK_UPDATE_REDUCTION; /* trust region updates based on predicted/actual reduction */ 154c14b763aSAlp Dener bnk->sval = 0.0; /* disable Hessian shifting */ 155c14b763aSAlp Dener PetscFunctionReturn(0); 156c14b763aSAlp Dener }