xref: /petsc/src/tao/constrained/impls/admm/admm.c (revision 6285c0a3eab9179dbf0b284c36c7c0086124b8a4)
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,&reg_func);CHKERRQ(ierr);
510*6285c0a3SHansol  Suh       } else {
511*6285c0a3SHansol  Suh         (*am->ops->regobjgrad)(am->subsolverZ,am->subsolverX->solution,&reg_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,&reg_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