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 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 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 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 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(PETSC_COMM_WORLD,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(PETSC_COMM_WORLD,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!");CHKERRQ(ierr); 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 specificed 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 baisc 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 = 0; 799 am->ops->reghess = 0; 800 am->gamma = 1; 801 am->regobjgradP = 0; 802 am->reghessP = 0; 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 PETSC_FALSE for the case when the Hessian matrix does not change. TRUE for otherwise. 831 832 Collective on Tao 833 834 Input Parameters: 835 + tao - the Tao solver context 836 - b - the Hessian matrix change status boolean 837 838 Level: advanced 839 @*/ 840 PetscErrorCode TaoADMMSetMisfitHessianChangeStatus(Tao tao, PetscBool b) 841 { 842 TAO_ADMM *am = (TAO_ADMM*)tao->data; 843 844 PetscFunctionBegin; 845 am->Hxchange = b; 846 PetscFunctionReturn(0); 847 } 848 849 /*@ 850 TaoADMMSetRegHessianChangeStatus - Set boolean that determines whether Hessian matrix of regularization subsolver changes with respect to input vector. 851 PETSC_FALSE for the case when the Hessian matrix does not change. TRUE for otherwise. 852 853 Collective on Tao 854 855 Input Parameters: 856 + tao - the Tao solver context 857 - b - the Hessian matrix change status boolean 858 859 Level: advanced 860 @*/ 861 PetscErrorCode TaoADMMSetRegHessianChangeStatus(Tao tao, PetscBool b) 862 { 863 TAO_ADMM *am = (TAO_ADMM*)tao->data; 864 865 PetscFunctionBegin; 866 am->Hzchange = b; 867 PetscFunctionReturn(0); 868 } 869 870 /*@ 871 TaoADMMSetSpectralPenalty - Set the spectral penalty (mu) value 872 873 Collective on Tao 874 875 Input Parameters: 876 + tao - the Tao solver context 877 - mu - spectral penalty to be set 878 879 Level: advanced 880 881 .seealso: TaoADMMSetMinimumSpectralPenalty() 882 @*/ 883 PetscErrorCode TaoADMMSetSpectralPenalty(Tao tao, PetscReal mu) 884 { 885 TAO_ADMM *am = (TAO_ADMM*)tao->data; 886 887 PetscFunctionBegin; 888 am->mu = mu; 889 PetscFunctionReturn(0); 890 } 891 892 /*@ 893 TaoADMMGetSpectralPenalty - Get the spectral penalty (mu) value 894 895 Collective on Tao 896 897 Input Parameters: 898 + tao - the Tao solver context 899 - mu - spectral penalty 900 901 Level: advanced 902 903 .seealso: TaoADMMSetMinimumSpectralPenalty(), TaoADMMSetSpectralPenalty() 904 @*/ 905 PetscErrorCode TaoADMMGetSpectralPenalty(Tao tao, PetscReal *mu) 906 { 907 TAO_ADMM *am = (TAO_ADMM*)tao->data; 908 909 PetscFunctionBegin; 910 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 911 PetscValidRealPointer(mu,2); 912 *mu = am->mu; 913 PetscFunctionReturn(0); 914 } 915 916 /*@ 917 TaoADMMGetMisfitSubsolver - Get the pointer to the misfit subsolver inside ADMM 918 919 Collective on Tao 920 921 Input Parameters: 922 + tao - the Tao solver context 923 - misfit - the Tao subsolver context 924 925 Level: advanced 926 @*/ 927 PetscErrorCode TaoADMMGetMisfitSubsolver(Tao tao, Tao *misfit) 928 { 929 TAO_ADMM *am = (TAO_ADMM*)tao->data; 930 931 PetscFunctionBegin; 932 *misfit = am->subsolverX; 933 PetscFunctionReturn(0); 934 } 935 936 /*@ 937 TaoADMMGetRegularizationSubsolver - Get the pointer to the regularization subsolver inside ADMM 938 939 Collective on Tao 940 941 Input Parameters: 942 + tao - the Tao solver context 943 - reg - the Tao subsolver context 944 945 Level: advanced 946 @*/ 947 PetscErrorCode TaoADMMGetRegularizationSubsolver(Tao tao, Tao *reg) 948 { 949 TAO_ADMM *am = (TAO_ADMM*)tao->data; 950 951 PetscFunctionBegin; 952 *reg = am->subsolverZ; 953 PetscFunctionReturn(0); 954 } 955 956 /*@ 957 TaoADMMSetConstraintVectorRHS - Set the RHS constraint vector for ADMM 958 959 Collective on Tao 960 961 Input Parameters: 962 + tao - the Tao solver context 963 - c - RHS vector 964 965 Level: advanced 966 @*/ 967 PetscErrorCode TaoADMMSetConstraintVectorRHS(Tao tao, Vec c) 968 { 969 TAO_ADMM *am = (TAO_ADMM*)tao->data; 970 971 PetscFunctionBegin; 972 am->constraint = c; 973 PetscFunctionReturn(0); 974 } 975 976 /*@ 977 TaoADMMSetMinimumSpectralPenalty - Set the minimum value for spectral penalty 978 979 Collective on Tao 980 981 Input Parameters: 982 + tao - the Tao solver context 983 - mu - minimum spectral penalty value 984 985 Level: advanced 986 987 .seealso: TaoADMMGetSpectralPenalty() 988 @*/ 989 PetscErrorCode TaoADMMSetMinimumSpectralPenalty(Tao tao, PetscReal mu) 990 { 991 TAO_ADMM *am = (TAO_ADMM*)tao->data; 992 993 PetscFunctionBegin; 994 am->mumin= mu; 995 PetscFunctionReturn(0); 996 } 997 998 /*@ 999 TaoADMMSetRegularizerCoefficient - Set the regularization coefficient lambda for L1 norm regularization case 1000 1001 Collective on Tao 1002 1003 Input Parameters: 1004 + tao - the Tao solver context 1005 - lambda - L1-norm regularizer coefficient 1006 1007 Level: advanced 1008 @*/ 1009 PetscErrorCode TaoADMMSetRegularizerCoefficient(Tao tao, PetscReal lambda) 1010 { 1011 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1012 1013 PetscFunctionBegin; 1014 am->lambda = lambda; 1015 PetscFunctionReturn(0); 1016 } 1017 1018 /*@C 1019 TaoADMMSetMisfitConstraintJacobian- Set the constraint matrix B for ADMM algorithm. Matrix B constraints z variable. 1020 1021 Collective on Tao 1022 1023 Input Parameters: 1024 + tao - the Tao solver context 1025 . J - user-created regularizer constraint Jacobian matrix 1026 . Jpre - user-created regularizer Jacobian constraint preconditioner matrix 1027 . func - function pointer for the regularizer constraint Jacobian update function 1028 - ctx - user context for the regularizer Hessian 1029 1030 Level: advanced 1031 @*/ 1032 PetscErrorCode TaoADMMSetMisfitConstraintJacobian(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1033 { 1034 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1035 PetscErrorCode ierr; 1036 1037 PetscFunctionBegin; 1038 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1039 if (J) { 1040 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1041 PetscCheckSameComm(tao,1,J,2); 1042 } 1043 if (Jpre) { 1044 PetscValidHeaderSpecific(Jpre,MAT_CLASSID,3); 1045 PetscCheckSameComm(tao,1,Jpre,3); 1046 } 1047 if (ctx) am->misfitjacobianP = ctx; 1048 if (func) am->ops->misfitjac = func; 1049 1050 if (J) { 1051 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 1052 ierr = MatDestroy(&am->JA);CHKERRQ(ierr); 1053 am->JA = J; 1054 } 1055 if (Jpre) { 1056 ierr = PetscObjectReference((PetscObject)Jpre);CHKERRQ(ierr); 1057 ierr = MatDestroy(&am->JApre);CHKERRQ(ierr); 1058 am->JApre = Jpre; 1059 } 1060 PetscFunctionReturn(0); 1061 } 1062 1063 /*@C 1064 TaoADMMSetRegularizerConstraintJacobian- Set the constraint matrix B for ADMM algorithm. Matrix B constraints z variable. 1065 1066 Collective on Tao 1067 1068 Input Parameters: 1069 + tao - the Tao solver context 1070 . J - user-created regularizer constraint Jacobian matrix 1071 . Jpre - user-created regularizer Jacobian constraint preconditioner matrix 1072 . func - function pointer for the regularizer constraint Jacobian update function 1073 - ctx - user context for the regularizer Hessian 1074 1075 Level: advanced 1076 @*/ 1077 PetscErrorCode TaoADMMSetRegularizerConstraintJacobian(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1078 { 1079 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1080 PetscErrorCode ierr; 1081 1082 PetscFunctionBegin; 1083 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1084 if (J) { 1085 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 1086 PetscCheckSameComm(tao,1,J,2); 1087 } 1088 if (Jpre) { 1089 PetscValidHeaderSpecific(Jpre,MAT_CLASSID,3); 1090 PetscCheckSameComm(tao,1,Jpre,3); 1091 } 1092 if (ctx) am->regjacobianP = ctx; 1093 if (func) am->ops->regjac = func; 1094 1095 if (J) { 1096 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 1097 ierr = MatDestroy(&am->JB);CHKERRQ(ierr); 1098 am->JB = J; 1099 } 1100 if (Jpre) { 1101 ierr = PetscObjectReference((PetscObject)Jpre);CHKERRQ(ierr); 1102 ierr = MatDestroy(&am->JBpre);CHKERRQ(ierr); 1103 am->JBpre = Jpre; 1104 } 1105 PetscFunctionReturn(0); 1106 } 1107 1108 /*@C 1109 TaoADMMSetMisfitObjectiveAndGradientRoutine - Sets the user-defined misfit call-back 1110 function into the algorithm. 1111 1112 Input Parameters: 1113 + tao - the Tao context 1114 . func - function pointer for the misfit value and gradient evaluation 1115 - ctx - user context for the misfit 1116 1117 Level: advanced 1118 @*/ 1119 PetscErrorCode TaoADMMSetMisfitObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx) 1120 { 1121 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1122 1123 PetscFunctionBegin; 1124 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1125 am->misfitobjgradP = ctx; 1126 am->ops->misfitobjgrad = func; 1127 PetscFunctionReturn(0); 1128 } 1129 1130 /*@C 1131 TaoADMMSetMisfitHessianRoutine - Sets the user-defined misfit Hessian call-back 1132 function into the algorithm, to be used for subsolverX. 1133 1134 Input Parameters: 1135 + tao - the Tao context 1136 . H - user-created matrix for the Hessian of the misfit term 1137 . Hpre - user-created matrix for the preconditioner of Hessian of the misfit term 1138 . func - function pointer for the misfit Hessian evaluation 1139 - ctx - user context for the misfit Hessian 1140 1141 Level: advanced 1142 @*/ 1143 PetscErrorCode TaoADMMSetMisfitHessianRoutine(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1144 { 1145 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1146 PetscErrorCode ierr; 1147 1148 PetscFunctionBegin; 1149 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1150 if (H) { 1151 PetscValidHeaderSpecific(H,MAT_CLASSID,2); 1152 PetscCheckSameComm(tao,1,H,2); 1153 } 1154 if (Hpre) { 1155 PetscValidHeaderSpecific(Hpre,MAT_CLASSID,3); 1156 PetscCheckSameComm(tao,1,Hpre,3); 1157 } 1158 if (ctx) { 1159 am->misfithessP = ctx; 1160 } 1161 if (func) { 1162 am->ops->misfithess = func; 1163 } 1164 if (H) { 1165 ierr = PetscObjectReference((PetscObject)H);CHKERRQ(ierr); 1166 ierr = MatDestroy(&am->Hx);CHKERRQ(ierr); 1167 am->Hx = H; 1168 } 1169 if (Hpre) { 1170 ierr = PetscObjectReference((PetscObject)Hpre);CHKERRQ(ierr); 1171 ierr = MatDestroy(&am->Hxpre);CHKERRQ(ierr); 1172 am->Hxpre = Hpre; 1173 } 1174 PetscFunctionReturn(0); 1175 } 1176 1177 /*@C 1178 TaoADMMSetRegularizerObjectiveAndGradientRoutine - Sets the user-defined regularizer call-back 1179 function into the algorithm. 1180 1181 Input Parameters: 1182 + tao - the Tao context 1183 . func - function pointer for the regularizer value and gradient evaluation 1184 - ctx - user context for the regularizer 1185 1186 Level: advanced 1187 @*/ 1188 PetscErrorCode TaoADMMSetRegularizerObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx) 1189 { 1190 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1191 1192 PetscFunctionBegin; 1193 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1194 am->regobjgradP = ctx; 1195 am->ops->regobjgrad = func; 1196 PetscFunctionReturn(0); 1197 } 1198 1199 /*@C 1200 TaoADMMSetRegularizerHessianRoutine - Sets the user-defined regularizer Hessian call-back 1201 function into the algorithm, to be used for subsolverZ. 1202 1203 Input Parameters: 1204 + tao - the Tao context 1205 . H - user-created matrix for the Hessian of the regularization term 1206 . Hpre - user-created matrix for the preconditioner of Hessian of the regularization term 1207 . func - function pointer for the regularizer Hessian evaluation 1208 - ctx - user context for the regularizer Hessian 1209 1210 Level: advanced 1211 @*/ 1212 PetscErrorCode TaoADMMSetRegularizerHessianRoutine(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao, Vec, Mat, Mat, void*), void *ctx) 1213 { 1214 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1215 PetscErrorCode ierr; 1216 1217 PetscFunctionBegin; 1218 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1219 if (H) { 1220 PetscValidHeaderSpecific(H,MAT_CLASSID,2); 1221 PetscCheckSameComm(tao,1,H,2); 1222 } 1223 if (Hpre) { 1224 PetscValidHeaderSpecific(Hpre,MAT_CLASSID,3); 1225 PetscCheckSameComm(tao,1,Hpre,3); 1226 } 1227 if (ctx) { 1228 am->reghessP = ctx; 1229 } 1230 if (func) { 1231 am->ops->reghess = func; 1232 } 1233 if (H) { 1234 ierr = PetscObjectReference((PetscObject)H);CHKERRQ(ierr); 1235 ierr = MatDestroy(&am->Hz);CHKERRQ(ierr); 1236 am->Hz = H; 1237 } 1238 if (Hpre) { 1239 ierr = PetscObjectReference((PetscObject)Hpre);CHKERRQ(ierr); 1240 ierr = MatDestroy(&am->Hzpre);CHKERRQ(ierr); 1241 am->Hzpre = Hpre; 1242 } 1243 PetscFunctionReturn(0); 1244 } 1245 1246 /*@ 1247 TaoGetADMMParentTao - Gets pointer to parent ADMM tao. 1248 To be used by inner subsolver. 1249 1250 Input Parameters: 1251 + tao - the Tao context 1252 - admm_tao - the parent Tao context 1253 1254 Level: advanced 1255 @*/ 1256 PetscErrorCode TaoGetADMMParentTao(Tao tao, Tao *admm_tao) 1257 { 1258 PetscErrorCode ierr; 1259 1260 PetscFunctionBegin; 1261 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1262 ierr = PetscObjectQuery((PetscObject)tao,"TaoGetADMMParentTao_ADMM", (PetscObject*) admm_tao);CHKERRQ(ierr); 1263 PetscFunctionReturn(0); 1264 } 1265 1266 /*@ 1267 TaoADMMGetDualVector - Returns the dual vector with the current TAOADMM state 1268 1269 Not Collective 1270 1271 Input Parameter: 1272 + tao - the Tao context 1273 - Y - the current solution 1274 1275 Level: intermediate 1276 @*/ 1277 PetscErrorCode TaoADMMGetDualVector(Tao tao, Vec *Y) 1278 { 1279 TAO_ADMM *am = (TAO_ADMM*)tao->data; 1280 1281 PetscFunctionBegin; 1282 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1283 *Y = am->y; 1284 PetscFunctionReturn(0); 1285 } 1286 1287 /*@ 1288 TaoADMMSetRegularizerType - Set regularizer type for ADMM routine 1289 1290 Not Collective 1291 1292 Input Parameter: 1293 + tao - the Tao context 1294 - type - regulairzer type 1295 1296 Level: intermediate 1297 1298 .seealso: TaoADMMGetRegularizerType(), TaoADMMRegularizerType 1299 @*/ 1300 PetscErrorCode TaoADMMSetRegularizerType(Tao tao, TaoADMMRegularizerType type) 1301 { 1302 PetscErrorCode ierr; 1303 1304 PetscFunctionBegin; 1305 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1306 PetscValidLogicalCollectiveEnum(tao,type,2); 1307 ierr = PetscTryMethod(tao,"TaoADMMSetRegularizerType_C",(Tao,TaoADMMRegularizerType),(tao,type));CHKERRQ(ierr); 1308 PetscFunctionReturn(0); 1309 } 1310 1311 /*@ 1312 TaoADMMGetRegularizerType - Gets the type of regularizer routine for ADMM 1313 1314 Not Collective 1315 1316 Input Parameter: 1317 . tao - the Tao context 1318 1319 Output Parameter: 1320 . type - the type of regularizer 1321 1322 Options Database: 1323 . -tao_admm_regularizer_type <admm_regularizer_user,admm_regularizer_soft_thresh> 1324 1325 Level: intermediate 1326 1327 .seealso: TaoADMMSetRegularizerType(), TaoADMMRegularizerType 1328 @*/ 1329 PetscErrorCode TaoADMMGetRegularizerType(Tao tao, TaoADMMRegularizerType *type) 1330 { 1331 PetscErrorCode ierr; 1332 1333 PetscFunctionBegin; 1334 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1335 ierr = PetscUseMethod(tao,"TaoADMMGetRegularizerType_C",(Tao,TaoADMMRegularizerType*),(tao,type));CHKERRQ(ierr); 1336 PetscFunctionReturn(0); 1337 } 1338 1339 /*@ 1340 TaoADMMSetUpdateType - Set update routine for ADMM routine 1341 1342 Not Collective 1343 1344 Input Parameter: 1345 + tao - the Tao context 1346 - type - spectral parameter update type 1347 1348 Level: intermediate 1349 1350 .seealso: TaoADMMGetUpdateType(), TaoADMMUpdateType 1351 @*/ 1352 PetscErrorCode TaoADMMSetUpdateType(Tao tao, TaoADMMUpdateType type) 1353 { 1354 PetscErrorCode ierr; 1355 1356 PetscFunctionBegin; 1357 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1358 PetscValidLogicalCollectiveEnum(tao,type,2); 1359 ierr = PetscTryMethod(tao,"TaoADMMSetUpdateType_C",(Tao,TaoADMMUpdateType),(tao,type));CHKERRQ(ierr); 1360 PetscFunctionReturn(0); 1361 } 1362 1363 /*@ 1364 TaoADMMGetUpdateType - Gets the type of spectral penalty update routine for ADMM 1365 1366 Not Collective 1367 1368 Input Parameter: 1369 + tao - the Tao context 1370 1371 Output Parameter: 1372 . type - the type of spectral penalty update routine 1373 1374 Level: intermediate 1375 1376 .seealso: TaoADMMSetUpdateType(), TaoADMMUpdateType 1377 @*/ 1378 PetscErrorCode TaoADMMGetUpdateType(Tao tao, TaoADMMUpdateType *type) 1379 { 1380 PetscErrorCode ierr; 1381 1382 PetscFunctionBegin; 1383 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 1384 ierr = PetscUseMethod(tao,"TaoADMMGetUpdateType_C",(Tao,TaoADMMUpdateType*),(tao,type));CHKERRQ(ierr); 1385 PetscFunctionReturn(0); 1386 } 1387 1388