1ac9112b8SAlp Dener #include <petsctaolinesearch.h> 2ac9112b8SAlp Dener #include <../src/tao/bound/impls/bncg/bncg.h> 3*50b47da0SAdam Denchfield #include <petscksp.h> 4ac9112b8SAlp Dener 5c8bcdf1eSAdam Denchfield #define CG_GradientDescent 0 6c8bcdf1eSAdam Denchfield #define CG_HestenesStiefel 1 7c8bcdf1eSAdam Denchfield #define CG_FletcherReeves 2 8*50b47da0SAdam Denchfield #define CG_PolakRibierePolyak 3 9c8bcdf1eSAdam Denchfield #define CG_PolakRibierePlus 4 10c8bcdf1eSAdam Denchfield #define CG_DaiYuan 5 11c8bcdf1eSAdam Denchfield #define CG_HagerZhang 6 12c8bcdf1eSAdam Denchfield #define CG_DaiKou 7 13c8bcdf1eSAdam Denchfield #define CG_KouDai 8 14c8bcdf1eSAdam Denchfield #define CG_SSML_BFGS 9 15c8bcdf1eSAdam Denchfield #define CG_SSML_DFP 10 16c8bcdf1eSAdam Denchfield #define CG_SSML_BROYDEN 11 17*50b47da0SAdam Denchfield #define CG_Types 12 18ac9112b8SAlp Dener 19*50b47da0SAdam Denchfield static const char *CG_Table[64] = {"gd", "hs", "fr", "pr", "prp", "dy", "hz", "dk", "kd", "ssml_bfgs", "ssml_dfp", "ssml_brdn"}; 20ac9112b8SAlp Dener 2161be54a6SAlp Dener #define CG_AS_NONE 0 2261be54a6SAlp Dener #define CG_AS_BERTSEKAS 1 2361be54a6SAlp Dener #define CG_AS_SIZE 2 24ac9112b8SAlp Dener 2561be54a6SAlp Dener static const char *CG_AS_TYPE[64] = {"none", "bertsekas"}; 26ac9112b8SAlp Dener 27c0f10754SAlp Dener PetscErrorCode TaoBNCGSetRecycleFlag(Tao tao, PetscBool recycle) 28c0f10754SAlp Dener { 29c0f10754SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 30c0f10754SAlp Dener 31c0f10754SAlp Dener PetscFunctionBegin; 32c0f10754SAlp Dener cg->recycle = recycle; 33c0f10754SAlp Dener PetscFunctionReturn(0); 34c0f10754SAlp Dener } 35c0f10754SAlp Dener 3661be54a6SAlp Dener PetscErrorCode TaoBNCGEstimateActiveSet(Tao tao, PetscInt asType) 3761be54a6SAlp Dener { 3861be54a6SAlp Dener PetscErrorCode ierr; 3961be54a6SAlp Dener TAO_BNCG *cg = (TAO_BNCG *)tao->data; 4061be54a6SAlp Dener 4161be54a6SAlp Dener PetscFunctionBegin; 4261be54a6SAlp Dener ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 4361be54a6SAlp Dener if (cg->inactive_idx) { 4461be54a6SAlp Dener ierr = ISDuplicate(cg->inactive_idx, &cg->inactive_old);CHKERRQ(ierr); 4561be54a6SAlp Dener ierr = ISCopy(cg->inactive_idx, cg->inactive_old);CHKERRQ(ierr); 4661be54a6SAlp Dener } 4761be54a6SAlp Dener switch (asType) { 4861be54a6SAlp Dener case CG_AS_NONE: 4961be54a6SAlp Dener ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 5061be54a6SAlp Dener ierr = VecWhichInactive(tao->XL, tao->solution, cg->unprojected_gradient, tao->XU, PETSC_TRUE, &cg->inactive_idx);CHKERRQ(ierr); 5161be54a6SAlp Dener ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 5261be54a6SAlp Dener ierr = ISComplementVec(cg->inactive_idx, tao->solution, &cg->active_idx);CHKERRQ(ierr); 5361be54a6SAlp Dener break; 5461be54a6SAlp Dener 5561be54a6SAlp Dener case CG_AS_BERTSEKAS: 5661be54a6SAlp Dener /* Use gradient descent to estimate the active set */ 5761be54a6SAlp Dener ierr = VecCopy(cg->unprojected_gradient, cg->W);CHKERRQ(ierr); 5861be54a6SAlp Dener ierr = VecScale(cg->W, -1.0);CHKERRQ(ierr); 5989da521bSAlp Dener ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, cg->unprojected_gradient, cg->W, cg->work, cg->as_step, &cg->as_tol, 6089da521bSAlp Dener &cg->active_lower, &cg->active_upper, &cg->active_fixed, &cg->active_idx, &cg->inactive_idx);CHKERRQ(ierr); 61c4b75bccSAlp Dener break; 6261be54a6SAlp Dener 6361be54a6SAlp Dener default: 6461be54a6SAlp Dener break; 6561be54a6SAlp Dener } 6661be54a6SAlp Dener PetscFunctionReturn(0); 6761be54a6SAlp Dener } 6861be54a6SAlp Dener 69a1318120SAlp Dener PetscErrorCode TaoBNCGBoundStep(Tao tao, PetscInt asType, Vec step) 7061be54a6SAlp Dener { 7161be54a6SAlp Dener PetscErrorCode ierr; 7261be54a6SAlp Dener TAO_BNCG *cg = (TAO_BNCG *)tao->data; 7361be54a6SAlp Dener 7461be54a6SAlp Dener PetscFunctionBegin; 75a1318120SAlp Dener switch (asType) { 7661be54a6SAlp Dener case CG_AS_NONE: 77c4b75bccSAlp Dener ierr = VecISSet(step, cg->active_idx, 0.0);CHKERRQ(ierr); 7861be54a6SAlp Dener break; 7961be54a6SAlp Dener 8061be54a6SAlp Dener case CG_AS_BERTSEKAS: 81c4b75bccSAlp Dener ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, cg->active_lower, cg->active_upper, cg->active_fixed, 1.0, step);CHKERRQ(ierr); 8261be54a6SAlp Dener break; 8361be54a6SAlp Dener 8461be54a6SAlp Dener default: 8561be54a6SAlp Dener break; 8661be54a6SAlp Dener } 8761be54a6SAlp Dener PetscFunctionReturn(0); 8861be54a6SAlp Dener } 8961be54a6SAlp Dener 90ac9112b8SAlp Dener static PetscErrorCode TaoSolve_BNCG(Tao tao) 91ac9112b8SAlp Dener { 92ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 93ac9112b8SAlp Dener PetscErrorCode ierr; 94c8bcdf1eSAdam Denchfield PetscReal step=1.0,gnorm,gnorm2; 95c4b75bccSAlp Dener PetscInt nDiff; 96ac9112b8SAlp Dener 97ac9112b8SAlp Dener PetscFunctionBegin; 98ac9112b8SAlp Dener /* Project the current point onto the feasible set */ 99ac9112b8SAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 100cd929ea3SAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 101ac9112b8SAlp Dener 102c8bcdf1eSAdam Denchfield /* Project the initial point onto the feasible region */ 103c8bcdf1eSAdam Denchfield ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr); 104c0f10754SAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &cg->f, cg->unprojected_gradient);CHKERRQ(ierr); 105ac9112b8SAlp Dener ierr = VecNorm(cg->unprojected_gradient,NORM_2,&gnorm);CHKERRQ(ierr); 106c0f10754SAlp Dener if (PetscIsInfOrNanReal(cg->f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 107ac9112b8SAlp Dener 10861be54a6SAlp Dener /* Estimate the active set and compute the projected gradient */ 10961be54a6SAlp Dener ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 11061be54a6SAlp Dener 111ac9112b8SAlp Dener /* Project the gradient and calculate the norm */ 11261be54a6SAlp Dener ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 11361be54a6SAlp Dener ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 114ac9112b8SAlp Dener ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 115ac9112b8SAlp Dener gnorm2 = gnorm*gnorm; 116ac9112b8SAlp Dener 117c8bcdf1eSAdam Denchfield /* Initialize counters */ 118e031d6f5SAlp Dener tao->niter = 0; 119*50b47da0SAdam Denchfield cg->ls_fails = cg->descent_error = 0; 120c8bcdf1eSAdam Denchfield cg->resets = -1; 121c8bcdf1eSAdam Denchfield cg->iter_quad = 0; 122c8bcdf1eSAdam Denchfield 123c8bcdf1eSAdam Denchfield /* Convergence test at the starting point. */ 124ac9112b8SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 125c8bcdf1eSAdam Denchfield ierr = TaoLogConvergenceHistory(tao, cg->f, gnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 126c8bcdf1eSAdam Denchfield ierr = TaoMonitor(tao, tao->niter, cg->f, gnorm, 0.0, step);CHKERRQ(ierr); 127ac9112b8SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 128ac9112b8SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 129ac9112b8SAlp Dener 130c8bcdf1eSAdam Denchfield /* Assert that we have not converged. Calculate initial direction. */ 131c8bcdf1eSAdam Denchfield /* This is where recycling goes. The outcome of this code must be */ 132c8bcdf1eSAdam Denchfield /* the direction that we will use. */ 133c8bcdf1eSAdam Denchfield if (cg->recycle) { 134ac9112b8SAlp Dener } 135c8bcdf1eSAdam Denchfield /* Initial gradient descent step. Scaling by 1.0 also does a decent job for some problems. */ 136*50b47da0SAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 137ac9112b8SAlp Dener 138c8bcdf1eSAdam Denchfield while(1) { 139c8bcdf1eSAdam Denchfield ierr = TaoBNCGConductIteration(tao, gnorm);CHKERRQ(ierr); 140*50b47da0SAdam Denchfield /* Steffenson is currently an experimental (broken) feature. Do not use. */ 141*50b47da0SAdam Denchfield if (cg->use_steffenson) { 142*50b47da0SAdam Denchfield ierr = TaoBNCGSteffensonAcceleration(tao);CHKERRQ(ierr); 143*50b47da0SAdam Denchfield } 144c8bcdf1eSAdam Denchfield if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 145ac9112b8SAlp Dener } 146ac9112b8SAlp Dener PetscFunctionReturn(0); 147ac9112b8SAlp Dener } 148ac9112b8SAlp Dener 149ac9112b8SAlp Dener static PetscErrorCode TaoSetUp_BNCG(Tao tao) 150ac9112b8SAlp Dener { 151ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 152ac9112b8SAlp Dener PetscErrorCode ierr; 153ac9112b8SAlp Dener 154ac9112b8SAlp Dener PetscFunctionBegin; 155c4b75bccSAlp Dener if (!tao->gradient) { 156c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); 157c4b75bccSAlp Dener } 158c4b75bccSAlp Dener if (!tao->stepdirection) { 159c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr); 160c4b75bccSAlp Dener } 161c4b75bccSAlp Dener if (!cg->W) { 162c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->W);CHKERRQ(ierr); 163c4b75bccSAlp Dener } 164c4b75bccSAlp Dener if (!cg->work) { 165c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->work);CHKERRQ(ierr); 166c4b75bccSAlp Dener } 167c8bcdf1eSAdam Denchfield if (!cg->sk) { 168c8bcdf1eSAdam Denchfield ierr = VecDuplicate(tao->solution,&cg->sk);CHKERRQ(ierr); 169c8bcdf1eSAdam Denchfield } 170c8bcdf1eSAdam Denchfield if (!cg->yk) { 171c8bcdf1eSAdam Denchfield ierr = VecDuplicate(tao->gradient,&cg->yk);CHKERRQ(ierr); 172c8bcdf1eSAdam Denchfield } 173c4b75bccSAlp Dener if (!cg->X_old) { 174c4b75bccSAlp Dener ierr = VecDuplicate(tao->solution,&cg->X_old);CHKERRQ(ierr); 175c4b75bccSAlp Dener } 176c4b75bccSAlp Dener if (!cg->G_old) { 177c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->G_old);CHKERRQ(ierr); 178c8bcdf1eSAdam Denchfield } 179c8bcdf1eSAdam Denchfield if (cg->use_steffenson){ 180*50b47da0SAdam Denchfield if (!cg->steffnm1) { 181*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution, &cg->steffnm1);CHKERRQ(ierr); 182*50b47da0SAdam Denchfield } 183*50b47da0SAdam Denchfield if (!cg->steffn) { 184*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution, &cg->steffn);CHKERRQ(ierr); 185*50b47da0SAdam Denchfield } 186*50b47da0SAdam Denchfield if (!cg->steffnp1) { 187*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution, &cg->steffnp1);CHKERRQ(ierr); 188*50b47da0SAdam Denchfield } 189*50b47da0SAdam Denchfield if (!cg->steffva) { 190*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution, &cg->steffva);CHKERRQ(ierr); 191*50b47da0SAdam Denchfield } 192*50b47da0SAdam Denchfield if (!cg->steffvatmp) { 193*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution, &cg->steffvatmp);CHKERRQ(ierr); 194*50b47da0SAdam Denchfield } 195c8bcdf1eSAdam Denchfield } 196c8bcdf1eSAdam Denchfield if (cg->diag_scaling){ 197c8bcdf1eSAdam Denchfield ierr = VecDuplicate(tao->solution,&cg->d_work);CHKERRQ(ierr); 198c8bcdf1eSAdam Denchfield ierr = VecDuplicate(tao->solution,&cg->y_work);CHKERRQ(ierr); 199*50b47da0SAdam Denchfield ierr = VecDuplicate(tao->solution,&cg->g_work);CHKERRQ(ierr); 200c4b75bccSAlp Dener } 201c4b75bccSAlp Dener if (!cg->unprojected_gradient) { 202c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient);CHKERRQ(ierr); 203c4b75bccSAlp Dener } 204c4b75bccSAlp Dener if (!cg->unprojected_gradient_old) { 205c4b75bccSAlp Dener ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient_old);CHKERRQ(ierr); 206c4b75bccSAlp Dener } 207*50b47da0SAdam Denchfield 208*50b47da0SAdam Denchfield ierr = MatLMVMAllocate(cg->B, cg->sk, cg->yk);CHKERRQ(ierr); 209ac9112b8SAlp Dener PetscFunctionReturn(0); 210ac9112b8SAlp Dener } 211ac9112b8SAlp Dener 212ac9112b8SAlp Dener static PetscErrorCode TaoDestroy_BNCG(Tao tao) 213ac9112b8SAlp Dener { 214ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*) tao->data; 215ac9112b8SAlp Dener PetscErrorCode ierr; 216ac9112b8SAlp Dener 217ac9112b8SAlp Dener PetscFunctionBegin; 218ac9112b8SAlp Dener if (tao->setupcalled) { 21961be54a6SAlp Dener ierr = VecDestroy(&cg->W);CHKERRQ(ierr); 220c4b75bccSAlp Dener ierr = VecDestroy(&cg->work);CHKERRQ(ierr); 221ac9112b8SAlp Dener ierr = VecDestroy(&cg->X_old);CHKERRQ(ierr); 222ac9112b8SAlp Dener ierr = VecDestroy(&cg->G_old);CHKERRQ(ierr); 223ac9112b8SAlp Dener ierr = VecDestroy(&cg->unprojected_gradient);CHKERRQ(ierr); 224ac9112b8SAlp Dener ierr = VecDestroy(&cg->unprojected_gradient_old);CHKERRQ(ierr); 225*50b47da0SAdam Denchfield ierr = VecDestroy(&cg->g_work);CHKERRQ(ierr); 226*50b47da0SAdam Denchfield ierr = VecDestroy(&cg->d_work);CHKERRQ(ierr); 227*50b47da0SAdam Denchfield ierr = VecDestroy(&cg->y_work);CHKERRQ(ierr); 228*50b47da0SAdam Denchfield ierr = VecDestroy(&cg->sk);CHKERRQ(ierr); 229*50b47da0SAdam Denchfield ierr = VecDestroy(&cg->yk);CHKERRQ(ierr); 230*50b47da0SAdam Denchfield ierr = MatDestroy(&cg->B);CHKERRQ(ierr); 231ac9112b8SAlp Dener } 232ca964c49SAlp Dener ierr = ISDestroy(&cg->active_lower);CHKERRQ(ierr); 233ca964c49SAlp Dener ierr = ISDestroy(&cg->active_upper);CHKERRQ(ierr); 234ca964c49SAlp Dener ierr = ISDestroy(&cg->active_fixed);CHKERRQ(ierr); 235ca964c49SAlp Dener ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 236ca964c49SAlp Dener ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 237ca964c49SAlp Dener ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 238ca964c49SAlp Dener ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 239*50b47da0SAdam Denchfield 240ac9112b8SAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 241ac9112b8SAlp Dener PetscFunctionReturn(0); 242ac9112b8SAlp Dener } 243ac9112b8SAlp Dener 244ac9112b8SAlp Dener static PetscErrorCode TaoSetFromOptions_BNCG(PetscOptionItems *PetscOptionsObject,Tao tao) 245ac9112b8SAlp Dener { 246ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 247ac9112b8SAlp Dener PetscErrorCode ierr; 248ac9112b8SAlp Dener 249ac9112b8SAlp Dener PetscFunctionBegin; 250ac9112b8SAlp Dener ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 251ac9112b8SAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Nonlinear Conjugate Gradient method for unconstrained optimization");CHKERRQ(ierr); 252*50b47da0SAdam Denchfield ierr = PetscOptionsEList("-tao_bncg_type","cg formula", "", CG_Table, CG_Types, CG_Table[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr); 253*50b47da0SAdam Denchfield ierr = PetscOptionsEList("-tao_bncg_as_type","active set estimation method", "", CG_AS_TYPE, CG_AS_SIZE, CG_AS_TYPE[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr); 254*50b47da0SAdam Denchfield 255*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_hz_eta","(developer) cutoff tolerance for HZ", "", cg->hz_eta,&cg->hz_eta,NULL);CHKERRQ(ierr); 256*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_eps","(developer) cutoff value for restarts", "", cg->epsilon,&cg->epsilon,NULL);CHKERRQ(ierr); 257*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_dk_eta","(developer) cutoff tolerance for DK", "", cg->dk_eta,&cg->dk_eta,NULL);CHKERRQ(ierr); 258*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_xi","(developer) Parameter in the KD method", "", cg->xi,&cg->xi,NULL);CHKERRQ(ierr); 259*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_theta", "(developer) update parameter for the Broyden method", "", cg->theta, &cg->theta, NULL);CHKERRQ(ierr); 260*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_hz_theta", "(developer) parameter for the HZ (2006) method", "", cg->hz_theta, &cg->hz_theta, NULL);CHKERRQ(ierr); 261*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_alpha","(developer) parameter for the scalar scaling","",cg->alpha,&cg->alpha,NULL);CHKERRQ(ierr); 262c8bcdf1eSAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_bfgs_scale", "(developer) update parameter for bfgs/brdn CG methods", "", cg->bfgs_scale, &cg->bfgs_scale, NULL);CHKERRQ(ierr); 263c8bcdf1eSAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_dfp_scale", "(developer) update parameter for bfgs/brdn CG methods", "", cg->dfp_scale, &cg->dfp_scale, NULL);CHKERRQ(ierr); 264c8bcdf1eSAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_diag_scaling","Enable diagonal Broyden-like preconditioning","",cg->diag_scaling,&cg->diag_scaling,NULL);CHKERRQ(ierr); 265*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_dynamic_restart","(developer) use dynamic restarts as in HZ, DK, KD","",cg->use_dynamic_restart,&cg->use_dynamic_restart,NULL);CHKERRQ(ierr); 266*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_unscaled_restart","(developer) use unscaled gradient restarts","",cg->unscaled_restart,&cg->unscaled_restart,NULL);CHKERRQ(ierr); 267*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_use_steffenson","(developer - incomplete, do not use) use vector-Steffenson acceleration","",cg->use_steffenson,&cg->use_steffenson,NULL);CHKERRQ(ierr); 268*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_zeta", "(developer) Free parameter for the Kou-Dai method", "", cg->zeta, &cg->zeta, NULL);CHKERRQ(ierr); 269c8bcdf1eSAdam Denchfield ierr = PetscOptionsInt("-tao_bncg_min_quad", "(developer) Number of iterations with approximate quadratic behavior needed for restart", "", cg->min_quad, &cg->min_quad, NULL);CHKERRQ(ierr); 270*50b47da0SAdam Denchfield ierr = PetscOptionsInt("-tao_bncg_min_restart_num", "(developer) Number of iterations between restarts (times dimension)", "", cg->min_restart_num, &cg->min_restart_num, NULL);CHKERRQ(ierr); 271*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_recycle","(developer) enable recycling the existing solution and gradient at the start of a new solve","",cg->recycle,&cg->recycle,NULL);CHKERRQ(ierr); 272*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_spaced_restart","(developer) Enable regular steepest descent restarting every fixed number of iterations","",cg->spaced_restart,&cg->spaced_restart,NULL);CHKERRQ(ierr); 273*50b47da0SAdam Denchfield ierr = PetscOptionsBool("-tao_bncg_neg_xi","(developer) Use negative xi when it might be a smaller descent direction than necessary","",cg->neg_xi,&cg->neg_xi,NULL);CHKERRQ(ierr); 274*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_as_tol", "(developer) initial tolerance used when estimating actively bounded variables","",cg->as_tol,&cg->as_tol,NULL);CHKERRQ(ierr); 275*50b47da0SAdam Denchfield ierr = PetscOptionsReal("-tao_bncg_as_step", "(developer) step length used when estimating actively bounded variables","",cg->as_step,&cg->as_step,NULL);CHKERRQ(ierr); 276*50b47da0SAdam Denchfield 277ac9112b8SAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 278*50b47da0SAdam Denchfield ierr = MatSetFromOptions(cg->B);CHKERRQ(ierr); 279ac9112b8SAlp Dener PetscFunctionReturn(0); 280ac9112b8SAlp Dener } 281ac9112b8SAlp Dener 282ac9112b8SAlp Dener static PetscErrorCode TaoView_BNCG(Tao tao, PetscViewer viewer) 283ac9112b8SAlp Dener { 284ac9112b8SAlp Dener PetscBool isascii; 285ac9112b8SAlp Dener TAO_BNCG *cg = (TAO_BNCG*)tao->data; 286ac9112b8SAlp Dener PetscErrorCode ierr; 287ac9112b8SAlp Dener 288ac9112b8SAlp Dener PetscFunctionBegin; 289ac9112b8SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 290ac9112b8SAlp Dener if (isascii) { 291ac9112b8SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 292ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "CG Type: %s\n", CG_Table[cg->cg_type]);CHKERRQ(ierr); 293ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Resets: %i\n", cg->resets);CHKERRQ(ierr); 294*50b47da0SAdam Denchfield 295ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " Not a descent dir.: %i\n", cg->descent_error);CHKERRQ(ierr); 296ac9112b8SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Line search fails: %i\n", cg->ls_fails);CHKERRQ(ierr); 297ac9112b8SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 298ac9112b8SAlp Dener } 299ac9112b8SAlp Dener PetscFunctionReturn(0); 300ac9112b8SAlp Dener } 301ac9112b8SAlp Dener 302c8bcdf1eSAdam Denchfield PetscErrorCode TaoBNCGComputeScalarScaling(PetscReal yty, PetscReal yts, PetscReal sts, PetscReal *scale, PetscReal alpha) 303c8bcdf1eSAdam Denchfield { 304c8bcdf1eSAdam Denchfield PetscReal a, b, c, sig1, sig2; 305c8bcdf1eSAdam Denchfield 306c8bcdf1eSAdam Denchfield PetscFunctionBegin; 307c8bcdf1eSAdam Denchfield *scale = 0.0; 308c8bcdf1eSAdam Denchfield 309*50b47da0SAdam Denchfield if (1.0 == alpha){ 310c8bcdf1eSAdam Denchfield *scale = yts/yty; 311*50b47da0SAdam Denchfield } else if (0.0 == alpha){ 312c8bcdf1eSAdam Denchfield *scale = sts/yts; 313c8bcdf1eSAdam Denchfield } 314*50b47da0SAdam Denchfield else if (-1.0 == alpha) *scale = 1.0; 315c8bcdf1eSAdam Denchfield else { 316c8bcdf1eSAdam Denchfield a = yty; 317c8bcdf1eSAdam Denchfield b = yts; 318c8bcdf1eSAdam Denchfield c = sts; 319c8bcdf1eSAdam Denchfield a *= alpha; 320c8bcdf1eSAdam Denchfield b *= -(2.0*alpha - 1.0); 321c8bcdf1eSAdam Denchfield c *= alpha - 1.0; 322c8bcdf1eSAdam Denchfield sig1 = (-b + PetscSqrtReal(b*b - 4.0*a*c))/(2.0*a); 323c8bcdf1eSAdam Denchfield sig2 = (-b - PetscSqrtReal(b*b - 4.0*a*c))/(2.0*a); 324c8bcdf1eSAdam Denchfield /* accept the positive root as the scalar */ 325c8bcdf1eSAdam Denchfield if (sig1 > 0.0) { 326c8bcdf1eSAdam Denchfield *scale = sig1; 327c8bcdf1eSAdam Denchfield } else if (sig2 > 0.0) { 328c8bcdf1eSAdam Denchfield *scale = sig2; 329c8bcdf1eSAdam Denchfield } else { 330c8bcdf1eSAdam Denchfield SETERRQ(PETSC_COMM_SELF, PETSC_ERR_CONV_FAILED, "Cannot find positive scalar"); 331c8bcdf1eSAdam Denchfield } 332c8bcdf1eSAdam Denchfield } 333c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 334c8bcdf1eSAdam Denchfield } 335c8bcdf1eSAdam Denchfield 336ac9112b8SAlp Dener /*MC 337ac9112b8SAlp Dener TAOBNCG - Bound-constrained Nonlinear Conjugate Gradient method. 338ac9112b8SAlp Dener 339ac9112b8SAlp Dener Options Database Keys: 340*50b47da0SAdam Denchfield + -tao_bncg_recycle - enable recycling the latest calculated gradient vector in subsequent TaoSolve() calls (currently disabled) 341c4b75bccSAlp Dener . -tao_bncg_eta <r> - restart tolerance 34261be54a6SAlp Dener . -tao_bncg_type <taocg_type> - cg formula 343c4b75bccSAlp Dener . -tao_bncg_as_type <none,bertsekas> - active set estimation method 344c4b75bccSAlp Dener . -tao_bncg_as_tol <r> - tolerance used in Bertsekas active-set estimation 345c4b75bccSAlp Dener . -tao_bncg_as_step <r> - trial step length used in Bertsekas active-set estimation 346*50b47da0SAdam Denchfield . -tao_bncg_eps <r> - cutoff used for determining whether or not we restart based on steplength each iteration, as well as determining whether or not we continue using the last stepdirection. Defaults to machine precision. 347*50b47da0SAdam Denchfield . -tao_bncg_theta <r> - convex combination parameter for the Broyden method 348*50b47da0SAdam Denchfield . -tao_bncg_hz_eta <r> - cutoff tolerance for the beta term in the HZ, DK methods 349*50b47da0SAdam Denchfield . -tao_bncg_dk_eta <r> - cutoff tolerance for the beta term in the HZ, DK methods 350*50b47da0SAdam Denchfield . -tao_bncg_xi <r> - Multiplicative constant of the gamma term in the KD method 351*50b47da0SAdam Denchfield . -tao_bncg_hz_theta <r> - Multiplicative constant of the theta term for the HZ method 352*50b47da0SAdam Denchfield . -tao_bncg_bfgs_scale <r> - Scaling parameter of the bfgs contribution to the scalar Broyden method 353*50b47da0SAdam Denchfield . -tao_bncg_dfp_scale <r> - Scaling parameter of the dfp contribution to the scalar Broyden method 354*50b47da0SAdam Denchfield . -tao_bncg_diag_scaling <b> - Whether or not to use diagonal initialization/preconditioning for the CG methods. Default True. 355*50b47da0SAdam Denchfield . -tao_bncg_dynamic_restart <b> - use dynamic restart strategy in the HZ, DK, KD methods 356*50b47da0SAdam Denchfield . -tao_bncg_unscaled_restart <b> - whether or not to scale the gradient when doing gradient descent restarts 357*50b47da0SAdam Denchfield . -tao_bncg_use_steffenson <b> (not implemented) - use Steffenson acceleration 358*50b47da0SAdam Denchfield . -tao_bncg_zeta <r> - Scaling parameter in the KD method 359*50b47da0SAdam Denchfield . -tao_bncg_min_quad <i> - Number of quadratic-like steps in a row necessary to do a dynamic restart 360*50b47da0SAdam Denchfield . -tao_bncg_min_restart_num <i> - This number, x, makes sure there is a gradient descent step every x*n iterations, where n is the dimension of the problem 361*50b47da0SAdam Denchfield . -tao_bncg_spaced_restart <b> - whether or not to do gradient descent steps every x*n iterations 362*50b47da0SAdam Denchfield . -tao_bncg_neg_xi <b> - Whether or not to use negative xi in the KD method under certain conditions 363ac9112b8SAlp Dener 364ac9112b8SAlp Dener Notes: 365ac9112b8SAlp Dener CG formulas are: 366*50b47da0SAdam Denchfield "gd" - Gradient Descent 367ac9112b8SAlp Dener "fr" - Fletcher-Reeves 368*50b47da0SAdam Denchfield "pr" - Polak-Ribiere-Polyak 369ac9112b8SAlp Dener "prp" - Polak-Ribiere-Plus 370ac9112b8SAlp Dener "hs" - Hestenes-Steifel 371ac9112b8SAlp Dener "dy" - Dai-Yuan 372*50b47da0SAdam Denchfield "ssml_bfgs" - Self-Scaling Memoryless BFGS 373*50b47da0SAdam Denchfield "ssml_dfp" - Self-Scaling Memoryless DFP 374*50b47da0SAdam Denchfield "ssml_brdn" - Self-Scaling Memoryless Broyden 375*50b47da0SAdam Denchfield "hz" - Hager-Zhang (CG_DESCENT 5.3) 376*50b47da0SAdam Denchfield "dk" - Dai-Kou (2013) 377*50b47da0SAdam Denchfield "kd" - Kou-Dai (2015) 378ac9112b8SAlp Dener Level: beginner 379ac9112b8SAlp Dener M*/ 380ac9112b8SAlp Dener 381ac9112b8SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNCG(Tao tao) 382ac9112b8SAlp Dener { 383ac9112b8SAlp Dener TAO_BNCG *cg; 384ac9112b8SAlp Dener const char *morethuente_type = TAOLINESEARCHMT; 385ac9112b8SAlp Dener PetscErrorCode ierr; 386ac9112b8SAlp Dener 387ac9112b8SAlp Dener PetscFunctionBegin; 388ac9112b8SAlp Dener tao->ops->setup = TaoSetUp_BNCG; 389ac9112b8SAlp Dener tao->ops->solve = TaoSolve_BNCG; 390ac9112b8SAlp Dener tao->ops->view = TaoView_BNCG; 391ac9112b8SAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BNCG; 392ac9112b8SAlp Dener tao->ops->destroy = TaoDestroy_BNCG; 393ac9112b8SAlp Dener 394ac9112b8SAlp Dener /* Override default settings (unless already changed) */ 395ac9112b8SAlp Dener if (!tao->max_it_changed) tao->max_it = 2000; 396ac9112b8SAlp Dener if (!tao->max_funcs_changed) tao->max_funcs = 4000; 397ac9112b8SAlp Dener 398ac9112b8SAlp Dener /* Note: nondefault values should be used for nonlinear conjugate gradient */ 399ac9112b8SAlp Dener /* method. In particular, gtol should be less that 0.5; the value used in */ 400ac9112b8SAlp Dener /* Nocedal and Wright is 0.10. We use the default values for the */ 401ac9112b8SAlp Dener /* linesearch because it seems to work better. */ 402ac9112b8SAlp Dener ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr); 403ac9112b8SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 404ac9112b8SAlp Dener ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr); 405ac9112b8SAlp Dener ierr = TaoLineSearchUseTaoRoutines(tao->linesearch, tao);CHKERRQ(ierr); 406ac9112b8SAlp Dener ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 407ac9112b8SAlp Dener 408ac9112b8SAlp Dener ierr = PetscNewLog(tao,&cg);CHKERRQ(ierr); 409ac9112b8SAlp Dener tao->data = (void*)cg; 410c8bcdf1eSAdam Denchfield 411*50b47da0SAdam Denchfield ierr = MatCreate(PetscObjectComm((PetscObject)tao), &cg->B);CHKERRQ(ierr); 412*50b47da0SAdam Denchfield ierr = PetscObjectIncrementTabLevel((PetscObject)cg->B, (PetscObject)tao, 1);CHKERRQ(ierr); 413*50b47da0SAdam Denchfield ierr = MatSetOptionsPrefix(cg->B, "tao_bncg_");CHKERRQ(ierr); 414*50b47da0SAdam Denchfield ierr = MatSetType(cg->B, MATLMVMDIAGBRDN);CHKERRQ(ierr); 415*50b47da0SAdam Denchfield 416*50b47da0SAdam Denchfield cg->dk_eta = 0.5; 417*50b47da0SAdam Denchfield cg->hz_eta = 0.4; 418c8bcdf1eSAdam Denchfield cg->dynamic_restart = PETSC_FALSE; 419c8bcdf1eSAdam Denchfield cg->unscaled_restart = PETSC_FALSE; 420c8bcdf1eSAdam Denchfield cg->theta = 1.0; 421c8bcdf1eSAdam Denchfield cg->hz_theta = 1.0; 422c8bcdf1eSAdam Denchfield cg->dfp_scale = 1.0; 423c8bcdf1eSAdam Denchfield cg->bfgs_scale = 1.0; 424*50b47da0SAdam Denchfield cg->zeta = 0.1; 425*50b47da0SAdam Denchfield cg->min_quad = 6; 426*50b47da0SAdam Denchfield cg->use_steffenson = PETSC_FALSE; 427c8bcdf1eSAdam Denchfield cg->min_restart_num = 6; /* As in CG_DESCENT and KD2015*/ 428c8bcdf1eSAdam Denchfield cg->xi = 1.0; 429*50b47da0SAdam Denchfield cg->neg_xi = PETSC_TRUE; 430c8bcdf1eSAdam Denchfield cg->spaced_restart = PETSC_FALSE; 431c8bcdf1eSAdam Denchfield cg->tol_quad = 1e-8; 43261be54a6SAlp Dener cg->as_step = 0.001; 43361be54a6SAlp Dener cg->as_tol = 0.001; 434*50b47da0SAdam Denchfield cg->eps_23 = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0); /* Just a little tighter*/ 43561be54a6SAlp Dener cg->as_type = CG_AS_BERTSEKAS; 436c8bcdf1eSAdam Denchfield cg->cg_type = CG_SSML_BFGS; 437c0f10754SAlp Dener cg->recycle = PETSC_FALSE; 438c8bcdf1eSAdam Denchfield cg->alpha = 1.0; 439c8bcdf1eSAdam Denchfield cg->diag_scaling = PETSC_TRUE; 440c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 441c8bcdf1eSAdam Denchfield } 442c8bcdf1eSAdam Denchfield 443c8bcdf1eSAdam Denchfield 444c8bcdf1eSAdam Denchfield PetscErrorCode TaoBNCGResetUpdate(Tao tao, PetscReal gnormsq) 445c8bcdf1eSAdam Denchfield { 446c8bcdf1eSAdam Denchfield TAO_BNCG *cg = (TAO_BNCG*)tao->data; 447c8bcdf1eSAdam Denchfield PetscErrorCode ierr; 448c8bcdf1eSAdam Denchfield PetscReal scaling; 449c8bcdf1eSAdam Denchfield 450c8bcdf1eSAdam Denchfield PetscFunctionBegin; 451c8bcdf1eSAdam Denchfield ++cg->resets; 452c8bcdf1eSAdam Denchfield scaling = 2.0 * PetscMax(1.0, PetscAbsScalar(cg->f)) / PetscMax(gnormsq, cg->eps_23); 453c8bcdf1eSAdam Denchfield scaling = PetscMin(100.0, PetscMax(1e-7, scaling)); 454c8bcdf1eSAdam Denchfield if (cg->unscaled_restart) scaling = 1.0; 455c8bcdf1eSAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -scaling, 0.0, tao->gradient);CHKERRQ(ierr); 456c8bcdf1eSAdam Denchfield /* Also want to reset our diagonal scaling with each restart */ 457c8bcdf1eSAdam Denchfield if (cg->diag_scaling) { 458*50b47da0SAdam Denchfield ierr = MatLMVMReset(cg->B, PETSC_FALSE);CHKERRQ(ierr); 459c8bcdf1eSAdam Denchfield } 460c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 461c8bcdf1eSAdam Denchfield } 462c8bcdf1eSAdam Denchfield 463c8bcdf1eSAdam Denchfield PetscErrorCode TaoBNCGCheckDynamicRestart(Tao tao, PetscReal stepsize, PetscReal gd, PetscReal gd_old, PetscBool *dynrestart, PetscReal fold) 464c8bcdf1eSAdam Denchfield { 465c8bcdf1eSAdam Denchfield TAO_BNCG *cg = (TAO_BNCG*)tao->data; 466c8bcdf1eSAdam Denchfield PetscReal quadinterp; 467c8bcdf1eSAdam Denchfield 468c8bcdf1eSAdam Denchfield PetscFunctionBegin; 469*50b47da0SAdam Denchfield if (cg->f < cg->min_quad/10) { 470*50b47da0SAdam Denchfield *dynrestart = PETSC_FALSE; 471*50b47da0SAdam Denchfield PetscFunctionReturn(0); 472*50b47da0SAdam Denchfield } /* just skip this since this strategy doesn't work well for functions near zero */ 473c8bcdf1eSAdam Denchfield quadinterp = 2*(cg->f - fold)/(stepsize*(gd + gd_old)); 474*50b47da0SAdam Denchfield if (PetscAbs(quadinterp - 1.0) < cg->tol_quad) ++cg->iter_quad; 475c8bcdf1eSAdam Denchfield else { 476c8bcdf1eSAdam Denchfield cg->iter_quad = 0; 477c8bcdf1eSAdam Denchfield *dynrestart = PETSC_FALSE; 478c8bcdf1eSAdam Denchfield } 479c8bcdf1eSAdam Denchfield if (cg->iter_quad >= cg->min_quad) { 480c8bcdf1eSAdam Denchfield cg->iter_quad = 0; 481c8bcdf1eSAdam Denchfield *dynrestart = PETSC_TRUE; 482c8bcdf1eSAdam Denchfield } 483c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 484c8bcdf1eSAdam Denchfield } 485c8bcdf1eSAdam Denchfield 486*50b47da0SAdam Denchfield PETSC_INTERN PetscErrorCode TaoBNCGStepDirectionUpdate(Tao tao, PetscReal gnorm2, PetscReal step, PetscReal fold, PetscReal gnorm2_old, PetscBool cg_restart, PetscReal dnorm, PetscReal ginner) 487*50b47da0SAdam Denchfield { 488c8bcdf1eSAdam Denchfield TAO_BNCG *cg = (TAO_BNCG*)tao->data; 489c8bcdf1eSAdam Denchfield PetscErrorCode ierr; 490*50b47da0SAdam Denchfield PetscReal gamma = 1.0, tau_k, beta; 491*50b47da0SAdam Denchfield PetscReal tmp = 1.0, ynorm, ynorm2, snorm = 1.0, dk_yk=1.0, gd; 492*50b47da0SAdam Denchfield PetscReal gkp1_yk, gd_old, tau_bfgs, tau_dfp, gkp1D_yk, gtDg; 493c8bcdf1eSAdam Denchfield PetscInt dim; 494c8bcdf1eSAdam Denchfield PetscFunctionBegin; 495c8bcdf1eSAdam Denchfield 496*50b47da0SAdam Denchfield /* Local curvature check to see if we need to restart */ 497*50b47da0SAdam Denchfield if (tao->niter >= 1){ 498c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->yk, -1.0, cg->G_old, tao->gradient);CHKERRQ(ierr); 499c8bcdf1eSAdam Denchfield ierr = VecNorm(cg->yk, NORM_2, &ynorm);CHKERRQ(ierr); 500c8bcdf1eSAdam Denchfield ynorm2 = ynorm*ynorm; 501c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->stepdirection, &dk_yk);CHKERRQ(ierr); 502*50b47da0SAdam Denchfield if (step*dnorm < PETSC_MACHINE_EPSILON || step*dk_yk < PETSC_MACHINE_EPSILON) cg_restart = 1; 503*50b47da0SAdam Denchfield if (cg->spaced_restart) { 504*50b47da0SAdam Denchfield ierr = VecGetSize(tao->gradient, &dim);CHKERRQ(ierr); 505*50b47da0SAdam Denchfield if (tao->niter % (dim*cg->min_restart_num)) cg_restart = 1; 506*50b47da0SAdam Denchfield } 507*50b47da0SAdam Denchfield } 508*50b47da0SAdam Denchfield /* If the user wants regular restarts, do it every 6n iterations, where n=dimension */ 509*50b47da0SAdam Denchfield if (cg->spaced_restart){ 510*50b47da0SAdam Denchfield ierr = VecGetSize(tao->gradient, &dim);CHKERRQ(ierr); 511*50b47da0SAdam Denchfield if (0 == tao->niter % (6*dim)) cg_restart = 1; 512*50b47da0SAdam Denchfield } 513*50b47da0SAdam Denchfield /* Compute the diagonal scaling vector if applicable */ 514*50b47da0SAdam Denchfield if (cg->diag_scaling) { 515*50b47da0SAdam Denchfield ierr = MatLMVMUpdate(cg->B, tao->solution, tao->gradient);CHKERRQ(ierr); 516*50b47da0SAdam Denchfield } 517*50b47da0SAdam Denchfield 518*50b47da0SAdam Denchfield /* A note on diagonal scaling (to be added to paper): For the FR, PR, PRP, and DY methods, the diagonally scaled versions must be derived as a preconditioned CG method rather than as a Hessian initialization like in the Broyden methods. */ 519*50b47da0SAdam Denchfield 520*50b47da0SAdam Denchfield /* In that case, one writes the objective function as f(x) \equiv f(Ay). Gradient evaluations yield g(x_k) = A g(Ay_k) = A g(x_k). Furthermore, the direction d_k \equiv (x_k - x_{k-1})/step according to HZ (2006) becomes A^{-1} d_k, such that d_k^T g_k remains the same under preconditioning. Note that A is diagonal, such that A^T = A. */ 521*50b47da0SAdam Denchfield 522*50b47da0SAdam Denchfield /* This yields questions like what the dot product d_k^T y_k should look like. HZ mistakenly treats that as the same under preconditioning, but that is not necessarily true. */ 523*50b47da0SAdam Denchfield 524*50b47da0SAdam Denchfield /* Observe y_k \equiv g_k - g_{k-1}, and under the P.C. transformation, we get d_k^T y_k = (d_k^T A_k^{-T} A_k g_k - d_k^T A_k^{-T} A_{k-1} g_{k-1}), yielding d_k^T y_k = d_k^T g_k - d_k^T (A_k^{-T} A_{k-1} g_{k-1}), which is NOT the same if our preconditioning matrix is updated between iterations. This same issue is found when considering dot products of the form g_{k+1}^T y_k. */ 525*50b47da0SAdam Denchfield 526*50b47da0SAdam Denchfield /* As of now, for PR, PRP, and DY, the above considerations have not been fully taken into account, explaining their poorer performance. FR is implemented correctly, and yields some marginal improvement on performance. Working on the rest now. */ 527*50b47da0SAdam Denchfield 528*50b47da0SAdam Denchfield /* Compute CG step direction */ 529*50b47da0SAdam Denchfield if (cg_restart) { 530*50b47da0SAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 531*50b47da0SAdam Denchfield } else if (ynorm2 > PETSC_MACHINE_EPSILON) { 532*50b47da0SAdam Denchfield switch (cg->cg_type) { 533*50b47da0SAdam Denchfield case CG_GradientDescent: 534*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 535*50b47da0SAdam Denchfield cg->sts = step*step*dnorm*dnorm; 536*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, cg->sts, &tau_k, cg->alpha);CHKERRQ(ierr); 537*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, 0.0, tao->gradient);CHKERRQ(ierr); 538*50b47da0SAdam Denchfield } else { 539*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 540*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, 0.0, cg->g_work);CHKERRQ(ierr); 541*50b47da0SAdam Denchfield } 542*50b47da0SAdam Denchfield break; 543*50b47da0SAdam Denchfield case CG_HestenesStiefel: 544*50b47da0SAdam Denchfield /* Classic Hestenes-Stiefel method, modified with scalar and diagonal preconditioning. */ 545*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 546*50b47da0SAdam Denchfield cg->sts = step*step*dnorm*dnorm; 547*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 548*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, cg->sts, &tau_k, cg->alpha);CHKERRQ(ierr); 549*50b47da0SAdam Denchfield beta = tau_k*gkp1_yk/dk_yk; 550*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 551*50b47da0SAdam Denchfield } else { 552*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 553*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, cg->g_work, &gkp1_yk);CHKERRQ(ierr); 554*50b47da0SAdam Denchfield beta = gkp1_yk/dk_yk; 555*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, beta, cg->g_work);CHKERRQ(ierr); 556*50b47da0SAdam Denchfield } 557c8bcdf1eSAdam Denchfield break; 558c8bcdf1eSAdam Denchfield case CG_FletcherReeves: 559*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->G_old, &gnorm2_old);CHKERRQ(ierr); 560*50b47da0SAdam Denchfield ierr = VecWAXPY(cg->yk, -1.0, cg->G_old, tao->gradient);CHKERRQ(ierr); 561*50b47da0SAdam Denchfield ierr = VecNorm(cg->yk, NORM_2, &ynorm);CHKERRQ(ierr); 562*50b47da0SAdam Denchfield ynorm2 = ynorm*ynorm; 563*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, tao->stepdirection, &dk_yk);CHKERRQ(ierr); 564*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 565*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, step*step*dnorm*dnorm, &tau_k, cg->alpha);CHKERRQ(ierr); 566*50b47da0SAdam Denchfield beta = tau_k*gnorm2/gnorm2_old; 567*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 568*50b47da0SAdam Denchfield } else { 569*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->g_work, &gnorm2_old);CHKERRQ(ierr); /* Before it's updated */ 570*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 571*50b47da0SAdam Denchfield ierr = VecDot(tao->gradient, cg->g_work, &tmp);CHKERRQ(ierr); 572*50b47da0SAdam Denchfield beta = tmp/gnorm2_old; 573*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, beta, cg->g_work);CHKERRQ(ierr); 574*50b47da0SAdam Denchfield } 575c8bcdf1eSAdam Denchfield break; 576*50b47da0SAdam Denchfield case CG_PolakRibierePolyak: 577*50b47da0SAdam Denchfield snorm = step*dnorm; 578*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 579*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->G_old, &gnorm2_old);CHKERRQ(ierr); 580*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 581*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, snorm*snorm, &tau_k, cg->alpha);CHKERRQ(ierr); 582*50b47da0SAdam Denchfield beta = tau_k*gkp1_yk/gnorm2_old; 583*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 584*50b47da0SAdam Denchfield } else { 585*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->g_work, &gnorm2_old);CHKERRQ(ierr); 586*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 587*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, cg->yk, &gkp1_yk);CHKERRQ(ierr); 588*50b47da0SAdam Denchfield beta = gkp1_yk/gnorm2_old; 589*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, beta, cg->g_work);CHKERRQ(ierr); 590*50b47da0SAdam Denchfield } 591c8bcdf1eSAdam Denchfield break; 592c8bcdf1eSAdam Denchfield case CG_PolakRibierePlus: 593*50b47da0SAdam Denchfield ierr = VecWAXPY(cg->yk, -1.0, cg->G_old, tao->gradient);CHKERRQ(ierr); 594*50b47da0SAdam Denchfield ierr = VecNorm(cg->yk, NORM_2, &ynorm);CHKERRQ(ierr); 595*50b47da0SAdam Denchfield ynorm2 = ynorm*ynorm; 596*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 597*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->G_old, &gnorm2_old);CHKERRQ(ierr); 598*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 599*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, snorm*snorm, &tau_k, cg->alpha);CHKERRQ(ierr); 600*50b47da0SAdam Denchfield beta = tau_k*gkp1_yk/gnorm2_old; 601*50b47da0SAdam Denchfield beta = PetscMax(beta, 0.0); 602*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 603*50b47da0SAdam Denchfield } else { 604*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->g_work, &gnorm2_old);CHKERRQ(ierr); /* Old gtDg */ 605*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 606*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, cg->yk, &gkp1_yk);CHKERRQ(ierr); 607*50b47da0SAdam Denchfield beta = gkp1_yk/gnorm2_old; 608*50b47da0SAdam Denchfield beta = PetscMax(beta, 0.0); 609*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, beta, cg->g_work);CHKERRQ(ierr); 610*50b47da0SAdam Denchfield } 611c8bcdf1eSAdam Denchfield break; 612*50b47da0SAdam Denchfield case CG_DaiYuan: /* TODO: suspect this is broken in the diag part - test4 */ 613*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 614*50b47da0SAdam Denchfield ierr = VecDot(tao->stepdirection, tao->gradient, &gd);CHKERRQ(ierr); 615c8bcdf1eSAdam Denchfield ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 616*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, cg->yts, &tau_k, cg->alpha);CHKERRQ(ierr); 617*50b47da0SAdam Denchfield beta = tau_k*gnorm2/(gd - gd_old); 618*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 619*50b47da0SAdam Denchfield } else { 620*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->stepdirection, cg->d_work);CHKERRQ(ierr); 621*50b47da0SAdam Denchfield ierr = MatMult(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 622*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, tao->gradient, >Dg);CHKERRQ(ierr); 623*50b47da0SAdam Denchfield ierr = VecDot(tao->stepdirection, cg->G_old, &gd_old);CHKERRQ(ierr); 624*50b47da0SAdam Denchfield ierr = VecDot(cg->d_work, cg->g_work, &dk_yk);CHKERRQ(ierr); 625*50b47da0SAdam Denchfield dk_yk = dk_yk - gd_old; 626*50b47da0SAdam Denchfield beta = gtDg/dk_yk; 627*50b47da0SAdam Denchfield ierr = VecScale(cg->d_work, beta); 628*50b47da0SAdam Denchfield ierr = VecWAXPY(tao->stepdirection, -1.0, cg->g_work, cg->d_work);CHKERRQ(ierr); 629*50b47da0SAdam Denchfield } 630c8bcdf1eSAdam Denchfield break; 631c8bcdf1eSAdam Denchfield case CG_SSML_BFGS: 632c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 633c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 634*50b47da0SAdam Denchfield snorm = step*dnorm; 635*50b47da0SAdam Denchfield cg->yts = dk_yk*step; 636c8bcdf1eSAdam Denchfield cg->yty = ynorm2; 637c8bcdf1eSAdam Denchfield cg->sts = snorm*snorm; 638c8bcdf1eSAdam Denchfield if (!cg->diag_scaling){ 639c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 640*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(cg->yty, cg->yts, cg->sts, &tau_k, cg->alpha);CHKERRQ(ierr); 641c8bcdf1eSAdam Denchfield tmp = gd/dk_yk; 642*50b47da0SAdam Denchfield beta = tau_k*(gkp1_yk/dk_yk - cg->yty*gd/(dk_yk*dk_yk)) - step*tmp; 643c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*t*d + t*tmp*yk */ 644c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -tau_k, tmp*tau_k, beta, tao->gradient, cg->yk);CHKERRQ(ierr); 645c8bcdf1eSAdam Denchfield } else { 646c8bcdf1eSAdam Denchfield /* We have diagonal scaling enabled and are taking a diagonally-scaled memoryless BFGS step */ 647*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 648*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 649*50b47da0SAdam Denchfield /* compute scalar gamma */ 650*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, cg->yk, &gkp1_yk);CHKERRQ(ierr); 651*50b47da0SAdam Denchfield ierr = VecDot(cg->y_work, cg->yk, &tmp);CHKERRQ(ierr); 652*50b47da0SAdam Denchfield gamma = gd/dk_yk; 653*50b47da0SAdam Denchfield /* Compute scalar beta */ 654*50b47da0SAdam Denchfield beta = (gkp1_yk/dk_yk - gd*tmp/(dk_yk*dk_yk)) - step*gd/dk_yk; 655*50b47da0SAdam Denchfield /* Compute stepdirection d_kp1 = gamma*Dkyk + beta*dk - Dkgkp1 */ 656*50b47da0SAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -1.0, gamma, beta, cg->g_work, cg->y_work);CHKERRQ(ierr); 657*50b47da0SAdam Denchfield } 658c8bcdf1eSAdam Denchfield break; 659c8bcdf1eSAdam Denchfield case CG_SSML_DFP: 660c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 661c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 662*50b47da0SAdam Denchfield snorm = step*dnorm; 663*50b47da0SAdam Denchfield cg->yts = dk_yk*step; 664*50b47da0SAdam Denchfield cg->yty = ynorm2; 665*50b47da0SAdam Denchfield cg->sts = snorm*snorm; 666*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 667*50b47da0SAdam Denchfield /* Instead of a regular convex combination, we will solve a quadratic formula. */ 668*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(cg->yty, cg->yts, cg->sts, &tau_k, cg->alpha);CHKERRQ(ierr); 669c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 670*50b47da0SAdam Denchfield tau_k = cg->dfp_scale*tau_k; 671c8bcdf1eSAdam Denchfield tmp = tau_k*gkp1_yk/ynorm2; 672c8bcdf1eSAdam Denchfield beta = -step*gd/dk_yk; 673c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*d + tmp*yk */ 674c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -tau_k, tmp, beta, tao->gradient, cg->yk);CHKERRQ(ierr); 675*50b47da0SAdam Denchfield } else { 676*50b47da0SAdam Denchfield /* We have diagonal scaling enabled and are taking a diagonally-scaled memoryless DFP step */ 677*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 678*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 679*50b47da0SAdam Denchfield /* compute scalar gamma */ 680*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, cg->yk, &gkp1_yk);CHKERRQ(ierr); 681*50b47da0SAdam Denchfield ierr = VecDot(cg->y_work, cg->yk, &tmp);CHKERRQ(ierr); 682*50b47da0SAdam Denchfield gamma = (gkp1_yk/tmp); 683*50b47da0SAdam Denchfield /* Compute scalar beta */ 684*50b47da0SAdam Denchfield beta = -step*gd/dk_yk; 685*50b47da0SAdam Denchfield /* Compute stepdirection d_kp1 = gamma*Dkyk + beta*dk - Dkgkp1 */ 686*50b47da0SAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -1.0, gamma, beta, cg->g_work, cg->y_work);CHKERRQ(ierr); 687c8bcdf1eSAdam Denchfield } 688c8bcdf1eSAdam Denchfield break; 689c8bcdf1eSAdam Denchfield case CG_SSML_BROYDEN: 690c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 691c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 692*50b47da0SAdam Denchfield snorm = step*dnorm; 693*50b47da0SAdam Denchfield cg->yts = step*dk_yk; 694*50b47da0SAdam Denchfield cg->yty = ynorm2; 695*50b47da0SAdam Denchfield cg->sts = snorm*snorm; 696*50b47da0SAdam Denchfield if (!cg->diag_scaling){ 697c8bcdf1eSAdam Denchfield /* Instead of a regular convex combination, we will solve a quadratic formula. */ 698*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, snorm*snorm, &tau_bfgs, cg->bfgs_scale);CHKERRQ(ierr); 699*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, step*dk_yk, snorm*snorm, &tau_dfp, cg->dfp_scale);CHKERRQ(ierr); 700*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 701c8bcdf1eSAdam Denchfield tau_k = cg->theta*tau_bfgs + (1.0-cg->theta)*tau_dfp; 702c8bcdf1eSAdam Denchfield /* If bfgs_scale = 1.0, it should reproduce the bfgs tau_bfgs. If bfgs_scale = 0.0, it should reproduce the tau_dfp scaling. Same with dfp_scale. */ 703c8bcdf1eSAdam Denchfield tmp = cg->theta*tau_bfgs*gd/dk_yk + (1-cg->theta)*tau_dfp*gkp1_yk/ynorm2; 704c8bcdf1eSAdam Denchfield beta = cg->theta*tau_bfgs*(gkp1_yk/dk_yk - ynorm2*gd/(dk_yk*dk_yk)) - step*gd/dk_yk; 705c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*d + tmp*yk */ 706c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -tau_k, tmp, beta, tao->gradient, cg->yk);CHKERRQ(ierr); 707*50b47da0SAdam Denchfield } else { 708*50b47da0SAdam Denchfield /* We have diagonal scaling enabled */ 709*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 710*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 711*50b47da0SAdam Denchfield /* compute scalar gamma */ 712*50b47da0SAdam Denchfield ierr = VecDot(cg->g_work, cg->yk, &gkp1_yk);CHKERRQ(ierr); 713*50b47da0SAdam Denchfield ierr = VecDot(cg->y_work, cg->yk, &tmp);CHKERRQ(ierr); 714*50b47da0SAdam Denchfield gamma = cg->theta*gd/dk_yk + (1-cg->theta)*(gkp1_yk/tmp); 715*50b47da0SAdam Denchfield /* Compute scalar beta */ 716*50b47da0SAdam Denchfield beta = cg->theta*(gkp1_yk/dk_yk - gd*tmp/(dk_yk*dk_yk)) - step*gd/dk_yk; 717*50b47da0SAdam Denchfield /* Compute stepdirection dkp1 = gamma*Dkyk + beta*dk - Dkgkp1 */ 718*50b47da0SAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -1.0, gamma, beta, cg->g_work, cg->y_work);CHKERRQ(ierr); 719c8bcdf1eSAdam Denchfield } 720c8bcdf1eSAdam Denchfield break; 721c8bcdf1eSAdam Denchfield case CG_HagerZhang: 722*50b47da0SAdam Denchfield /* Their 2006 paper. Comes from deleting the y_k term from SSML_BFGS, introducing a theta parameter, and using a cutoff for beta. See DK 2013 pg. 315 for a review of CG_DESCENT 5.3. One can use the dynamic restart strategy they implement, but it doesn't work well for us. */ 723c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 724c8bcdf1eSAdam Denchfield ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 725c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 726*50b47da0SAdam Denchfield snorm = dnorm*step; 727*50b47da0SAdam Denchfield cg->yts = step*dk_yk; 728c8bcdf1eSAdam Denchfield if (cg->use_dynamic_restart){ 729c8bcdf1eSAdam Denchfield ierr = TaoBNCGCheckDynamicRestart(tao, step, gd, gd_old, &cg->dynamic_restart, fold);CHKERRQ(ierr); 730c8bcdf1eSAdam Denchfield } 731*50b47da0SAdam Denchfield if (cg->dynamic_restart){ 732c8bcdf1eSAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 733c8bcdf1eSAdam Denchfield } else { 734c8bcdf1eSAdam Denchfield if (!cg->diag_scaling){ 735c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 736c8bcdf1eSAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, cg->yts, snorm*snorm, &tau_k, cg->alpha);CHKERRQ(ierr); 737c8bcdf1eSAdam Denchfield /* Supplying cg->alpha = -1.0 will give the CG_DESCENT 5.3 special case of tau_k = 1.0 */ 738c8bcdf1eSAdam Denchfield tmp = gd/dk_yk; 739c8bcdf1eSAdam Denchfield beta = tau_k*(gkp1_yk/dk_yk - ynorm2*gd/(dk_yk*dk_yk)); 740c8bcdf1eSAdam Denchfield /* Bound beta as in CG_DESCENT 5.3, as implemented, with the third comparison from DK 2013 */ 741*50b47da0SAdam Denchfield beta = PetscMax(PetscMax(beta, cg->hz_eta*tau_k*gd_old/(dnorm*dnorm)), cg->dk_eta*tau_k*gd/(dnorm*dnorm)); 742c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*t*d */ 743*50b47da0SAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -tau_k, beta, tao->gradient);CHKERRQ(ierr); 744c8bcdf1eSAdam Denchfield } else { 745c8bcdf1eSAdam Denchfield /* We have diagonal scaling enabled and are taking a diagonally-scaled memoryless BFGS step */ 746c8bcdf1eSAdam Denchfield cg->yty = ynorm2; 747c8bcdf1eSAdam Denchfield cg->sts = snorm*snorm; 748*50b47da0SAdam Denchfield /* Apply the diagonal scaling to all my vectors */ 749*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 750*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 751*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->stepdirection, cg->d_work);CHKERRQ(ierr); 752c8bcdf1eSAdam Denchfield /* Construct the constant ytDgkp1 */ 753c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, cg->g_work, &gkp1_yk);CHKERRQ(ierr); 754c8bcdf1eSAdam Denchfield /* Construct the constant for scaling Dkyk in the update */ 755c8bcdf1eSAdam Denchfield tmp = gd/dk_yk; 756c8bcdf1eSAdam Denchfield /* tau_bfgs can be a parameter we tune via command line in future versions. For now, just setting to one. May instead put this inside the ComputeDiagonalScaling function... */ 757c8bcdf1eSAdam Denchfield cg->tau_bfgs = 1.0; 758*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, cg->y_work, &tau_k);CHKERRQ(ierr); 759c8bcdf1eSAdam Denchfield tau_k = -tau_k*gd/(dk_yk*dk_yk); 760c8bcdf1eSAdam Denchfield /* beta is the constant which adds the dk contribution */ 761c8bcdf1eSAdam Denchfield beta = cg->tau_bfgs*gkp1_yk/dk_yk + cg->hz_theta*tau_k; /* HZ; (1.15) from DK 2013 */ 762c8bcdf1eSAdam Denchfield /* From HZ2013, modified to account for diagonal scaling*/ 763*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->d_work, &gd_old);CHKERRQ(ierr); 764*50b47da0SAdam Denchfield ierr = VecDot(tao->stepdirection, cg->g_work, &gd);CHKERRQ(ierr); 765*50b47da0SAdam Denchfield beta = PetscMax(PetscMax(beta, cg->hz_eta*gd_old/(dnorm*dnorm)), cg->dk_eta*gd/(dnorm*dnorm)); 766c8bcdf1eSAdam Denchfield /* Do the update */ 767c8bcdf1eSAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -cg->tau_bfgs, beta, cg->g_work);CHKERRQ(ierr); 768*50b47da0SAdam Denchfield } 769*50b47da0SAdam Denchfield } 770c8bcdf1eSAdam Denchfield break; 771c8bcdf1eSAdam Denchfield case CG_DaiKou: 772c8bcdf1eSAdam Denchfield /* 2013 paper. */ 773c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 774c8bcdf1eSAdam Denchfield ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 775c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 776*50b47da0SAdam Denchfield snorm = step*dnorm; 777*50b47da0SAdam Denchfield cg->yts = dk_yk*step; 778c8bcdf1eSAdam Denchfield if (!cg->diag_scaling){ 779c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 780*50b47da0SAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, cg->yts, snorm*snorm, &tau_k, cg->alpha);CHKERRQ(ierr); 781c8bcdf1eSAdam Denchfield /* Use cg->alpha = -1.0 to get tau_k = 1.0 as in CG_DESCENT 5.3 */ 782c8bcdf1eSAdam Denchfield tmp = gd/dk_yk; 783*50b47da0SAdam Denchfield beta = tau_k*(gkp1_yk/dk_yk - ynorm2*gd/(dk_yk*dk_yk) + gd/(dnorm*dnorm)) - step*gd/dk_yk; 784*50b47da0SAdam Denchfield beta = PetscMax(PetscMax(beta, cg->hz_eta*tau_k*gd_old/(dnorm*dnorm)), cg->dk_eta*tau_k*gd/(dnorm*dnorm)); 785c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*t*d */ 786c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -tau_k, 0.0, beta, tao->gradient, cg->yk);CHKERRQ(ierr); 787c8bcdf1eSAdam Denchfield } else { 788c8bcdf1eSAdam Denchfield /* We have diagonal scaling enabled and are taking a diagonally-scaled memoryless BFGS step */ 789c8bcdf1eSAdam Denchfield cg->yty = ynorm2; 790c8bcdf1eSAdam Denchfield cg->sts = snorm*snorm; 791*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 792*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 793*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->stepdirection, cg->d_work);CHKERRQ(ierr); 794c8bcdf1eSAdam Denchfield /* Construct the constant ytDgkp1 */ 795c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, cg->g_work, &gkp1_yk);CHKERRQ(ierr); 796c8bcdf1eSAdam Denchfield /* tau_bfgs can be a parameter we tune via command line in future versions. For now, just setting to one. May instead put this inside the ComputeDiagonalScaling function... */ 797c8bcdf1eSAdam Denchfield cg->tau_bfgs = 1.0; 798*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, cg->y_work, &tau_k);CHKERRQ(ierr); 799c8bcdf1eSAdam Denchfield tau_k = tau_k*gd/(dk_yk*dk_yk); 800c8bcdf1eSAdam Denchfield tmp = gd/dk_yk; 801c8bcdf1eSAdam Denchfield /* beta is the constant which adds the dk contribution */ 802c8bcdf1eSAdam Denchfield beta = cg->tau_bfgs*gkp1_yk/dk_yk - step*tmp - tau_k; 803c8bcdf1eSAdam Denchfield /* Update this for the last term in beta */ 804c8bcdf1eSAdam Denchfield ierr = VecDot(cg->y_work, tao->stepdirection, &dk_yk);CHKERRQ(ierr); 805c8bcdf1eSAdam Denchfield beta += tmp*dk_yk/(dnorm*dnorm); /* projection of y_work onto dk */ 806*50b47da0SAdam Denchfield ierr = VecDot(tao->stepdirection, cg->g_work, &gd);CHKERRQ(ierr); 807*50b47da0SAdam Denchfield ierr = VecDot(cg->G_old, cg->d_work, &gd_old);CHKERRQ(ierr); 808*50b47da0SAdam Denchfield beta = PetscMax(PetscMax(beta, cg->hz_eta*gd_old/(dnorm*dnorm)), cg->dk_eta*gd/(dnorm*dnorm)); 809c8bcdf1eSAdam Denchfield /* Do the update */ 810c8bcdf1eSAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -cg->tau_bfgs, beta, cg->g_work);CHKERRQ(ierr); 811*50b47da0SAdam Denchfield } 812c8bcdf1eSAdam Denchfield break; 813c8bcdf1eSAdam Denchfield case CG_KouDai: 814c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 815c8bcdf1eSAdam Denchfield ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 816c8bcdf1eSAdam Denchfield ierr = VecWAXPY(cg->sk, -1.0, cg->X_old, tao->solution);CHKERRQ(ierr); 817*50b47da0SAdam Denchfield snorm = step*dnorm; 818*50b47da0SAdam Denchfield cg->yts = dk_yk*step; 819c8bcdf1eSAdam Denchfield if (cg->use_dynamic_restart){ 820c8bcdf1eSAdam Denchfield ierr = TaoBNCGCheckDynamicRestart(tao, step, gd, gd_old, &cg->dynamic_restart, fold);CHKERRQ(ierr); 821c8bcdf1eSAdam Denchfield } 822*50b47da0SAdam Denchfield if (cg->dynamic_restart){ 823c8bcdf1eSAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 824c8bcdf1eSAdam Denchfield } else { 825c8bcdf1eSAdam Denchfield if (!cg->diag_scaling){ 826c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, tao->gradient, &gkp1_yk);CHKERRQ(ierr); 827c8bcdf1eSAdam Denchfield ierr = TaoBNCGComputeScalarScaling(ynorm2, cg->yts, snorm*snorm, &tau_k, cg->alpha);CHKERRQ(ierr); 828c8bcdf1eSAdam Denchfield beta = tau_k*(gkp1_yk/dk_yk - ynorm2*gd/(dk_yk*dk_yk)) - step*gd/dk_yk; 829c8bcdf1eSAdam Denchfield if (beta < cg->zeta*tau_k*gd/(dnorm*dnorm)) /* 0.1 is KD's zeta parameter */ 830c8bcdf1eSAdam Denchfield { 831c8bcdf1eSAdam Denchfield beta = cg->zeta*tau_k*gd/(dnorm*dnorm); 832c8bcdf1eSAdam Denchfield gamma = 0.0; 833c8bcdf1eSAdam Denchfield } else { 834c8bcdf1eSAdam Denchfield if (gkp1_yk < 0 && cg->neg_xi) gamma = -1.0*gd/dk_yk; 835*50b47da0SAdam Denchfield /* This seems to be very effective when there's no tau_k scaling. This guarantees a large descent step every iteration, going through DK 2015 Lemma 3.1's proof but allowing for negative xi */ 836*50b47da0SAdam Denchfield else { 837*50b47da0SAdam Denchfield gamma = cg->xi*gd/dk_yk; 838*50b47da0SAdam Denchfield } 839c8bcdf1eSAdam Denchfield } 840c8bcdf1eSAdam Denchfield /* d <- -t*g + beta*t*d + t*tmp*yk */ 841c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(tao->stepdirection, -tau_k, gamma*tau_k, beta, tao->gradient, cg->yk);CHKERRQ(ierr); 842c8bcdf1eSAdam Denchfield } else { 843c8bcdf1eSAdam Denchfield /* We have diagonal scaling enabled and are taking a diagonally-scaled memoryless BFGS step */ 844c8bcdf1eSAdam Denchfield cg->yty = ynorm2; 845c8bcdf1eSAdam Denchfield cg->sts = snorm*snorm; 846*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, tao->gradient, cg->g_work);CHKERRQ(ierr); 847*50b47da0SAdam Denchfield ierr = MatSolve(cg->B, cg->yk, cg->y_work);CHKERRQ(ierr); 848c8bcdf1eSAdam Denchfield /* Construct the constant ytDgkp1 */ 849c8bcdf1eSAdam Denchfield ierr = VecDot(cg->yk, cg->g_work, &gkp1D_yk);CHKERRQ(ierr); 850c8bcdf1eSAdam Denchfield /* Construct the constant for scaling Dkyk in the update */ 851c8bcdf1eSAdam Denchfield gamma = gd/dk_yk; 852c8bcdf1eSAdam Denchfield /* tau_k = -ytDy/(ytd)^2 * gd */ 853*50b47da0SAdam Denchfield ierr = VecDot(cg->yk, cg->y_work, &tau_k);CHKERRQ(ierr); 854c8bcdf1eSAdam Denchfield tau_k = tau_k*gd/(dk_yk*dk_yk); 855c8bcdf1eSAdam Denchfield /* beta is the constant which adds the d_k contribution */ 856c8bcdf1eSAdam Denchfield beta = gkp1D_yk/dk_yk - step*gamma - tau_k; 857c8bcdf1eSAdam Denchfield /* Here is the requisite check */ 858*50b47da0SAdam Denchfield ierr = VecDot(tao->stepdirection, cg->g_work, &tmp);CHKERRQ(ierr); 859c8bcdf1eSAdam Denchfield if (cg->neg_xi){ 860c8bcdf1eSAdam Denchfield /* modified KD implementation */ 861c8bcdf1eSAdam Denchfield if (gkp1D_yk/dk_yk < 0) gamma = -1.0*gd/dk_yk; 862*50b47da0SAdam Denchfield else { 863*50b47da0SAdam Denchfield gamma = cg->xi*gd/dk_yk; 864*50b47da0SAdam Denchfield } 865c8bcdf1eSAdam Denchfield if (beta < cg->zeta*tmp/(dnorm*dnorm)){ 866c8bcdf1eSAdam Denchfield beta = cg->zeta*tmp/(dnorm*dnorm); 867c8bcdf1eSAdam Denchfield gamma = 0.0; 868c8bcdf1eSAdam Denchfield } 869c8bcdf1eSAdam Denchfield } else { /* original KD 2015 implementation */ 870c8bcdf1eSAdam Denchfield if (beta < cg->zeta*tmp/(dnorm*dnorm)) { 871c8bcdf1eSAdam Denchfield beta = cg->zeta*tmp/(dnorm*dnorm); 872c8bcdf1eSAdam Denchfield gamma = 0.0; 873c8bcdf1eSAdam Denchfield } else { 874c8bcdf1eSAdam Denchfield gamma = cg->xi*gd/dk_yk; 875c8bcdf1eSAdam Denchfield } 876c8bcdf1eSAdam Denchfield } 877c8bcdf1eSAdam Denchfield /* Do the update in two steps */ 878c8bcdf1eSAdam Denchfield ierr = VecAXPBY(tao->stepdirection, -1.0, beta, cg->g_work);CHKERRQ(ierr); 879c8bcdf1eSAdam Denchfield ierr = VecAXPY(tao->stepdirection, gamma, cg->y_work);CHKERRQ(ierr); 880*50b47da0SAdam Denchfield } 881*50b47da0SAdam Denchfield } 882c8bcdf1eSAdam Denchfield break; 883c8bcdf1eSAdam Denchfield default: 884c8bcdf1eSAdam Denchfield beta = 0.0; 885c8bcdf1eSAdam Denchfield break; 886c8bcdf1eSAdam Denchfield } 887c8bcdf1eSAdam Denchfield } 888*50b47da0SAdam Denchfield cg_restart = 0; /* Will check in next iteration */ 889c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 890c8bcdf1eSAdam Denchfield } 891c8bcdf1eSAdam Denchfield 892*50b47da0SAdam Denchfield PETSC_INTERN PetscErrorCode TaoBNCGSteffensonAcceleration(Tao tao) 893*50b47da0SAdam Denchfield { 894*50b47da0SAdam Denchfield /* Steffenson is currently an experimental (broken) feature. Do not use. */ 895c8bcdf1eSAdam Denchfield TAO_BNCG *cg = (TAO_BNCG*)tao->data; 896c8bcdf1eSAdam Denchfield PetscErrorCode ierr; 897c8bcdf1eSAdam Denchfield PetscReal mag1, mag2; 898c8bcdf1eSAdam Denchfield PetscReal resnorm; 899c8bcdf1eSAdam Denchfield PetscReal steff_f; 900c8bcdf1eSAdam Denchfield PetscFunctionBegin; 901c8bcdf1eSAdam Denchfield if (tao->niter > 2 && tao->niter % 2 == 0){ 902c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->steffnp1, cg->steffnm1);CHKERRQ(ierr); /* X_np1 to X_nm1 since it's been two iterations*/ 903c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->X_old, cg->steffn);CHKERRQ(ierr); /* Get X_n */ 904c8bcdf1eSAdam Denchfield ierr = VecCopy(tao->solution, cg->steffnp1);CHKERRQ(ierr); 905c8bcdf1eSAdam Denchfield 906c8bcdf1eSAdam Denchfield /* Begin step 4 */ 907c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->steffnm1, cg->W);CHKERRQ(ierr); 908c8bcdf1eSAdam Denchfield ierr = VecAXPBY(cg->W, 1.0, -1.0, cg->steffn);CHKERRQ(ierr); 909*50b47da0SAdam Denchfield ierr = VecDot(cg->W, cg->W, &mag1);CHKERRQ(ierr); 910c8bcdf1eSAdam Denchfield ierr = VecAXPBYPCZ(cg->W, -1.0, 1.0, -1.0, cg->steffn, cg->steffnp1);CHKERRQ(ierr); 911*50b47da0SAdam Denchfield ierr = VecDot(cg->W, cg->W, &mag2);CHKERRQ(ierr); 912c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->steffnm1, cg->steffva);CHKERRQ(ierr); 913c8bcdf1eSAdam Denchfield ierr = VecAXPY(cg->steffva, -mag1/mag2, cg->W);CHKERRQ(ierr); 914c8bcdf1eSAdam Denchfield 915c8bcdf1eSAdam Denchfield ierr = TaoComputeObjectiveAndGradient(tao, cg->steffva, &steff_f, cg->g_work);CHKERRQ(ierr); 916c8bcdf1eSAdam Denchfield 917c8bcdf1eSAdam Denchfield /* Check if the accelerated point has converged*/ 918c8bcdf1eSAdam Denchfield ierr = VecFischer(cg->steffva, cg->g_work, tao->XL, tao->XU, cg->W);CHKERRQ(ierr); 919c8bcdf1eSAdam Denchfield ierr = VecNorm(cg->W, NORM_2, &resnorm);CHKERRQ(ierr); 920c8bcdf1eSAdam Denchfield if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 921c8bcdf1eSAdam Denchfield ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 922*50b47da0SAdam Denchfield ierr = PetscPrintf(PETSC_COMM_SELF, "va f: %20.19e\t va gnorm: %20.19e\n", steff_f, resnorm);CHKERRQ(ierr); 923c8bcdf1eSAdam Denchfield 924*50b47da0SAdam Denchfield } else if (2 == tao->niter){ 925c8bcdf1eSAdam Denchfield ierr = VecCopy(tao->solution, cg->steffnp1);CHKERRQ(ierr); 926c8bcdf1eSAdam Denchfield mag1 = cg->sts; /* = |x1 - x0|^2 */ 927c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->steffnm1, cg->steffvatmp);CHKERRQ(ierr); 928*50b47da0SAdam Denchfield ierr = VecAXPBYPCZ(cg->steffva, 1.0, -1.0, 0.0, cg->steffnp1, cg->steffn);CHKERRQ(ierr); 929*50b47da0SAdam Denchfield ierr = VecAXPBYPCZ(cg->steffva, 1.0, -1.0, 1.0, cg->steffnm1, cg->steffn);CHKERRQ(ierr); 930c8bcdf1eSAdam Denchfield ierr = VecNorm(cg->steffva, NORM_2, &mag2);CHKERRQ(ierr); 931c8bcdf1eSAdam Denchfield mag2 = mag2*mag2; 932c8bcdf1eSAdam Denchfield ierr = VecAXPBY(cg->steffva, 1.0, -mag1/mag2, cg->steffvatmp);CHKERRQ(ierr); 933c8bcdf1eSAdam Denchfield // finished step 2 934*50b47da0SAdam Denchfield } else if (1 == tao->niter){ 935c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->X_old, cg->steffnm1);CHKERRQ(ierr); 936c8bcdf1eSAdam Denchfield ierr = VecCopy(tao->solution, cg->steffn);CHKERRQ(ierr); 937c8bcdf1eSAdam Denchfield } 938c8bcdf1eSAdam Denchfield /* Now have step 2 done of method */ 939c8bcdf1eSAdam Denchfield PetscFunctionReturn(0); 940c8bcdf1eSAdam Denchfield } 941c8bcdf1eSAdam Denchfield 942c8bcdf1eSAdam Denchfield PETSC_INTERN PetscErrorCode TaoBNCGConductIteration(Tao tao, PetscReal gnorm) 943c8bcdf1eSAdam Denchfield { 944c8bcdf1eSAdam Denchfield TAO_BNCG *cg = (TAO_BNCG*)tao->data; 945c8bcdf1eSAdam Denchfield PetscErrorCode ierr; 946c8bcdf1eSAdam Denchfield TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING; 947c8bcdf1eSAdam Denchfield PetscReal step=1.0,gnorm2,gd,ginner,dnorm; 948c8bcdf1eSAdam Denchfield PetscReal gnorm2_old,f_old,resnorm, gnorm_old; 949c8bcdf1eSAdam Denchfield PetscBool cg_restart, gd_fallback = PETSC_FALSE; 950c8bcdf1eSAdam Denchfield 951c8bcdf1eSAdam Denchfield PetscFunctionBegin; 952c8bcdf1eSAdam Denchfield /* We are now going to perform a line search along the direction. */ 953c8bcdf1eSAdam Denchfield ++tao->niter; 954c8bcdf1eSAdam Denchfield 955c8bcdf1eSAdam Denchfield /* Store solution and gradient info before it changes */ 956c8bcdf1eSAdam Denchfield ierr = VecCopy(tao->solution, cg->X_old);CHKERRQ(ierr); 957c8bcdf1eSAdam Denchfield ierr = VecCopy(tao->gradient, cg->G_old);CHKERRQ(ierr); 958c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->unprojected_gradient, cg->unprojected_gradient_old);CHKERRQ(ierr); 959c8bcdf1eSAdam Denchfield 960c8bcdf1eSAdam Denchfield gnorm_old = gnorm; 961c8bcdf1eSAdam Denchfield gnorm2_old = gnorm_old*gnorm_old; 962c8bcdf1eSAdam Denchfield f_old = cg->f; 963c8bcdf1eSAdam Denchfield /* Perform bounded line search */ 964c8bcdf1eSAdam Denchfield ierr = TaoLineSearchSetInitialStepLength(tao->linesearch, 1.0);CHKERRQ(ierr); 965c8bcdf1eSAdam Denchfield ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 966c8bcdf1eSAdam Denchfield ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 967c8bcdf1eSAdam Denchfield 968c8bcdf1eSAdam Denchfield /* Check linesearch failure */ 969c8bcdf1eSAdam Denchfield if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) { 970c8bcdf1eSAdam Denchfield ++cg->ls_fails; 971c8bcdf1eSAdam Denchfield 972c8bcdf1eSAdam Denchfield if (cg->cg_type == CG_GradientDescent || gd_fallback){ 973c8bcdf1eSAdam Denchfield /* Nothing left to do but fail out of the optimization */ 974c8bcdf1eSAdam Denchfield step = 0.0; 975c8bcdf1eSAdam Denchfield tao->reason = TAO_DIVERGED_LS_FAILURE; 976c8bcdf1eSAdam Denchfield } else { 977c8bcdf1eSAdam Denchfield /* Restore previous point */ 978c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr); 979c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr); 980c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr); 981c8bcdf1eSAdam Denchfield 982c8bcdf1eSAdam Denchfield gnorm = gnorm_old; 983c8bcdf1eSAdam Denchfield gnorm2 = gnorm2_old; 984c8bcdf1eSAdam Denchfield cg->f = f_old; 985c8bcdf1eSAdam Denchfield 986c8bcdf1eSAdam Denchfield /* Fall back on the scaled gradient step */ 987*50b47da0SAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 988c8bcdf1eSAdam Denchfield ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 989c8bcdf1eSAdam Denchfield 990c8bcdf1eSAdam Denchfield ierr = TaoLineSearchSetInitialStepLength(tao->linesearch, 1.0);CHKERRQ(ierr); 991c8bcdf1eSAdam Denchfield ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 992c8bcdf1eSAdam Denchfield ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 993c8bcdf1eSAdam Denchfield 994c8bcdf1eSAdam Denchfield if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER){ 995c8bcdf1eSAdam Denchfield /* Nothing left to do but fail out of the optimization */ 996*50b47da0SAdam Denchfield ++cg->ls_fails; 997c8bcdf1eSAdam Denchfield step = 0.0; 998c8bcdf1eSAdam Denchfield tao->reason = TAO_DIVERGED_LS_FAILURE; 999c8bcdf1eSAdam Denchfield } 1000c8bcdf1eSAdam Denchfield } 1001c8bcdf1eSAdam Denchfield } 1002c8bcdf1eSAdam Denchfield /* Convergence test for line search failure */ 1003c8bcdf1eSAdam Denchfield if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 1004c8bcdf1eSAdam Denchfield 1005c8bcdf1eSAdam Denchfield /* Standard convergence test */ 1006c8bcdf1eSAdam Denchfield /* Make sure convergence test is the same. */ 1007c8bcdf1eSAdam Denchfield ierr = VecFischer(tao->solution, cg->unprojected_gradient, tao->XL, tao->XU, cg->W);CHKERRQ(ierr); 1008c8bcdf1eSAdam Denchfield ierr = VecNorm(cg->W, NORM_2, &resnorm);CHKERRQ(ierr); 1009c8bcdf1eSAdam Denchfield if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 1010c8bcdf1eSAdam Denchfield ierr = TaoLogConvergenceHistory(tao, cg->f, resnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 1011c8bcdf1eSAdam Denchfield ierr = TaoMonitor(tao, tao->niter, cg->f, resnorm, 0.0, step);CHKERRQ(ierr); 1012c8bcdf1eSAdam Denchfield ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 1013c8bcdf1eSAdam Denchfield if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 1014c8bcdf1eSAdam Denchfield 1015c8bcdf1eSAdam Denchfield /* Assert we have an updated step and we need at least one more iteration. */ 1016c8bcdf1eSAdam Denchfield /* Calculate the next direction */ 1017c8bcdf1eSAdam Denchfield /* Estimate the active set at the new solution */ 1018c8bcdf1eSAdam Denchfield ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 1019c8bcdf1eSAdam Denchfield /* Compute the projected gradient and its norm */ 1020c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 1021c8bcdf1eSAdam Denchfield ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 1022c8bcdf1eSAdam Denchfield ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 1023c8bcdf1eSAdam Denchfield gnorm2 = gnorm*gnorm; 1024c8bcdf1eSAdam Denchfield 1025c8bcdf1eSAdam Denchfield /* Check restart conditions for using steepest descent */ 1026*50b47da0SAdam Denchfield cg_restart = 0; 1027c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, cg->G_old, &ginner);CHKERRQ(ierr); 1028c8bcdf1eSAdam Denchfield ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);CHKERRQ(ierr); 1029c8bcdf1eSAdam Denchfield 1030c8bcdf1eSAdam Denchfield ierr = TaoBNCGStepDirectionUpdate(tao, gnorm2, step, f_old, gnorm2_old, cg_restart, dnorm, ginner);CHKERRQ(ierr); 1031c8bcdf1eSAdam Denchfield 1032c8bcdf1eSAdam Denchfield ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 1033c8bcdf1eSAdam Denchfield 1034c8bcdf1eSAdam Denchfield if (cg->cg_type != CG_GradientDescent) { 1035c8bcdf1eSAdam Denchfield /* Figure out which previously active variables became inactive this iteration */ 1036c8bcdf1eSAdam Denchfield ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 1037c8bcdf1eSAdam Denchfield if (cg->inactive_idx && cg->inactive_old) { 1038c8bcdf1eSAdam Denchfield ierr = ISDifference(cg->inactive_idx, cg->inactive_old, &cg->new_inactives);CHKERRQ(ierr); 1039c8bcdf1eSAdam Denchfield } 1040c8bcdf1eSAdam Denchfield /* Selectively reset the CG step those freshly inactive variables */ 1041c8bcdf1eSAdam Denchfield if (cg->new_inactives) { 1042c8bcdf1eSAdam Denchfield ierr = VecGetSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 1043c8bcdf1eSAdam Denchfield ierr = VecGetSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 1044c8bcdf1eSAdam Denchfield ierr = VecCopy(cg->inactive_grad, cg->inactive_step);CHKERRQ(ierr); 1045c8bcdf1eSAdam Denchfield ierr = VecScale(cg->inactive_step, -1.0);CHKERRQ(ierr); 1046c8bcdf1eSAdam Denchfield ierr = VecRestoreSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 1047c8bcdf1eSAdam Denchfield ierr = VecRestoreSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 1048c8bcdf1eSAdam Denchfield } 1049c8bcdf1eSAdam Denchfield 1050c8bcdf1eSAdam Denchfield /* Verify that this is a descent direction */ 1051c8bcdf1eSAdam Denchfield ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 1052*50b47da0SAdam Denchfield ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);CHKERRQ(ierr); 1053*50b47da0SAdam Denchfield if (PetscIsInfOrNanReal(gd) || (gd/(dnorm*dnorm) <= -1e10 || gd/(dnorm*dnorm) >= -1e-10)) { 1054c8bcdf1eSAdam Denchfield /* Not a descent direction, so we reset back to projected gradient descent */ 1055*50b47da0SAdam Denchfield PetscPrintf(PETSC_COMM_SELF, "gtd/(dtd) is small or positive: %20.19e\n", gd/(dnorm*dnorm)); 1056*50b47da0SAdam Denchfield ierr = TaoBNCGResetUpdate(tao, gnorm2);CHKERRQ(ierr); 1057c8bcdf1eSAdam Denchfield ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 1058c8bcdf1eSAdam Denchfield ++cg->descent_error; 1059c8bcdf1eSAdam Denchfield gd_fallback = PETSC_TRUE; 1060c8bcdf1eSAdam Denchfield } else { 1061c8bcdf1eSAdam Denchfield gd_fallback = PETSC_FALSE; 1062c8bcdf1eSAdam Denchfield } 1063c8bcdf1eSAdam Denchfield } 1064ac9112b8SAlp Dener PetscFunctionReturn(0); 1065ac9112b8SAlp Dener } 1066