1ac9112b8SAlp Dener #include <petsctaolinesearch.h> 2ac9112b8SAlp Dener #include <../src/tao/bound/impls/bncg/bncg.h> 3ac9112b8SAlp Dener 4ac9112b8SAlp Dener #define CG_FletcherReeves 0 5ac9112b8SAlp Dener #define CG_PolakRibiere 1 6ac9112b8SAlp Dener #define CG_PolakRibierePlus 2 7ac9112b8SAlp Dener #define CG_HestenesStiefel 3 8ac9112b8SAlp Dener #define CG_DaiYuan 4 9560169d0SAlp Dener #define CG_GradientDescent 5 10560169d0SAlp Dener #define CG_Types 6 11ac9112b8SAlp Dener 12560169d0SAlp Dener static const char *CG_Table[64] = {"fr", "pr", "prp", "hs", "dy", "gd"}; 13ac9112b8SAlp Dener 1461be54a6SAlp Dener #define CG_AS_NONE 0 1561be54a6SAlp Dener #define CG_AS_BERTSEKAS 1 1661be54a6SAlp Dener #define CG_AS_SIZE 2 17ac9112b8SAlp Dener 1861be54a6SAlp Dener static const char *CG_AS_TYPE[64] = {"none", "bertsekas"}; 19ac9112b8SAlp Dener 20c0f10754SAlp Dener PetscErrorCode TaoBNCGSetRecycleFlag(Tao tao, PetscBool recycle) 21c0f10754SAlp Dener { 22c0f10754SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 23c0f10754SAlp Dener 24c0f10754SAlp Dener PetscFunctionBegin; 25c0f10754SAlp Dener cg->recycle = recycle; 26c0f10754SAlp Dener PetscFunctionReturn(0); 27c0f10754SAlp Dener } 28c0f10754SAlp Dener 2961be54a6SAlp Dener PetscErrorCode TaoBNCGEstimateActiveSet(Tao tao, PetscInt asType) 3061be54a6SAlp Dener { 3161be54a6SAlp Dener PetscErrorCode ierr; 3261be54a6SAlp Dener TAO_BNCG *cg = (TAO_BNCG *)tao->data; 3361be54a6SAlp Dener 3461be54a6SAlp Dener PetscFunctionBegin; 35*cd929ea3SAlp Dener if (!tao->bounded) PetscFunctionReturn(0); 3661be54a6SAlp Dener ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 3761be54a6SAlp Dener if (cg->inactive_idx) { 3861be54a6SAlp Dener ierr = ISDuplicate(cg->inactive_idx, &cg->inactive_old);CHKERRQ(ierr); 3961be54a6SAlp Dener ierr = ISCopy(cg->inactive_idx, cg->inactive_old);CHKERRQ(ierr); 4061be54a6SAlp Dener } 4161be54a6SAlp Dener switch (asType) { 4261be54a6SAlp Dener case CG_AS_NONE: 4361be54a6SAlp Dener ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 4461be54a6SAlp Dener ierr = VecWhichInactive(tao->XL, tao->solution, cg->unprojected_gradient, tao->XU, PETSC_TRUE, &cg->inactive_idx);CHKERRQ(ierr); 4561be54a6SAlp Dener ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 4661be54a6SAlp Dener ierr = ISComplementVec(cg->inactive_idx, tao->solution, &cg->active_idx);CHKERRQ(ierr); 4761be54a6SAlp Dener break; 4861be54a6SAlp Dener 4961be54a6SAlp Dener case CG_AS_BERTSEKAS: 5061be54a6SAlp Dener /* Use gradient descent to estimate the active set */ 5161be54a6SAlp Dener ierr = VecCopy(cg->unprojected_gradient, cg->W);CHKERRQ(ierr); 5261be54a6SAlp Dener ierr = VecScale(cg->W, -1.0);CHKERRQ(ierr); 5389da521bSAlp Dener ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, cg->unprojected_gradient, cg->W, cg->work, cg->as_step, &cg->as_tol, 5489da521bSAlp Dener &cg->active_lower, &cg->active_upper, &cg->active_fixed, &cg->active_idx, &cg->inactive_idx);CHKERRQ(ierr); 55c4b75bccSAlp Dener break; 5661be54a6SAlp Dener 5761be54a6SAlp Dener default: 5861be54a6SAlp Dener break; 5961be54a6SAlp Dener } 6061be54a6SAlp Dener PetscFunctionReturn(0); 6161be54a6SAlp Dener } 6261be54a6SAlp Dener 63a1318120SAlp Dener PetscErrorCode TaoBNCGBoundStep(Tao tao, PetscInt asType, Vec step) 6461be54a6SAlp Dener { 6561be54a6SAlp Dener PetscErrorCode ierr; 6661be54a6SAlp Dener TAO_BNCG *cg = (TAO_BNCG *)tao->data; 6761be54a6SAlp Dener 6861be54a6SAlp Dener PetscFunctionBegin; 69*cd929ea3SAlp Dener if (!tao->bounded) PetscFunctionReturn(0); 70a1318120SAlp Dener switch (asType) { 7161be54a6SAlp Dener case CG_AS_NONE: 72c4b75bccSAlp Dener ierr = VecISSet(step, cg->active_idx, 0.0);CHKERRQ(ierr); 7361be54a6SAlp Dener break; 7461be54a6SAlp Dener 7561be54a6SAlp Dener case CG_AS_BERTSEKAS: 76c4b75bccSAlp Dener ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, cg->active_lower, cg->active_upper, cg->active_fixed, 1.0, step);CHKERRQ(ierr); 7761be54a6SAlp Dener break; 7861be54a6SAlp Dener 7961be54a6SAlp Dener default: 8061be54a6SAlp Dener break; 8161be54a6SAlp Dener } 8261be54a6SAlp Dener PetscFunctionReturn(0); 8361be54a6SAlp Dener } 8461be54a6SAlp Dener 85ac9112b8SAlp Dener static PetscErrorCode TaoSolve_BNCG(Tao tao) 86ac9112b8SAlp Dener { 87ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 88ac9112b8SAlp Dener PetscErrorCode ierr; 89ac9112b8SAlp Dener TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING; 9089da521bSAlp Dener PetscReal step=1.0,gnorm,gnorm2,gd,ginner,beta,dnorm; 9189da521bSAlp Dener PetscReal gd_old,gnorm2_old,f_old,resnorm; 92560169d0SAlp Dener PetscBool cg_restart, gd_fallback = PETSC_FALSE; 93c4b75bccSAlp Dener PetscInt nDiff; 94ac9112b8SAlp Dener 95ac9112b8SAlp Dener PetscFunctionBegin; 96ac9112b8SAlp Dener /* Project the current point onto the feasible set */ 97ac9112b8SAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 983b063059SAlp Dener ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr); 99*cd929ea3SAlp Dener if (tao->bounded) { 100*cd929ea3SAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 101*cd929ea3SAlp Dener } 102ac9112b8SAlp Dener 103e046c495SAlp Dener if (nDiff > 0 || !cg->recycle) { 10411eb65dcSAlp Dener /* Solver is not being recycled so just compute the objective function and criteria */ 105c0f10754SAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &cg->f, cg->unprojected_gradient);CHKERRQ(ierr); 10611eb65dcSAlp Dener } else { 10711eb65dcSAlp Dener /* We are recycling, so we have to compute ||g_old||^2 for use in the CG step calculation */ 10811eb65dcSAlp Dener ierr = VecDot(cg->G_old, cg->G_old, &gnorm2_old);CHKERRQ(ierr); 109c0f10754SAlp Dener } 110ac9112b8SAlp Dener ierr = VecNorm(cg->unprojected_gradient,NORM_2,&gnorm);CHKERRQ(ierr); 111c0f10754SAlp Dener if (PetscIsInfOrNanReal(cg->f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 112ac9112b8SAlp Dener 11361be54a6SAlp Dener /* Estimate the active set and compute the projected gradient */ 11461be54a6SAlp Dener ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 11561be54a6SAlp Dener 116ac9112b8SAlp Dener /* Project the gradient and calculate the norm */ 11761be54a6SAlp Dener ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 11861be54a6SAlp Dener ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 119ac9112b8SAlp Dener ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 120ac9112b8SAlp Dener gnorm2 = gnorm*gnorm; 121ac9112b8SAlp Dener 122ac9112b8SAlp Dener /* Convergence check */ 123e031d6f5SAlp Dener tao->niter = 0; 124ac9112b8SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 125*cd929ea3SAlp Dener ierr = VecFischer(tao->solution, cg->unprojected_gradient, tao->XL, tao->XU, cg->W);CHKERRQ(ierr); 126*cd929ea3SAlp Dener ierr = VecNorm(cg->W, NORM_2, &resnorm);CHKERRQ(ierr); 127*cd929ea3SAlp Dener ierr = TaoLogConvergenceHistory(tao, cg->f, resnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 128*cd929ea3SAlp Dener ierr = TaoMonitor(tao, tao->niter, cg->f, resnorm, 0.0, step);CHKERRQ(ierr); 129ac9112b8SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 130ac9112b8SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 131ac9112b8SAlp Dener 132ac9112b8SAlp Dener /* Start optimization iterations */ 133e031d6f5SAlp Dener cg->ls_fails = cg->broken_ortho = cg->descent_error = 0; 134ac9112b8SAlp Dener cg->resets = -1; 135ac9112b8SAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 136c4b75bccSAlp Dener ++tao->niter; 13789da521bSAlp Dener 13889da521bSAlp Dener /* Check restart conditions for using steepest descent */ 139ac9112b8SAlp Dener cg_restart = PETSC_FALSE; 140ac9112b8SAlp Dener ierr = VecDot(tao->gradient, cg->G_old, &ginner);CHKERRQ(ierr); 141937a31a1SAlp Dener ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);CHKERRQ(ierr); 142c4b75bccSAlp Dener if (tao->niter == 1 && !cg->recycle && dnorm != 0.0) { 143937a31a1SAlp Dener /* 1) First iteration, with recycle disabled, and a non-zero previous step */ 144ac9112b8SAlp Dener cg_restart = PETSC_TRUE; 145ac9112b8SAlp Dener } else if (PetscAbsScalar(ginner) >= cg->eta * gnorm2) { 146ac9112b8SAlp Dener /* 2) Gradients are far from orthogonal */ 147ac9112b8SAlp Dener cg_restart = PETSC_TRUE; 148c4b75bccSAlp Dener ++cg->broken_ortho; 149ac9112b8SAlp Dener } 150ac9112b8SAlp Dener 151ac9112b8SAlp Dener /* Compute CG step */ 152ac9112b8SAlp Dener if (cg_restart) { 153ac9112b8SAlp Dener beta = 0.0; 154c4b75bccSAlp Dener ++cg->resets; 155ac9112b8SAlp Dener } else { 156ac9112b8SAlp Dener switch (cg->cg_type) { 157ac9112b8SAlp Dener case CG_FletcherReeves: 158ac9112b8SAlp Dener beta = gnorm2 / gnorm2_old; 159ac9112b8SAlp Dener break; 160ac9112b8SAlp Dener 161ac9112b8SAlp Dener case CG_PolakRibiere: 162ac9112b8SAlp Dener beta = (gnorm2 - ginner) / gnorm2_old; 163ac9112b8SAlp Dener break; 164ac9112b8SAlp Dener 165ac9112b8SAlp Dener case CG_PolakRibierePlus: 166ac9112b8SAlp Dener beta = PetscMax((gnorm2-ginner)/gnorm2_old, 0.0); 167ac9112b8SAlp Dener break; 168ac9112b8SAlp Dener 169ac9112b8SAlp Dener case CG_HestenesStiefel: 170ac9112b8SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 171ac9112b8SAlp Dener ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 172ac9112b8SAlp Dener beta = (gnorm2 - ginner) / (gd - gd_old); 173ac9112b8SAlp Dener break; 174ac9112b8SAlp Dener 175ac9112b8SAlp Dener case CG_DaiYuan: 176ac9112b8SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 177ac9112b8SAlp Dener ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 178ac9112b8SAlp Dener beta = gnorm2 / (gd - gd_old); 179ac9112b8SAlp Dener break; 180ac9112b8SAlp Dener 181560169d0SAlp Dener case CG_GradientDescent: 182560169d0SAlp Dener beta = 0.0; 183560169d0SAlp Dener break; 184560169d0SAlp Dener 185ac9112b8SAlp Dener default: 186ac9112b8SAlp Dener beta = 0.0; 187ac9112b8SAlp Dener break; 188ac9112b8SAlp Dener } 189ac9112b8SAlp Dener } 190ac9112b8SAlp Dener 191ac9112b8SAlp Dener /* Compute the direction d=-g + beta*d */ 192ac9112b8SAlp Dener ierr = VecAXPBY(tao->stepdirection, -1.0, beta, tao->gradient);CHKERRQ(ierr); 193a1318120SAlp Dener ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 19489da521bSAlp Dener 195560169d0SAlp Dener if (cg->cg_type != CG_GradientDescent) { 19689da521bSAlp Dener /* Figure out which previously active variables became inactive this iteration */ 19761be54a6SAlp Dener ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 19889da521bSAlp Dener if (cg->inactive_idx && cg->inactive_old) { 1990b7db9bbSAlp Dener ierr = ISDifference(cg->inactive_idx, cg->inactive_old, &cg->new_inactives);CHKERRQ(ierr); 20089da521bSAlp Dener } 20189da521bSAlp Dener 20289da521bSAlp Dener /* Selectively reset the CG step those freshly inactive variables */ 2037529f6b4SAlp Dener if (cg->new_inactives) { 20461be54a6SAlp Dener ierr = VecGetSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 20589da521bSAlp Dener ierr = VecGetSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 20661be54a6SAlp Dener ierr = VecCopy(cg->inactive_grad, cg->inactive_step);CHKERRQ(ierr); 20761be54a6SAlp Dener ierr = VecScale(cg->inactive_step, -1.0);CHKERRQ(ierr); 20861be54a6SAlp Dener ierr = VecRestoreSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 20989da521bSAlp Dener ierr = VecRestoreSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 2107529f6b4SAlp Dener } 211ac9112b8SAlp Dener 212ac9112b8SAlp Dener /* Verify that this is a descent direction */ 213ac9112b8SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 214560169d0SAlp Dener ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm); 215ac9112b8SAlp Dener if (gd > -cg->rho*PetscPowReal(dnorm, cg->pow)) { 216ac9112b8SAlp Dener /* Not a descent direction, so we reset back to projected gradient descent */ 217ac9112b8SAlp Dener ierr = VecAXPBY(tao->stepdirection, -1.0, 0.0, tao->gradient);CHKERRQ(ierr); 218560169d0SAlp Dener ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 219c4b75bccSAlp Dener ++cg->resets; 220c4b75bccSAlp Dener ++cg->descent_error; 221560169d0SAlp Dener gd_fallback = PETSC_TRUE; 222560169d0SAlp Dener } else { 223560169d0SAlp Dener gd_fallback = PETSC_FALSE; 224560169d0SAlp Dener } 225ac9112b8SAlp Dener } 226ac9112b8SAlp Dener 227ac9112b8SAlp Dener /* Store solution and gradient info before it changes */ 228ac9112b8SAlp Dener ierr = VecCopy(tao->solution, cg->X_old);CHKERRQ(ierr); 229ac9112b8SAlp Dener ierr = VecCopy(tao->gradient, cg->G_old);CHKERRQ(ierr); 230ac9112b8SAlp Dener ierr = VecCopy(cg->unprojected_gradient, cg->unprojected_gradient_old);CHKERRQ(ierr); 231ac9112b8SAlp Dener gnorm2_old = gnorm2; 232c0f10754SAlp Dener f_old = cg->f; 233ac9112b8SAlp Dener 234ac9112b8SAlp Dener /* Perform bounded line search */ 235c0f10754SAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 236ac9112b8SAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 237ac9112b8SAlp Dener 238ac9112b8SAlp Dener /* Check linesearch failure */ 239ac9112b8SAlp Dener if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) { 240c4b75bccSAlp Dener ++cg->ls_fails; 241ac9112b8SAlp Dener /* Restore previous point */ 242ac9112b8SAlp Dener gnorm2 = gnorm2_old; 243c0f10754SAlp Dener cg->f = f_old; 244ac9112b8SAlp Dener ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr); 245ac9112b8SAlp Dener ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr); 246ac9112b8SAlp Dener ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr); 247ac9112b8SAlp Dener 248560169d0SAlp Dener if (cg->cg_type == CG_GradientDescent || gd_fallback){ 249560169d0SAlp Dener /* Nothing left to do but fail out of the optimization */ 250560169d0SAlp Dener step = 0.0; 251560169d0SAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 252560169d0SAlp Dener } else { 253560169d0SAlp Dener /* Fall back on the unscaled gradient step */ 25461be54a6SAlp Dener ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr); 255ac9112b8SAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 256a1318120SAlp Dener ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 257560169d0SAlp Dener 258560169d0SAlp Dener ierr = TaoLineSearchSetInitialStepLength(tao->linesearch, 1.0);CHKERRQ(ierr); 259c0f10754SAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 260ac9112b8SAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 261ac9112b8SAlp Dener 262ac9112b8SAlp Dener if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER){ 263560169d0SAlp Dener cg->ls_fails++; 264ac9112b8SAlp Dener /* Restore previous point */ 265ac9112b8SAlp Dener gnorm2 = gnorm2_old; 266c0f10754SAlp Dener cg->f = f_old; 267ac9112b8SAlp Dener ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr); 268ac9112b8SAlp Dener ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr); 269ac9112b8SAlp Dener ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr); 270ac9112b8SAlp Dener 271ac9112b8SAlp Dener /* Nothing left to do but fail out of the optimization */ 272ac9112b8SAlp Dener step = 0.0; 273ac9112b8SAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 274ac9112b8SAlp Dener } 275ac9112b8SAlp Dener } 276560169d0SAlp Dener } 277ac9112b8SAlp Dener 278c4b75bccSAlp Dener if (tao->reason != TAO_DIVERGED_LS_FAILURE) { 27961be54a6SAlp Dener /* Estimate the active set at the new solution */ 28061be54a6SAlp Dener ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 28161be54a6SAlp Dener 282ac9112b8SAlp Dener /* Compute the projected gradient and its norm */ 28361be54a6SAlp Dener ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 28461be54a6SAlp Dener ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 285ac9112b8SAlp Dener ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 286ac9112b8SAlp Dener gnorm2 = gnorm*gnorm; 287c4b75bccSAlp Dener } 288ac9112b8SAlp Dener 289ac9112b8SAlp Dener /* Convergence test */ 29061be54a6SAlp Dener ierr = VecFischer(tao->solution, cg->unprojected_gradient, tao->XL, tao->XU, cg->W);CHKERRQ(ierr); 29161be54a6SAlp Dener ierr = VecNorm(cg->W, NORM_2, &resnorm);CHKERRQ(ierr); 292b4a30f08SAlp Dener if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 29361be54a6SAlp Dener ierr = TaoLogConvergenceHistory(tao, cg->f, resnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 29461be54a6SAlp Dener ierr = TaoMonitor(tao, tao->niter, cg->f, resnorm, 0.0, step);CHKERRQ(ierr); 295ac9112b8SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 296ac9112b8SAlp Dener } 297ac9112b8SAlp Dener PetscFunctionReturn(0); 298ac9112b8SAlp Dener } 299ac9112b8SAlp Dener 300ac9112b8SAlp Dener static PetscErrorCode TaoSetUp_BNCG(Tao tao) 301ac9112b8SAlp Dener { 302ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 303ac9112b8SAlp Dener PetscErrorCode ierr; 304ac9112b8SAlp Dener 305ac9112b8SAlp Dener PetscFunctionBegin; 306c4b75bccSAlp Dener if (!tao->gradient) { 307c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); 308c4b75bccSAlp Dener } 309c4b75bccSAlp Dener if (!tao->stepdirection) { 310c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr); 311c4b75bccSAlp Dener } 312c4b75bccSAlp Dener if (!cg->W) { 313c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->W);CHKERRQ(ierr); 314c4b75bccSAlp Dener } 315c4b75bccSAlp Dener if (!cg->work) { 316c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->work);CHKERRQ(ierr); 317c4b75bccSAlp Dener } 318c4b75bccSAlp Dener if (!cg->X_old) { 319c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->X_old);CHKERRQ(ierr); 320c4b75bccSAlp Dener } 321c4b75bccSAlp Dener if (!cg->G_old) { 322c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->G_old);CHKERRQ(ierr); 323c4b75bccSAlp Dener } 324c4b75bccSAlp Dener if (!cg->unprojected_gradient) { 325c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient);CHKERRQ(ierr); 326c4b75bccSAlp Dener } 327c4b75bccSAlp Dener if (!cg->unprojected_gradient_old) { 328c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient_old);CHKERRQ(ierr); 329c4b75bccSAlp Dener } 330ac9112b8SAlp Dener PetscFunctionReturn(0); 331ac9112b8SAlp Dener } 332ac9112b8SAlp Dener 333ac9112b8SAlp Dener static PetscErrorCode TaoDestroy_BNCG(Tao tao) 334ac9112b8SAlp Dener { 335ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*) tao->data; 336ac9112b8SAlp Dener PetscErrorCode ierr; 337ac9112b8SAlp Dener 338ac9112b8SAlp Dener PetscFunctionBegin; 339ac9112b8SAlp Dener if (tao->setupcalled) { 34061be54a6SAlp Dener ierr = VecDestroy(&cg->W);CHKERRQ(ierr); 341c4b75bccSAlp Dener ierr = VecDestroy(&cg->work);CHKERRQ(ierr); 342ac9112b8SAlp Dener ierr = VecDestroy(&cg->X_old);CHKERRQ(ierr); 343ac9112b8SAlp Dener ierr = VecDestroy(&cg->G_old);CHKERRQ(ierr); 344ac9112b8SAlp Dener ierr = VecDestroy(&cg->unprojected_gradient);CHKERRQ(ierr); 345ac9112b8SAlp Dener ierr = VecDestroy(&cg->unprojected_gradient_old);CHKERRQ(ierr); 346ac9112b8SAlp Dener } 347ca964c49SAlp Dener ierr = ISDestroy(&cg->active_lower);CHKERRQ(ierr); 348ca964c49SAlp Dener ierr = ISDestroy(&cg->active_upper);CHKERRQ(ierr); 349ca964c49SAlp Dener ierr = ISDestroy(&cg->active_fixed);CHKERRQ(ierr); 350ca964c49SAlp Dener ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 351ca964c49SAlp Dener ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 352ca964c49SAlp Dener ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 353ca964c49SAlp Dener ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 354ac9112b8SAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 355ac9112b8SAlp Dener PetscFunctionReturn(0); 356ac9112b8SAlp Dener } 357ac9112b8SAlp Dener 358ac9112b8SAlp Dener static PetscErrorCode TaoSetFromOptions_BNCG(PetscOptionItems *PetscOptionsObject,Tao tao) 359ac9112b8SAlp Dener { 360ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 361ac9112b8SAlp Dener PetscErrorCode ierr; 362ac9112b8SAlp Dener 363ac9112b8SAlp Dener PetscFunctionBegin; 364ac9112b8SAlp Dener ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 365ac9112b8SAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Nonlinear Conjugate Gradient method for unconstrained optimization");CHKERRQ(ierr); 36661be54a6SAlp Dener ierr = PetscOptionsReal("-tao_bncg_eta","restart tolerance", "", cg->eta,&cg->eta,NULL);CHKERRQ(ierr); 36761be54a6SAlp Dener ierr = PetscOptionsReal("-tao_bncg_rho","descent direction tolerance", "", cg->rho,&cg->rho,NULL);CHKERRQ(ierr); 36861be54a6SAlp Dener ierr = PetscOptionsReal("-tao_bncg_pow","descent direction exponent", "", cg->pow,&cg->pow,NULL);CHKERRQ(ierr); 36961be54a6SAlp Dener ierr = PetscOptionsEList("-tao_bncg_type","cg formula", "", CG_Table, CG_Types, CG_Table[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr); 370*cd929ea3SAlp Dener ierr = PetscOptionsEList("-tao_bncg_as_type","active set estimation method", "", CG_AS_TYPE, CG_AS_SIZE, CG_AS_TYPE[cg->as_type], &cg->as_type,NULL);CHKERRQ(ierr); 37161be54a6SAlp Dener ierr = PetscOptionsBool("-tao_bncg_recycle","enable recycling the existing solution and gradient at the start of a new solve","",cg->recycle,&cg->recycle,NULL);CHKERRQ(ierr); 37261be54a6SAlp Dener ierr = PetscOptionsReal("-tao_bncg_as_tol", "initial tolerance used when estimating actively bounded variables","",cg->as_tol,&cg->as_tol,NULL);CHKERRQ(ierr); 37361be54a6SAlp Dener ierr = PetscOptionsReal("-tao_bncg_as_step", "step length used when estimating actively bounded variables","",cg->as_step,&cg->as_step,NULL);CHKERRQ(ierr); 374ac9112b8SAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 375ac9112b8SAlp Dener PetscFunctionReturn(0); 376ac9112b8SAlp Dener } 377ac9112b8SAlp Dener 378ac9112b8SAlp Dener static PetscErrorCode TaoView_BNCG(Tao tao, PetscViewer viewer) 379ac9112b8SAlp Dener { 380ac9112b8SAlp Dener PetscBool isascii; 381ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 382ac9112b8SAlp Dener PetscErrorCode ierr; 383ac9112b8SAlp Dener 384ac9112b8SAlp Dener PetscFunctionBegin; 385ac9112b8SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 386ac9112b8SAlp Dener if (isascii) { 387ac9112b8SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 388ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "CG Type: %s\n", CG_Table[cg->cg_type]);CHKERRQ(ierr); 389ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Resets: %i\n", cg->resets);CHKERRQ(ierr); 390ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " Broken ortho: %i\n", cg->broken_ortho);CHKERRQ(ierr); 391ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " Not a descent dir.: %i\n", cg->descent_error);CHKERRQ(ierr); 392ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Line search fails: %i\n", cg->ls_fails);CHKERRQ(ierr); 393ac9112b8SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 394ac9112b8SAlp Dener } 395ac9112b8SAlp Dener PetscFunctionReturn(0); 396ac9112b8SAlp Dener } 397ac9112b8SAlp Dener 398ac9112b8SAlp Dener /*MC 399ac9112b8SAlp Dener TAOBNCG - Bound-constrained Nonlinear Conjugate Gradient method. 400ac9112b8SAlp Dener 401ac9112b8SAlp Dener Options Database Keys: 402c4b75bccSAlp Dener + -tao_bncg_recycle - enable recycling the latest calculated gradient vector in subsequent TaoSolve() calls 403c4b75bccSAlp Dener . -tao_bncg_eta <r> - restart tolerance 40461be54a6SAlp Dener . -tao_bncg_type <taocg_type> - cg formula 405c4b75bccSAlp Dener . -tao_bncg_as_type <none,bertsekas> - active set estimation method 406c4b75bccSAlp Dener . -tao_bncg_as_tol <r> - tolerance used in Bertsekas active-set estimation 407c4b75bccSAlp Dener . -tao_bncg_as_step <r> - trial step length used in Bertsekas active-set estimation 408ac9112b8SAlp Dener 409ac9112b8SAlp Dener Notes: 410ac9112b8SAlp Dener CG formulas are: 411ac9112b8SAlp Dener "fr" - Fletcher-Reeves 412ac9112b8SAlp Dener "pr" - Polak-Ribiere 413ac9112b8SAlp Dener "prp" - Polak-Ribiere-Plus 414ac9112b8SAlp Dener "hs" - Hestenes-Steifel 415ac9112b8SAlp Dener "dy" - Dai-Yuan 416560169d0SAlp Dener "gd" - Gradient Descent 417ac9112b8SAlp Dener Level: beginner 418ac9112b8SAlp Dener M*/ 419ac9112b8SAlp Dener 420ac9112b8SAlp Dener 421ac9112b8SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNCG(Tao tao) 422ac9112b8SAlp Dener { 423ac9112b8SAlp Dener TAO_BNCG *cg; 424ac9112b8SAlp Dener const char *morethuente_type = TAOLINESEARCHMT; 425ac9112b8SAlp Dener PetscErrorCode ierr; 426ac9112b8SAlp Dener 427ac9112b8SAlp Dener PetscFunctionBegin; 428ac9112b8SAlp Dener tao->ops->setup = TaoSetUp_BNCG; 429ac9112b8SAlp Dener tao->ops->solve = TaoSolve_BNCG; 430ac9112b8SAlp Dener tao->ops->view = TaoView_BNCG; 431ac9112b8SAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BNCG; 432ac9112b8SAlp Dener tao->ops->destroy = TaoDestroy_BNCG; 433ac9112b8SAlp Dener 434ac9112b8SAlp Dener /* Override default settings (unless already changed) */ 435ac9112b8SAlp Dener if (!tao->max_it_changed) tao->max_it = 2000; 436ac9112b8SAlp Dener if (!tao->max_funcs_changed) tao->max_funcs = 4000; 437ac9112b8SAlp Dener 438ac9112b8SAlp Dener /* Note: nondefault values should be used for nonlinear conjugate gradient */ 439ac9112b8SAlp Dener /* method. In particular, gtol should be less that 0.5; the value used in */ 440ac9112b8SAlp Dener /* Nocedal and Wright is 0.10. We use the default values for the */ 441ac9112b8SAlp Dener /* linesearch because it seems to work better. */ 442ac9112b8SAlp Dener ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr); 443ac9112b8SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 444ac9112b8SAlp Dener ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr); 445ac9112b8SAlp Dener ierr = TaoLineSearchUseTaoRoutines(tao->linesearch, tao);CHKERRQ(ierr); 446ac9112b8SAlp Dener ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 447ac9112b8SAlp Dener 448ac9112b8SAlp Dener ierr = PetscNewLog(tao,&cg);CHKERRQ(ierr); 449ac9112b8SAlp Dener tao->data = (void*)cg; 450ac9112b8SAlp Dener cg->rho = 1e-4; 451ac9112b8SAlp Dener cg->pow = 2.1; 452ac9112b8SAlp Dener cg->eta = 0.5; 45361be54a6SAlp Dener cg->as_step = 0.001; 45461be54a6SAlp Dener cg->as_tol = 0.001; 45561be54a6SAlp Dener cg->as_type = CG_AS_BERTSEKAS; 456ac9112b8SAlp Dener cg->cg_type = CG_DaiYuan; 457c0f10754SAlp Dener cg->recycle = PETSC_FALSE; 458ac9112b8SAlp Dener PetscFunctionReturn(0); 459ac9112b8SAlp Dener } 460