1ba92ff59SBarry Smith #include <petsctaolinesearch.h> 2aaa7dc30SBarry Smith #include <../src/tao/unconstrained/impls/lmvm/lmvm.h> 3a7e14dcfSSatish Balay 4cd929ea3SAlp Dener #define LMVM_STEP_BFGS 0 5cd929ea3SAlp Dener #define LMVM_STEP_GRAD 1 6a7e14dcfSSatish Balay 7441846f8SBarry Smith static PetscErrorCode TaoSolve_LMVM(Tao tao) 8a7e14dcfSSatish Balay { 9a7e14dcfSSatish Balay TAO_LMVM *lmP = (TAO_LMVM *)tao->data; 10a7e14dcfSSatish Balay PetscReal f, fold, gdx, gnorm; 11a7e14dcfSSatish Balay PetscReal step = 1.0; 12a7e14dcfSSatish Balay PetscErrorCode ierr; 13cd929ea3SAlp Dener PetscInt stepType = LMVM_STEP_GRAD, nupdates; 14e4cb33bbSBarry Smith TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING; 15a7e14dcfSSatish Balay 16a7e14dcfSSatish Balay PetscFunctionBegin; 17a7e14dcfSSatish Balay 18a7e14dcfSSatish Balay if (tao->XL || tao->XU || tao->ops->computebounds) { 19a7e14dcfSSatish Balay ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by lmvm algorithm\n");CHKERRQ(ierr); 20a7e14dcfSSatish Balay } 21a7e14dcfSSatish Balay 22a7e14dcfSSatish Balay /* Check convergence criteria */ 23a7e14dcfSSatish Balay ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient);CHKERRQ(ierr); 24a9603a14SPatrick Farrell ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 25a9603a14SPatrick Farrell 2687f595a5SBarry Smith if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 27a7e14dcfSSatish Balay 283ecd9318SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 293ecd9318SAlp Dener ierr = TaoLogConvergenceHistory(tao,f,gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 303ecd9318SAlp Dener ierr = TaoMonitor(tao,tao->niter,f,gnorm,0.0,step);CHKERRQ(ierr); 313ecd9318SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 323ecd9318SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 33a7e14dcfSSatish Balay 34a7e14dcfSSatish Balay /* Set counter for gradient/reset steps */ 35cd929ea3SAlp Dener if (!lmP->recycle) { 36a7e14dcfSSatish Balay lmP->bfgs = 0; 37a7e14dcfSSatish Balay lmP->grad = 0; 38cd929ea3SAlp Dener ierr = MatLMVMReset(lmP->M, PETSC_FALSE); CHKERRQ(ierr); 39de6ffafeSAlp Dener } 40a7e14dcfSSatish Balay 41a7e14dcfSSatish Balay /* Have not converged; continue with Newton method */ 423ecd9318SAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 43a7e14dcfSSatish Balay /* Compute direction */ 44cd929ea3SAlp Dener if (lmP->H0) { 45cd929ea3SAlp Dener ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr); 46cd929ea3SAlp Dener stepType = LMVM_STEP_BFGS; 47cd929ea3SAlp Dener } 48a7e14dcfSSatish Balay ierr = MatLMVMUpdate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr); 49*9515a401SAlp Dener ierr = MatSolve(lmP->M, tao->gradient, lmP->D);CHKERRQ(ierr); 50cd929ea3SAlp Dener ierr = MatLMVMGetUpdateCount(lmP->M, &nupdates); CHKERRQ(ierr); 51cd929ea3SAlp Dener if (nupdates > 0) stepType = LMVM_STEP_BFGS; 52a7e14dcfSSatish Balay 53a7e14dcfSSatish Balay /* Check for success (descent direction) */ 54a7e14dcfSSatish Balay ierr = VecDot(lmP->D, tao->gradient, &gdx);CHKERRQ(ierr); 55a7e14dcfSSatish Balay if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) { 56a7e14dcfSSatish Balay /* Step is not descent or direction produced not a number 57a7e14dcfSSatish Balay We can assert bfgsUpdates > 1 in this case because 58a7e14dcfSSatish Balay the first solve produces the scaled gradient direction, 59a7e14dcfSSatish Balay which is guaranteed to be descent 60a7e14dcfSSatish Balay 61a7e14dcfSSatish Balay Use steepest descent direction (scaled) 62a7e14dcfSSatish Balay */ 63a7e14dcfSSatish Balay 64cd929ea3SAlp Dener ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr); 650ad3a497SAlp Dener ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr); 66a7e14dcfSSatish Balay ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr); 67*9515a401SAlp Dener ierr = MatSolve(lmP->M,tao->gradient, lmP->D);CHKERRQ(ierr); 68a7e14dcfSSatish Balay 69a7e14dcfSSatish Balay /* On a reset, the direction cannot be not a number; it is a 70a7e14dcfSSatish Balay scaled gradient step. No need to check for this condition. */ 71cd929ea3SAlp Dener stepType = LMVM_STEP_GRAD; 72a7e14dcfSSatish Balay } 73a7e14dcfSSatish Balay ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr); 74a7e14dcfSSatish Balay 75a7e14dcfSSatish Balay /* Perform the linesearch */ 76a7e14dcfSSatish Balay fold = f; 77a7e14dcfSSatish Balay ierr = VecCopy(tao->solution, lmP->Xold);CHKERRQ(ierr); 78a7e14dcfSSatish Balay ierr = VecCopy(tao->gradient, lmP->Gold);CHKERRQ(ierr); 79a7e14dcfSSatish Balay 80a7e14dcfSSatish Balay ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step,&ls_status);CHKERRQ(ierr); 81a7e14dcfSSatish Balay ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 82a7e14dcfSSatish Balay 83cd929ea3SAlp Dener if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER && (stepType != LMVM_STEP_GRAD)) { 84a7e14dcfSSatish Balay /* Reset factors and use scaled gradient step */ 85a7e14dcfSSatish Balay f = fold; 86a7e14dcfSSatish Balay ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr); 87a7e14dcfSSatish Balay ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr); 88a7e14dcfSSatish Balay 89a7e14dcfSSatish Balay /* Failed to obtain acceptable iterate with BFGS step */ 90a7e14dcfSSatish Balay /* Attempt to use the scaled gradient direction */ 91a7e14dcfSSatish Balay 92cd929ea3SAlp Dener ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr); 930ad3a497SAlp Dener ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr); 94a7e14dcfSSatish Balay ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr); 95*9515a401SAlp Dener ierr = MatSolve(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr); 96a7e14dcfSSatish Balay 97a7e14dcfSSatish Balay /* On a reset, the direction cannot be not a number; it is a 98a7e14dcfSSatish Balay scaled gradient step. No need to check for this condition. */ 99cd929ea3SAlp Dener stepType = LMVM_STEP_GRAD; 100a7e14dcfSSatish Balay ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr); 101a7e14dcfSSatish Balay 102a7e14dcfSSatish Balay /* Perform the linesearch */ 103a7e14dcfSSatish Balay ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step, &ls_status);CHKERRQ(ierr); 104a7e14dcfSSatish Balay ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 105a7e14dcfSSatish Balay } 106a7e14dcfSSatish Balay 10787f595a5SBarry Smith if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) { 108a7e14dcfSSatish Balay /* Failed to find an improving point */ 109a7e14dcfSSatish Balay f = fold; 110a7e14dcfSSatish Balay ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr); 111a7e14dcfSSatish Balay ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr); 112a7e14dcfSSatish Balay step = 0.0; 113a7e14dcfSSatish Balay tao->reason = TAO_DIVERGED_LS_FAILURE; 114cd929ea3SAlp Dener } else { 115cd929ea3SAlp Dener /* LS found valid step, so tally up step type */ 116cd929ea3SAlp Dener switch (stepType) { 117cd929ea3SAlp Dener case LMVM_STEP_BFGS: 118cd929ea3SAlp Dener ++lmP->bfgs; 119cd929ea3SAlp Dener break; 120cd929ea3SAlp Dener case LMVM_STEP_GRAD: 121cd929ea3SAlp Dener ++lmP->grad; 122cd929ea3SAlp Dener break; 123cd929ea3SAlp Dener default: 124cd929ea3SAlp Dener break; 125cd929ea3SAlp Dener } 126cd929ea3SAlp Dener /* Compute new gradient norm */ 127cd929ea3SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 128a7e14dcfSSatish Balay } 129a9603a14SPatrick Farrell 130cd929ea3SAlp Dener /* Check convergence */ 1318931d482SJason Sarich tao->niter++; 1323ecd9318SAlp Dener ierr = TaoLogConvergenceHistory(tao,f,gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 1333ecd9318SAlp Dener ierr = TaoMonitor(tao,tao->niter,f,gnorm,0.0,step);CHKERRQ(ierr); 1343ecd9318SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 135a7e14dcfSSatish Balay } 136a7e14dcfSSatish Balay PetscFunctionReturn(0); 137a7e14dcfSSatish Balay } 13887f595a5SBarry Smith 139441846f8SBarry Smith static PetscErrorCode TaoSetUp_LMVM(Tao tao) 140a7e14dcfSSatish Balay { 141a7e14dcfSSatish Balay TAO_LMVM *lmP = (TAO_LMVM *)tao->data; 142a7e14dcfSSatish Balay PetscInt n,N; 143a7e14dcfSSatish Balay PetscErrorCode ierr; 144d5ae2380SAlp Dener PetscBool is_spd; 145a7e14dcfSSatish Balay 146a7e14dcfSSatish Balay PetscFunctionBegin; 147a7e14dcfSSatish Balay /* Existence of tao->solution checked in TaoSetUp() */ 148a7e14dcfSSatish Balay if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); } 149a7e14dcfSSatish Balay if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr); } 150a7e14dcfSSatish Balay if (!lmP->D) {ierr = VecDuplicate(tao->solution,&lmP->D);CHKERRQ(ierr); } 151a7e14dcfSSatish Balay if (!lmP->Xold) {ierr = VecDuplicate(tao->solution,&lmP->Xold);CHKERRQ(ierr); } 152a7e14dcfSSatish Balay if (!lmP->Gold) {ierr = VecDuplicate(tao->solution,&lmP->Gold);CHKERRQ(ierr); } 153a7e14dcfSSatish Balay 154a7e14dcfSSatish Balay /* Create matrix for the limited memory approximation */ 155a7e14dcfSSatish Balay ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); 156a7e14dcfSSatish Balay ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); 157cd929ea3SAlp Dener ierr = MatSetSizes(lmP->M, n, n, N, N);CHKERRQ(ierr); 158cd929ea3SAlp Dener ierr = MatLMVMAllocate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr); 1590ad3a497SAlp Dener ierr = MatGetOption(lmP->M, MAT_SPD, &is_spd);CHKERRQ(ierr); 1600ad3a497SAlp Dener if (!is_spd) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix is not symmetric positive-definite."); 161a9603a14SPatrick Farrell 162a9603a14SPatrick Farrell /* If the user has set a matrix to solve as the initial H0, set the options prefix here, and set up the KSP */ 163a9603a14SPatrick Farrell if (lmP->H0) { 164cd929ea3SAlp Dener ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr); 165a9603a14SPatrick Farrell } 166a9603a14SPatrick Farrell 167a7e14dcfSSatish Balay PetscFunctionReturn(0); 168a7e14dcfSSatish Balay } 169a7e14dcfSSatish Balay 170a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 171441846f8SBarry Smith static PetscErrorCode TaoDestroy_LMVM(Tao tao) 172a7e14dcfSSatish Balay { 173a7e14dcfSSatish Balay TAO_LMVM *lmP = (TAO_LMVM *)tao->data; 174a7e14dcfSSatish Balay PetscErrorCode ierr; 175a7e14dcfSSatish Balay 176a7e14dcfSSatish Balay PetscFunctionBegin; 177a7e14dcfSSatish Balay if (tao->setupcalled) { 178a7e14dcfSSatish Balay ierr = VecDestroy(&lmP->Xold);CHKERRQ(ierr); 179a7e14dcfSSatish Balay ierr = VecDestroy(&lmP->Gold);CHKERRQ(ierr); 180a7e14dcfSSatish Balay ierr = VecDestroy(&lmP->D);CHKERRQ(ierr); 181a7e14dcfSSatish Balay } 182cd929ea3SAlp Dener ierr = MatDestroy(&lmP->M);CHKERRQ(ierr); 183a9603a14SPatrick Farrell if (lmP->H0) { 184a9603a14SPatrick Farrell ierr = PetscObjectDereference((PetscObject)lmP->H0);CHKERRQ(ierr); 185a9603a14SPatrick Farrell } 186a7e14dcfSSatish Balay ierr = PetscFree(tao->data);CHKERRQ(ierr); 187a9603a14SPatrick Farrell 188a7e14dcfSSatish Balay PetscFunctionReturn(0); 189a7e14dcfSSatish Balay } 190a7e14dcfSSatish Balay 191a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 1924416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LMVM(PetscOptionItems *PetscOptionsObject,Tao tao) 193a7e14dcfSSatish Balay { 194cd929ea3SAlp Dener TAO_LMVM *lm = (TAO_LMVM *)tao->data; 195a7e14dcfSSatish Balay PetscErrorCode ierr; 196a7e14dcfSSatish Balay 197a7e14dcfSSatish Balay PetscFunctionBegin; 1981a1499c8SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Limited-memory variable-metric method for unconstrained optimization");CHKERRQ(ierr); 199cd929ea3SAlp Dener ierr = PetscOptionsBool("-tao_lmvm_recycle","enable recycling of the BFGS matrix between subsequent TaoSolve() calls","",lm->recycle,&lm->recycle,NULL);CHKERRQ(ierr); 200114d2d62SAlp Dener ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 201cd929ea3SAlp Dener ierr = MatSetFromOptions(lm->M);CHKERRQ(ierr); 202288b7216SAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 203a7e14dcfSSatish Balay PetscFunctionReturn(0); 204a7e14dcfSSatish Balay } 205a7e14dcfSSatish Balay 206a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 207441846f8SBarry Smith static PetscErrorCode TaoView_LMVM(Tao tao, PetscViewer viewer) 208a7e14dcfSSatish Balay { 209a7e14dcfSSatish Balay TAO_LMVM *lm = (TAO_LMVM *)tao->data; 210cd929ea3SAlp Dener PetscBool isascii; 2114d6623b4SAlp Dener PetscInt recycled_its; 212a7e14dcfSSatish Balay PetscErrorCode ierr; 213a7e14dcfSSatish Balay 214a7e14dcfSSatish Balay PetscFunctionBegin; 215a7e14dcfSSatish Balay ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 216a7e14dcfSSatish Balay if (isascii) { 217a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, " Gradient steps: %D\n", lm->grad);CHKERRQ(ierr); 218cd929ea3SAlp Dener if (lm->recycle) { 219288b7216SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " Recycle: on\n");CHKERRQ(ierr); 220cd929ea3SAlp Dener recycled_its = lm->bfgs + lm->grad; 2214d6623b4SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " Total recycled iterations: %D\n", recycled_its);CHKERRQ(ierr); 222a0bfee83SAlp Dener } 223a7e14dcfSSatish Balay } 224a7e14dcfSSatish Balay PetscFunctionReturn(0); 225a7e14dcfSSatish Balay } 226a7e14dcfSSatish Balay 227a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 228a7e14dcfSSatish Balay 2294aa34175SJason Sarich /*MC 2304aa34175SJason Sarich TAOLMVM - Limited Memory Variable Metric method is a quasi-Newton 2314aa34175SJason Sarich optimization solver for unconstrained minimization. It solves 2324aa34175SJason Sarich the Newton step 2334aa34175SJason Sarich Hkdk = - gk 2344aa34175SJason Sarich 2354aa34175SJason Sarich using an approximation Bk in place of Hk, where Bk is composed using 2364aa34175SJason Sarich the BFGS update formula. A More-Thuente line search is then used 2374aa34175SJason Sarich to computed the steplength in the dk direction 2380ad3a497SAlp Dener 2394aa34175SJason Sarich Options Database Keys: 240cd929ea3SAlp Dener . -tao_lmvm_recycle - enable recycling LMVM updates between TaoSolve() calls 2410ad3a497SAlp Dener . -tao_lmvm_no_scale - (developer) disables diagonal Broyden scaling on the LMVM approximation 2424aa34175SJason Sarich 2431eb8069cSJason Sarich Level: beginner 2444aa34175SJason Sarich M*/ 2454aa34175SJason Sarich 246728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LMVM(Tao tao) 247a7e14dcfSSatish Balay { 248a7e14dcfSSatish Balay TAO_LMVM *lmP; 2498caf6e8cSBarry Smith const char *morethuente_type = TAOLINESEARCHMT; 250a7e14dcfSSatish Balay PetscErrorCode ierr; 251a7e14dcfSSatish Balay 252a7e14dcfSSatish Balay PetscFunctionBegin; 253a7e14dcfSSatish Balay tao->ops->setup = TaoSetUp_LMVM; 254a7e14dcfSSatish Balay tao->ops->solve = TaoSolve_LMVM; 255a7e14dcfSSatish Balay tao->ops->view = TaoView_LMVM; 256a7e14dcfSSatish Balay tao->ops->setfromoptions = TaoSetFromOptions_LMVM; 257a7e14dcfSSatish Balay tao->ops->destroy = TaoDestroy_LMVM; 258a7e14dcfSSatish Balay 2593c9e27cfSGeoffrey Irving ierr = PetscNewLog(tao,&lmP);CHKERRQ(ierr); 260a7e14dcfSSatish Balay lmP->D = 0; 261a7e14dcfSSatish Balay lmP->M = 0; 262a7e14dcfSSatish Balay lmP->Xold = 0; 263a7e14dcfSSatish Balay lmP->Gold = 0; 264a9603a14SPatrick Farrell lmP->H0 = NULL; 265cd929ea3SAlp Dener lmP->recycle = PETSC_FALSE; 266a7e14dcfSSatish Balay 267a7e14dcfSSatish Balay tao->data = (void*)lmP; 2686552cf8aSJason Sarich /* Override default settings (unless already changed) */ 2696552cf8aSJason Sarich if (!tao->max_it_changed) tao->max_it = 2000; 2706552cf8aSJason Sarich if (!tao->max_funcs_changed) tao->max_funcs = 4000; 271a7e14dcfSSatish Balay 272a7e14dcfSSatish Balay ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr); 27363b15415SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 274a7e14dcfSSatish Balay ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr); 275441846f8SBarry Smith ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr); 2765d527766SPatrick Farrell ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 277cd929ea3SAlp Dener 278cd929ea3SAlp Dener ierr = KSPInitializePackage();CHKERRQ(ierr); 279cd929ea3SAlp Dener ierr = MatCreate(((PetscObject)tao)->comm, &lmP->M);CHKERRQ(ierr); 280cd929ea3SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)lmP->M, (PetscObject)tao, 1);CHKERRQ(ierr); 28178e4361aSAlp Dener ierr = MatSetType(lmP->M, MATLMVMBFGS);CHKERRQ(ierr); 282cd929ea3SAlp Dener ierr = MatSetOptionsPrefix(lmP->M, "tao_lmvm_");CHKERRQ(ierr); 283a7e14dcfSSatish Balay PetscFunctionReturn(0); 284a7e14dcfSSatish Balay } 285