1 #include <../src/tao/constrained/impls/admm/admm.h> /*I "petsctao.h" I*/ 2 #include <petsctao.h> 3 #include <petsc/private/petscimpl.h> 4 5 /* Updates terminating criteria 6 * 7 * 1 ||r_k|| = ||Ax+Bz-c|| =< catol_admm* max{||Ax||,||Bz||,||c||} 8 * 9 * 2. Updates dual residual, d_k 10 * 11 * 3. ||d_k|| = ||mu*A^T*B(z_k-z_{k-1})|| =< gatol_admm * ||A^Ty|| */ 12 13 static PetscBool cited = PETSC_FALSE; 14 static const char citation[] = 15 "@misc{xu2017adaptive,\n" 16 " title={Adaptive Relaxed ADMM: Convergence Theory and Practical Implementation},\n" 17 " author={Zheng Xu and Mario A. T. Figueiredo and Xiaoming Yuan and Christoph Studer and Tom Goldstein},\n" 18 " year={2017},\n" 19 " eprint={1704.02712},\n" 20 " archivePrefix={arXiv},\n" 21 " primaryClass={cs.CV}\n" 22 "} \n"; 23 24 static PetscErrorCode TaoADMMToleranceUpdate(Tao tao) 25 { 26 TAO_ADMM *am = (TAO_ADMM*)tao->data; 27 PetscErrorCode ierr; 28 PetscReal Axnorm,Bznorm,ATynorm,temp; 29 Vec tempJR,tempL; 30 Tao mis; 31 32 PetscFunctionBegin; 33 mis = am->subsolverX; 34 tempJR = am->workJacobianRight; 35 tempL = am->workLeft; 36 /* ATy */ 37 ierr = TaoComputeJacobianEquality(mis, am->y, mis->jacobian_equality, mis->jacobian_equality_pre);CHKERRQ(ierr); 38 ierr = MatMultTranspose(mis->jacobian_equality,am->y,tempJR);CHKERRQ(ierr); 39 ierr = VecNorm(tempJR,NORM_2,&ATynorm);CHKERRQ(ierr); 40 /* dualres = mu * ||AT(Bz-Bzold)||_2 */ 41 ierr = VecWAXPY(tempJR,-1.,am->Bzold,am->Bz);CHKERRQ(ierr); 42 ierr = MatMultTranspose(mis->jacobian_equality,tempJR,tempL);CHKERRQ(ierr); 43 ierr = VecNorm(tempL,NORM_2,&am->dualres);CHKERRQ(ierr); 44 am->dualres *= am->mu; 45 46 /* ||Ax||_2, ||Bz||_2 */ 47 ierr = VecNorm(am->Ax,NORM_2,&Axnorm);CHKERRQ(ierr); 48 ierr = VecNorm(am->Bz,NORM_2,&Bznorm);CHKERRQ(ierr); 49 50 /* Set catol to be catol_admm * max{||Ax||,||Bz||,||c||} * 51 * Set gatol to be gatol_admm * ||A^Ty|| * 52 * while cnorm is ||r_k||_2, and gnorm is ||d_k||_2 */ 53 temp = am->catol_admm * PetscMax(Axnorm, (!am->const_norm) ? Bznorm : PetscMax(Bznorm,am->const_norm)); 54 ierr = TaoSetConstraintTolerances(tao,temp,PETSC_DEFAULT);CHKERRQ(ierr); 55 ierr = TaoSetTolerances(tao, am->gatol_admm*ATynorm, PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 56 PetscFunctionReturn(0); 57 } 58 59 /* Penaly Update for Adaptive ADMM. */ 60 static PetscErrorCode AdaptiveADMMPenaltyUpdate(Tao tao) 61 { 62 TAO_ADMM *am = (TAO_ADMM*)tao->data; 63 PetscErrorCode ierr; 64 PetscReal ydiff_norm, yhatdiff_norm, Axdiff_norm, Bzdiff_norm, Axyhat, Bzy, a_sd, a_mg, a_k, b_sd, b_mg, b_k; 65 PetscBool hflag, gflag; 66 Vec tempJR,tempJR2; 67 68 PetscFunctionBegin; 69 tempJR = am->workJacobianRight; 70 tempJR2 = am->workJacobianRight2; 71 hflag = PETSC_FALSE; 72 gflag = PETSC_FALSE; 73 a_k = -1; 74 b_k = -1; 75 76 ierr = VecWAXPY(tempJR,-1.,am->Axold,am->Ax);CHKERRQ(ierr); 77 ierr = VecWAXPY(tempJR2,-1.,am->yhatold,am->yhat);CHKERRQ(ierr); 78 ierr = VecNorm(tempJR,NORM_2,&Axdiff_norm);CHKERRQ(ierr); 79 ierr = VecNorm(tempJR2,NORM_2,&yhatdiff_norm);CHKERRQ(ierr); 80 ierr = VecDot(tempJR,tempJR2,&Axyhat);CHKERRQ(ierr); 81 82 ierr = VecWAXPY(tempJR,-1.,am->Bz0,am->Bz);CHKERRQ(ierr); 83 ierr = VecWAXPY(tempJR2,-1.,am->y,am->y0);CHKERRQ(ierr); 84 ierr = VecNorm(tempJR,NORM_2,&Bzdiff_norm);CHKERRQ(ierr); 85 ierr = VecNorm(tempJR2,NORM_2,&ydiff_norm);CHKERRQ(ierr); 86 ierr = VecDot(tempJR,tempJR2,&Bzy);CHKERRQ(ierr); 87 88 if (Axyhat > am->orthval*Axdiff_norm*yhatdiff_norm + am->mueps) { 89 hflag = PETSC_TRUE; 90 a_sd = PetscSqr(yhatdiff_norm)/Axyhat; /* alphaSD */ 91 a_mg = Axyhat/PetscSqr(Axdiff_norm); /* alphaMG */ 92 a_k = (a_mg/a_sd) > 0.5 ? a_mg : a_sd - 0.5*a_mg; 93 } 94 if (Bzy > am->orthval*Bzdiff_norm*ydiff_norm + am->mueps) { 95 gflag = PETSC_TRUE; 96 b_sd = PetscSqr(ydiff_norm)/Bzy; /* betaSD */ 97 b_mg = Bzy/PetscSqr(Bzdiff_norm); /* betaMG */ 98 b_k = (b_mg/b_sd) > 0.5 ? b_mg : b_sd - 0.5*b_mg; 99 } 100 am->muold = am->mu; 101 if (gflag && hflag) { 102 am->mu = PetscSqrtReal(a_k*b_k); 103 } else if (hflag) { 104 am->mu = a_k; 105 } else if (gflag) { 106 am->mu = b_k; 107 } 108 if (am->mu > am->muold) { 109 am->mu = am->muold; 110 } 111 if (am->mu < am->mumin) { 112 am->mu = am->mumin; 113 } 114 PetscFunctionReturn(0); 115 } 116 117 static PetscErrorCode TaoADMMSetRegularizerType_ADMM(Tao tao, TaoADMMRegularizerType type) 118 { 119 TAO_ADMM *am = (TAO_ADMM*)tao->data; 120 121 PetscFunctionBegin; 122 am->regswitch = type; 123 PetscFunctionReturn(0); 124 } 125 126 static PetscErrorCode TaoADMMGetRegularizerType_ADMM(Tao tao, TaoADMMRegularizerType *type) 127 { 128 TAO_ADMM *am = (TAO_ADMM*)tao->data; 129 130 PetscFunctionBegin; 131 *type = am->regswitch; 132 PetscFunctionReturn(0); 133 } 134 135 static PetscErrorCode TaoADMMSetUpdateType_ADMM(Tao tao, TaoADMMUpdateType type) 136 { 137 TAO_ADMM *am = (TAO_ADMM*)tao->data; 138 139 PetscFunctionBegin; 140 am->update = type; 141 PetscFunctionReturn(0); 142 } 143 144 static PetscErrorCode TaoADMMGetUpdateType_ADMM(Tao tao, TaoADMMUpdateType *type) 145 { 146 TAO_ADMM *am = (TAO_ADMM*)tao->data; 147 148 PetscFunctionBegin; 149 *type = am->update; 150 PetscFunctionReturn(0); 151 } 152 153 /* This routine updates Jacobians with new x,z vectors, 154 * and then updates Ax and Bz vectors, then computes updated residual vector*/ 155 static PetscErrorCode ADMMUpdateConstraintResidualVector(Tao tao, Vec x, Vec z, Vec Ax, Vec Bz, Vec residual) 156 { 157 TAO_ADMM *am = (TAO_ADMM*)tao->data; 158 Tao mis,reg; 159 PetscErrorCode ierr; 160 161 PetscFunctionBegin; 162 mis = am->subsolverX; 163 reg = am->subsolverZ; 164 ierr = TaoComputeJacobianEquality(mis, x, mis->jacobian_equality, mis->jacobian_equality_pre);CHKERRQ(ierr); 165 ierr = MatMult(mis->jacobian_equality,x,Ax);CHKERRQ(ierr); 166 ierr = TaoComputeJacobianEquality(reg, z, reg->jacobian_equality, reg->jacobian_equality_pre);CHKERRQ(ierr); 167 ierr = MatMult(reg->jacobian_equality,z,Bz);CHKERRQ(ierr); 168 169 ierr = VecWAXPY(residual,1.,Bz,Ax);CHKERRQ(ierr); 170 if (am->constraint != NULL) { 171 ierr = VecAXPY(residual,-1.,am->constraint);CHKERRQ(ierr); 172 } 173 PetscFunctionReturn(0); 174 } 175 176 /* Updates Augmented Lagrangians to given routines * 177 * For subsolverX, routine needs to be ComputeObjectiveAndGraidnet 178 * Separate Objective and Gradient routines are not supported. */ 179 static PetscErrorCode SubObjGradUpdate(Tao tao, Vec x, PetscReal *f, Vec g, void *ptr) 180 { 181 Tao parent = (Tao)ptr; 182 TAO_ADMM *am = (TAO_ADMM*)parent->data; 183 PetscErrorCode ierr; 184 PetscReal temp,temp2; 185 Vec tempJR; 186 187 PetscFunctionBegin; 188 tempJR = am->workJacobianRight; 189 ierr = ADMMUpdateConstraintResidualVector(parent, x, am->subsolverZ->solution, am->Ax, am->Bz, am->residual);CHKERRQ(ierr); 190 ierr = (*am->ops->misfitobjgrad)(am->subsolverX,x,f,g,am->misfitobjgradP);CHKERRQ(ierr); 191 192 am->last_misfit_val = *f; 193 /* Objective Add + yT(Ax+Bz-c) + mu/2*||Ax+Bz-c||_2^2 */ 194 ierr = VecTDot(am->residual,am->y,&temp);CHKERRQ(ierr); 195 ierr = VecTDot(am->residual,am->residual,&temp2);CHKERRQ(ierr); 196 *f += temp + (am->mu/2)*temp2; 197 198 /* Gradient. Add + mu*AT(Ax+Bz-c) + yTA*/ 199 ierr = MatMultTranspose(tao->jacobian_equality,am->residual,tempJR);CHKERRQ(ierr); 200 ierr = VecAXPY(g,am->mu,tempJR);CHKERRQ(ierr); 201 ierr = MatMultTranspose(tao->jacobian_equality,am->y,tempJR);CHKERRQ(ierr); 202 ierr = VecAXPY(g,1.,tempJR);CHKERRQ(ierr); 203 PetscFunctionReturn(0); 204 } 205 206 /* Updates Augmented Lagrangians to given routines 207 * For subsolverZ, routine needs to be ComputeObjectiveAndGraidnet 208 * Separate Objective and Gradient routines are not supported. */ 209 static PetscErrorCode RegObjGradUpdate(Tao tao, Vec z, PetscReal *f, Vec g, void *ptr) 210 { 211 Tao parent = (Tao)ptr; 212 TAO_ADMM *am = (TAO_ADMM*)parent->data; 213 PetscErrorCode ierr; 214 PetscReal temp,temp2; 215 Vec tempJR; 216 217 PetscFunctionBegin; 218 tempJR = am->workJacobianRight; 219 ierr = ADMMUpdateConstraintResidualVector(parent, am->subsolverX->solution, z, am->Ax, am->Bz, am->residual);CHKERRQ(ierr); 220 ierr = (*am->ops->regobjgrad)(am->subsolverZ,z,f,g,am->regobjgradP);CHKERRQ(ierr); 221 am->last_reg_val= *f; 222 /* Objective Add + yT(Ax+Bz-c) + mu/2*||Ax+Bz-c||_2^2 */ 223 ierr = VecTDot(am->residual,am->y,&temp);CHKERRQ(ierr); 224 ierr = VecTDot(am->residual,am->residual,&temp2);CHKERRQ(ierr); 225 *f += temp + (am->mu/2)*temp2; 226 227 /* Gradient. Add + mu*BT(Ax+Bz-c) + yTB*/ 228 ierr = MatMultTranspose(am->subsolverZ->jacobian_equality,am->residual,tempJR);CHKERRQ(ierr); 229 ierr = VecAXPY(g,am->mu,tempJR);CHKERRQ(ierr); 230 ierr = MatMultTranspose(am->subsolverZ->jacobian_equality,am->y,tempJR);CHKERRQ(ierr); 231 ierr = VecAXPY(g,1.,tempJR);CHKERRQ(ierr); 232 PetscFunctionReturn(0); 233 } 234 235 /* Computes epsilon padded L1 norm lambda*sum(sqrt(x^2+eps^2)-eps */ 236 static PetscErrorCode ADMML1EpsilonNorm(Tao tao, Vec x, PetscReal eps, PetscReal *norm) 237 { 238 TAO_ADMM *am = (TAO_ADMM*)tao->data; 239 PetscInt N; 240 PetscErrorCode ierr; 241 242 PetscFunctionBegin; 243 ierr = VecGetSize(am->workLeft,&N);CHKERRQ(ierr); 244 ierr = VecPointwiseMult(am->workLeft,x,x);CHKERRQ(ierr); 245 ierr = VecShift(am->workLeft,am->l1epsilon*am->l1epsilon);CHKERRQ(ierr); 246 ierr = VecSqrtAbs(am->workLeft);CHKERRQ(ierr); 247 ierr = VecSum(am->workLeft,norm);CHKERRQ(ierr); 248 *norm += N*am->l1epsilon; 249 *norm *= am->lambda; 250 PetscFunctionReturn(0); 251 } 252 253 static PetscErrorCode ADMMInternalHessianUpdate(Mat H, Mat Constraint, PetscBool Identity, void *ptr) 254 { 255 TAO_ADMM *am = (TAO_ADMM*)ptr; 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 switch (am->update) { 260 case (TAO_ADMM_UPDATE_BASIC): 261 break; 262 case (TAO_ADMM_UPDATE_ADAPTIVE): 263 case (TAO_ADMM_UPDATE_ADAPTIVE_RELAXED): 264 if (H && (am->muold != am->mu)) { 265 if (!Identity) { 266 ierr = MatAXPY(H,am->mu-am->muold,Constraint,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 267 } else { 268 ierr = MatShift(H,am->mu-am->muold);CHKERRQ(ierr); 269 } 270 } 271 break; 272 } 273 PetscFunctionReturn(0); 274 } 275 276 /* Updates Hessian - adds second derivative of augmented Lagrangian 277 * H \gets H + \rho*ATA 278 * Here, \rho does not change in TAO_ADMM_UPDATE_BASIC - thus no-op 279 * For ADAPTAIVE,ADAPTIVE_RELAXED, 280 * H \gets H + (\rho-\rhoold)*ATA 281 * Here, we assume that A is linear constraint i.e., doesnt change. 282 * Thus, for both ADAPTIVE, and RELAXED, ATA matrix is pre-set (except for A=I (null case)) see TaoSetUp_ADMM */ 283 static PetscErrorCode SubHessianUpdate(Tao tao, Vec x, Mat H, Mat Hpre, void *ptr) 284 { 285 Tao parent = (Tao)ptr; 286 TAO_ADMM *am = (TAO_ADMM*)parent->data; 287 PetscErrorCode ierr; 288 289 PetscFunctionBegin; 290 if (am->Hxchange) { 291 /* Case where Hessian gets updated with respect to x vector input. */ 292 ierr = (*am->ops->misfithess)(am->subsolverX,x,H,Hpre,am->misfithessP);CHKERRQ(ierr); 293 ierr = ADMMInternalHessianUpdate(am->subsolverX->hessian,am->ATA,am->xJI,am);CHKERRQ(ierr); 294 } else if (am->Hxbool) { 295 /* Hessian doesn't get updated. H(x) = c */ 296 /* Update Lagrangian only only per TAO call */ 297 ierr = ADMMInternalHessianUpdate(am->subsolverX->hessian,am->ATA,am->xJI,am);CHKERRQ(ierr); 298 am->Hxbool = PETSC_FALSE; 299 } 300 PetscFunctionReturn(0); 301 } 302 303 /* Same as SubHessianUpdate, except for B matrix instead of A matrix */ 304 static PetscErrorCode RegHessianUpdate(Tao tao, Vec z, Mat H, Mat Hpre, void *ptr) 305 { 306 Tao parent = (Tao)ptr; 307 TAO_ADMM *am = (TAO_ADMM*)parent->data; 308 PetscErrorCode ierr; 309 310 PetscFunctionBegin; 311 312 if (am->Hzchange) { 313 /* Case where Hessian gets updated with respect to x vector input. */ 314 ierr = (*am->ops->reghess)(am->subsolverZ,z,H,Hpre,am->reghessP);CHKERRQ(ierr); 315 ierr = ADMMInternalHessianUpdate(am->subsolverZ->hessian,am->BTB,am->zJI,am);CHKERRQ(ierr); 316 } else if (am->Hzbool) { 317 /* Hessian doesn't get updated. H(x) = c */ 318 /* Update Lagrangian only only per TAO call */ 319 ierr = ADMMInternalHessianUpdate(am->subsolverZ->hessian,am->BTB,am->zJI,am);CHKERRQ(ierr); 320 am->Hzbool = PETSC_FALSE; 321 } 322 PetscFunctionReturn(0); 323 } 324 325 /* Shell Matrix routine for A matrix. 326 * This gets used when user puts NULL for 327 * TaoSetJacobianEqualityRoutine(tao, NULL,NULL, ...) 328 * Essentially sets A=I*/ 329 static PetscErrorCode JacobianIdentity(Mat mat,Vec in,Vec out) 330 { 331 PetscErrorCode ierr; 332 333 PetscFunctionBegin; 334 ierr = VecCopy(in,out);CHKERRQ(ierr); 335 PetscFunctionReturn(0); 336 } 337 338 /* Shell Matrix routine for B matrix. 339 * This gets used when user puts NULL for 340 * TaoADMMSetRegularizerConstraintJacobian(tao, NULL,NULL, ...) 341 * Sets B=-I */ 342 static PetscErrorCode JacobianIdentityB(Mat mat,Vec in,Vec out) 343 { 344 PetscErrorCode ierr; 345 346 PetscFunctionBegin; 347 ierr = VecCopy(in,out);CHKERRQ(ierr); 348 ierr = VecScale(out,-1.);CHKERRQ(ierr); 349 PetscFunctionReturn(0); 350 } 351 352 /* Solve f(x) + g(z) s.t. Ax + Bz = c */ 353 static PetscErrorCode TaoSolve_ADMM(Tao tao) 354 { 355 TAO_ADMM *am = (TAO_ADMM*)tao->data; 356 PetscErrorCode ierr; 357 PetscInt N; 358 PetscReal reg_func; 359 PetscBool is_reg_shell; 360 Vec tempL; 361 362 PetscFunctionBegin; 363 if (am->regswitch != TAO_ADMM_REGULARIZER_SOFT_THRESH) { 364 if (!am->subsolverX->ops->computejacobianequality) SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"Must call TaoADMMSetMisfitConstraintJacobian() first"); 365 if (!am->subsolverZ->ops->computejacobianequality) SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"Must call TaoADMMSetRegularizerConstraintJacobian() first"); 366 if (am->constraint != NULL) { 367 ierr = VecNorm(am->constraint,NORM_2,&am->const_norm);CHKERRQ(ierr); 368 } 369 } 370 tempL = am->workLeft; 371 ierr = VecGetSize(tempL,&N);CHKERRQ(ierr); 372 373 if (am->Hx && am->ops->misfithess) { 374 ierr = TaoSetHessianRoutine(am->subsolverX, am->Hx, am->Hx, SubHessianUpdate, tao);CHKERRQ(ierr); 375 } 376 377 if (!am->zJI) { 378 /* Currently, B is assumed to be a linear system, i.e., not getting updated*/ 379 ierr = MatTransposeMatMult(am->JB,am->JB,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&(am->BTB));CHKERRQ(ierr); 380 } 381 if (!am->xJI) { 382 /* Currently, A is assumed to be a linear system, i.e., not getting updated*/ 383 ierr = MatTransposeMatMult(am->subsolverX->jacobian_equality,am->subsolverX->jacobian_equality,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&(am->ATA));CHKERRQ(ierr); 384 } 385 386 is_reg_shell = PETSC_FALSE; 387 388 ierr = PetscObjectTypeCompare((PetscObject)am->subsolverZ, TAOSHELL, &is_reg_shell);CHKERRQ(ierr); 389 390 if (!is_reg_shell) { 391 switch (am->regswitch) { 392 case (TAO_ADMM_REGULARIZER_USER): 393 if (!am->ops->regobjgrad) SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"Must call TaoADMMSetRegularizerObjectiveAndGradientRoutine() first if one wishes to use TAO_ADMM_REGULARIZER_USER with non-TAOSHELL type"); 394 break; 395 case (TAO_ADMM_REGULARIZER_SOFT_THRESH): 396 /* Soft Threshold. */ 397 break; 398 } 399 if (am->ops->regobjgrad) { 400 ierr = TaoSetObjectiveAndGradientRoutine(am->subsolverZ, RegObjGradUpdate, tao);CHKERRQ(ierr); 401 } 402 if (am->Hz && am->ops->reghess) { 403 ierr = TaoSetHessianRoutine(am->subsolverZ, am->Hz, am->Hzpre, RegHessianUpdate, tao);CHKERRQ(ierr); 404 } 405 } 406 407 switch (am->update) { 408 case TAO_ADMM_UPDATE_BASIC: 409 if (am->subsolverX->hessian) { 410 /* In basic case, Hessian does not get updated w.r.t. to spectral penalty 411 * Here, when A is set, i.e., am->xJI, add mu*ATA to Hessian*/ 412 if (!am->xJI) { 413 ierr = MatAXPY(am->subsolverX->hessian,am->mu,am->ATA,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 414 } else { 415 ierr = MatShift(am->subsolverX->hessian,am->mu);CHKERRQ(ierr); 416 } 417 } 418 if (am->subsolverZ->hessian && am->regswitch == TAO_ADMM_REGULARIZER_USER) { 419 if (am->regswitch == TAO_ADMM_REGULARIZER_USER && !am->zJI) { 420 ierr = MatAXPY(am->subsolverZ->hessian,am->mu,am->BTB,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 421 } else { 422 ierr = MatShift(am->subsolverZ->hessian,am->mu);CHKERRQ(ierr); 423 } 424 } 425 break; 426 case TAO_ADMM_UPDATE_ADAPTIVE: 427 case TAO_ADMM_UPDATE_ADAPTIVE_RELAXED: 428 break; 429 } 430 431 ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); 432 tao->reason = TAO_CONTINUE_ITERATING; 433 434 while (tao->reason == TAO_CONTINUE_ITERATING) { 435 if (tao->ops->update) { 436 ierr = (*tao->ops->update)(tao, tao->niter, tao->user_update);CHKERRQ(ierr); 437 } 438 ierr = VecCopy(am->Bz, am->Bzold);CHKERRQ(ierr); 439 440 /* x update */ 441 ierr = TaoSolve(am->subsolverX);CHKERRQ(ierr); 442 ierr = TaoComputeJacobianEquality(am->subsolverX, am->subsolverX->solution, am->subsolverX->jacobian_equality, am->subsolverX->jacobian_equality_pre);CHKERRQ(ierr); 443 ierr = MatMult(am->subsolverX->jacobian_equality, am->subsolverX->solution,am->Ax);CHKERRQ(ierr); 444 445 am->Hxbool = PETSC_TRUE; 446 447 /* z update */ 448 switch (am->regswitch) { 449 case TAO_ADMM_REGULARIZER_USER: 450 ierr = TaoSolve(am->subsolverZ);CHKERRQ(ierr); 451 break; 452 case TAO_ADMM_REGULARIZER_SOFT_THRESH: 453 /* L1 assumes A,B jacobians are identity nxn matrix */ 454 ierr = VecWAXPY(am->workJacobianRight,1/am->mu,am->y,am->Ax);CHKERRQ(ierr); 455 ierr = TaoSoftThreshold(am->workJacobianRight,-am->lambda/am->mu,am->lambda/am->mu,am->subsolverZ->solution);CHKERRQ(ierr); 456 break; 457 } 458 am->Hzbool = PETSC_TRUE; 459 /* Returns Ax + Bz - c with updated Ax,Bz vectors */ 460 ierr = ADMMUpdateConstraintResidualVector(tao, am->subsolverX->solution, am->subsolverZ->solution, am->Ax, am->Bz, am->residual);CHKERRQ(ierr); 461 /* Dual variable, y += y + mu*(Ax+Bz-c) */ 462 ierr = VecWAXPY(am->y, am->mu, am->residual, am->yold);CHKERRQ(ierr); 463 464 /* stopping tolerance update */ 465 ierr = TaoADMMToleranceUpdate(tao);CHKERRQ(ierr); 466 467 /* Updating Spectral Penalty */ 468 switch (am->update) { 469 case TAO_ADMM_UPDATE_BASIC: 470 am->muold = am->mu; 471 break; 472 case TAO_ADMM_UPDATE_ADAPTIVE: 473 case TAO_ADMM_UPDATE_ADAPTIVE_RELAXED: 474 if (tao->niter == 0) { 475 ierr = VecCopy(am->y, am->y0);CHKERRQ(ierr); 476 ierr = VecWAXPY(am->residual, 1., am->Ax, am->Bzold);CHKERRQ(ierr); 477 if (am->constraint) { 478 ierr = VecAXPY(am->residual, -1., am->constraint);CHKERRQ(ierr); 479 } 480 ierr = VecWAXPY(am->yhatold, -am->mu, am->residual, am->yold);CHKERRQ(ierr); 481 ierr = VecCopy(am->Ax, am->Axold);CHKERRQ(ierr); 482 ierr = VecCopy(am->Bz, am->Bz0);CHKERRQ(ierr); 483 am->muold = am->mu; 484 } else if (tao->niter % am->T == 1) { 485 /* we have compute Bzold in a previous iteration, and we computed Ax above */ 486 ierr = VecWAXPY(am->residual, 1., am->Ax, am->Bzold);CHKERRQ(ierr); 487 if (am->constraint) { 488 ierr = VecAXPY(am->residual, -1., am->constraint);CHKERRQ(ierr); 489 } 490 ierr = VecWAXPY(am->yhat, -am->mu, am->residual, am->yold);CHKERRQ(ierr); 491 ierr = AdaptiveADMMPenaltyUpdate(tao);CHKERRQ(ierr); 492 ierr = VecCopy(am->Ax, am->Axold);CHKERRQ(ierr); 493 ierr = VecCopy(am->Bz, am->Bz0);CHKERRQ(ierr); 494 ierr = VecCopy(am->yhat, am->yhatold);CHKERRQ(ierr); 495 ierr = VecCopy(am->y, am->y0);CHKERRQ(ierr); 496 } else { 497 am->muold = am->mu; 498 } 499 break; 500 default: 501 break; 502 } 503 tao->niter++; 504 505 /* Calculate original function values. misfit part was done in TaoADMMToleranceUpdate*/ 506 switch (am->regswitch) { 507 case TAO_ADMM_REGULARIZER_USER: 508 if (is_reg_shell) { 509 ierr = ADMML1EpsilonNorm(tao,am->subsolverZ->solution,am->l1epsilon,®_func);CHKERRQ(ierr); 510 } else { 511 (*am->ops->regobjgrad)(am->subsolverZ,am->subsolverX->solution,®_func,tempL,am->regobjgradP); 512 } 513 break; 514 case TAO_ADMM_REGULARIZER_SOFT_THRESH: 515 ierr = ADMML1EpsilonNorm(tao,am->subsolverZ->solution,am->l1epsilon,®_func);CHKERRQ(ierr); 516 break; 517 } 518 ierr = VecCopy(am->y,am->yold);CHKERRQ(ierr); 519 ierr = ADMMUpdateConstraintResidualVector(tao, am->subsolverX->solution, am->subsolverZ->solution, am->Ax, am->Bz, am->residual);CHKERRQ(ierr); 520 ierr = VecNorm(am->residual,NORM_2,&am->resnorm);CHKERRQ(ierr); 521 ierr = TaoLogConvergenceHistory(tao,am->last_misfit_val + reg_func,am->dualres,am->resnorm,tao->ksp_its);CHKERRQ(ierr); 522 523 ierr = TaoMonitor(tao,tao->niter,am->last_misfit_val + reg_func,am->dualres,am->resnorm,1.0);CHKERRQ(ierr); 524 ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 525 } 526 /* Update vectors */ 527 ierr = VecCopy(am->subsolverX->solution,tao->solution);CHKERRQ(ierr); 528 ierr = VecCopy(am->subsolverX->gradient,tao->gradient);CHKERRQ(ierr); 529 ierr = PetscObjectCompose((PetscObject)am->subsolverX,"TaoGetADMMParentTao_ADMM", NULL);CHKERRQ(ierr); 530 ierr = PetscObjectCompose((PetscObject)am->subsolverZ,"TaoGetADMMParentTao_ADMM", NULL);CHKERRQ(ierr); 531 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMSetRegularizerType_C",NULL);CHKERRQ(ierr); 532 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMGetRegularizerType_C",NULL);CHKERRQ(ierr); 533 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMSetUpdateType_C",NULL);CHKERRQ(ierr); 534 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMGetUpdateType_C",NULL);CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 538 static PetscErrorCode TaoSetFromOptions_ADMM(PetscOptionItems *PetscOptionsObject,Tao tao) 539 { 540 TAO_ADMM *am = (TAO_ADMM*)tao->data; 541 PetscErrorCode ierr; 542 543 PetscFunctionBegin; 544 ierr = PetscOptionsHead(PetscOptionsObject,"ADMM problem that solves f(x) in a form of f(x) + g(z) subject to x - z = 0. Norm 1 and 2 are supported. Different subsolver routines can be selected. ");CHKERRQ(ierr); 545 ierr = PetscOptionsReal("-tao_admm_regularizer_coefficient","regularizer constant","",am->lambda,&am->lambda,NULL);CHKERRQ(ierr); 546 ierr = PetscOptionsReal("-tao_admm_spectral_penalty","Constant for Augmented Lagrangian term.","",am->mu,&am->mu,NULL);CHKERRQ(ierr); 547 ierr = PetscOptionsReal("-tao_admm_relaxation_parameter","x relaxation parameter for Z update.","",am->gamma,&am->gamma,NULL);CHKERRQ(ierr); 548 ierr = PetscOptionsReal("-tao_admm_tolerance_update_factor","ADMM dynamic tolerance update factor.","",am->tol,&am->tol,NULL);CHKERRQ(ierr); 549 ierr = PetscOptionsReal("-tao_admm_spectral_penalty_update_factor","ADMM spectral penalty update curvature safeguard value.","",am->orthval,&am->orthval,NULL);CHKERRQ(ierr); 550 ierr = PetscOptionsReal("-tao_admm_minimum_spectral_penalty","Set ADMM minimum spectral penalty.","",am->mumin,&am->mumin,NULL);CHKERRQ(ierr); 551 ierr = PetscOptionsEnum("-tao_admm_dual_update","Lagrangian dual update policy","TaoADMMUpdateType", 552 TaoADMMUpdateTypes,(PetscEnum)am->update,(PetscEnum*)&am->update,NULL);CHKERRQ(ierr); 553 ierr = PetscOptionsEnum("-tao_admm_regularizer_type","ADMM regularizer update rule","TaoADMMRegularizerType", 554 TaoADMMRegularizerTypes,(PetscEnum)am->regswitch,(PetscEnum*)&am->regswitch,NULL);CHKERRQ(ierr); 555 ierr = PetscOptionsTail();CHKERRQ(ierr); 556 ierr = TaoSetFromOptions(am->subsolverX);CHKERRQ(ierr); 557 if (am->regswitch != TAO_ADMM_REGULARIZER_SOFT_THRESH) { 558 ierr = TaoSetFromOptions(am->subsolverZ);CHKERRQ(ierr); 559 } 560 PetscFunctionReturn(0); 561 } 562 563 static PetscErrorCode TaoView_ADMM(Tao tao,PetscViewer viewer) 564 { 565 TAO_ADMM *am = (TAO_ADMM*)tao->data; 566 PetscErrorCode ierr; 567 568 PetscFunctionBegin; 569 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 570 ierr = TaoView(am->subsolverX,viewer);CHKERRQ(ierr); 571 ierr = TaoView(am->subsolverZ,viewer);CHKERRQ(ierr); 572 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 573 PetscFunctionReturn(0); 574 } 575 576 static PetscErrorCode TaoSetUp_ADMM(Tao tao) 577 { 578 TAO_ADMM *am = (TAO_ADMM*)tao->data; 579 PetscErrorCode ierr; 580 PetscInt n,N,M; 581 582 PetscFunctionBegin; 583 ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); 584 ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); 585 /* If Jacobian is given as NULL, it means Jacobian is identity matrix with size of solution vector */ 586 if (!am->JB) { 587 am->zJI = PETSC_TRUE; 588 ierr = MatCreateShell(PetscObjectComm((PetscObject)tao),n,n,PETSC_DETERMINE,PETSC_DETERMINE,NULL,&am->JB);CHKERRQ(ierr); 589 ierr = MatShellSetOperation(am->JB,MATOP_MULT,(void (*)(void))JacobianIdentityB);CHKERRQ(ierr); 590 ierr = MatShellSetOperation(am->JB,MATOP_MULT_TRANSPOSE,(void (*)(void))JacobianIdentityB);CHKERRQ(ierr); 591 ierr = MatShellSetOperation(am->JB,MATOP_TRANSPOSE_MAT_MULT,(void (*)(void))JacobianIdentityB);CHKERRQ(ierr); 592 am->JBpre = am->JB; 593 } 594 if (!am->JA) { 595 am->xJI = PETSC_TRUE; 596 ierr = MatCreateShell(PetscObjectComm((PetscObject)tao),n,n,PETSC_DETERMINE,PETSC_DETERMINE,NULL,&am->JA);CHKERRQ(ierr); 597 ierr = MatShellSetOperation(am->JA,MATOP_MULT,(void (*)(void))JacobianIdentity);CHKERRQ(ierr); 598 ierr = MatShellSetOperation(am->JA,MATOP_MULT_TRANSPOSE,(void (*)(void))JacobianIdentity);CHKERRQ(ierr); 599 ierr = MatShellSetOperation(am->JA,MATOP_TRANSPOSE_MAT_MULT,(void (*)(void))JacobianIdentity);CHKERRQ(ierr); 600 am->JApre = am->JA; 601 } 602 ierr = MatCreateVecs(am->JA,NULL,&am->Ax);CHKERRQ(ierr); 603 if (!tao->gradient) { 604 ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); 605 } 606 ierr = TaoSetInitialVector(am->subsolverX, tao->solution);CHKERRQ(ierr); 607 if (!am->z) { 608 ierr = VecDuplicate(tao->solution,&am->z);CHKERRQ(ierr); 609 ierr = VecSet(am->z,0.0);CHKERRQ(ierr); 610 } 611 ierr = TaoSetInitialVector(am->subsolverZ, am->z);CHKERRQ(ierr); 612 if (!am->workLeft) { 613 ierr = VecDuplicate(tao->solution,&am->workLeft);CHKERRQ(ierr); 614 } 615 if (!am->Axold) { 616 ierr = VecDuplicate(am->Ax,&am->Axold);CHKERRQ(ierr); 617 } 618 if (!am->workJacobianRight) { 619 ierr = VecDuplicate(am->Ax,&am->workJacobianRight);CHKERRQ(ierr); 620 } 621 if (!am->workJacobianRight2) { 622 ierr = VecDuplicate(am->Ax,&am->workJacobianRight2);CHKERRQ(ierr); 623 } 624 if (!am->Bz) { 625 ierr = VecDuplicate(am->Ax,&am->Bz);CHKERRQ(ierr); 626 } 627 if (!am->Bzold) { 628 ierr = VecDuplicate(am->Ax,&am->Bzold);CHKERRQ(ierr); 629 } 630 if (!am->Bz0) { 631 ierr = VecDuplicate(am->Ax,&am->Bz0);CHKERRQ(ierr); 632 } 633 if (!am->y) { 634 ierr = VecDuplicate(am->Ax,&am->y);CHKERRQ(ierr); 635 ierr = VecSet(am->y,0.0);CHKERRQ(ierr); 636 } 637 if (!am->yold) { 638 ierr = VecDuplicate(am->Ax,&am->yold);CHKERRQ(ierr); 639 ierr = VecSet(am->yold,0.0);CHKERRQ(ierr); 640 } 641 if (!am->y0) { 642 ierr = VecDuplicate(am->Ax,&am->y0);CHKERRQ(ierr); 643 ierr = VecSet(am->y0,0.0);CHKERRQ(ierr); 644 } 645 if (!am->yhat) { 646 ierr = VecDuplicate(am->Ax,&am->yhat);CHKERRQ(ierr); 647 ierr = VecSet(am->yhat,0.0);CHKERRQ(ierr); 648 } 649 if (!am->yhatold) { 650 ierr = VecDuplicate(am->Ax,&am->yhatold);CHKERRQ(ierr); 651 ierr = VecSet(am->yhatold,0.0);CHKERRQ(ierr); 652 } 653 if (!am->residual) { 654 ierr = VecDuplicate(am->Ax,&am->residual);CHKERRQ(ierr); 655 ierr = VecSet(am->residual,0.0);CHKERRQ(ierr); 656 } 657 if (!am->constraint) { 658 am->constraint = NULL; 659 } else { 660 ierr = VecGetSize(am->constraint,&M);CHKERRQ(ierr); 661 if (M != N) SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"Solution vector and constraint vector must be of same size!"); 662 } 663 664 /* Save changed tao tolerance for adaptive tolerance */ 665 if (tao->gatol_changed) { 666 am->gatol_admm = tao->gatol; 667 } 668 if (tao->catol_changed) { 669 am->catol_admm = tao->catol; 670 } 671 672 /*Update spectral and dual elements to X subsolver */ 673 ierr = TaoSetObjectiveAndGradientRoutine(am->subsolverX, SubObjGradUpdate, tao);CHKERRQ(ierr); 674 ierr = TaoSetJacobianEqualityRoutine(am->subsolverX,am->JA,am->JApre, am->ops->misfitjac, am->misfitjacobianP);CHKERRQ(ierr); 675 ierr = TaoSetJacobianEqualityRoutine(am->subsolverZ,am->JB,am->JBpre, am->ops->regjac, am->regjacobianP);CHKERRQ(ierr); 676 PetscFunctionReturn(0); 677 } 678 679 static PetscErrorCode TaoDestroy_ADMM(Tao tao) 680 { 681 TAO_ADMM *am = (TAO_ADMM*)tao->data; 682 PetscErrorCode ierr; 683 684 PetscFunctionBegin; 685 ierr = VecDestroy(&am->z);CHKERRQ(ierr); 686 ierr = VecDestroy(&am->Ax);CHKERRQ(ierr); 687 ierr = VecDestroy(&am->Axold);CHKERRQ(ierr); 688 ierr = VecDestroy(&am->Bz);CHKERRQ(ierr); 689 ierr = VecDestroy(&am->Bzold);CHKERRQ(ierr); 690 ierr = VecDestroy(&am->Bz0);CHKERRQ(ierr); 691 ierr = VecDestroy(&am->residual);CHKERRQ(ierr); 692 ierr = VecDestroy(&am->y);CHKERRQ(ierr); 693 ierr = VecDestroy(&am->yold);CHKERRQ(ierr); 694 ierr = VecDestroy(&am->y0);CHKERRQ(ierr); 695 ierr = VecDestroy(&am->yhat);CHKERRQ(ierr); 696 ierr = VecDestroy(&am->yhatold);CHKERRQ(ierr); 697 ierr = VecDestroy(&am->workLeft);CHKERRQ(ierr); 698 ierr = VecDestroy(&am->workJacobianRight);CHKERRQ(ierr); 699 ierr = VecDestroy(&am->workJacobianRight2);CHKERRQ(ierr); 700 701 ierr = MatDestroy(&am->JA);CHKERRQ(ierr); 702 ierr = MatDestroy(&am->JB);CHKERRQ(ierr); 703 if (!am->xJI) { 704 ierr = MatDestroy(&am->JApre);CHKERRQ(ierr); 705 } 706 if (!am->zJI) { 707 ierr = MatDestroy(&am->JBpre);CHKERRQ(ierr); 708 } 709 if (am->Hx) { 710 ierr = MatDestroy(&am->Hx);CHKERRQ(ierr); 711 ierr = MatDestroy(&am->Hxpre);CHKERRQ(ierr); 712 } 713 if (am->Hz) { 714 ierr = MatDestroy(&am->Hz);CHKERRQ(ierr); 715 ierr = MatDestroy(&am->Hzpre);CHKERRQ(ierr); 716 } 717 ierr = MatDestroy(&am->ATA);CHKERRQ(ierr); 718 ierr = MatDestroy(&am->BTB);CHKERRQ(ierr); 719 ierr = TaoDestroy(&am->subsolverX);CHKERRQ(ierr); 720 ierr = TaoDestroy(&am->subsolverZ);CHKERRQ(ierr); 721 am->parent = NULL; 722 ierr = PetscFree(tao->data);CHKERRQ(ierr); 723 PetscFunctionReturn(0); 724 } 725 726 /*MC 727 728 TAOADMM - Alternating direction method of multipliers method fo solving linear problems with 729 constraints. in a min_x f(x) + g(z) s.t. Ax+Bz=c. 730 This algorithm employs two sub Tao solvers, of which type can be specified 731 by the user. User need to provide ObjectiveAndGradient routine, and/or HessianRoutine for both subsolvers. 732 Hessians can be given boolean flag determining whether they change with respect to a input vector. This can be set via 733 TaoADMMSet{Misfit,Regularizer}HessianChangeStatus. 734 Second subsolver does support TAOSHELL. It should be noted that L1-norm is used for objective value for TAOSHELL type. 735 There is option to set regularizer option, and currently soft-threshold is implemented. For spectral penalty update, 736 currently there are basic option and adaptive option. 737 Constraint is set at Ax+Bz=c, and A and B can be set with TaoADMMSet{Misfit,Regularizer}ConstraintJacobian. 738 c can be set with TaoADMMSetConstraintVectorRHS. 739 The user can also provide regularizer weight for second subsolver. 740 741 References: 742 . 1. - Xu, Zheng and Figueiredo, Mario A. T. and Yuan, Xiaoming and Studer, Christoph and Goldstein, Tom 743 "Adaptive Relaxed ADMM: Convergence Theory and Practical Implementation" 744 The IEEE Conference on Computer Vision and Pattern Recognition (CVPR), July, 2017. 745 746 Options Database Keys: 747 + -tao_admm_regularizer_coefficient - regularizer constant (default 1.e-6) 748 . -tao_admm_spectral_penalty - Constant for Augmented Lagrangian term (default 1.) 749 . -tao_admm_relaxation_parameter - relaxation parameter for Z update (default 1.) 750 . -tao_admm_tolerance_update_factor - ADMM dynamic tolerance update factor (default 1.e-12) 751 . -tao_admm_spectral_penalty_update_factor - ADMM spectral penalty update curvature safeguard value (default 0.2) 752 . -tao_admm_minimum_spectral_penalty - Set ADMM minimum spectral penalty (default 0) 753 . -tao_admm_dual_update - Lagrangian dual update policy ("basic","adaptive","adaptive-relaxed") (default "basic") 754 - -tao_admm_regularizer_type - ADMM regularizer update rule ("user","soft-threshold") (default "soft-threshold") 755 756 Level: beginner 757 758 .seealso: TaoADMMSetMisfitHessianChangeStatus(), TaoADMMSetRegHessianChangeStatus(), TaoADMMGetSpectralPenalty(), 759 TaoADMMGetMisfitSubsolver(), TaoADMMGetRegularizationSubsolver(), TaoADMMSetConstraintVectorRHS(), 760 TaoADMMSetMinimumSpectralPenalty(), TaoADMMSetRegularizerCoefficient(), 761 TaoADMMSetRegularizerConstraintJacobian(), TaoADMMSetMisfitConstraintJacobian(), 762 TaoADMMSetMisfitObjectiveAndGradientRoutine(), TaoADMMSetMisfitHessianRoutine(), 763 TaoADMMSetRegularizerObjectiveAndGradientRoutine(), TaoADMMSetRegularizerHessianRoutine(), 764 TaoGetADMMParentTao(), TaoADMMGetDualVector(), TaoADMMSetRegularizerType(), 765 TaoADMMGetRegularizerType(), TaoADMMSetUpdateType(), TaoADMMGetUpdateType() 766 M*/ 767 768 PETSC_EXTERN PetscErrorCode TaoCreate_ADMM(Tao tao) 769 { 770 TAO_ADMM *am; 771 PetscErrorCode ierr; 772 773 PetscFunctionBegin; 774 ierr = PetscNewLog(tao,&am);CHKERRQ(ierr); 775 776 tao->ops->destroy = TaoDestroy_ADMM; 777 tao->ops->setup = TaoSetUp_ADMM; 778 tao->ops->setfromoptions = TaoSetFromOptions_ADMM; 779 tao->ops->view = TaoView_ADMM; 780 tao->ops->solve = TaoSolve_ADMM; 781 782 tao->data = (void*)am; 783 am->l1epsilon = 1e-6; 784 am->lambda = 1e-4; 785 am->mu = 1.; 786 am->muold = 0.; 787 am->mueps = PETSC_MACHINE_EPSILON; 788 am->mumin = 0.; 789 am->orthval = 0.2; 790 am->T = 2; 791 am->parent = tao; 792 am->update = TAO_ADMM_UPDATE_BASIC; 793 am->regswitch = TAO_ADMM_REGULARIZER_SOFT_THRESH; 794 am->tol = PETSC_SMALL; 795 am->const_norm = 0; 796 am->resnorm = 0; 797 am->dualres = 0; 798 am->ops->regobjgrad = NULL; 799 am->ops->reghess = NULL; 800 am->gamma = 1; 801 am->regobjgradP = NULL; 802 am->reghessP = NULL; 803 am->gatol_admm = 1e-8; 804 am->catol_admm = 0; 805 am->Hxchange = PETSC_TRUE; 806 am->Hzchange = PETSC_TRUE; 807 am->Hzbool = PETSC_TRUE; 808 am->Hxbool = PETSC_TRUE; 809 810 ierr = TaoCreate(PetscObjectComm((PetscObject)tao),&am->subsolverX);CHKERRQ(ierr); 811 ierr = TaoSetOptionsPrefix(am->subsolverX,"misfit_");CHKERRQ(ierr); 812 ierr = PetscObjectIncrementTabLevel((PetscObject)am->subsolverX,(PetscObject)tao,1);CHKERRQ(ierr); 813 ierr = TaoCreate(PetscObjectComm((PetscObject)tao),&am->subsolverZ);CHKERRQ(ierr); 814 ierr = TaoSetOptionsPrefix(am->subsolverZ,"reg_");CHKERRQ(ierr); 815 ierr = PetscObjectIncrementTabLevel((PetscObject)am->subsolverZ,(PetscObject)tao,1);CHKERRQ(ierr); 816 817 ierr = TaoSetType(am->subsolverX,TAONLS);CHKERRQ(ierr); 818 ierr = TaoSetType(am->subsolverZ,TAONLS);CHKERRQ(ierr); 819 ierr = PetscObjectCompose((PetscObject)am->subsolverX,"TaoGetADMMParentTao_ADMM", (PetscObject) tao);CHKERRQ(ierr); 820 ierr = PetscObjectCompose((PetscObject)am->subsolverZ,"TaoGetADMMParentTao_ADMM", (PetscObject) tao);CHKERRQ(ierr); 821 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMSetRegularizerType_C",TaoADMMSetRegularizerType_ADMM);CHKERRQ(ierr); 822 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMGetRegularizerType_C",TaoADMMGetRegularizerType_ADMM);CHKERRQ(ierr); 823 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMSetUpdateType_C",TaoADMMSetUpdateType_ADMM);CHKERRQ(ierr); 824 ierr = PetscObjectComposeFunction((PetscObject)tao,"TaoADMMGetUpdateType_C",TaoADMMGetUpdateType_ADMM);CHKERRQ(ierr); 825 PetscFunctionReturn(0); 826 } 827 828 /*@ 829 TaoADMMSetMisfitHessianChangeStatus - Set boolean that determines whether Hessian matrix of misfit subsolver changes with respect to input vector. 830 831 Collective on Tao 832 833 Input Parameters: 834 + tao - the Tao solver context. 835 - b - the Hessian matrix change status boolean, PETSC_FALSE when the Hessian matrix does not change, TRUE otherwise. 836 837 Level: advanced 838 839 .seealso: TAOADMM 840 841 @*/ 842 PetscErrorCode TaoADMMSetMisfitHessianChangeStatus(Tao tao, PetscBool b) 843 { 844 TAO_ADMM *am = (TAO_ADMM*)tao->data; 845 846 PetscFunctionBegin; 847 am->Hxchange = b; 848 PetscFunctionReturn(0); 849 } 850 851 /*@ 852 TaoADMMSetRegHessianChangeStatus - Set boolean that determines whether Hessian matrix of regularization subsolver changes with respect to input vector. 853 854 Collective on Tao 855 856 Input Parameters: 857 + tao - the Tao solver context 858 - b - the Hessian matrix change status boolean, PETSC_FALSE when the Hessian matrix does not change, TRUE otherwise. 859 860 Level: advanced 861 862 .seealso: TAOADMM 863 864 @*/ 865 PetscErrorCode TaoADMMSetRegHessianChangeStatus(Tao tao, PetscBool b) 866 { 867 TAO_ADMM *am = (TAO_ADMM*)tao->data; 868 869 PetscFunctionBegin; 870 am->Hzchange = b; 871 PetscFunctionReturn(0); 872 } 873 874 /*@ 875 TaoADMMSetSpectralPenalty - Set the spectral penalty (mu) value 876 877 Collective on Tao 878 879 Input Parameters: 880 + tao - the Tao solver context 881 - mu - spectral penalty 882 883 Level: advanced 884 885 .seealso: TaoADMMSetMinimumSpectralPenalty(), TAOADMM 886 @*/ 887 PetscErrorCode TaoADMMSetSpectralPenalty(Tao tao, PetscReal mu) 888 { 889 TAO_ADMM *am = (TAO_ADMM*)tao->data; 890 891 PetscFunctionBegin; 892 am->mu = mu; 893 PetscFunctionReturn(0); 894 } 895 896 /*@ 897 TaoADMMGetSpectralPenalty - Get the spectral penalty (mu) value 898 899 Collective on Tao 900 901 Input Parameter: 902 . tao - the Tao solver context 903 904 Output Parameter: 905 . mu - spectral penalty 906 907 Level: advanced 908 909 .seealso: TaoADMMSetMinimumSpectralPenalty(), TaoADMMSetSpectralPenalty(), TAOADMM 910 @*/ 911 PetscErrorCode TaoADMMGetSpectralPenalty(Tao tao, PetscReal *mu) 912 { 913 TAO_ADMM *am = (TAO_ADMM*)tao->data; 914 915 PetscFunctionBegin; 916 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 917 PetscValidRealPointer(mu,2); 918 *mu = am->mu; 919 PetscFunctionReturn(0); 920 } 921 922 /*@ 923 TaoADMMGetMisfitSubsolver - Get the pointer to the misfit subsolver inside ADMM 924 925 Collective on Tao 926 927 Input Parameter: 928 . tao - the Tao solver context 929 930 Output Parameter: 931 . misfit - the Tao subsolver context 932 933 Level: advanced 934 935 .seealso: TAOADMM 936 937 @*/ 938 PetscErrorCode TaoADMMGetMisfitSubsolver(Tao tao, Tao *misfit) 939 { 940 TAO_ADMM *am = (TAO_ADMM*)tao->data; 941 942 PetscFunctionBegin; 943 *misfit = am->subsolverX; 944 PetscFunctionReturn(0); 945 } 946 947 /*@ 948 TaoADMMGetRegularizationSubsolver - Get the pointer to the regularization subsolver inside ADMM 949 950 Collective on Tao 951 952 Input Parameter: 953 . tao - the Tao solver context 954 955 Output Parameter: 956 . reg - the Tao subsolver context 957 958 Level: advanced 959 960 .seealso: TAOADMM 961 962 @*/ 963 PetscErrorCode TaoADMMGetRegularizationSubsolver(Tao tao, Tao *reg) 964 { 965 TAO_ADMM *am = (TAO_ADMM*)tao->data; 966 967 PetscFunctionBegin; 968 *reg = am->subsolverZ; 969 PetscFunctionReturn(0); 970 } 971 972 /*@ 973 TaoADMMSetConstraintVectorRHS - Set the RHS constraint vector for ADMM 974 975 Collective on Tao 976 977 Input Parameters: 978 + tao - the Tao solver context 979 - c - RHS vector 980 981 Level: advanced 982 983 .seealso: TAOADMM 984 985 @*/ 986 PetscErrorCode TaoADMMSetConstraintVectorRHS(Tao tao, Vec c) 987 { 988 TAO_ADMM *am = (TAO_ADMM*)tao->data; 989 990 PetscFunctionBegin; 991 am->constraint = c; 992 PetscFunctionReturn(0); 993 } 994 995 /*@ 996 TaoADMMSetMinimumSpectralPenalty - Set the minimum value for the spectral penalty 997 998 Collective on Tao 999 1000 Input Parameters: 1001 + tao - the Tao solver context 1002 - mu - minimum spectral penalty value 1003 1004 Level: advanced 1005 1006 .seealso: TaoADMMGetSpectralPenalty(), TAOADMM 1007 @*/ 1008 PetscErrorCode TaoADMMSetMinimumSpectralPenalty(Tao tao, PetscReal mu) 1009 { 1010 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1011 1012 PetscFunctionBegin; 1013 am->mumin= mu; 1014 PetscFunctionReturn(0); 1015 } 1016 1017 /*@ 1018 TaoADMMSetRegularizerCoefficient - Set the regularization coefficient lambda for L1 norm regularization case 1019 1020 Collective on Tao 1021 1022 Input Parameters: 1023 + tao - the Tao solver context 1024 - lambda - L1-norm regularizer coefficient 1025 1026 Level: advanced 1027 1028 .seealso: TaoADMMSetMisfitConstraintJacobian(), TaoADMMSetRegularizerConstraintJacobian(), TAOADMM 1029 1030 @*/ 1031 PetscErrorCode TaoADMMSetRegularizerCoefficient(Tao tao, PetscReal lambda) 1032 { 1033 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1034 1035 PetscFunctionBegin; 1036 am->lambda = lambda; 1037 PetscFunctionReturn(0); 1038 } 1039 1040 /*@C 1041 TaoADMMSetMisfitConstraintJacobian - Set the constraint matrix B for the ADMM algorithm. Matrix B constrains the z variable. 1042 1043 Collective on Tao 1044 1045 Input Parameters: 1046 + tao - the Tao solver context 1047 . J - user-created regularizer constraint Jacobian matrix 1048 . Jpre - user-created regularizer Jacobian constraint preconditioner matrix 1049 . func - function pointer for the regularizer constraint Jacobian update function 1050 - ctx - user context for the regularizer Hessian 1051 1052 Level: advanced 1053 1054 .seealso: TaoADMMSetRegularizerCoefficient(), TaoADMMSetRegularizerConstraintJacobian(), TAOADMM 1055 1056 @*/ 1057 PetscErrorCode TaoADMMSetMisfitConstraintJacobian(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1058 { 1059 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1060 PetscErrorCode ierr; 1061 1062 PetscFunctionBegin; 1063 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1064 if (J) { 1065 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1066 PetscCheckSameComm(tao,1,J,2); 1067 } 1068 if (Jpre) { 1069 PetscValidHeaderSpecific(Jpre,MAT_CLASSID,3); 1070 PetscCheckSameComm(tao,1,Jpre,3); 1071 } 1072 if (ctx) am->misfitjacobianP = ctx; 1073 if (func) am->ops->misfitjac = func; 1074 1075 if (J) { 1076 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 1077 ierr = MatDestroy(&am->JA);CHKERRQ(ierr); 1078 am->JA = J; 1079 } 1080 if (Jpre) { 1081 ierr = PetscObjectReference((PetscObject)Jpre);CHKERRQ(ierr); 1082 ierr = MatDestroy(&am->JApre);CHKERRQ(ierr); 1083 am->JApre = Jpre; 1084 } 1085 PetscFunctionReturn(0); 1086 } 1087 1088 /*@C 1089 TaoADMMSetRegularizerConstraintJacobian - Set the constraint matrix B for ADMM algorithm. Matrix B constraints z variable. 1090 1091 Collective on Tao 1092 1093 Input Parameters: 1094 + tao - the Tao solver context 1095 . J - user-created regularizer constraint Jacobian matrix 1096 . Jpre - user-created regularizer Jacobian constraint preconditioner matrix 1097 . func - function pointer for the regularizer constraint Jacobian update function 1098 - ctx - user context for the regularizer Hessian 1099 1100 Level: advanced 1101 1102 .seealso: TaoADMMSetRegularizerCoefficient(), TaoADMMSetMisfitConstraintJacobian(), TAOADMM 1103 1104 @*/ 1105 PetscErrorCode TaoADMMSetRegularizerConstraintJacobian(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1106 { 1107 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1108 PetscErrorCode ierr; 1109 1110 PetscFunctionBegin; 1111 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1112 if (J) { 1113 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1114 PetscCheckSameComm(tao,1,J,2); 1115 } 1116 if (Jpre) { 1117 PetscValidHeaderSpecific(Jpre,MAT_CLASSID,3); 1118 PetscCheckSameComm(tao,1,Jpre,3); 1119 } 1120 if (ctx) am->regjacobianP = ctx; 1121 if (func) am->ops->regjac = func; 1122 1123 if (J) { 1124 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 1125 ierr = MatDestroy(&am->JB);CHKERRQ(ierr); 1126 am->JB = J; 1127 } 1128 if (Jpre) { 1129 ierr = PetscObjectReference((PetscObject)Jpre);CHKERRQ(ierr); 1130 ierr = MatDestroy(&am->JBpre);CHKERRQ(ierr); 1131 am->JBpre = Jpre; 1132 } 1133 PetscFunctionReturn(0); 1134 } 1135 1136 /*@C 1137 TaoADMMSetMisfitObjectiveAndGradientRoutine - Sets the user-defined misfit call-back function 1138 1139 Collective on tao 1140 1141 Input Parameters: 1142 + tao - the Tao context 1143 . func - function pointer for the misfit value and gradient evaluation 1144 - ctx - user context for the misfit 1145 1146 Level: advanced 1147 1148 .seealso: TAOADMM 1149 1150 @*/ 1151 PetscErrorCode TaoADMMSetMisfitObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx) 1152 { 1153 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1154 1155 PetscFunctionBegin; 1156 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1157 am->misfitobjgradP = ctx; 1158 am->ops->misfitobjgrad = func; 1159 PetscFunctionReturn(0); 1160 } 1161 1162 /*@C 1163 TaoADMMSetMisfitHessianRoutine - Sets the user-defined misfit Hessian call-back 1164 function into the algorithm, to be used for subsolverX. 1165 1166 Collective on tao 1167 1168 Input Parameters: 1169 + tao - the Tao context 1170 . H - user-created matrix for the Hessian of the misfit term 1171 . Hpre - user-created matrix for the preconditioner of Hessian of the misfit term 1172 . func - function pointer for the misfit Hessian evaluation 1173 - ctx - user context for the misfit Hessian 1174 1175 Level: advanced 1176 1177 .seealso: TAOADMM 1178 1179 @*/ 1180 PetscErrorCode TaoADMMSetMisfitHessianRoutine(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1181 { 1182 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1183 PetscErrorCode ierr; 1184 1185 PetscFunctionBegin; 1186 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1187 if (H) { 1188 PetscValidHeaderSpecific(H,MAT_CLASSID,2); 1189 PetscCheckSameComm(tao,1,H,2); 1190 } 1191 if (Hpre) { 1192 PetscValidHeaderSpecific(Hpre,MAT_CLASSID,3); 1193 PetscCheckSameComm(tao,1,Hpre,3); 1194 } 1195 if (ctx) { 1196 am->misfithessP = ctx; 1197 } 1198 if (func) { 1199 am->ops->misfithess = func; 1200 } 1201 if (H) { 1202 ierr = PetscObjectReference((PetscObject)H);CHKERRQ(ierr); 1203 ierr = MatDestroy(&am->Hx);CHKERRQ(ierr); 1204 am->Hx = H; 1205 } 1206 if (Hpre) { 1207 ierr = PetscObjectReference((PetscObject)Hpre);CHKERRQ(ierr); 1208 ierr = MatDestroy(&am->Hxpre);CHKERRQ(ierr); 1209 am->Hxpre = Hpre; 1210 } 1211 PetscFunctionReturn(0); 1212 } 1213 1214 /*@C 1215 TaoADMMSetRegularizerObjectiveAndGradientRoutine - Sets the user-defined regularizer call-back function 1216 1217 Collective on tao 1218 1219 Input Parameters: 1220 + tao - the Tao context 1221 . func - function pointer for the regularizer value and gradient evaluation 1222 - ctx - user context for the regularizer 1223 1224 Level: advanced 1225 1226 .seealso: TAOADMM 1227 1228 @*/ 1229 PetscErrorCode TaoADMMSetRegularizerObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx) 1230 { 1231 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1232 1233 PetscFunctionBegin; 1234 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1235 am->regobjgradP = ctx; 1236 am->ops->regobjgrad = func; 1237 PetscFunctionReturn(0); 1238 } 1239 1240 /*@C 1241 TaoADMMSetRegularizerHessianRoutine - Sets the user-defined regularizer Hessian call-back 1242 function, to be used for subsolverZ. 1243 1244 Collective on tao 1245 1246 Input Parameters: 1247 + tao - the Tao context 1248 . H - user-created matrix for the Hessian of the regularization term 1249 . Hpre - user-created matrix for the preconditioner of Hessian of the regularization term 1250 . func - function pointer for the regularizer Hessian evaluation 1251 - ctx - user context for the regularizer Hessian 1252 1253 Level: advanced 1254 1255 .seealso: TAOADMM 1256 1257 @*/ 1258 PetscErrorCode TaoADMMSetRegularizerHessianRoutine(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1259 { 1260 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1261 PetscErrorCode ierr; 1262 1263 PetscFunctionBegin; 1264 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1265 if (H) { 1266 PetscValidHeaderSpecific(H,MAT_CLASSID,2); 1267 PetscCheckSameComm(tao,1,H,2); 1268 } 1269 if (Hpre) { 1270 PetscValidHeaderSpecific(Hpre,MAT_CLASSID,3); 1271 PetscCheckSameComm(tao,1,Hpre,3); 1272 } 1273 if (ctx) { 1274 am->reghessP = ctx; 1275 } 1276 if (func) { 1277 am->ops->reghess = func; 1278 } 1279 if (H) { 1280 ierr = PetscObjectReference((PetscObject)H);CHKERRQ(ierr); 1281 ierr = MatDestroy(&am->Hz);CHKERRQ(ierr); 1282 am->Hz = H; 1283 } 1284 if (Hpre) { 1285 ierr = PetscObjectReference((PetscObject)Hpre);CHKERRQ(ierr); 1286 ierr = MatDestroy(&am->Hzpre);CHKERRQ(ierr); 1287 am->Hzpre = Hpre; 1288 } 1289 PetscFunctionReturn(0); 1290 } 1291 1292 /*@ 1293 TaoGetADMMParentTao - Gets pointer to parent ADMM tao, used by inner subsolver. 1294 1295 Collective on tao 1296 1297 Input Parameter: 1298 . tao - the Tao context 1299 1300 Output Parameter: 1301 . admm_tao - the parent Tao context 1302 1303 Level: advanced 1304 1305 .seealso: TAOADMM 1306 1307 @*/ 1308 PetscErrorCode TaoGetADMMParentTao(Tao tao, Tao *admm_tao) 1309 { 1310 PetscErrorCode ierr; 1311 1312 PetscFunctionBegin; 1313 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1314 ierr = PetscObjectQuery((PetscObject)tao,"TaoGetADMMParentTao_ADMM", (PetscObject*) admm_tao);CHKERRQ(ierr); 1315 PetscFunctionReturn(0); 1316 } 1317 1318 /*@ 1319 TaoADMMGetDualVector - Returns the dual vector associated with the current TAOADMM state 1320 1321 Not Collective 1322 1323 Input Parameter: 1324 . tao - the Tao context 1325 1326 Output Parameter: 1327 . Y - the current solution 1328 1329 Level: intermediate 1330 1331 .seealso: TAOADMM 1332 1333 @*/ 1334 PetscErrorCode TaoADMMGetDualVector(Tao tao, Vec *Y) 1335 { 1336 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1337 1338 PetscFunctionBegin; 1339 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1340 *Y = am->y; 1341 PetscFunctionReturn(0); 1342 } 1343 1344 /*@ 1345 TaoADMMSetRegularizerType - Set regularizer type for ADMM routine 1346 1347 Not Collective 1348 1349 Input Parameters: 1350 + tao - the Tao context 1351 - type - regularizer type 1352 1353 Options Database: 1354 . -tao_admm_regularizer_type <admm_regularizer_user,admm_regularizer_soft_thresh> 1355 1356 Level: intermediate 1357 1358 .seealso: TaoADMMGetRegularizerType(), TaoADMMRegularizerType, TAOADMM 1359 @*/ 1360 PetscErrorCode TaoADMMSetRegularizerType(Tao tao, TaoADMMRegularizerType type) 1361 { 1362 PetscErrorCode ierr; 1363 1364 PetscFunctionBegin; 1365 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1366 PetscValidLogicalCollectiveEnum(tao,type,2); 1367 ierr = PetscTryMethod(tao,"TaoADMMSetRegularizerType_C",(Tao,TaoADMMRegularizerType),(tao,type));CHKERRQ(ierr); 1368 PetscFunctionReturn(0); 1369 } 1370 1371 /*@ 1372 TaoADMMGetRegularizerType - Gets the type of regularizer routine for ADMM 1373 1374 Not Collective 1375 1376 Input Parameter: 1377 . tao - the Tao context 1378 1379 Output Parameter: 1380 . type - the type of regularizer 1381 1382 Options Database: 1383 . -tao_admm_regularizer_type <admm_regularizer_user,admm_regularizer_soft_thresh> 1384 1385 Level: intermediate 1386 1387 .seealso: TaoADMMSetRegularizerType(), TaoADMMRegularizerType, TAOADMM 1388 @*/ 1389 PetscErrorCode TaoADMMGetRegularizerType(Tao tao, TaoADMMRegularizerType *type) 1390 { 1391 PetscErrorCode ierr; 1392 1393 PetscFunctionBegin; 1394 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1395 ierr = PetscUseMethod(tao,"TaoADMMGetRegularizerType_C",(Tao,TaoADMMRegularizerType*),(tao,type));CHKERRQ(ierr); 1396 PetscFunctionReturn(0); 1397 } 1398 1399 /*@ 1400 TaoADMMSetUpdateType - Set update routine for ADMM routine 1401 1402 Not Collective 1403 1404 Input Parameters: 1405 + tao - the Tao context 1406 - type - spectral parameter update type 1407 1408 Level: intermediate 1409 1410 .seealso: TaoADMMGetUpdateType(), TaoADMMUpdateType, TAOADMM 1411 @*/ 1412 PetscErrorCode TaoADMMSetUpdateType(Tao tao, TaoADMMUpdateType type) 1413 { 1414 PetscErrorCode ierr; 1415 1416 PetscFunctionBegin; 1417 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1418 PetscValidLogicalCollectiveEnum(tao,type,2); 1419 ierr = PetscTryMethod(tao,"TaoADMMSetUpdateType_C",(Tao,TaoADMMUpdateType),(tao,type));CHKERRQ(ierr); 1420 PetscFunctionReturn(0); 1421 } 1422 1423 /*@ 1424 TaoADMMGetUpdateType - Gets the type of spectral penalty update routine for ADMM 1425 1426 Not Collective 1427 1428 Input Parameter: 1429 . tao - the Tao context 1430 1431 Output Parameter: 1432 . type - the type of spectral penalty update routine 1433 1434 Level: intermediate 1435 1436 .seealso: TaoADMMSetUpdateType(), TaoADMMUpdateType, TAOADMM 1437 @*/ 1438 PetscErrorCode TaoADMMGetUpdateType(Tao tao, TaoADMMUpdateType *type) 1439 { 1440 PetscErrorCode ierr; 1441 1442 PetscFunctionBegin; 1443 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1444 ierr = PetscUseMethod(tao,"TaoADMMGetUpdateType_C",(Tao,TaoADMMUpdateType*),(tao,type));CHKERRQ(ierr); 1445 PetscFunctionReturn(0); 1446 } 1447