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; 16*e465cd6fSAlp Dener KSPConvergedReason ksp_reason; 17c14b763aSAlp Dener TaoLineSearchConvergedReason ls_reason; 18c14b763aSAlp Dener 19*e465cd6fSAlp Dener PetscReal oldTrust, prered, actred, stepNorm, steplen; 20c14b763aSAlp Dener PetscBool stepAccepted = PETSC_TRUE; 21*e465cd6fSAlp Dener PetscInt stepType, updateType; 22c14b763aSAlp Dener 23c14b763aSAlp Dener PetscFunctionBegin; 24c14b763aSAlp Dener /* Project the current point onto the feasible set */ 25c14b763aSAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 26c14b763aSAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 27c14b763aSAlp Dener 28c14b763aSAlp Dener /* Project the initial point onto the feasible region */ 29c14b763aSAlp Dener ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); 30c14b763aSAlp Dener 31c14b763aSAlp Dener /* Check convergence criteria */ 32c14b763aSAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr); 33c14b763aSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 34c14b763aSAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 35c14b763aSAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 36c14b763aSAlp Dener 37c14b763aSAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 38c14b763aSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 39c14b763aSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,tao->trust);CHKERRQ(ierr); 40c14b763aSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 41c14b763aSAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 42c14b763aSAlp Dener 43c14b763aSAlp Dener /* Initialize the preconditioner and trust radius */ 44c14b763aSAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 45c14b763aSAlp Dener 46c14b763aSAlp Dener /* Have not converged; continue with Newton method */ 47c14b763aSAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 48c14b763aSAlp Dener tao->niter++; 49c14b763aSAlp Dener tao->ksp_its=0; 50c14b763aSAlp Dener /* Compute the Hessian */ 51c14b763aSAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 52c14b763aSAlp Dener /* Update the BFGS preconditioner */ 53c14b763aSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 54c14b763aSAlp Dener if (BFGS_SCALE_PHESS == bnk->bfgs_scale_type) { 55c14b763aSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 56c14b763aSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 57c14b763aSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 58c14b763aSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 59c14b763aSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 60c14b763aSAlp Dener } 61c14b763aSAlp Dener /* Update the limited memory preconditioner and get existing # of updates */ 62c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 63c14b763aSAlp Dener } 64c14b763aSAlp Dener 658d5ead36SAlp Dener /* Use the common BNK kernel to compute the Newton step (for inactive variables only) */ 66*e465cd6fSAlp Dener ierr = TaoBNKComputeStep(tao, &ksp_reason);CHKERRQ(ierr); 67c14b763aSAlp Dener 68c14b763aSAlp Dener /* Store current solution before it changes */ 69c14b763aSAlp Dener oldTrust = tao->trust; 70c14b763aSAlp Dener bnk->fold = bnk->f; 71c14b763aSAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 72c14b763aSAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 73c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->unprojected_gradient_old);CHKERRQ(ierr); 74c14b763aSAlp Dener 75c14b763aSAlp Dener /* Temporarily accept the step and project it into the bounds */ 76c14b763aSAlp Dener ierr = VecAXPY(tao->solution, 1.0, tao->stepdirection);CHKERRQ(ierr); 77c14b763aSAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 78c14b763aSAlp Dener 79c14b763aSAlp Dener /* Check if the projection changed the step direction */ 80c14b763aSAlp Dener ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr); 818d5ead36SAlp Dener ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr); 82c14b763aSAlp Dener ierr = VecNorm(tao->stepdirection, NORM_2, &stepNorm);CHKERRQ(ierr); 83c14b763aSAlp Dener if (stepNorm != bnk->dnorm) { 848d5ead36SAlp Dener /* Projection changed the step, so we have to recompute predicted reduction. 858d5ead36SAlp Dener However, we deliberately do not change the step norm and the trust radius 868d5ead36SAlp Dener in order for the safeguard to more closely mimic a piece-wise linesearch 878d5ead36SAlp Dener along the bounds. */ 88c14b763aSAlp Dener ierr = MatMult(tao->hessian, tao->stepdirection, bnk->Xwork);CHKERRQ(ierr); 89c14b763aSAlp Dener ierr = VecAYPX(bnk->Xwork, -0.5, tao->gradient);CHKERRQ(ierr); 90c14b763aSAlp Dener ierr = VecDot(bnk->Xwork, tao->stepdirection, &prered); 91c14b763aSAlp Dener } else { 92c14b763aSAlp Dener /* Step did not change, so we can just recover the pre-computed prediction */ 93c14b763aSAlp Dener ierr = KSPCGGetObjFcn(tao->ksp, &prered);CHKERRQ(ierr); 94c14b763aSAlp Dener } 95c14b763aSAlp Dener prered = -prered; 96c14b763aSAlp Dener 97c14b763aSAlp Dener /* Compute the actual reduction and update the trust radius */ 98c14b763aSAlp Dener ierr = TaoComputeObjective(tao, tao->solution, &bnk->f);CHKERRQ(ierr); 99c14b763aSAlp Dener actred = bnk->fold - bnk->f; 100c14b763aSAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, stepType, &stepAccepted);CHKERRQ(ierr); 101c14b763aSAlp Dener 102c14b763aSAlp Dener if (stepAccepted) { 103c14b763aSAlp Dener /* Step is good, evaluate the gradient and the hessian */ 1048d5ead36SAlp Dener steplen = 1.0; 105*e465cd6fSAlp Dener ++bnk->newt; 106c14b763aSAlp Dener ierr = TaoComputeGradient(tao, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 107c14b763aSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 108c14b763aSAlp Dener } else { 109c14b763aSAlp Dener /* Trust-region rejected the step. Revert the solution. */ 110c14b763aSAlp Dener bnk->f = bnk->fold; 111c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 112c14b763aSAlp Dener 113c14b763aSAlp Dener /* Trigger the line search */ 114*e465cd6fSAlp Dener ierr = TaoBNKSafeguardStep(tao, ksp_reason, &stepType);CHKERRQ(ierr); 115c14b763aSAlp Dener ierr = TaoBNKPerformLineSearch(tao, stepType, &steplen, &ls_reason);CHKERRQ(ierr); 116c14b763aSAlp Dener if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) { 117c14b763aSAlp Dener /* Line search failed, revert solution and terminate */ 118c14b763aSAlp Dener bnk->f = bnk->fold; 119c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 120c14b763aSAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 121c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 122c14b763aSAlp Dener tao->trust = 0.0; 123c14b763aSAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 124c14b763aSAlp Dener } else { 125c14b763aSAlp Dener /* Line search succeeded so we should update the trust radius based on the LS step length */ 126c14b763aSAlp Dener updateType = bnk->update_type; 127c14b763aSAlp Dener bnk->update_type = BNK_UPDATE_STEP; 128770b7498SAlp Dener tao->trust = oldTrust; 129c14b763aSAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, stepType, &stepAccepted);CHKERRQ(ierr); 130c14b763aSAlp Dener bnk->update_type = updateType; 131*e465cd6fSAlp Dener /* count the accepted step types */ 132*e465cd6fSAlp Dener switch (stepType) { 133*e465cd6fSAlp Dener case BNK_NEWTON: 134*e465cd6fSAlp Dener ++bnk->newt; 135*e465cd6fSAlp Dener break; 136*e465cd6fSAlp Dener case BNK_BFGS: 137*e465cd6fSAlp Dener ++bnk->bfgs; 138*e465cd6fSAlp Dener break; 139*e465cd6fSAlp Dener case BNK_SCALED_GRADIENT: 140*e465cd6fSAlp Dener ++bnk->sgrad; 141*e465cd6fSAlp Dener break; 142*e465cd6fSAlp Dener case BNK_GRADIENT: 143*e465cd6fSAlp Dener ++bnk->grad; 144*e465cd6fSAlp Dener break; 145*e465cd6fSAlp Dener default: 146*e465cd6fSAlp Dener break; 147*e465cd6fSAlp Dener } 148c14b763aSAlp Dener } 149c14b763aSAlp Dener } 150c14b763aSAlp Dener 151c14b763aSAlp Dener /* Check for termination */ 152c14b763aSAlp Dener ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr); 153c14b763aSAlp Dener if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 154c14b763aSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 1558d5ead36SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 156c14b763aSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 157c14b763aSAlp Dener } 158c14b763aSAlp Dener PetscFunctionReturn(0); 159c14b763aSAlp Dener } 160c14b763aSAlp Dener 161df278d8fSAlp Dener /*------------------------------------------------------------*/ 162df278d8fSAlp Dener 163c14b763aSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNTL(Tao tao) 164c14b763aSAlp Dener { 165c14b763aSAlp Dener TAO_BNK *bnk; 166c14b763aSAlp Dener PetscErrorCode ierr; 167c14b763aSAlp Dener 168c14b763aSAlp Dener PetscFunctionBegin; 169c14b763aSAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 170c14b763aSAlp Dener tao->ops->solve=TaoSolve_BNTL; 171c14b763aSAlp Dener 172c14b763aSAlp Dener bnk = (TAO_BNK *)tao->data; 173c14b763aSAlp Dener bnk->update_type = BNK_UPDATE_REDUCTION; /* trust region updates based on predicted/actual reduction */ 174c14b763aSAlp Dener bnk->sval = 0.0; /* disable Hessian shifting */ 175c14b763aSAlp Dener PetscFunctionReturn(0); 176c14b763aSAlp Dener }