1737f463aSAlp Dener #include <../src/tao/leastsquares/impls/brgn/brgn.h> 2737f463aSAlp Dener 30d71dc2bSXiang Huang /* Old code 4737f463aSAlp Dener static PetscErrorCode GNHessianProd(Mat H, Vec in, Vec out) 5737f463aSAlp Dener { 6737f463aSAlp Dener TAO_BRGN *gn; 7737f463aSAlp Dener PetscErrorCode ierr; 8737f463aSAlp Dener 9737f463aSAlp Dener PetscFunctionBegin; 10737f463aSAlp Dener ierr = MatShellGetContext(H, &gn);CHKERRQ(ierr); 11737f463aSAlp Dener ierr = MatMult(gn->subsolver->ls_jac, in, gn->r_work);CHKERRQ(ierr); 12737f463aSAlp Dener ierr = MatMultTranspose(gn->subsolver->ls_jac, gn->r_work, out);CHKERRQ(ierr); 13737f463aSAlp Dener ierr = VecAXPY(out, gn->lambda, in);CHKERRQ(ierr); 14737f463aSAlp Dener PetscFunctionReturn(0); 15737f463aSAlp Dener } 16737f463aSAlp Dener 17737f463aSAlp Dener static PetscErrorCode GNObjectiveGradientEval(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr) 18737f463aSAlp Dener { 19737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)ptr; 20737f463aSAlp Dener PetscScalar xnorm2; 21737f463aSAlp Dener PetscErrorCode ierr; 22737f463aSAlp Dener 23737f463aSAlp Dener PetscFunctionBegin; 24737f463aSAlp Dener ierr = TaoComputeResidual(tao, X, tao->ls_res);CHKERRQ(ierr); 25737f463aSAlp Dener ierr = VecDotBegin(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 26e1e80dc8SAlp Dener ierr = VecAXPBYPCZ(gn->x_work, 1.0, -1.0, 0.0, X, gn->x_old);CHKERRQ(ierr); 27737f463aSAlp Dener ierr = VecDotBegin(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr); 28737f463aSAlp Dener ierr = VecDotEnd(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 29737f463aSAlp Dener ierr = VecDotEnd(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr); 30e1e80dc8SAlp Dener *fcn = 0.5*(*fcn) + 0.5*gn->lambda*xnorm2; 31737f463aSAlp Dener 32737f463aSAlp Dener ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 33737f463aSAlp Dener ierr = MatMultTranspose(tao->ls_jac, tao->ls_res, G);CHKERRQ(ierr); 34e1e80dc8SAlp Dener ierr = VecAXPBYPCZ(G, gn->lambda, -gn->lambda, 1.0, X, gn->x_old);CHKERRQ(ierr); 35737f463aSAlp Dener PetscFunctionReturn(0); 36737f463aSAlp Dener } 370d71dc2bSXiang Huang */ 380d71dc2bSXiang Huang 390d71dc2bSXiang Huang static PetscErrorCode GNHessianProd(Mat H, Vec in, Vec out) 400d71dc2bSXiang Huang { 410d71dc2bSXiang Huang TAO_BRGN *gn; 420d71dc2bSXiang Huang PetscErrorCode ierr; 430d71dc2bSXiang Huang 440d71dc2bSXiang Huang PetscFunctionBegin; 450d71dc2bSXiang Huang ierr = MatShellGetContext(H, &gn);CHKERRQ(ierr); 460d71dc2bSXiang Huang ierr = MatMult(gn->subsolver->ls_jac, in, gn->r_work);CHKERRQ(ierr); 470d71dc2bSXiang Huang ierr = MatMultTranspose(gn->subsolver->ls_jac, gn->r_work, out);CHKERRQ(ierr); 48*7cea06e1SXiang Huang /* out = out + lambda*D'*(diag.*(D*in)) */ 49*7cea06e1SXiang Huang ierr = MatMult(gn->D, in, gn->y);CHKERRQ(ierr); /* y = D*in */ 50*7cea06e1SXiang Huang ierr = VecPointwiseMult(gn->y_work, gn->diag, gn->y);CHKERRQ(ierr); /* y_work = diag.*(D*in), where diag = epsilon^2 ./ sqrt(x.^2+epsilon^2).^3 */ 51*7cea06e1SXiang Huang ierr = MatMultTranspose(gn->D, gn->y_work, gn->x_work);CHKERRQ(ierr); /* x_work = D'*(diag.*(D*in)) */ 528ac80d48SXiang Huang ierr = VecAXPY(out, gn->lambda, gn->x_work);CHKERRQ(ierr); 530d71dc2bSXiang Huang 540d71dc2bSXiang Huang PetscFunctionReturn(0); 550d71dc2bSXiang Huang } 560d71dc2bSXiang Huang 570d71dc2bSXiang Huang static PetscErrorCode GNObjectiveGradientEval(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr) 580d71dc2bSXiang Huang { 590d71dc2bSXiang Huang TAO_BRGN *gn = (TAO_BRGN *)ptr; 60*7cea06e1SXiang Huang PetscInt Ny; /* dimension of D*X */ 61*7cea06e1SXiang Huang PetscScalar yESum; 620d71dc2bSXiang Huang PetscErrorCode ierr; 630d71dc2bSXiang Huang 640d71dc2bSXiang Huang PetscFunctionBegin; 658ac80d48SXiang Huang /* compute objective */ 668ac80d48SXiang Huang /* compute first term ||ls_res||^2 */ 670d71dc2bSXiang Huang ierr = TaoComputeResidual(tao, X, tao->ls_res);CHKERRQ(ierr); 680d71dc2bSXiang Huang ierr = VecDotBegin(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 690d71dc2bSXiang Huang ierr = VecDotEnd(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 70*7cea06e1SXiang Huang /* add the second term lambda*sum(sqrt(y.^2+epsilon^2) - epsilon), where y = D*x*/ 71*7cea06e1SXiang Huang ierr = MatMult(gn->D, X, gn->y);CHKERRQ(ierr); /* y = D*x */ 72*7cea06e1SXiang Huang ierr = VecPointwiseMult(gn->y_work, gn->y, gn->y);CHKERRQ(ierr); 73*7cea06e1SXiang Huang ierr = VecShift(gn->y_work, gn->epsilon*gn->epsilon);CHKERRQ(ierr); 74*7cea06e1SXiang Huang ierr = VecSqrtAbs(gn->y_work);CHKERRQ(ierr); /* gn->y_work = sqrt(y.^2+epsilon^2) */ 75*7cea06e1SXiang Huang ierr = VecSum(gn->y_work, &yESum);CHKERRQ(ierr);CHKERRQ(ierr); 76*7cea06e1SXiang Huang ierr = VecGetSize(gn->y, &Ny);CHKERRQ(ierr); 77*7cea06e1SXiang Huang *fcn = 0.5*(*fcn) + gn->lambda*(yESum - Ny*gn->epsilon); 780d71dc2bSXiang Huang 798ac80d48SXiang Huang /* compute gradient G */ 800d71dc2bSXiang Huang ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 810d71dc2bSXiang Huang ierr = MatMultTranspose(tao->ls_jac, tao->ls_res, G);CHKERRQ(ierr); 82*7cea06e1SXiang Huang /* compute G = G + lambda*D'*(y./sqrt(y.^2+epsilon^2)), where y = D*x */ 83*7cea06e1SXiang Huang ierr = VecPointwiseDivide(gn->y_work, gn->y, gn->y_work);CHKERRQ(ierr); /* reuse y_work = y./sqrt(y.^2+epsilon^2) */ 84*7cea06e1SXiang Huang ierr = MatMultTranspose(gn->D, gn->y_work, gn->x_work);CHKERRQ(ierr); 858ac80d48SXiang Huang ierr = VecAXPY(G, gn->lambda, gn->x_work);CHKERRQ(ierr); 860d71dc2bSXiang Huang 870d71dc2bSXiang Huang PetscFunctionReturn(0); 880d71dc2bSXiang Huang } 890d71dc2bSXiang Huang 90737f463aSAlp Dener 91737f463aSAlp Dener static PetscErrorCode GNComputeHessian(Tao tao, Vec X, Mat H, Mat Hpre, void *ptr) 92737f463aSAlp Dener { 938ac80d48SXiang Huang TAO_BRGN *gn = (TAO_BRGN *)ptr; 94737f463aSAlp Dener PetscErrorCode ierr; 95737f463aSAlp Dener 96737f463aSAlp Dener PetscFunctionBegin; 97e1e80dc8SAlp Dener ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 980d71dc2bSXiang Huang 99*7cea06e1SXiang Huang /* calculate and store diagonal matrix as a vector: diag = epsilon^2 ./ sqrt(x.^2+epsilon^2).^3* --> diag = epsilon^2 ./ sqrt(y.^2+epsilon^2).^3, where y = D*x */ 100*7cea06e1SXiang Huang ierr = MatMult(gn->D, X, gn->y);CHKERRQ(ierr); /* y = D*x */ 101*7cea06e1SXiang Huang ierr = VecPointwiseMult(gn->y_work, gn->y, gn->y);CHKERRQ(ierr); 102*7cea06e1SXiang Huang ierr = VecShift(gn->y_work, gn->epsilon*gn->epsilon);CHKERRQ(ierr); 103*7cea06e1SXiang Huang ierr = VecCopy(gn->y_work, gn->diag);CHKERRQ(ierr); /* gn->diag = y.^2+epsilon^2 */ 104*7cea06e1SXiang Huang ierr = VecSqrtAbs(gn->y_work);CHKERRQ(ierr); /* gn->y_work = sqrt(y.^2+epsilon^2) */ 105*7cea06e1SXiang Huang ierr = VecPointwiseMult(gn->diag, gn->y_work, gn->diag);CHKERRQ(ierr); /* gn->diag = sqrt(y.^2+epsilon^2).^3 */ 1068ac80d48SXiang Huang ierr = VecReciprocal(gn->diag);CHKERRQ(ierr); 1078ac80d48SXiang Huang ierr = VecScale(gn->diag, gn->epsilon*gn->epsilon);CHKERRQ(ierr); 1088ac80d48SXiang Huang 109e1e80dc8SAlp Dener PetscFunctionReturn(0); 110e1e80dc8SAlp Dener } 111e1e80dc8SAlp Dener 112e1e80dc8SAlp Dener static PetscErrorCode GNHookFunction(Tao tao, PetscInt iter) 113e1e80dc8SAlp Dener { 114e1e80dc8SAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->user_update; 115e1e80dc8SAlp Dener PetscErrorCode ierr; 116e1e80dc8SAlp Dener 117e1e80dc8SAlp Dener PetscFunctionBegin; 118e1e80dc8SAlp Dener /* Update basic tao information from the subsolver */ 119e1e80dc8SAlp Dener gn->parent->nfuncs = tao->nfuncs; 120e1e80dc8SAlp Dener gn->parent->ngrads = tao->ngrads; 121e1e80dc8SAlp Dener gn->parent->nfuncgrads = tao->nfuncgrads; 122e1e80dc8SAlp Dener gn->parent->nhess = tao->nhess; 123e1e80dc8SAlp Dener gn->parent->niter = tao->niter; 124e1e80dc8SAlp Dener gn->parent->ksp_its = tao->ksp_its; 125e1e80dc8SAlp Dener gn->parent->ksp_tot_its = tao->ksp_tot_its; 126e1e80dc8SAlp Dener ierr = TaoGetConvergedReason(tao, &gn->parent->reason);CHKERRQ(ierr); 127e1e80dc8SAlp Dener /* Update the solution vectors */ 128e1e80dc8SAlp Dener if (iter == 0) { 129e1e80dc8SAlp Dener ierr = VecSet(gn->x_old, 0.0);CHKERRQ(ierr); 130e1e80dc8SAlp Dener } else { 131e1e80dc8SAlp Dener ierr = VecCopy(tao->solution, gn->x_old);CHKERRQ(ierr); 132e1e80dc8SAlp Dener ierr = VecCopy(tao->solution, gn->parent->solution);CHKERRQ(ierr); 133e1e80dc8SAlp Dener } 134e1e80dc8SAlp Dener /* Update the gradient */ 135e1e80dc8SAlp Dener ierr = VecCopy(tao->gradient, gn->parent->gradient);CHKERRQ(ierr); 136e1e80dc8SAlp Dener /* Call general purpose update function */ 137e1e80dc8SAlp Dener if (gn->parent->ops->update) { 138e1e80dc8SAlp Dener ierr = (*gn->parent->ops->update)(gn->parent, gn->parent->niter);CHKERRQ(ierr); 139737f463aSAlp Dener } 140737f463aSAlp Dener PetscFunctionReturn(0); 141737f463aSAlp Dener } 142737f463aSAlp Dener 143737f463aSAlp Dener static PetscErrorCode TaoSolve_BRGN(Tao tao) 144737f463aSAlp Dener { 145737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 146737f463aSAlp Dener PetscErrorCode ierr; 147737f463aSAlp Dener 148737f463aSAlp Dener PetscFunctionBegin; 149737f463aSAlp Dener ierr = TaoSolve(gn->subsolver);CHKERRQ(ierr); 150e1e80dc8SAlp Dener /* Update basic tao information from the subsolver */ 151e1e80dc8SAlp Dener tao->nfuncs = gn->subsolver->nfuncs; 152e1e80dc8SAlp Dener tao->ngrads = gn->subsolver->ngrads; 153e1e80dc8SAlp Dener tao->nfuncgrads = gn->subsolver->nfuncgrads; 154e1e80dc8SAlp Dener tao->nhess = gn->subsolver->nhess; 155e1e80dc8SAlp Dener tao->niter = gn->subsolver->niter; 156e1e80dc8SAlp Dener tao->ksp_its = gn->subsolver->ksp_its; 157e1e80dc8SAlp Dener tao->ksp_tot_its = gn->subsolver->ksp_tot_its; 158e1e80dc8SAlp Dener ierr = TaoGetConvergedReason(gn->subsolver, &tao->reason);CHKERRQ(ierr); 159e1e80dc8SAlp Dener /* Update vectors */ 160e1e80dc8SAlp Dener ierr = VecCopy(gn->subsolver->solution, tao->solution);CHKERRQ(ierr); 161e1e80dc8SAlp Dener ierr = VecCopy(gn->subsolver->gradient, tao->gradient);CHKERRQ(ierr); 162737f463aSAlp Dener PetscFunctionReturn(0); 163737f463aSAlp Dener } 164737f463aSAlp Dener 165737f463aSAlp Dener static PetscErrorCode TaoSetFromOptions_BRGN(PetscOptionItems *PetscOptionsObject,Tao tao) 166737f463aSAlp Dener { 167737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 168737f463aSAlp Dener PetscErrorCode ierr; 169737f463aSAlp Dener 170737f463aSAlp Dener PetscFunctionBegin; 1718ac80d48SXiang Huang /* old Tikhonov regularization code 172737f463aSAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Gauss-Newton method for least-squares problems using Tikhonov regularization");CHKERRQ(ierr); 173737f463aSAlp Dener ierr = PetscOptionsReal("-tao_brgn_lambda", "Tikhonov regularization factor", "", gn->lambda, &gn->lambda, NULL);CHKERRQ(ierr); 1748ac80d48SXiang Huang */ 1758ac80d48SXiang Huang ierr = PetscOptionsHead(PetscOptionsObject,"least-squares problems with L1 regularizer: ||f(x)||^2 + lambda*||x||_1. Currently L1-norm is approximated with smooth form");CHKERRQ(ierr); 1768ac80d48SXiang Huang ierr = PetscOptionsReal("-tao_brgn_lambda", "L1-norm regularizer weight", "", gn->lambda, &gn->lambda, NULL);CHKERRQ(ierr); 1778ac80d48SXiang Huang ierr = PetscOptionsReal("-tao_brgn_epsilon", "L1-norm smooth approximation parameter: ||x||_1 = sum(sqrt(x.^2+epsilon^2)-epsilon)", "", gn->epsilon, &gn->epsilon, NULL);CHKERRQ(ierr); 178737f463aSAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 179737f463aSAlp Dener ierr = TaoSetFromOptions(gn->subsolver);CHKERRQ(ierr); 180737f463aSAlp Dener PetscFunctionReturn(0); 181737f463aSAlp Dener } 182737f463aSAlp Dener 183737f463aSAlp Dener static PetscErrorCode TaoView_BRGN(Tao tao, PetscViewer viewer) 184737f463aSAlp Dener { 185737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 186737f463aSAlp Dener PetscErrorCode ierr; 187737f463aSAlp Dener 188737f463aSAlp Dener PetscFunctionBegin; 189e1e80dc8SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 190737f463aSAlp Dener ierr = TaoView(gn->subsolver, viewer);CHKERRQ(ierr); 191e1e80dc8SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 192737f463aSAlp Dener PetscFunctionReturn(0); 193737f463aSAlp Dener } 194737f463aSAlp Dener 195737f463aSAlp Dener static PetscErrorCode TaoSetUp_BRGN(Tao tao) 196737f463aSAlp Dener { 197737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 198737f463aSAlp Dener PetscErrorCode ierr; 199737f463aSAlp Dener PetscBool is_bnls, is_bntr, is_bntl; 200*7cea06e1SXiang Huang PetscInt i, nx, Nx, Ny; /* XH: added Ny for size of y=D*x*/ 201*7cea06e1SXiang Huang PetscScalar v = 1.0; /* XH: hack to set value of matrix */ 202737f463aSAlp Dener 203737f463aSAlp Dener PetscFunctionBegin; 204737f463aSAlp Dener if (!tao->ls_res) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualRoutine() must be called before setup!"); 205737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNLS, &is_bnls);CHKERRQ(ierr); 206737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTR, &is_bntr);CHKERRQ(ierr); 207737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTL, &is_bntl);CHKERRQ(ierr); 208737f463aSAlp Dener if ((is_bnls || is_bntr || is_bntl) && !tao->ls_jac) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualJacobianRoutine() must be called before setup!"); 209e1e80dc8SAlp Dener if (!tao->gradient){ 210e1e80dc8SAlp Dener ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr); 211e1e80dc8SAlp Dener } 212737f463aSAlp Dener if (!gn->x_work){ 213737f463aSAlp Dener ierr = VecDuplicate(tao->solution, &gn->x_work);CHKERRQ(ierr); 214737f463aSAlp Dener } 215737f463aSAlp Dener if (!gn->r_work){ 216737f463aSAlp Dener ierr = VecDuplicate(tao->ls_res, &gn->r_work);CHKERRQ(ierr); 217737f463aSAlp Dener } 218e1e80dc8SAlp Dener if (!gn->x_old) { 219e1e80dc8SAlp Dener ierr = VecDuplicate(tao->solution, &gn->x_old);CHKERRQ(ierr); 220e1e80dc8SAlp Dener ierr = VecSet(gn->x_old, 0.0);CHKERRQ(ierr); 221e1e80dc8SAlp Dener } 222*7cea06e1SXiang Huang 223*7cea06e1SXiang Huang 224*7cea06e1SXiang Huang /* XH: hack: following works only when D is a squared matrix, to fix dimension of gn->diag/y/y_work, when D is not squared matrix */ 225*7cea06e1SXiang Huang ierr = VecGetSize(tao->solution, &Nx);CHKERRQ(ierr); 226*7cea06e1SXiang Huang /* Ny = Nx; */ /* for identity matrix */ 227*7cea06e1SXiang Huang Ny = Nx - 1; /* for gradient matrix */ 228*7cea06e1SXiang Huang if (!gn->y){ 229*7cea06e1SXiang Huang ierr = VecCreate(PETSC_COMM_SELF,&gn->y);CHKERRQ(ierr); 230*7cea06e1SXiang Huang ierr = VecSetSizes(gn->y,PETSC_DECIDE,Ny);CHKERRQ(ierr); 231*7cea06e1SXiang Huang ierr = VecSetFromOptions(gn->y);CHKERRQ(ierr); 232*7cea06e1SXiang Huang ierr = VecSet(gn->y,0.0);CHKERRQ(ierr); 233*7cea06e1SXiang Huang 234*7cea06e1SXiang Huang } 235*7cea06e1SXiang Huang if (!gn->y_work){ 236*7cea06e1SXiang Huang ierr = VecDuplicate(gn->y, &gn->y_work);CHKERRQ(ierr); 237*7cea06e1SXiang Huang } 2388ac80d48SXiang Huang if (!gn->diag){ 239*7cea06e1SXiang Huang ierr = VecDuplicate(gn->y, &gn->diag);CHKERRQ(ierr); 2408ac80d48SXiang Huang ierr = VecSet(gn->diag, 0.0);CHKERRQ(ierr); 2418ac80d48SXiang Huang } 2420d71dc2bSXiang Huang 243*7cea06e1SXiang Huang /* XH: hack: set gn->D as identity/gradient matrix here for text , how to set D matrix from user data?*/ 244*7cea06e1SXiang Huang if (!gn->D){ 245*7cea06e1SXiang Huang ierr = MatCreate(PETSC_COMM_SELF,&gn->D);CHKERRQ(ierr); 246*7cea06e1SXiang Huang ierr = MatSetSizes(gn->D,PETSC_DECIDE,PETSC_DECIDE,Ny,Nx);CHKERRQ(ierr); 247*7cea06e1SXiang Huang ierr = MatSetFromOptions(gn->D);CHKERRQ(ierr); 248*7cea06e1SXiang Huang ierr = MatSetUp(gn->D);CHKERRQ(ierr); 249*7cea06e1SXiang Huang /* identity matrix */ 250*7cea06e1SXiang Huang /* 251*7cea06e1SXiang Huang for (i=0; i<Ny; i++) { 252*7cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); 253*7cea06e1SXiang Huang } 254*7cea06e1SXiang Huang */ 255*7cea06e1SXiang Huang /* gradient matrix */ 256*7cea06e1SXiang Huang /* [-1, 1, 0,...; 0, -1, 1, 0, ...] */ 257*7cea06e1SXiang Huang for (i=0; i<Ny; i++) { 258*7cea06e1SXiang Huang v = 1.0; 259*7cea06e1SXiang Huang nx = i+1; 260*7cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&nx,&v,INSERT_VALUES);CHKERRQ(ierr); 261*7cea06e1SXiang Huang v = -1.0; 262*7cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); 263*7cea06e1SXiang Huang } 264*7cea06e1SXiang Huang ierr = MatAssemblyBegin(gn->D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 265*7cea06e1SXiang Huang ierr = MatAssemblyEnd(gn->D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 266*7cea06e1SXiang Huang } 267*7cea06e1SXiang Huang 268*7cea06e1SXiang Huang /* XH: debug: check matrix */ 269*7cea06e1SXiang Huang PetscPrintf(PETSC_COMM_SELF, "-------- Check D matrix. -------- \n"); 270*7cea06e1SXiang Huang ierr = MatView(gn->D,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 271*7cea06e1SXiang Huang getchar(); 272*7cea06e1SXiang Huang 273e1e80dc8SAlp Dener if (!tao->setupcalled) { 274737f463aSAlp Dener /* Hessian setup */ 275737f463aSAlp Dener ierr = VecGetLocalSize(tao->solution, &nx);CHKERRQ(ierr); 276737f463aSAlp Dener ierr = VecGetSize(tao->solution, &Nx);CHKERRQ(ierr); 277737f463aSAlp Dener ierr = MatSetSizes(gn->H, nx, nx, Nx, Nx);CHKERRQ(ierr); 278737f463aSAlp Dener ierr = MatSetType(gn->H, MATSHELL);CHKERRQ(ierr); 279737f463aSAlp Dener ierr = MatSetUp(gn->H);CHKERRQ(ierr); 280737f463aSAlp Dener ierr = MatShellSetOperation(gn->H, MATOP_MULT, (void (*)(void))GNHessianProd);CHKERRQ(ierr); 281737f463aSAlp Dener ierr = MatShellSetContext(gn->H, (void*)gn);CHKERRQ(ierr); 282737f463aSAlp Dener /* Subsolver setup */ 283e1e80dc8SAlp Dener ierr = TaoSetUpdate(gn->subsolver, GNHookFunction, (void*)gn);CHKERRQ(ierr); 284737f463aSAlp Dener ierr = TaoSetInitialVector(gn->subsolver, tao->solution);CHKERRQ(ierr); 285737f463aSAlp Dener if (tao->bounded) { 286737f463aSAlp Dener ierr = TaoSetVariableBounds(gn->subsolver, tao->XL, tao->XU);CHKERRQ(ierr); 287737f463aSAlp Dener } 288737f463aSAlp Dener ierr = TaoSetResidualRoutine(gn->subsolver, tao->ls_res, tao->ops->computeresidual, tao->user_lsresP);CHKERRQ(ierr); 2894ffbe8acSAlp Dener ierr = TaoSetJacobianResidualRoutine(gn->subsolver, tao->ls_jac, tao->ls_jac, tao->ops->computeresidualjacobian, tao->user_lsjacP);CHKERRQ(ierr); 290737f463aSAlp Dener ierr = TaoSetObjectiveAndGradientRoutine(gn->subsolver, GNObjectiveGradientEval, (void*)gn);CHKERRQ(ierr); 291737f463aSAlp Dener ierr = TaoSetHessianRoutine(gn->subsolver, gn->H, gn->H, GNComputeHessian, (void*)gn);CHKERRQ(ierr); 292e1e80dc8SAlp Dener /* Propagate some options down */ 293e1e80dc8SAlp Dener ierr = TaoSetTolerances(gn->subsolver, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr); 294e1e80dc8SAlp Dener ierr = TaoSetMaximumIterations(gn->subsolver, tao->max_it);CHKERRQ(ierr); 295e1e80dc8SAlp Dener ierr = TaoSetMaximumFunctionEvaluations(gn->subsolver, tao->max_funcs);CHKERRQ(ierr); 296737f463aSAlp Dener for (i=0; i<tao->numbermonitors; ++i) { 297737f463aSAlp Dener ierr = TaoSetMonitor(gn->subsolver, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr); 298737f463aSAlp Dener ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr); 299737f463aSAlp Dener } 300737f463aSAlp Dener ierr = TaoSetUp(gn->subsolver);CHKERRQ(ierr); 301e1e80dc8SAlp Dener } 302737f463aSAlp Dener PetscFunctionReturn(0); 303737f463aSAlp Dener } 304737f463aSAlp Dener 305737f463aSAlp Dener static PetscErrorCode TaoDestroy_BRGN(Tao tao) 306737f463aSAlp Dener { 307737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 308737f463aSAlp Dener PetscErrorCode ierr; 309737f463aSAlp Dener 310737f463aSAlp Dener PetscFunctionBegin; 311737f463aSAlp Dener if (tao->setupcalled) { 312e1e80dc8SAlp Dener ierr = VecDestroy(&tao->gradient);CHKERRQ(ierr); 313737f463aSAlp Dener ierr = VecDestroy(&gn->x_work);CHKERRQ(ierr); 314737f463aSAlp Dener ierr = VecDestroy(&gn->r_work);CHKERRQ(ierr); 315e1e80dc8SAlp Dener ierr = VecDestroy(&gn->x_old);CHKERRQ(ierr); 3168ac80d48SXiang Huang ierr = VecDestroy(&gn->diag);CHKERRQ(ierr); 317*7cea06e1SXiang Huang ierr = VecDestroy(&gn->y);CHKERRQ(ierr); 318*7cea06e1SXiang Huang ierr = VecDestroy(&gn->y_work);CHKERRQ(ierr); 319737f463aSAlp Dener } 320737f463aSAlp Dener ierr = MatDestroy(&gn->H);CHKERRQ(ierr); 321*7cea06e1SXiang Huang ierr = MatDestroy(&gn->D);CHKERRQ(ierr); 322737f463aSAlp Dener ierr = TaoDestroy(&gn->subsolver);CHKERRQ(ierr); 323e1e80dc8SAlp Dener gn->parent = NULL; 324737f463aSAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 325737f463aSAlp Dener PetscFunctionReturn(0); 326737f463aSAlp Dener } 327737f463aSAlp Dener 3283850be85SAlp Dener /*MC 3293850be85SAlp Dener TAOBRGN - Bounded Regularized Gauss-Newton method for solving nonlinear least-squares 3303850be85SAlp Dener problems with bound constraints. This algorithm is a thin wrapper around TAOBNTL 3313850be85SAlp Dener that constructs the Guass-Newton problem with the user-provided least-squares 3323850be85SAlp Dener residual and Jacobian. The problem is regularized with an L2-norm proximal point 3333850be85SAlp Dener term. 3343850be85SAlp Dener 3353850be85SAlp Dener Options Database Keys: 3363850be85SAlp Dener + -tao_bqnk_max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop 3373850be85SAlp Dener . -tao_bqnk_init_type - trust radius initialization method ("constant", "direction", "interpolation") 3383850be85SAlp Dener . -tao_bqnk_update_type - trust radius update method ("step", "direction", "interpolation") 3393850be85SAlp Dener - -tao_bqnk_as_type - active-set estimation method ("none", "bertsekas") 3403850be85SAlp Dener 3413850be85SAlp Dener Level: beginner 3423850be85SAlp Dener M*/ 343737f463aSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BRGN(Tao tao) 344737f463aSAlp Dener { 345737f463aSAlp Dener TAO_BRGN *gn; 346737f463aSAlp Dener PetscErrorCode ierr; 347737f463aSAlp Dener 348737f463aSAlp Dener PetscFunctionBegin; 349737f463aSAlp Dener ierr = PetscNewLog(tao,&gn);CHKERRQ(ierr); 350737f463aSAlp Dener 351737f463aSAlp Dener tao->ops->destroy = TaoDestroy_BRGN; 352737f463aSAlp Dener tao->ops->setup = TaoSetUp_BRGN; 353737f463aSAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BRGN; 354737f463aSAlp Dener tao->ops->view = TaoView_BRGN; 355737f463aSAlp Dener tao->ops->solve = TaoSolve_BRGN; 356737f463aSAlp Dener 357737f463aSAlp Dener tao->data = (void*)gn; 358e1e80dc8SAlp Dener gn->lambda = 1e-4; 3598ac80d48SXiang Huang gn->epsilon = 1e-6; 360e1e80dc8SAlp Dener gn->parent = tao; 361737f463aSAlp Dener 362737f463aSAlp Dener ierr = MatCreate(PetscObjectComm((PetscObject)tao), &gn->H);CHKERRQ(ierr); 363737f463aSAlp Dener ierr = MatSetOptionsPrefix(gn->H, "tao_brgn_hessian_");CHKERRQ(ierr); 364737f463aSAlp Dener 365737f463aSAlp Dener ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &gn->subsolver);CHKERRQ(ierr); 366737f463aSAlp Dener ierr = TaoSetType(gn->subsolver, TAOBNLS);CHKERRQ(ierr); 367737f463aSAlp Dener ierr = TaoSetOptionsPrefix(gn->subsolver, "tao_brgn_subsolver_");CHKERRQ(ierr); 368e1e80dc8SAlp Dener PetscFunctionReturn(0); 369e1e80dc8SAlp Dener } 370e1e80dc8SAlp Dener 371e1e80dc8SAlp Dener /*@C 372e1e80dc8SAlp Dener TaoBRGNGetSubsolver - Get the pointer to the subsolver inside BRGN 373e1e80dc8SAlp Dener 374e1e80dc8SAlp Dener Collective on Tao 375e1e80dc8SAlp Dener 376e1e80dc8SAlp Dener Level: developer 377e1e80dc8SAlp Dener 378e1e80dc8SAlp Dener Input Parameters: 379e1e80dc8SAlp Dener + tao - the Tao solver context 380e1e80dc8SAlp Dener - subsolver - the Tao sub-solver context 381e1e80dc8SAlp Dener @*/ 382e1e80dc8SAlp Dener PetscErrorCode TaoBRGNGetSubsolver(Tao tao, Tao *subsolver) 383e1e80dc8SAlp Dener { 384e1e80dc8SAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 385e1e80dc8SAlp Dener 386e1e80dc8SAlp Dener PetscFunctionBegin; 387e1e80dc8SAlp Dener *subsolver = gn->subsolver; 388737f463aSAlp Dener PetscFunctionReturn(0); 389737f463aSAlp Dener } 390737f463aSAlp Dener 391737f463aSAlp Dener /*@C 392737f463aSAlp Dener TaoBRGNSetTikhonovLambda - Set the Tikhonov regularization factor for the Gauss-Newton least-squares algorithm 393737f463aSAlp Dener 394737f463aSAlp Dener Collective on Tao 395737f463aSAlp Dener 396737f463aSAlp Dener Level: developer 397737f463aSAlp Dener 398737f463aSAlp Dener Input Parameters: 399737f463aSAlp Dener + tao - the Tao solver context 400737f463aSAlp Dener - lambda - Tikhonov regularization factor 401737f463aSAlp Dener @*/ 402737f463aSAlp Dener PetscErrorCode TaoBRGNSetTikhonovLambda(Tao tao, PetscReal lambda) 403737f463aSAlp Dener { 404737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 405737f463aSAlp Dener 4068ac80d48SXiang Huang /* Initialize lambda here */ 4070d71dc2bSXiang Huang 408737f463aSAlp Dener PetscFunctionBegin; 409737f463aSAlp Dener gn->lambda = lambda; 410737f463aSAlp Dener PetscFunctionReturn(0); 411737f463aSAlp Dener } 4120d71dc2bSXiang Huang 4138ac80d48SXiang Huang /*@C 4148ac80d48SXiang Huang TaoBRGNSetL1SmoothEpsilon - Set the L1-norm smooth approximation parameter for L1-regularized least-squares algorithm 4158ac80d48SXiang Huang 4168ac80d48SXiang Huang Collective on Tao 4178ac80d48SXiang Huang 4188ac80d48SXiang Huang Level: developer 4198ac80d48SXiang Huang 4208ac80d48SXiang Huang Input Parameters: 4218ac80d48SXiang Huang + tao - the Tao solver context 4228ac80d48SXiang Huang - epsilon - L1-norm smooth approximation parameter 4238ac80d48SXiang Huang @*/ 4248ac80d48SXiang Huang PetscErrorCode TaoBRGNSetL1SmoothEpsilon(Tao tao, PetscReal epsilon) 4258ac80d48SXiang Huang { 4268ac80d48SXiang Huang TAO_BRGN *gn = (TAO_BRGN *)tao->data; 4278ac80d48SXiang Huang 4288ac80d48SXiang Huang /* Initialize epsilon here */ 4298ac80d48SXiang Huang 4308ac80d48SXiang Huang PetscFunctionBegin; 4318ac80d48SXiang Huang gn->epsilon = epsilon; 4328ac80d48SXiang Huang PetscFunctionReturn(0); 4338ac80d48SXiang Huang } 4348ac80d48SXiang Huang /* XH: done TaoBRGNSetL1SmoothEpsilon by copy TaoBRGNSetTikhonovLambda in peststao.h, brgn.c and zbrgnf.c. 435*7cea06e1SXiang Huang maybe change the name of Tikhonov in TaoBRGNSetTikhonovLambda() etc, as lambda is no longer the Tikhonov regularizer weight but the L1 regularizer weight 436*7cea06e1SXiang Huang Maybe change D*x to D(x), and A*x to A(x) as function handle 437*7cea06e1SXiang Huang Maybe need to also keep y = D*x, to avoid duplicate frequent computation of D*x 438*7cea06e1SXiang Huang */ 439