1661095bbSAlp Dener #include <../src/tao/constrained/impls/almm/almm.h> /*I "petsctao.h" I*/ /*I "petscvec.h" I*/ 2661095bbSAlp Dener #include <petsctao.h> 3661095bbSAlp Dener #include <petsc/private/petscimpl.h> 4661095bbSAlp Dener #include <petsc/private/vecimpl.h> 5661095bbSAlp Dener 6661095bbSAlp Dener static PetscErrorCode TaoALMMCombinePrimal_Private(Tao,Vec,Vec,Vec); 7661095bbSAlp Dener static PetscErrorCode TaoALMMCombineDual_Private(Tao,Vec,Vec,Vec); 8661095bbSAlp Dener static PetscErrorCode TaoALMMSplitPrimal_Private(Tao,Vec,Vec,Vec); 9661095bbSAlp Dener static PetscErrorCode TaoALMMComputeOptimalityNorms_Private(Tao); 10661095bbSAlp Dener static PetscErrorCode TaoALMMComputeAugLagAndGradient_Private(Tao); 11661095bbSAlp Dener static PetscErrorCode TaoALMMComputePHRLagAndGradient_Private(Tao); 12661095bbSAlp Dener 13661095bbSAlp Dener static PetscErrorCode TaoSolve_ALMM(Tao tao) 14661095bbSAlp Dener { 15661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 16661095bbSAlp Dener TaoConvergedReason reason; 17661095bbSAlp Dener PetscReal updated; 18661095bbSAlp Dener PetscErrorCode ierr; 19661095bbSAlp Dener 20661095bbSAlp Dener PetscFunctionBegin; 21661095bbSAlp Dener /* reset initial multiplier/slack guess */ 22661095bbSAlp Dener if (!tao->recycle) { 23661095bbSAlp Dener if (tao->ineq_constrained) { 24661095bbSAlp Dener ierr = VecZeroEntries(auglag->Ps);CHKERRQ(ierr); 25661095bbSAlp Dener ierr = TaoALMMCombinePrimal_Private(tao, auglag->Px, auglag->Ps, auglag->P);CHKERRQ(ierr); 26661095bbSAlp Dener ierr = VecZeroEntries(auglag->Yi);CHKERRQ(ierr); 27661095bbSAlp Dener } 28661095bbSAlp Dener if (tao->eq_constrained) { 29661095bbSAlp Dener ierr = VecZeroEntries(auglag->Ye);CHKERRQ(ierr); 30661095bbSAlp Dener } 31661095bbSAlp Dener } 32661095bbSAlp Dener 33661095bbSAlp Dener /* compute initial nonlinear Lagrangian and its derivatives */ 34661095bbSAlp Dener ierr = (*auglag->sub_obj)(tao);CHKERRQ(ierr); 35661095bbSAlp Dener ierr = TaoALMMComputeOptimalityNorms_Private(tao);CHKERRQ(ierr); 36661095bbSAlp Dener /* print initial step and check convergence */ 37661095bbSAlp Dener ierr = PetscInfo1(tao,"Solving with %s formulation\n",TaoALMMTypes[auglag->type]);CHKERRQ(ierr); 38661095bbSAlp Dener ierr = TaoLogConvergenceHistory(tao, auglag->Lval, auglag->gnorm, auglag->cnorm, tao->ksp_its);CHKERRQ(ierr); 39661095bbSAlp Dener ierr = TaoMonitor(tao, tao->niter, auglag->fval, auglag->gnorm, auglag->cnorm, 0.0);CHKERRQ(ierr); 40661095bbSAlp Dener ierr = (*tao->ops->convergencetest)(tao, tao->cnvP);CHKERRQ(ierr); 41661095bbSAlp Dener /* set initial penalty factor and inner solver tolerance */ 42661095bbSAlp Dener switch (auglag->type) { 43661095bbSAlp Dener case (TAO_ALMM_CLASSIC): 44661095bbSAlp Dener auglag->mu = auglag->mu0; 45661095bbSAlp Dener break; 46661095bbSAlp Dener case (TAO_ALMM_PHR): 47661095bbSAlp Dener auglag->cenorm = 0.0; 48661095bbSAlp Dener if (tao->eq_constrained) { 49661095bbSAlp Dener ierr = VecDot(auglag->Ce, auglag->Ce, &auglag->cenorm);CHKERRQ(ierr); 50661095bbSAlp Dener } 51661095bbSAlp Dener auglag->cinorm = 0.0; 52661095bbSAlp Dener if (tao->ineq_constrained) { 53661095bbSAlp Dener ierr = VecCopy(auglag->Ci, auglag->Ciwork);CHKERRQ(ierr); 54661095bbSAlp Dener ierr = VecScale(auglag->Ciwork, -1.0);CHKERRQ(ierr); 55661095bbSAlp Dener ierr = VecPointwiseMax(auglag->Ciwork, auglag->Cizero, auglag->Ciwork);CHKERRQ(ierr); 56661095bbSAlp Dener ierr = VecDot(auglag->Ciwork, auglag->Ciwork, &auglag->cinorm);CHKERRQ(ierr); 57661095bbSAlp Dener } 58661095bbSAlp Dener /* determine initial penalty factor based on the balance of constraint violation and objective function value */ 59661095bbSAlp Dener auglag->mu = PetscMax(1.e-6, PetscMin(10.0, 2.0*PetscAbsReal(auglag->fval)/(auglag->cenorm + auglag->cinorm))); 60661095bbSAlp Dener break; 61661095bbSAlp Dener default: 62661095bbSAlp Dener break; 63661095bbSAlp Dener } 64661095bbSAlp Dener auglag->gtol = auglag->gtol0; 65661095bbSAlp Dener ierr = PetscInfo1(tao,"Initial penalty: %.2f\n",auglag->mu);CHKERRQ(ierr); 66661095bbSAlp Dener 67661095bbSAlp Dener /* start aug-lag outer loop */ 68661095bbSAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 69661095bbSAlp Dener ++tao->niter; 70661095bbSAlp Dener /* update subsolver tolerance */ 71661095bbSAlp Dener ierr = PetscInfo1(tao,"Subsolver tolerance: ||G|| <= %e\n",auglag->gtol);CHKERRQ(ierr); 72661095bbSAlp Dener ierr = TaoSetTolerances(auglag->subsolver, auglag->gtol, 0.0, 0.0);CHKERRQ(ierr); 73661095bbSAlp Dener /* solve the bound-constrained or unconstrained subproblem */ 74661095bbSAlp Dener ierr = TaoSolve(auglag->subsolver);CHKERRQ(ierr); 75661095bbSAlp Dener ierr = TaoGetConvergedReason(auglag->subsolver, &reason);CHKERRQ(ierr); 76661095bbSAlp Dener tao->ksp_its += auglag->subsolver->ksp_its; 77661095bbSAlp Dener if (reason != TAO_CONVERGED_GATOL) { 78661095bbSAlp Dener ierr = PetscInfo1(tao,"Subsolver failed to converge, reason: %s\n",TaoConvergedReasons[reason]);CHKERRQ(ierr); 79661095bbSAlp Dener } 80661095bbSAlp Dener /* evaluate solution and test convergence */ 81661095bbSAlp Dener ierr = (*auglag->sub_obj)(tao);CHKERRQ(ierr); 82661095bbSAlp Dener ierr = TaoALMMComputeOptimalityNorms_Private(tao);CHKERRQ(ierr); 83661095bbSAlp Dener /* decide whether to update multipliers or not */ 84661095bbSAlp Dener updated = 0.0; 85661095bbSAlp Dener if (auglag->cnorm <= auglag->ytol) { 86661095bbSAlp Dener ierr = PetscInfo1(tao,"Multipliers updated: ||C|| <= %e\n",auglag->ytol);CHKERRQ(ierr); 87661095bbSAlp Dener /* constraints are good, update multipliers and convergence tolerances */ 88661095bbSAlp Dener if (tao->eq_constrained) { 89661095bbSAlp Dener ierr = VecAXPY(auglag->Ye, auglag->mu, auglag->Ce);CHKERRQ(ierr); 90661095bbSAlp Dener ierr = VecSet(auglag->Cework, auglag->ye_max);CHKERRQ(ierr); 91661095bbSAlp Dener ierr = VecPointwiseMin(auglag->Ye, auglag->Cework, auglag->Ye);CHKERRQ(ierr); 92661095bbSAlp Dener ierr = VecSet(auglag->Cework, auglag->ye_min);CHKERRQ(ierr); 93661095bbSAlp Dener ierr = VecPointwiseMax(auglag->Ye, auglag->Cework, auglag->Ye);CHKERRQ(ierr); 94661095bbSAlp Dener } 95661095bbSAlp Dener if (tao->ineq_constrained) { 96661095bbSAlp Dener ierr = VecAXPY(auglag->Yi, auglag->mu, auglag->Ci);CHKERRQ(ierr); 97661095bbSAlp Dener ierr = VecSet(auglag->Ciwork, auglag->yi_max);CHKERRQ(ierr); 98661095bbSAlp Dener ierr = VecPointwiseMin(auglag->Yi, auglag->Ciwork, auglag->Yi);CHKERRQ(ierr); 99661095bbSAlp Dener ierr = VecSet(auglag->Ciwork, auglag->yi_min);CHKERRQ(ierr); 100661095bbSAlp Dener ierr = VecPointwiseMax(auglag->Yi, auglag->Ciwork, auglag->Yi);CHKERRQ(ierr); 101661095bbSAlp Dener } 102661095bbSAlp Dener /* tolerances are updated only for non-PHR methods */ 103661095bbSAlp Dener if (auglag->type != TAO_ALMM_PHR) { 104661095bbSAlp Dener auglag->ytol = PetscMax(tao->catol, auglag->ytol/PetscPowReal(auglag->mu, auglag->mu_pow_good)); 105661095bbSAlp Dener auglag->gtol = PetscMax(tao->gatol, auglag->gtol/auglag->mu); 106661095bbSAlp Dener } 107661095bbSAlp Dener updated = 1.0; 108661095bbSAlp Dener } else { 109661095bbSAlp Dener /* constraints are bad, update penalty factor */ 110661095bbSAlp Dener auglag->mu = PetscMin(auglag->mu_max, auglag->mu_fac*auglag->mu); 111661095bbSAlp Dener /* tolerances are reset only for non-PHR methods */ 112661095bbSAlp Dener if (auglag->type != TAO_ALMM_PHR) { 113661095bbSAlp Dener auglag->ytol = PetscMax(tao->catol, 0.1/PetscPowReal(auglag->mu, auglag->mu_pow_bad)); 114661095bbSAlp Dener auglag->gtol = PetscMax(tao->gatol, 1.0/auglag->mu); 115661095bbSAlp Dener } 116661095bbSAlp Dener ierr = PetscInfo1(tao,"Penalty increased: mu = %.2f\n",auglag->mu);CHKERRQ(ierr); 117661095bbSAlp Dener } 118661095bbSAlp Dener ierr = TaoLogConvergenceHistory(tao, auglag->fval, auglag->gnorm, auglag->cnorm, tao->ksp_its);CHKERRQ(ierr); 119661095bbSAlp Dener ierr = TaoMonitor(tao, tao->niter, auglag->fval, auglag->gnorm, auglag->cnorm, updated);CHKERRQ(ierr); 120661095bbSAlp Dener ierr = (*tao->ops->convergencetest)(tao, tao->cnvP);CHKERRQ(ierr); 121661095bbSAlp Dener } 122661095bbSAlp Dener 123661095bbSAlp Dener PetscFunctionReturn(0); 124661095bbSAlp Dener } 125661095bbSAlp Dener 126661095bbSAlp Dener static PetscErrorCode TaoView_ALMM(Tao tao,PetscViewer viewer) 127661095bbSAlp Dener { 128661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 129661095bbSAlp Dener PetscBool isascii; 130661095bbSAlp Dener PetscErrorCode ierr; 131661095bbSAlp Dener 132661095bbSAlp Dener PetscFunctionBegin; 133661095bbSAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 134661095bbSAlp Dener ierr = TaoView(auglag->subsolver,viewer);CHKERRQ(ierr); 135661095bbSAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 136661095bbSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 137661095bbSAlp Dener if (isascii) { 138661095bbSAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 139661095bbSAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "ALMM Formulation Type: %s\n", TaoALMMTypes[auglag->type]);CHKERRQ(ierr); 140661095bbSAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 141661095bbSAlp Dener } 142661095bbSAlp Dener PetscFunctionReturn(0); 143661095bbSAlp Dener } 144661095bbSAlp Dener 145661095bbSAlp Dener static PetscErrorCode TaoSetUp_ALMM(Tao tao) 146661095bbSAlp Dener { 147661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 148661095bbSAlp Dener VecType vec_type; 149661095bbSAlp Dener Vec SL, SU; 150661095bbSAlp Dener PetscBool is_cg = PETSC_FALSE, is_lmvm = PETSC_FALSE; 151661095bbSAlp Dener PetscErrorCode ierr; 152661095bbSAlp Dener 153661095bbSAlp Dener PetscFunctionBegin; 154661095bbSAlp Dener if (tao->ineq_doublesided) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TAOALMM does not support double-sided inequality constraint definition. Please restructure your inequality constrainst to fit the form c(x) >= 0."); 155661095bbSAlp Dener if (!tao->eq_constrained && !tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "Equality and/or inequality constraints must be defined before solver setup."); 156661095bbSAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 157661095bbSAlp Dener /* alias base vectors and create extras */ 158661095bbSAlp Dener ierr = VecGetType(tao->solution, &vec_type);CHKERRQ(ierr); 159661095bbSAlp Dener auglag->Px = tao->solution; 160661095bbSAlp Dener if (!tao->gradient) { /* base gradient */ 161661095bbSAlp Dener ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr); 162661095bbSAlp Dener } 163661095bbSAlp Dener auglag->LgradX = tao->gradient; 164661095bbSAlp Dener if (!auglag->Xwork) { /* opt var work vector */ 165661095bbSAlp Dener ierr = VecDuplicate(tao->solution, &auglag->Xwork);CHKERRQ(ierr); 166661095bbSAlp Dener } 167661095bbSAlp Dener if (tao->eq_constrained) { 168661095bbSAlp Dener auglag->Ce = tao->constraints_equality; 169661095bbSAlp Dener auglag->Ae = tao->jacobian_equality; 170661095bbSAlp Dener if (!auglag->Ye) { /* equality multipliers */ 171661095bbSAlp Dener ierr = VecDuplicate(auglag->Ce, &auglag->Ye);CHKERRQ(ierr); 172661095bbSAlp Dener } 173661095bbSAlp Dener if (!auglag->Cework) { 174661095bbSAlp Dener ierr = VecDuplicate(auglag->Ce, &auglag->Cework);CHKERRQ(ierr); 175661095bbSAlp Dener } 176661095bbSAlp Dener } 177661095bbSAlp Dener if (tao->ineq_constrained) { 178661095bbSAlp Dener auglag->Ci = tao->constraints_inequality; 179661095bbSAlp Dener auglag->Ai = tao->jacobian_inequality; 180661095bbSAlp Dener if (!auglag->Yi) { /* inequality multipliers */ 181661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &auglag->Yi);CHKERRQ(ierr); 182661095bbSAlp Dener } 183661095bbSAlp Dener if (!auglag->Ciwork) { 184661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &auglag->Ciwork);CHKERRQ(ierr); 185661095bbSAlp Dener } 186661095bbSAlp Dener if (!auglag->Cizero) { 187661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &auglag->Cizero);CHKERRQ(ierr); 188661095bbSAlp Dener ierr = VecZeroEntries(auglag->Cizero);CHKERRQ(ierr); 189661095bbSAlp Dener } 190661095bbSAlp Dener if (!auglag->Ps) { /* slack vars */ 191661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &auglag->Ps);CHKERRQ(ierr); 192661095bbSAlp Dener } 193661095bbSAlp Dener if (!auglag->LgradS) { /* slack component of Lagrangian gradient */ 194661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &auglag->LgradS);CHKERRQ(ierr); 195661095bbSAlp Dener } 196661095bbSAlp Dener /* create vector for combined primal space and the associated communication objects */ 197661095bbSAlp Dener if (!auglag->P) { 198661095bbSAlp Dener ierr = PetscMalloc1(2, &auglag->Parr);CHKERRQ(ierr); 199661095bbSAlp Dener auglag->Parr[0] = auglag->Px; auglag->Parr[1] = auglag->Ps; 200*1e1ea65dSPierre Jolivet ierr = VecConcatenate(2, auglag->Parr, &auglag->P, &auglag->Pis);CHKERRQ(ierr); 201661095bbSAlp Dener ierr = PetscMalloc1(2, &auglag->Pscatter);CHKERRQ(ierr); 202*1e1ea65dSPierre Jolivet ierr = VecScatterCreate(auglag->P, auglag->Pis[0], auglag->Px, NULL, &auglag->Pscatter[0]);CHKERRQ(ierr); 203*1e1ea65dSPierre Jolivet ierr = VecScatterCreate(auglag->P, auglag->Pis[1], auglag->Ps, NULL, &auglag->Pscatter[1]);CHKERRQ(ierr); 204661095bbSAlp Dener } 205661095bbSAlp Dener if (tao->eq_constrained) { 206661095bbSAlp Dener /* create vector for combined dual space and the associated communication objects */ 207661095bbSAlp Dener if (!auglag->Y) { 208661095bbSAlp Dener ierr = PetscMalloc1(2, &auglag->Yarr);CHKERRQ(ierr); 209661095bbSAlp Dener auglag->Yarr[0] = auglag->Ye; auglag->Yarr[1] = auglag->Yi; 210*1e1ea65dSPierre Jolivet ierr = VecConcatenate(2, auglag->Yarr, &auglag->Y, &auglag->Yis);CHKERRQ(ierr); 211661095bbSAlp Dener ierr = PetscMalloc1(2, &auglag->Yscatter);CHKERRQ(ierr); 212*1e1ea65dSPierre Jolivet ierr = VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);CHKERRQ(ierr); 213*1e1ea65dSPierre Jolivet ierr = VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);CHKERRQ(ierr); 214661095bbSAlp Dener } 215661095bbSAlp Dener if (!auglag->C) { 216661095bbSAlp Dener ierr = VecDuplicate(auglag->Y, &auglag->C);CHKERRQ(ierr); 217661095bbSAlp Dener } 218661095bbSAlp Dener } else { 219661095bbSAlp Dener if (!auglag->C) { 220661095bbSAlp Dener auglag->C = auglag->Ci; 221661095bbSAlp Dener } 222661095bbSAlp Dener if (!auglag->Y) { 223661095bbSAlp Dener auglag->Y = auglag->Yi; 224661095bbSAlp Dener } 225661095bbSAlp Dener } 226661095bbSAlp Dener } else { 227661095bbSAlp Dener if (!auglag->P) { 228661095bbSAlp Dener auglag->P = auglag->Px; 229661095bbSAlp Dener } 230661095bbSAlp Dener if (!auglag->G) { 231661095bbSAlp Dener auglag->G = auglag->LgradX; 232661095bbSAlp Dener } 233661095bbSAlp Dener if (!auglag->C) { 234661095bbSAlp Dener auglag->C = auglag->Ce; 235661095bbSAlp Dener } 236661095bbSAlp Dener if (!auglag->Y) { 237661095bbSAlp Dener auglag->Y = auglag->Ye; 238661095bbSAlp Dener } 239661095bbSAlp Dener } 240661095bbSAlp Dener /* initialize parameters */ 241661095bbSAlp Dener if (auglag->type == TAO_ALMM_PHR) { 242661095bbSAlp Dener auglag->mu_fac = 10.0; 243661095bbSAlp Dener auglag->yi_min = 0.0; 244661095bbSAlp Dener auglag->ytol0 = 0.5; 245661095bbSAlp Dener auglag->gtol0 = tao->gatol; 246661095bbSAlp Dener if (tao->gatol_changed && tao->catol_changed) { 247661095bbSAlp Dener ierr = PetscInfo(tao,"TAOALMM with PHR: different gradient and constraint tolerances are not supported, setting catol = gatol\n");CHKERRQ(ierr); 248661095bbSAlp Dener tao->catol = tao->gatol; 249661095bbSAlp Dener } 250661095bbSAlp Dener } 251661095bbSAlp Dener /* set the Lagrangian formulation type for the subsolver */ 252661095bbSAlp Dener switch (auglag->type) { 253661095bbSAlp Dener case (TAO_ALMM_CLASSIC): 254661095bbSAlp Dener auglag->sub_obj = TaoALMMComputeAugLagAndGradient_Private; 255661095bbSAlp Dener break; 256661095bbSAlp Dener case (TAO_ALMM_PHR): 257661095bbSAlp Dener auglag->sub_obj = TaoALMMComputePHRLagAndGradient_Private; 258661095bbSAlp Dener break; 259661095bbSAlp Dener default: 260661095bbSAlp Dener break; 261661095bbSAlp Dener } 262661095bbSAlp Dener /* set up the subsolver */ 263661095bbSAlp Dener ierr = TaoSetInitialVector(auglag->subsolver, auglag->P);CHKERRQ(ierr); 264661095bbSAlp Dener ierr = TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);CHKERRQ(ierr); 265661095bbSAlp Dener if (tao->bounded) { 266661095bbSAlp Dener /* make sure that the subsolver is a bound-constrained method */ 267661095bbSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)auglag->subsolver, TAOCG, &is_cg);CHKERRQ(ierr); 268661095bbSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)auglag->subsolver, TAOLMVM, &is_lmvm);CHKERRQ(ierr); 269661095bbSAlp Dener if (is_cg) { 270661095bbSAlp Dener ierr = TaoSetType(auglag->subsolver, TAOBNCG);CHKERRQ(ierr); 271661095bbSAlp Dener ierr = PetscInfo(tao,"TAOCG detected for bound-constrained problem, switching to TAOBNCG instead.");CHKERRQ(ierr); 272661095bbSAlp Dener } 273661095bbSAlp Dener if (is_lmvm) { 274661095bbSAlp Dener ierr = TaoSetType(auglag->subsolver, TAOBQNLS);CHKERRQ(ierr); 275661095bbSAlp Dener ierr = PetscInfo(tao,"TAOLMVM detected for bound-constrained problem, switching to TAOBQNLS instead.");CHKERRQ(ierr); 276661095bbSAlp Dener } 277661095bbSAlp Dener /* create lower and upper bound clone vectors for subsolver */ 278661095bbSAlp Dener if (!auglag->PL) { 279661095bbSAlp Dener ierr = VecDuplicate(auglag->P, &auglag->PL);CHKERRQ(ierr); 280661095bbSAlp Dener } 281661095bbSAlp Dener if (!auglag->PU) { 282661095bbSAlp Dener ierr = VecDuplicate(auglag->P, &auglag->PU);CHKERRQ(ierr); 283661095bbSAlp Dener } 284661095bbSAlp Dener if (tao->ineq_constrained) { 285661095bbSAlp Dener /* create lower and upper bounds for slack, set lower to 0 */ 286661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &SL);CHKERRQ(ierr); 287661095bbSAlp Dener ierr = VecSet(SL, 0.0);CHKERRQ(ierr); 288661095bbSAlp Dener ierr = VecDuplicate(auglag->Ci, &SU);CHKERRQ(ierr); 289661095bbSAlp Dener ierr = VecSet(SU, PETSC_INFINITY);CHKERRQ(ierr); 290661095bbSAlp Dener /* combine opt var bounds with slack bounds */ 291661095bbSAlp Dener ierr = TaoALMMCombinePrimal_Private(tao, tao->XL, SL, auglag->PL);CHKERRQ(ierr); 292661095bbSAlp Dener ierr = TaoALMMCombinePrimal_Private(tao, tao->XU, SU, auglag->PU);CHKERRQ(ierr); 293661095bbSAlp Dener /* destroy work vectors */ 294661095bbSAlp Dener ierr = VecDestroy(&SL);CHKERRQ(ierr); 295661095bbSAlp Dener ierr = VecDestroy(&SU);CHKERRQ(ierr); 296661095bbSAlp Dener } else { 297661095bbSAlp Dener /* no inequality constraints, just copy bounds into the subsolver */ 298661095bbSAlp Dener ierr = VecCopy(tao->XL, auglag->PL);CHKERRQ(ierr); 299661095bbSAlp Dener ierr = VecCopy(tao->XU, auglag->PU);CHKERRQ(ierr); 300661095bbSAlp Dener } 301661095bbSAlp Dener ierr = TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);CHKERRQ(ierr); 302661095bbSAlp Dener } 303661095bbSAlp Dener ierr = TaoSetUp(auglag->subsolver);CHKERRQ(ierr); 304661095bbSAlp Dener auglag->G = auglag->subsolver->gradient; 305661095bbSAlp Dener 306661095bbSAlp Dener PetscFunctionReturn(0); 307661095bbSAlp Dener } 308661095bbSAlp Dener 309661095bbSAlp Dener static PetscErrorCode TaoDestroy_ALMM(Tao tao) 310661095bbSAlp Dener { 311661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 312661095bbSAlp Dener PetscErrorCode ierr; 313661095bbSAlp Dener 314661095bbSAlp Dener PetscFunctionBegin; 315661095bbSAlp Dener ierr = TaoDestroy(&auglag->subsolver);CHKERRQ(ierr); 316661095bbSAlp Dener if (tao->setupcalled) { 317661095bbSAlp Dener ierr = VecDestroy(&auglag->Xwork);CHKERRQ(ierr); /* opt work */ 318661095bbSAlp Dener if (tao->eq_constrained) { 319661095bbSAlp Dener ierr = VecDestroy(&auglag->Ye);CHKERRQ(ierr); /* equality multipliers */ 320661095bbSAlp Dener ierr = VecDestroy(&auglag->Cework);CHKERRQ(ierr); /* equality work vector */ 321661095bbSAlp Dener } 322661095bbSAlp Dener if (tao->ineq_constrained) { 323661095bbSAlp Dener ierr = VecDestroy(&auglag->Ps);CHKERRQ(ierr); /* slack vars */ 324661095bbSAlp Dener auglag->Parr[0] = NULL; /* clear pointer to tao->solution, will be destroyed by TaoDestroy() shell */ 325661095bbSAlp Dener ierr = PetscFree(auglag->Parr);CHKERRQ(ierr); /* array of primal vectors */ 326661095bbSAlp Dener ierr = VecDestroy(&auglag->LgradS);CHKERRQ(ierr); /* slack grad */ 327661095bbSAlp Dener ierr = VecDestroy(&auglag->Cizero);CHKERRQ(ierr); /* zero vector for pointwise max */ 328661095bbSAlp Dener ierr = VecDestroy(&auglag->Yi);CHKERRQ(ierr); /* inequality multipliers */ 329661095bbSAlp Dener ierr = VecDestroy(&auglag->Ciwork);CHKERRQ(ierr); /* inequality work vector */ 330661095bbSAlp Dener ierr = VecDestroy(&auglag->P);CHKERRQ(ierr); /* combo primal */ 331661095bbSAlp Dener ierr = ISDestroy(&auglag->Pis[0]);CHKERRQ(ierr); /* index set for X inside P */ 332661095bbSAlp Dener ierr = ISDestroy(&auglag->Pis[1]);CHKERRQ(ierr); /* index set for S inside P */ 333661095bbSAlp Dener ierr = PetscFree(auglag->Pis);CHKERRQ(ierr); /* array of P index sets */ 334661095bbSAlp Dener ierr = VecScatterDestroy(&auglag->Pscatter[0]);CHKERRQ(ierr); 335661095bbSAlp Dener ierr = VecScatterDestroy(&auglag->Pscatter[1]);CHKERRQ(ierr); 336661095bbSAlp Dener ierr = PetscFree(auglag->Pscatter);CHKERRQ(ierr); 337661095bbSAlp Dener if (tao->eq_constrained) { 338661095bbSAlp Dener ierr = VecDestroy(&auglag->Y);CHKERRQ(ierr); /* combo multipliers */ 339661095bbSAlp Dener ierr = PetscFree(auglag->Yarr);CHKERRQ(ierr); /* array of dual vectors */ 340661095bbSAlp Dener ierr = VecDestroy(&auglag->C);CHKERRQ(ierr); /* combo constraints */ 341661095bbSAlp Dener ierr = ISDestroy(&auglag->Yis[0]);CHKERRQ(ierr); /* index set for Ye inside Y */ 342661095bbSAlp Dener ierr = ISDestroy(&auglag->Yis[1]);CHKERRQ(ierr); /* index set for Yi inside Y */ 343661095bbSAlp Dener ierr = PetscFree(auglag->Yis);CHKERRQ(ierr); 344661095bbSAlp Dener ierr = VecScatterDestroy(&auglag->Yscatter[0]);CHKERRQ(ierr); 345661095bbSAlp Dener ierr = VecScatterDestroy(&auglag->Yscatter[1]);CHKERRQ(ierr); 346661095bbSAlp Dener ierr = PetscFree(auglag->Yscatter);CHKERRQ(ierr); 347661095bbSAlp Dener } 348661095bbSAlp Dener } 349661095bbSAlp Dener if (tao->bounded) { 350661095bbSAlp Dener ierr = VecDestroy(&auglag->PL);CHKERRQ(ierr); /* lower bounds for subsolver */ 351661095bbSAlp Dener ierr = VecDestroy(&auglag->PU);CHKERRQ(ierr); /* upper bounds for subsolver */ 352661095bbSAlp Dener } 353661095bbSAlp Dener } 354661095bbSAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 355661095bbSAlp Dener PetscFunctionReturn(0); 356661095bbSAlp Dener } 357661095bbSAlp Dener 358661095bbSAlp Dener static PetscErrorCode TaoSetFromOptions_ALMM(PetscOptionItems *PetscOptionsObject,Tao tao) 359661095bbSAlp Dener { 360661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 361661095bbSAlp Dener PetscInt i; 362661095bbSAlp Dener PetscBool compatible; 363661095bbSAlp Dener PetscErrorCode ierr; 364661095bbSAlp Dener 365661095bbSAlp Dener PetscFunctionBegin; 366661095bbSAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Augmented Lagrangian multipler method solves problems with general constraints by converting them into a sequence of unconstrained problems.");CHKERRQ(ierr); 367661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_mu_init","initial penalty parameter","",auglag->mu0,&auglag->mu0,NULL);CHKERRQ(ierr); 368661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_mu_factor","increase factor for the penalty parameter","",auglag->mu_fac,&auglag->mu_fac,NULL);CHKERRQ(ierr); 369661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_mu_power_good","exponential for penalty parameter when multiplier update is accepted","",auglag->mu_pow_good,&auglag->mu_pow_good,NULL);CHKERRQ(ierr); 370661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_mu_power_bad","exponential for penalty parameter when multiplier update is rejected","",auglag->mu_pow_bad,&auglag->mu_pow_bad,NULL);CHKERRQ(ierr); 371661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_mu_max","maximum safeguard for penalty parameter updates","",auglag->mu_max,&auglag->mu_max,NULL);CHKERRQ(ierr); 372661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_ye_min","minimum safeguard for equality multiplier updates","",auglag->ye_min,&auglag->ye_min,NULL);CHKERRQ(ierr); 373661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_ye_max","maximum safeguard for equality multipliers updates","",auglag->ye_max,&auglag->ye_max,NULL);CHKERRQ(ierr); 374661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_yi_min","minimum safeguard for inequality multipliers updates","",auglag->yi_min,&auglag->yi_min,NULL);CHKERRQ(ierr); 375661095bbSAlp Dener ierr = PetscOptionsReal("-tao_almm_yi_max","maximum safeguard for inequality multipliers updates","",auglag->yi_max,&auglag->yi_max,NULL);CHKERRQ(ierr); 376661095bbSAlp Dener ierr = PetscOptionsEnum("-tao_almm_type","augmented Lagrangian formulation type for the subproblem","TaoALMMType",TaoALMMTypes,(PetscEnum)auglag->type,(PetscEnum*)&auglag->type,NULL);CHKERRQ(ierr); 377661095bbSAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 378661095bbSAlp Dener ierr = TaoSetFromOptions(auglag->subsolver);CHKERRQ(ierr); 379661095bbSAlp Dener ierr = PetscObjectTypeCompareAny((PetscObject)(auglag->subsolver), &compatible, TAOCG, TAOLMVM, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");CHKERRQ(ierr); 380661095bbSAlp Dener if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a first-order method (TAOCG, TABNCG, TAOLMVM, TAOBQN-family"); 381661095bbSAlp Dener for (i=0; i<tao->numbermonitors; i++) { 382661095bbSAlp Dener ierr = PetscObjectReference((PetscObject)tao->monitorcontext[i]);CHKERRQ(ierr); 383661095bbSAlp Dener ierr = TaoSetMonitor(auglag->subsolver, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr); 384661095bbSAlp Dener if (tao->monitor[i] == TaoMonitorDefault || tao->monitor[i] == TaoDefaultCMonitor || tao->monitor[i] == TaoDefaultGMonitor || tao->monitor[i] == TaoDefaultSMonitor) { 385661095bbSAlp Dener auglag->info = PETSC_TRUE; 386661095bbSAlp Dener } 387661095bbSAlp Dener } 388661095bbSAlp Dener PetscFunctionReturn(0); 389661095bbSAlp Dener } 390661095bbSAlp Dener 391661095bbSAlp Dener /* -------------------------------------------------------- */ 392661095bbSAlp Dener 393661095bbSAlp Dener /*MC 394661095bbSAlp Dener TaoALMM - Augmented Lagrangian multiplier method for solving nonlinear optimization problems with general constraints. 395661095bbSAlp Dener 396661095bbSAlp Dener Options Database Keys: 397661095bbSAlp Dener + -tao_almm_mu_init <real> - initial penalty parameter (default: 10.) 398661095bbSAlp Dener . -tao_almm_mu_factor <real> - increase factor for the penalty parameter (default: 100.) 399661095bbSAlp Dener . -tao_almm_mu_max <real> - maximum safeguard for penalty parameter updates (default: 1.e20) 400661095bbSAlp Dener . -tao_almm_mu_power_good <real> - exponential for penalty parameter when multiplier update is accepted (default: 0.9) 401661095bbSAlp Dener . -tao_almm_mu_power_bad <real> - exponential for penalty parameter when multiplier update is rejected (default: 0.1) 402661095bbSAlp Dener . -tao_almm_ye_min <real> - minimum safeguard for equality multiplier updates (default: -1.e20) 403661095bbSAlp Dener . -tao_almm_ye_max <real> - maximum safeguard for equality multiplier updates (default: 1.e20) 404661095bbSAlp Dener . -tao_almm_yi_min <real> - minimum safeguard for inequality multiplier updates (default: -1.e20) 405661095bbSAlp Dener . -tao_almm_yi_max <real> - maximum safeguard for inequality multiplier updates (default: 1.e20) 406661095bbSAlp Dener - -tao_almm_type <classic,phr> - change formulation of the augmented Lagrangian merit function for the subproblem (default: classic) 407661095bbSAlp Dener 408661095bbSAlp Dener Level: beginner 409661095bbSAlp Dener 410661095bbSAlp Dener Notes: 411661095bbSAlp Dener This method converts a constrained problem into a sequence of unconstrained problems via the augmented 412661095bbSAlp Dener Lagrangian merit function. Bound constraints are pushed down to the subproblem without any modifications. 413661095bbSAlp Dener 414661095bbSAlp Dener Two formulations are offered for the subproblem: canonical Hestenes-Powell augmented Lagrangian with slack 415661095bbSAlp Dener variables for inequality constraints, and a slack-less Powell-Hestenes-Rockafellar (PHR) formulation utilizing a 416661095bbSAlp Dener pointwise max() penalty on inequality constraints. The canonical augmented Lagrangian formulation typically 417661095bbSAlp Dener converges faster for most problems. However, PHR may be desirable for problems featuring a large number 418661095bbSAlp Dener of inequality constraints because it avoids inflating the size of the subproblem with slack variables. 419661095bbSAlp Dener 420661095bbSAlp Dener The subproblem is solved using a nested first-order TAO solver. The user can retrieve a pointer to 421661095bbSAlp Dener the subsolver via TaoALMMGetSubsolver() or pass command line arguments to it using the 422661095bbSAlp Dener "-tao_almm_subsolver_" prefix. Currently, TaoALMM does not support second-order methods for the 423661095bbSAlp Dener subproblem. It is also highly recommended that the subsolver chosen by the user utilize a trust-region 424661095bbSAlp Dener strategy for globalization (default: TAOBQNKTR) especially if the outer problem features bound constraints. 425661095bbSAlp Dener 426661095bbSAlp Dener .vb 427661095bbSAlp Dener while unconverged 428661095bbSAlp Dener solve argmin_x L(x) s.t. l <= x <= u 429661095bbSAlp Dener if ||c|| <= y_tol 430661095bbSAlp Dener if ||c|| <= c_tol && ||Lgrad|| <= g_tol: 431661095bbSAlp Dener problem converged, return solution 432661095bbSAlp Dener else 433661095bbSAlp Dener constraints sufficiently improved 434661095bbSAlp Dener update multipliers and tighten tolerances 435661095bbSAlp Dener endif 436661095bbSAlp Dener else 437661095bbSAlp Dener constraints did not improve 438661095bbSAlp Dener update penalty and loosen tolerances 439661095bbSAlp Dener endif 440661095bbSAlp Dener endwhile 441661095bbSAlp Dener .ve 442661095bbSAlp Dener 443661095bbSAlp Dener .seealso: TaoALMMGetType(), TaoALMMSetType(), TaoALMMSetSubsolver(), TaoALMMGetSubsolver(), 444661095bbSAlp Dener TaoALMMGetMultipliers(), TaoALMMSetMultipliers(), TaoALMMGetPrimalIS(), TaoALMMGetDualIS() 445661095bbSAlp Dener M*/ 446661095bbSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_ALMM(Tao tao) 447661095bbSAlp Dener { 448661095bbSAlp Dener TAO_ALMM *auglag; 449661095bbSAlp Dener PetscErrorCode ierr; 450661095bbSAlp Dener 451661095bbSAlp Dener PetscFunctionBegin; 452661095bbSAlp Dener ierr = PetscNewLog(tao, &auglag);CHKERRQ(ierr); 453661095bbSAlp Dener 454661095bbSAlp Dener tao->ops->destroy = TaoDestroy_ALMM; 455661095bbSAlp Dener tao->ops->setup = TaoSetUp_ALMM; 456661095bbSAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_ALMM; 457661095bbSAlp Dener tao->ops->view = TaoView_ALMM; 458661095bbSAlp Dener tao->ops->solve = TaoSolve_ALMM; 459661095bbSAlp Dener 460661095bbSAlp Dener tao->gatol = 1.e-5; 461661095bbSAlp Dener tao->grtol = 0.0; 462661095bbSAlp Dener tao->gttol = 0.0; 463661095bbSAlp Dener tao->catol = 1.e-5; 464661095bbSAlp Dener tao->crtol = 0.0; 465661095bbSAlp Dener 466661095bbSAlp Dener tao->data = (void*)auglag; 467661095bbSAlp Dener auglag->parent = tao; 468661095bbSAlp Dener auglag->mu0 = 10.0; 469661095bbSAlp Dener auglag->mu = auglag->mu0; 470661095bbSAlp Dener auglag->mu_fac = 10.0; 471661095bbSAlp Dener auglag->mu_max = PETSC_INFINITY; 472661095bbSAlp Dener auglag->mu_pow_good = 0.9; 473661095bbSAlp Dener auglag->mu_pow_bad = 0.1; 474661095bbSAlp Dener auglag->ye_min = PETSC_NINFINITY; 475661095bbSAlp Dener auglag->ye_max = PETSC_INFINITY; 476661095bbSAlp Dener auglag->yi_min = PETSC_NINFINITY; 477661095bbSAlp Dener auglag->yi_max = PETSC_INFINITY; 478661095bbSAlp Dener auglag->ytol0 = 0.1/PetscPowReal(auglag->mu0, auglag->mu_pow_bad); 479661095bbSAlp Dener auglag->ytol = auglag->ytol0; 480661095bbSAlp Dener auglag->gtol0 = 1.0/auglag->mu0; 481661095bbSAlp Dener auglag->gtol = auglag->gtol0; 482661095bbSAlp Dener 483661095bbSAlp Dener auglag->sub_obj = TaoALMMComputeAugLagAndGradient_Private; 484661095bbSAlp Dener auglag->type = TAO_ALMM_CLASSIC; 485661095bbSAlp Dener auglag->info = PETSC_FALSE; 486661095bbSAlp Dener 487661095bbSAlp Dener ierr = TaoCreate(PetscObjectComm((PetscObject)tao),&auglag->subsolver);CHKERRQ(ierr); 488661095bbSAlp Dener ierr = TaoSetType(auglag->subsolver, TAOBQNKTR);CHKERRQ(ierr); 489661095bbSAlp Dener ierr = TaoSetTolerances(auglag->subsolver, auglag->gtol, 0.0, 0.0);CHKERRQ(ierr); 490661095bbSAlp Dener ierr = TaoSetMaximumIterations(auglag->subsolver, 1000);CHKERRQ(ierr); 491661095bbSAlp Dener ierr = TaoSetMaximumFunctionEvaluations(auglag->subsolver, 10000);CHKERRQ(ierr); 492661095bbSAlp Dener ierr = TaoSetFunctionLowerBound(auglag->subsolver, PETSC_NINFINITY);CHKERRQ(ierr); 493661095bbSAlp Dener ierr = TaoSetOptionsPrefix(auglag->subsolver,"tao_almm_subsolver_");CHKERRQ(ierr); 494661095bbSAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)auglag->subsolver,(PetscObject)tao,1);CHKERRQ(ierr); 495661095bbSAlp Dener 496661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetType_C", TaoALMMGetType_Private);CHKERRQ(ierr); 497661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetType_C", TaoALMMSetType_Private);CHKERRQ(ierr); 498661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetSubsolver_C", TaoALMMGetSubsolver_Private);CHKERRQ(ierr); 499661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetSubsolver_C", TaoALMMSetSubsolver_Private);CHKERRQ(ierr); 500661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetMultipliers_C", TaoALMMGetMultipliers_Private);CHKERRQ(ierr); 501661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetMultipliers_C", TaoALMMSetMultipliers_Private);CHKERRQ(ierr); 502661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetPrimalIS_C", TaoALMMGetPrimalIS_Private);CHKERRQ(ierr); 503661095bbSAlp Dener ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetDualIS_C", TaoALMMGetDualIS_Private);CHKERRQ(ierr); 504661095bbSAlp Dener PetscFunctionReturn(0); 505661095bbSAlp Dener } 506661095bbSAlp Dener 507661095bbSAlp Dener static PetscErrorCode TaoALMMCombinePrimal_Private(Tao tao, Vec X, Vec S, Vec P) 508661095bbSAlp Dener { 509661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 510661095bbSAlp Dener PetscErrorCode ierr; 511661095bbSAlp Dener 512661095bbSAlp Dener PetscFunctionBegin; 513661095bbSAlp Dener if (tao->ineq_constrained) { 514661095bbSAlp Dener ierr = VecScatterBegin(auglag->Pscatter[0], X, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 515661095bbSAlp Dener ierr = VecScatterEnd(auglag->Pscatter[0], X, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 516661095bbSAlp Dener ierr = VecScatterBegin(auglag->Pscatter[1], S, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 517661095bbSAlp Dener ierr = VecScatterEnd(auglag->Pscatter[1], S, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 518661095bbSAlp Dener } else { 519661095bbSAlp Dener ierr = VecCopy(X, P);CHKERRQ(ierr); 520661095bbSAlp Dener } 521661095bbSAlp Dener PetscFunctionReturn(0); 522661095bbSAlp Dener } 523661095bbSAlp Dener 524661095bbSAlp Dener static PetscErrorCode TaoALMMCombineDual_Private(Tao tao, Vec EQ, Vec IN, Vec Y) 525661095bbSAlp Dener { 526661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 527661095bbSAlp Dener PetscErrorCode ierr; 528661095bbSAlp Dener 529661095bbSAlp Dener PetscFunctionBegin; 530661095bbSAlp Dener if (tao->eq_constrained) { 531661095bbSAlp Dener if (tao->ineq_constrained) { 532661095bbSAlp Dener ierr = VecScatterBegin(auglag->Yscatter[0], EQ, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 533661095bbSAlp Dener ierr = VecScatterEnd(auglag->Yscatter[0], EQ, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 534661095bbSAlp Dener ierr = VecScatterBegin(auglag->Yscatter[1], IN, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 535661095bbSAlp Dener ierr = VecScatterEnd(auglag->Yscatter[1], IN, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 536661095bbSAlp Dener } else { 537661095bbSAlp Dener ierr = VecCopy(EQ, Y);CHKERRQ(ierr); 538661095bbSAlp Dener } 539661095bbSAlp Dener } else { 540661095bbSAlp Dener ierr = VecCopy(IN, Y);CHKERRQ(ierr); 541661095bbSAlp Dener } 542661095bbSAlp Dener PetscFunctionReturn(0); 543661095bbSAlp Dener } 544661095bbSAlp Dener 545661095bbSAlp Dener static PetscErrorCode TaoALMMSplitPrimal_Private(Tao tao, Vec P, Vec X, Vec S) 546661095bbSAlp Dener { 547661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 548661095bbSAlp Dener PetscErrorCode ierr; 549661095bbSAlp Dener 550661095bbSAlp Dener PetscFunctionBegin; 551661095bbSAlp Dener if (tao->ineq_constrained) { 552661095bbSAlp Dener ierr = VecScatterBegin(auglag->Pscatter[0], P, X, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 553661095bbSAlp Dener ierr = VecScatterEnd(auglag->Pscatter[0], P, X, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 554661095bbSAlp Dener ierr = VecScatterBegin(auglag->Pscatter[1], P, S, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 555661095bbSAlp Dener ierr = VecScatterEnd(auglag->Pscatter[1], P, S, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 556661095bbSAlp Dener } else { 557661095bbSAlp Dener ierr = VecCopy(P, X);CHKERRQ(ierr); 558661095bbSAlp Dener } 559661095bbSAlp Dener PetscFunctionReturn(0); 560661095bbSAlp Dener } 561661095bbSAlp Dener 562661095bbSAlp Dener /* this assumes that the latest constraints are stored in Ce and Ci, and also combined in C */ 563661095bbSAlp Dener static PetscErrorCode TaoALMMComputeOptimalityNorms_Private(Tao tao) 564661095bbSAlp Dener { 565661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 566661095bbSAlp Dener PetscErrorCode ierr; 567661095bbSAlp Dener 568661095bbSAlp Dener PetscFunctionBegin; 569661095bbSAlp Dener /* if bounded, project the gradient */ 570661095bbSAlp Dener if (tao->bounded) { 571*1e1ea65dSPierre Jolivet ierr = VecBoundGradientProjection(auglag->LgradX, auglag->Px, tao->XL, tao->XU, auglag->LgradX);CHKERRQ(ierr); 572661095bbSAlp Dener } 573661095bbSAlp Dener if (auglag->type == TAO_ALMM_PHR) { 574661095bbSAlp Dener ierr = VecNorm(auglag->LgradX, NORM_INFINITY, &auglag->gnorm);CHKERRQ(ierr); 575661095bbSAlp Dener auglag->cenorm = 0.0; 576661095bbSAlp Dener if (tao->eq_constrained) { 577661095bbSAlp Dener ierr = VecNorm(auglag->Ce, NORM_INFINITY, &auglag->cenorm);CHKERRQ(ierr); 578661095bbSAlp Dener } 579661095bbSAlp Dener auglag->cinorm = 0.0; 580661095bbSAlp Dener if (tao->ineq_constrained) { 581661095bbSAlp Dener ierr = VecCopy(auglag->Yi, auglag->Ciwork);CHKERRQ(ierr); 582661095bbSAlp Dener ierr = VecScale(auglag->Ciwork, -1.0/auglag->mu);CHKERRQ(ierr); 583661095bbSAlp Dener ierr = VecPointwiseMax(auglag->Ciwork, auglag->Ci, auglag->Ciwork);CHKERRQ(ierr); 584661095bbSAlp Dener ierr = VecNorm(auglag->Ciwork, NORM_INFINITY, &auglag->cinorm);CHKERRQ(ierr); 585661095bbSAlp Dener } 586661095bbSAlp Dener auglag->cnorm_old = auglag->cnorm; 587661095bbSAlp Dener auglag->cnorm = PetscMax(auglag->cenorm, auglag->cinorm); 588661095bbSAlp Dener auglag->ytol = auglag->ytol0 * auglag->cnorm_old; 589661095bbSAlp Dener } else { 590661095bbSAlp Dener ierr = VecNorm(auglag->LgradX, NORM_2, &auglag->gnorm);CHKERRQ(ierr); 591661095bbSAlp Dener ierr = VecNorm(auglag->C, NORM_2, &auglag->cnorm);CHKERRQ(ierr); 592661095bbSAlp Dener } 593661095bbSAlp Dener PetscFunctionReturn(0); 594661095bbSAlp Dener } 595661095bbSAlp Dener 596661095bbSAlp Dener static PetscErrorCode TaoALMMEvaluateIterate_Private(Tao tao, Vec P) 597661095bbSAlp Dener { 598661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 599661095bbSAlp Dener PetscErrorCode ierr; 600661095bbSAlp Dener 601661095bbSAlp Dener PetscFunctionBegin; 602661095bbSAlp Dener /* split solution into primal and slack components */ 603661095bbSAlp Dener ierr = TaoALMMSplitPrimal_Private(tao, auglag->P, auglag->Px, auglag->Ps);CHKERRQ(ierr); 604661095bbSAlp Dener 605661095bbSAlp Dener /* compute f, df/dx and the constraints */ 606661095bbSAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, auglag->Px, &auglag->fval, auglag->LgradX);CHKERRQ(ierr); 607661095bbSAlp Dener if (tao->eq_constrained) { 608661095bbSAlp Dener ierr = TaoComputeEqualityConstraints(tao, auglag->Px, auglag->Ce);CHKERRQ(ierr); 609661095bbSAlp Dener ierr = TaoComputeJacobianEquality(tao, auglag->Px, auglag->Ae, auglag->Ae);CHKERRQ(ierr); 610661095bbSAlp Dener } 611661095bbSAlp Dener if (tao->ineq_constrained) { 612661095bbSAlp Dener ierr = TaoComputeInequalityConstraints(tao, auglag->Px, auglag->Ci);CHKERRQ(ierr); 613661095bbSAlp Dener ierr = TaoComputeJacobianInequality(tao, auglag->Px, auglag->Ai, auglag->Ai);CHKERRQ(ierr); 614661095bbSAlp Dener switch (auglag->type) { 615661095bbSAlp Dener case (TAO_ALMM_CLASSIC): 616661095bbSAlp Dener /* classic formulation converts inequality to equality constraints via slack variables */ 617661095bbSAlp Dener ierr = VecAXPY(auglag->Ci, -1.0, auglag->Ps);CHKERRQ(ierr); 618661095bbSAlp Dener break; 619661095bbSAlp Dener case (TAO_ALMM_PHR): 620661095bbSAlp Dener /* PHR is based on Ci <= 0 while TAO defines Ci >= 0 so we hit it with a negative sign */ 621661095bbSAlp Dener ierr = VecScale(auglag->Ci, -1.0);CHKERRQ(ierr); 622661095bbSAlp Dener ierr = MatScale(auglag->Ai, -1.0);CHKERRQ(ierr); 623661095bbSAlp Dener break; 624661095bbSAlp Dener default: 625661095bbSAlp Dener break; 626661095bbSAlp Dener } 627661095bbSAlp Dener } 628661095bbSAlp Dener /* combine constraints into one vector */ 629661095bbSAlp Dener ierr = TaoALMMCombineDual_Private(tao, auglag->Ce, auglag->Ci, auglag->C);CHKERRQ(ierr); 630661095bbSAlp Dener PetscFunctionReturn(0); 631661095bbSAlp Dener } 632661095bbSAlp Dener 633661095bbSAlp Dener /* 634661095bbSAlp Dener Lphr = f + 0.5*mu*[ (Ce + Ye/mu)^T (Ce + Ye/mu) + pmin(0, Ci + Yi/mu)^T pmin(0, Ci + Yi/mu)] 635661095bbSAlp Dener 636661095bbSAlp Dener dLphr/dX = dF/dX + mu*[ (Ce + Ye/mu)^T Ae + pmin(0, Ci + Yi/mu)^T Ai] 637661095bbSAlp Dener 638661095bbSAlp Dener dLphr/dS = 0 639661095bbSAlp Dener */ 640661095bbSAlp Dener static PetscErrorCode TaoALMMComputePHRLagAndGradient_Private(Tao tao) 641661095bbSAlp Dener { 642661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 643661095bbSAlp Dener PetscReal eq_norm=0.0, ineq_norm=0.0; 644661095bbSAlp Dener PetscErrorCode ierr; 645661095bbSAlp Dener 646661095bbSAlp Dener PetscFunctionBegin; 647661095bbSAlp Dener ierr = TaoALMMEvaluateIterate_Private(tao, auglag->P);CHKERRQ(ierr); 648661095bbSAlp Dener if (tao->eq_constrained) { 649661095bbSAlp Dener /* Ce_work = mu*(Ce + Ye/mu) */ 650661095bbSAlp Dener ierr = VecWAXPY(auglag->Cework, 1.0/auglag->mu, auglag->Ye, auglag->Ce);CHKERRQ(ierr); 651661095bbSAlp Dener ierr = VecDot(auglag->Cework, auglag->Cework, &eq_norm);CHKERRQ(ierr); /* contribution to scalar Lagrangian */ 652661095bbSAlp Dener ierr = VecScale(auglag->Cework, auglag->mu);CHKERRQ(ierr); 653661095bbSAlp Dener /* dL/dX += mu*(Ce + Ye/mu)^T Ae */ 654661095bbSAlp Dener ierr = MatMultTransposeAdd(auglag->Ae, auglag->Cework, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 655661095bbSAlp Dener } 656661095bbSAlp Dener if (tao->ineq_constrained) { 657661095bbSAlp Dener /* Ci_work = mu * pmax(0, Ci + Yi/mu) where pmax() is pointwise max() */ 658661095bbSAlp Dener ierr = VecWAXPY(auglag->Ciwork, 1.0/auglag->mu, auglag->Yi, auglag->Ci);CHKERRQ(ierr); 659661095bbSAlp Dener ierr = VecPointwiseMax(auglag->Ciwork, auglag->Cizero, auglag->Ciwork);CHKERRQ(ierr); 660661095bbSAlp Dener ierr = VecDot(auglag->Ciwork, auglag->Ciwork, &ineq_norm);CHKERRQ(ierr); /* contribution to scalar Lagrangian */ 661661095bbSAlp Dener /* dL/dX += mu * pmax(0, Ci + Yi/mu)^T Ai */ 662661095bbSAlp Dener ierr = VecScale(auglag->Ciwork, auglag->mu);CHKERRQ(ierr); 663661095bbSAlp Dener ierr = MatMultTransposeAdd(auglag->Ai, auglag->Ciwork, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 664661095bbSAlp Dener /* dL/dS = 0 becuase there are no slacks in PHR */ 665661095bbSAlp Dener ierr = VecZeroEntries(auglag->LgradS);CHKERRQ(ierr); 666661095bbSAlp Dener } 667661095bbSAlp Dener /* combine gradient together */ 668661095bbSAlp Dener ierr = TaoALMMCombinePrimal_Private(tao, auglag->LgradX, auglag->LgradS, auglag->G);CHKERRQ(ierr); 669661095bbSAlp Dener /* compute L = f + 0.5 * mu * [(Ce + Ye/mu)^T (Ce + Ye/mu) + pmax(0, Ci + Yi/mu)^T pmax(0, Ci + Yi/mu)] */ 670661095bbSAlp Dener auglag->Lval = auglag->fval + 0.5*auglag->mu*(eq_norm + ineq_norm);CHKERRQ(ierr); 671661095bbSAlp Dener PetscFunctionReturn(0); 672661095bbSAlp Dener } 673661095bbSAlp Dener 674661095bbSAlp Dener /* 675661095bbSAlp Dener Lc = F + Ye^TCe + Yi^T(Ci - S) + 0.5*mu*[Ce^TCe + (Ci - S)^T(Ci - S)] 676661095bbSAlp Dener 677661095bbSAlp Dener dLc/dX = dF/dX + Ye^TAe + Yi^TAi + 0.5*mu*[Ce^TAe + (Ci - S)^TAi] 678661095bbSAlp Dener 679661095bbSAlp Dener dLc/dS = -[Yi + mu*(Ci - S)] 680661095bbSAlp Dener */ 681661095bbSAlp Dener static PetscErrorCode TaoALMMComputeAugLagAndGradient_Private(Tao tao) 682661095bbSAlp Dener { 683661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 684661095bbSAlp Dener PetscReal yeTce=0.0, yiTcims=0.0, ceTce=0.0, cimsTcims=0.0; 685661095bbSAlp Dener PetscErrorCode ierr; 686661095bbSAlp Dener 687661095bbSAlp Dener PetscFunctionBegin; 688661095bbSAlp Dener ierr = TaoALMMEvaluateIterate_Private(tao, auglag->P);CHKERRQ(ierr); 689661095bbSAlp Dener if (tao->eq_constrained) { 690661095bbSAlp Dener /* compute scalar contributions */ 691661095bbSAlp Dener ierr = VecDot(auglag->Ye, auglag->Ce, &yeTce);CHKERRQ(ierr); 692661095bbSAlp Dener ierr = VecDot(auglag->Ce, auglag->Ce, &ceTce);CHKERRQ(ierr); 693661095bbSAlp Dener /* dL/dX += ye^T Ae */ 694661095bbSAlp Dener ierr = MatMultTransposeAdd(auglag->Ae, auglag->Ye, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 695661095bbSAlp Dener /* dL/dX += mu * ce^T Ae */ 696661095bbSAlp Dener ierr = MatMultTranspose(auglag->Ae, auglag->Ce, auglag->Xwork);CHKERRQ(ierr); 697661095bbSAlp Dener ierr = VecAXPY(auglag->LgradX, auglag->mu, auglag->Xwork);CHKERRQ(ierr); 698661095bbSAlp Dener } 699661095bbSAlp Dener if (tao->ineq_constrained) { 700661095bbSAlp Dener /* compute scalar contributions */ 701661095bbSAlp Dener ierr = VecDot(auglag->Yi, auglag->Ci, &yiTcims);CHKERRQ(ierr); 702661095bbSAlp Dener ierr = VecDot(auglag->Ci, auglag->Ci, &cimsTcims);CHKERRQ(ierr); 703661095bbSAlp Dener /* dL/dX += yi^T Ai */ 704661095bbSAlp Dener ierr = MatMultTransposeAdd(auglag->Ai, auglag->Yi, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 705661095bbSAlp Dener /* dL/dX += mu * (ci - s)^T Ai */ 706661095bbSAlp Dener ierr = MatMultTranspose(auglag->Ai, auglag->Ci, auglag->Xwork);CHKERRQ(ierr); 707661095bbSAlp Dener ierr = VecAXPY(auglag->LgradX, auglag->mu, auglag->Xwork);CHKERRQ(ierr); 708661095bbSAlp Dener /* dL/dS = -[yi + mu*(ci - s)] */ 709661095bbSAlp Dener ierr = VecWAXPY(auglag->LgradS, auglag->mu, auglag->Ci, auglag->Yi);CHKERRQ(ierr); 710661095bbSAlp Dener ierr = VecScale(auglag->LgradS, -1.0);CHKERRQ(ierr); 711661095bbSAlp Dener } 712661095bbSAlp Dener /* combine gradient together */ 713661095bbSAlp Dener ierr = TaoALMMCombinePrimal_Private(tao, auglag->LgradX, auglag->LgradS, auglag->G);CHKERRQ(ierr); 714661095bbSAlp Dener /* compute L = f + ye^T ce + yi^T (ci - s) + 0.5*mu*||ce||^2 + 0.5*mu*||ci - s||^2 */ 715661095bbSAlp Dener auglag->Lval = auglag->fval + yeTce + yiTcims + 0.5*auglag->mu*(ceTce + cimsTcims); 716661095bbSAlp Dener PetscFunctionReturn(0); 717661095bbSAlp Dener } 718661095bbSAlp Dener 719661095bbSAlp Dener PetscErrorCode TaoALMMSubsolverObjectiveAndGradient_Private(Tao tao, Vec P, PetscReal *Lval, Vec G, void *ctx) 720661095bbSAlp Dener { 721661095bbSAlp Dener TAO_ALMM *auglag = (TAO_ALMM*)ctx; 722661095bbSAlp Dener PetscErrorCode ierr; 723661095bbSAlp Dener 724661095bbSAlp Dener PetscFunctionBegin; 725661095bbSAlp Dener ierr = VecCopy(P, auglag->P);CHKERRQ(ierr); 726661095bbSAlp Dener ierr = (*auglag->sub_obj)(auglag->parent);CHKERRQ(ierr); 727661095bbSAlp Dener ierr = VecCopy(auglag->G, G);CHKERRQ(ierr); 728661095bbSAlp Dener *Lval = auglag->Lval; 729661095bbSAlp Dener PetscFunctionReturn(0); 730661095bbSAlp Dener } 731