1fed79b8eSAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h> 2fed79b8eSAlp Dener #include <petscksp.h> 3fed79b8eSAlp Dener 4fed79b8eSAlp Dener /* 5fed79b8eSAlp Dener Implements Newton's Method with a trust region approach for solving 6fed79b8eSAlp Dener bound constrained minimization problems. 7fed79b8eSAlp Dener 8df278d8fSAlp Dener The linear system solve has to be done with a conjugate gradient method. 9fed79b8eSAlp Dener */ 10fed79b8eSAlp Dener 11fed79b8eSAlp Dener static PetscErrorCode TaoSolve_BNTR(Tao tao) 12fed79b8eSAlp Dener { 13fed79b8eSAlp Dener PetscErrorCode ierr; 14fed79b8eSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 15*e465cd6fSAlp Dener KSPConvergedReason ksp_reason; 16fed79b8eSAlp Dener 178d5ead36SAlp Dener PetscReal oldTrust, prered, actred, stepNorm, steplen; 18fed79b8eSAlp Dener PetscBool stepAccepted = PETSC_TRUE; 19*e465cd6fSAlp Dener PetscInt stepType = BNK_NEWTON; 20fed79b8eSAlp Dener 21fed79b8eSAlp Dener PetscFunctionBegin; 22fed79b8eSAlp Dener /* Project the current point onto the feasible set */ 23fed79b8eSAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 24fed79b8eSAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 25fed79b8eSAlp Dener 26fed79b8eSAlp Dener /* Project the initial point onto the feasible region */ 27fed79b8eSAlp Dener ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); 28fed79b8eSAlp Dener 29fed79b8eSAlp Dener /* Check convergence criteria */ 30fed79b8eSAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr); 31fed79b8eSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 32fed79b8eSAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 33fed79b8eSAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 34fed79b8eSAlp Dener 35fed79b8eSAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 36fed79b8eSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 37fed79b8eSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,tao->trust);CHKERRQ(ierr); 38fed79b8eSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 39fed79b8eSAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 40fed79b8eSAlp Dener 41fed79b8eSAlp Dener /* Initialize the preconditioner and trust radius */ 42fed79b8eSAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 43fed79b8eSAlp Dener 44fed79b8eSAlp Dener /* Have not converged; continue with Newton method */ 45fed79b8eSAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 4666ed3702SAlp Dener 47fed79b8eSAlp Dener if (stepAccepted) { 48fed79b8eSAlp Dener tao->niter++; 49fed79b8eSAlp Dener tao->ksp_its=0; 50fed79b8eSAlp Dener /* Compute the Hessian */ 51fed79b8eSAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 52fed79b8eSAlp Dener /* Update the BFGS preconditioner */ 53fed79b8eSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 54fed79b8eSAlp Dener if (BFGS_SCALE_PHESS == bnk->bfgs_scale_type) { 55fed79b8eSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 56fed79b8eSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 57fed79b8eSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 58fed79b8eSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 59fed79b8eSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 60fed79b8eSAlp Dener } 61fed79b8eSAlp Dener /* Update the limited memory preconditioner and get existing # of updates */ 62fed79b8eSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 63fed79b8eSAlp Dener } 64fed79b8eSAlp Dener } 65fed79b8eSAlp Dener 668d5ead36SAlp Dener /* Use the common BNK kernel to compute the Newton step (for inactive variables only) */ 67*e465cd6fSAlp Dener ierr = TaoBNKComputeStep(tao, &ksp_reason);CHKERRQ(ierr); 68fed79b8eSAlp Dener 69fed79b8eSAlp Dener /* Store current solution before it changes */ 70fed79b8eSAlp Dener oldTrust = tao->trust; 71fed79b8eSAlp Dener bnk->fold = bnk->f; 72fed79b8eSAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 73fed79b8eSAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 74fed79b8eSAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->unprojected_gradient_old);CHKERRQ(ierr); 75fed79b8eSAlp Dener 76b1c2d0e3SAlp Dener /* Temporarily accept the step and project it into the bounds */ 77fed79b8eSAlp Dener ierr = VecAXPY(tao->solution, 1.0, tao->stepdirection);CHKERRQ(ierr); 78b1c2d0e3SAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 79b1c2d0e3SAlp Dener 80b1c2d0e3SAlp Dener /* Check if the projection changed the step direction */ 81b1c2d0e3SAlp Dener ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr); 828d5ead36SAlp Dener ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr); 83b1c2d0e3SAlp Dener ierr = VecNorm(tao->stepdirection, NORM_2, &stepNorm);CHKERRQ(ierr); 84b1c2d0e3SAlp Dener if (stepNorm != bnk->dnorm) { 858d5ead36SAlp Dener /* Projection changed the step, so we have to recompute predicted reduction. 868d5ead36SAlp Dener However, we deliberately do not change the step norm and the trust radius 878d5ead36SAlp Dener in order for the safeguard to more closely mimic a piece-wise linesearch 888d5ead36SAlp Dener along the bounds. */ 89b1c2d0e3SAlp Dener ierr = MatMult(tao->hessian, tao->stepdirection, bnk->Xwork);CHKERRQ(ierr); 90b1c2d0e3SAlp Dener ierr = VecAYPX(bnk->Xwork, -0.5, tao->gradient);CHKERRQ(ierr); 91b1c2d0e3SAlp Dener ierr = VecDot(bnk->Xwork, tao->stepdirection, &prered); 92b1c2d0e3SAlp Dener } else { 93b1c2d0e3SAlp Dener /* Step did not change, so we can just recover the pre-computed prediction */ 94b1c2d0e3SAlp Dener ierr = KSPCGGetObjFcn(tao->ksp, &prered);CHKERRQ(ierr); 95b1c2d0e3SAlp Dener } 96b1c2d0e3SAlp Dener prered = -prered; 97b1c2d0e3SAlp Dener 98b1c2d0e3SAlp Dener /* Compute the actual reduction and update the trust radius */ 99fed79b8eSAlp Dener ierr = TaoComputeObjective(tao, tao->solution, &bnk->f);CHKERRQ(ierr); 100b1c2d0e3SAlp Dener actred = bnk->fold - bnk->f; 101b1c2d0e3SAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, stepType, &stepAccepted);CHKERRQ(ierr); 102fed79b8eSAlp Dener 103fed79b8eSAlp Dener if (stepAccepted) { 10466ed3702SAlp Dener /* Step is good, evaluate the gradient and the hessian */ 1058d5ead36SAlp Dener steplen = 1.0; 106*e465cd6fSAlp Dener ++bnk->newt; 107fed79b8eSAlp Dener ierr = TaoComputeGradient(tao, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 108fed79b8eSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 109fed79b8eSAlp Dener } else { 110fed79b8eSAlp Dener /* Step is bad, revert old solution and re-solve with new radius*/ 1118d5ead36SAlp Dener steplen = 0.0; 112fed79b8eSAlp Dener bnk->f = bnk->fold; 113fed79b8eSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 114fed79b8eSAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 115fed79b8eSAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 11673e4db90SAlp Dener if (oldTrust == tao->trust) { 11773e4db90SAlp Dener /* Can't change the radius anymore so just terminate */ 118fed79b8eSAlp Dener tao->reason = TAO_DIVERGED_TR_REDUCTION; 119fed79b8eSAlp Dener } 120fed79b8eSAlp Dener } 121fed79b8eSAlp Dener 122fed79b8eSAlp Dener /* Check for termination */ 123fed79b8eSAlp Dener ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr); 12473e4db90SAlp Dener if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 125fed79b8eSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 1268d5ead36SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 127fed79b8eSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 128fed79b8eSAlp Dener } 129fed79b8eSAlp Dener PetscFunctionReturn(0); 130fed79b8eSAlp Dener } 131fed79b8eSAlp Dener 132df278d8fSAlp Dener /*------------------------------------------------------------*/ 133df278d8fSAlp Dener 134fed79b8eSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNTR(Tao tao) 135fed79b8eSAlp Dener { 136fed79b8eSAlp Dener TAO_BNK *bnk; 137fed79b8eSAlp Dener PetscErrorCode ierr; 138fed79b8eSAlp Dener 139fed79b8eSAlp Dener PetscFunctionBegin; 140fed79b8eSAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 141fed79b8eSAlp Dener tao->ops->solve=TaoSolve_BNTR; 142fed79b8eSAlp Dener 143fed79b8eSAlp Dener bnk = (TAO_BNK *)tao->data; 14466ed3702SAlp Dener bnk->update_type = BNK_UPDATE_REDUCTION; /* trust region updates based on predicted/actual reduction */ 14566ed3702SAlp Dener bnk->sval = 0.0; /* disable Hessian shifting */ 146fed79b8eSAlp Dener PetscFunctionReturn(0); 147fed79b8eSAlp Dener }