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; 22e465cd6fSAlp 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; 33*28017e9fSAlp Dener /* Initialize the preconditioner, KSP solver and trust radius/line search */ 34eb910715SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 35eb910715SAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 36*28017e9fSAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 37eb910715SAlp Dener 38eb910715SAlp Dener /* Have not converged; continue with Newton method */ 39eb910715SAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 40eb910715SAlp Dener ++tao->niter; 41eb910715SAlp Dener tao->ksp_its=0; 42eb910715SAlp Dener 4309164190SAlp Dener /* Compute the Hessian */ 4409164190SAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 45e465cd6fSAlp Dener /* Shift the Hessian matrix */ 46e465cd6fSAlp Dener if (bnk->pert > 0) { 47e465cd6fSAlp Dener ierr = MatShift(tao->hessian, bnk->pert);CHKERRQ(ierr); 48e465cd6fSAlp Dener if (tao->hessian != tao->hessian_pre) { 49e465cd6fSAlp Dener ierr = MatShift(tao->hessian_pre, bnk->pert);CHKERRQ(ierr); 50e465cd6fSAlp Dener } 51e465cd6fSAlp Dener } 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 ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 64fed79b8eSAlp Dener } 65fed79b8eSAlp Dener 668d5ead36SAlp Dener /* Use the common BNK kernel to compute the safeguarded Newton step (for inactive variables only) */ 67*28017e9fSAlp Dener tao->trust = bnk->max_radius; 68e465cd6fSAlp Dener ierr = TaoBNKComputeStep(tao, &ksp_reason);CHKERRQ(ierr); 69e465cd6fSAlp Dener ierr = TaoBNKSafeguardStep(tao, ksp_reason, &stepType);CHKERRQ(ierr); 70eb910715SAlp Dener 71080d2917SAlp Dener /* Store current solution before it changes */ 72080d2917SAlp Dener bnk->fold = bnk->f; 73eb910715SAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 74eb910715SAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 7509164190SAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->unprojected_gradient_old);CHKERRQ(ierr); 76eb910715SAlp Dener 77c14b763aSAlp Dener /* Trigger the line search */ 78c14b763aSAlp Dener ierr = TaoBNKPerformLineSearch(tao, stepType, &steplen, &ls_reason);CHKERRQ(ierr); 79eb910715SAlp Dener 80eb910715SAlp Dener if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) { 81eb910715SAlp Dener /* Failed to find an improving point */ 82080d2917SAlp Dener bnk->f = bnk->fold; 83eb910715SAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 84eb910715SAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 8509164190SAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 86c14b763aSAlp Dener steplen = 0.0; 87eb910715SAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 88eb910715SAlp Dener break; 89e465cd6fSAlp Dener } else { 90e465cd6fSAlp Dener /* count the accepted step types */ 91e465cd6fSAlp Dener switch (stepType) { 92e465cd6fSAlp Dener case BNK_NEWTON: 93e465cd6fSAlp Dener ++bnk->newt; 94e465cd6fSAlp Dener break; 95e465cd6fSAlp Dener case BNK_BFGS: 96e465cd6fSAlp Dener ++bnk->bfgs; 97e465cd6fSAlp Dener break; 98e465cd6fSAlp Dener case BNK_SCALED_GRADIENT: 99e465cd6fSAlp Dener ++bnk->sgrad; 100e465cd6fSAlp Dener break; 101e465cd6fSAlp Dener case BNK_GRADIENT: 102e465cd6fSAlp Dener ++bnk->grad; 103e465cd6fSAlp Dener break; 104e465cd6fSAlp Dener default: 105e465cd6fSAlp Dener break; 106e465cd6fSAlp Dener } 107eb910715SAlp Dener } 108eb910715SAlp Dener 109eb910715SAlp Dener /* Check for termination */ 110eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 111eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 112eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 113c14b763aSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,steplen);CHKERRQ(ierr); 114eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 115eb910715SAlp Dener } 116eb910715SAlp Dener PetscFunctionReturn(0); 117eb910715SAlp Dener } 118eb910715SAlp Dener 119df278d8fSAlp Dener /*------------------------------------------------------------*/ 120df278d8fSAlp Dener 121eb910715SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNLS(Tao tao) 122eb910715SAlp Dener { 123fed79b8eSAlp Dener TAO_BNK *bnk; 124eb910715SAlp Dener PetscErrorCode ierr; 125eb910715SAlp Dener 126eb910715SAlp Dener PetscFunctionBegin; 127eb910715SAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 128eb910715SAlp Dener tao->ops->solve = TaoSolve_BNLS; 129fed79b8eSAlp Dener 130fed79b8eSAlp Dener bnk = (TAO_BNK *)tao->data; 131*28017e9fSAlp Dener bnk->init_type = BNK_INIT_CONSTANT; 13266ed3702SAlp Dener bnk->update_type = BNK_UPDATE_STEP; /* trust region updates based on line search step length */ 133eb910715SAlp Dener PetscFunctionReturn(0); 134eb910715SAlp Dener }