1eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h> 2eb910715SAlp Dener #include <petscksp.h> 3eb910715SAlp Dener 4eb910715SAlp Dener /* 5eb910715SAlp Dener Implements Newton's Method with a line search approach for solving 62b97c8d8SAlp Dener bound constrained minimization problems. A projected More'-Thuente line 7770b7498SAlp Dener search is used to guarantee that the BFGS preconditioner remains positive 8eb910715SAlp Dener definite. 9eb910715SAlp Dener 10eb910715SAlp Dener The method can shift the Hessian matrix. The shifting procedure is 11eb910715SAlp Dener adapted from the PATH algorithm for solving complementarity 12eb910715SAlp Dener problems. 13eb910715SAlp Dener 14eb910715SAlp Dener The linear system solve should be done with a conjugate gradient 15eb910715SAlp Dener method, although any method can be used. 16eb910715SAlp Dener */ 17eb910715SAlp Dener 18eb910715SAlp Dener static PetscErrorCode TaoSolve_BNLS(Tao tao) 19eb910715SAlp Dener { 20eb910715SAlp Dener PetscErrorCode ierr; 21eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 22*e465cd6fSAlp Dener KSPConvergedReason ksp_reason; 23eb910715SAlp Dener TaoLineSearchConvergedReason ls_reason; 24eb910715SAlp Dener 25c14b763aSAlp Dener PetscReal f_full, prered, actred; 26c14b763aSAlp Dener PetscReal steplen = 1.0; 27eb910715SAlp Dener 28080d2917SAlp Dener PetscBool trustAccept; 29eb910715SAlp Dener PetscInt stepType; 30eb910715SAlp Dener PetscInt bfgsUpdates = 0; 31eb910715SAlp Dener 32eb910715SAlp Dener PetscFunctionBegin; 3309164190SAlp Dener /* Project the current point onto the feasible set */ 3409164190SAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 3509164190SAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 3609164190SAlp Dener 3709164190SAlp Dener /* Project the initial point onto the feasible region */ 3809164190SAlp Dener ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); 39eb910715SAlp Dener 40eb910715SAlp Dener /* Check convergence criteria */ 4109164190SAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr); 4209164190SAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 43eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 44eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 45eb910715SAlp Dener 46eb910715SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 47eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 48c14b763aSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 49eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 50eb910715SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 51eb910715SAlp Dener 52eb910715SAlp Dener /* Initialize the preconditioner and trust radius */ 53eb910715SAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 54eb910715SAlp Dener 55eb910715SAlp Dener /* Have not converged; continue with Newton method */ 56eb910715SAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 57eb910715SAlp Dener ++tao->niter; 58eb910715SAlp Dener tao->ksp_its=0; 59eb910715SAlp Dener 6009164190SAlp Dener /* Compute the Hessian */ 6109164190SAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 62*e465cd6fSAlp Dener /* Shift the Hessian matrix */ 63*e465cd6fSAlp Dener if (bnk->pert > 0) { 64*e465cd6fSAlp Dener ierr = MatShift(tao->hessian, bnk->pert);CHKERRQ(ierr); 65*e465cd6fSAlp Dener if (tao->hessian != tao->hessian_pre) { 66*e465cd6fSAlp Dener ierr = MatShift(tao->hessian_pre, bnk->pert);CHKERRQ(ierr); 67*e465cd6fSAlp Dener } 68*e465cd6fSAlp Dener } 69fed79b8eSAlp Dener /* Update the BFGS preconditioner */ 70fed79b8eSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 71fed79b8eSAlp Dener if (BFGS_SCALE_PHESS == bnk->bfgs_scale_type) { 72fed79b8eSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 73fed79b8eSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 74fed79b8eSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 75fed79b8eSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 76fed79b8eSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 77fed79b8eSAlp Dener } 78fed79b8eSAlp Dener /* Update the limited memory preconditioner and get existing # of updates */ 79fed79b8eSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 80fed79b8eSAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 81fed79b8eSAlp Dener } 82fed79b8eSAlp Dener 838d5ead36SAlp Dener /* Use the common BNK kernel to compute the safeguarded Newton step (for inactive variables only) */ 84*e465cd6fSAlp Dener ierr = TaoBNKComputeStep(tao, &ksp_reason);CHKERRQ(ierr); 85*e465cd6fSAlp Dener ierr = TaoBNKSafeguardStep(tao, ksp_reason, &stepType);CHKERRQ(ierr); 86eb910715SAlp Dener 87080d2917SAlp Dener /* Store current solution before it changes */ 88080d2917SAlp Dener bnk->fold = bnk->f; 89eb910715SAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 90eb910715SAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 9109164190SAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->unprojected_gradient_old);CHKERRQ(ierr); 92eb910715SAlp Dener 93c14b763aSAlp Dener /* Trigger the line search */ 94c14b763aSAlp Dener ierr = TaoBNKPerformLineSearch(tao, stepType, &steplen, &ls_reason);CHKERRQ(ierr); 95eb910715SAlp Dener 96eb910715SAlp Dener if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) { 97eb910715SAlp Dener /* Failed to find an improving point */ 98080d2917SAlp Dener bnk->f = bnk->fold; 99eb910715SAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 100eb910715SAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 10109164190SAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 102c14b763aSAlp Dener steplen = 0.0; 103eb910715SAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 104eb910715SAlp Dener break; 105*e465cd6fSAlp Dener } else { 106*e465cd6fSAlp Dener /* count the accepted step types */ 107*e465cd6fSAlp Dener switch (stepType) { 108*e465cd6fSAlp Dener case BNK_NEWTON: 109*e465cd6fSAlp Dener ++bnk->newt; 110*e465cd6fSAlp Dener break; 111*e465cd6fSAlp Dener case BNK_BFGS: 112*e465cd6fSAlp Dener ++bnk->bfgs; 113*e465cd6fSAlp Dener break; 114*e465cd6fSAlp Dener case BNK_SCALED_GRADIENT: 115*e465cd6fSAlp Dener ++bnk->sgrad; 116*e465cd6fSAlp Dener break; 117*e465cd6fSAlp Dener case BNK_GRADIENT: 118*e465cd6fSAlp Dener ++bnk->grad; 119*e465cd6fSAlp Dener break; 120*e465cd6fSAlp Dener default: 121*e465cd6fSAlp Dener break; 122*e465cd6fSAlp Dener } 123eb910715SAlp Dener } 124eb910715SAlp Dener 125080d2917SAlp Dener /* update trust radius */ 126080d2917SAlp Dener ierr = TaoLineSearchGetFullStepObjective(tao->linesearch, &f_full);CHKERRQ(ierr); 127b1c2d0e3SAlp Dener ierr = KSPCGGetObjFcn(tao->ksp, &prered);CHKERRQ(ierr); 128b1c2d0e3SAlp Dener prered = -prered; 129b1c2d0e3SAlp Dener actred = bnk->fold - f_full; 130b1c2d0e3SAlp Dener ierr = TaoBNKUpdateTrustRadius(tao, prered, actred, stepType, &trustAccept);CHKERRQ(ierr); 131eb910715SAlp Dener 132eb910715SAlp Dener /* Check for termination */ 133eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 134eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 135eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 136c14b763aSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 137eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 138eb910715SAlp Dener } 139eb910715SAlp Dener PetscFunctionReturn(0); 140eb910715SAlp Dener } 141eb910715SAlp Dener 142df278d8fSAlp Dener /*------------------------------------------------------------*/ 143df278d8fSAlp Dener 144eb910715SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNLS(Tao tao) 145eb910715SAlp Dener { 146fed79b8eSAlp Dener TAO_BNK *bnk; 147eb910715SAlp Dener PetscErrorCode ierr; 148eb910715SAlp Dener 149eb910715SAlp Dener PetscFunctionBegin; 150eb910715SAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 151eb910715SAlp Dener tao->ops->solve = TaoSolve_BNLS; 152fed79b8eSAlp Dener 153fed79b8eSAlp Dener bnk = (TAO_BNK *)tao->data; 15466ed3702SAlp Dener bnk->update_type = BNK_UPDATE_STEP; /* trust region updates based on line search step length */ 155eb910715SAlp Dener PetscFunctionReturn(0); 156eb910715SAlp Dener }