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