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); 487cea06e1SXiang Huang /* out = out + lambda*D'*(diag.*(D*in)) */ 497cea06e1SXiang Huang ierr = MatMult(gn->D, in, gn->y);CHKERRQ(ierr); /* y = D*in */ 507cea06e1SXiang 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 */ 517cea06e1SXiang 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; 607cea06e1SXiang Huang PetscInt Ny; /* dimension of D*X */ 617cea06e1SXiang 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); 707cea06e1SXiang Huang /* add the second term lambda*sum(sqrt(y.^2+epsilon^2) - epsilon), where y = D*x*/ 717cea06e1SXiang Huang ierr = MatMult(gn->D, X, gn->y);CHKERRQ(ierr); /* y = D*x */ 727cea06e1SXiang Huang ierr = VecPointwiseMult(gn->y_work, gn->y, gn->y);CHKERRQ(ierr); 737cea06e1SXiang Huang ierr = VecShift(gn->y_work, gn->epsilon*gn->epsilon);CHKERRQ(ierr); 747cea06e1SXiang Huang ierr = VecSqrtAbs(gn->y_work);CHKERRQ(ierr); /* gn->y_work = sqrt(y.^2+epsilon^2) */ 757cea06e1SXiang Huang ierr = VecSum(gn->y_work, &yESum);CHKERRQ(ierr);CHKERRQ(ierr); 767cea06e1SXiang Huang ierr = VecGetSize(gn->y, &Ny);CHKERRQ(ierr); 777cea06e1SXiang 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); 827cea06e1SXiang Huang /* compute G = G + lambda*D'*(y./sqrt(y.^2+epsilon^2)), where y = D*x */ 837cea06e1SXiang Huang ierr = VecPointwiseDivide(gn->y_work, gn->y, gn->y_work);CHKERRQ(ierr); /* reuse y_work = y./sqrt(y.^2+epsilon^2) */ 847cea06e1SXiang 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 997cea06e1SXiang 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 */ 1007cea06e1SXiang Huang ierr = MatMult(gn->D, X, gn->y);CHKERRQ(ierr); /* y = D*x */ 1017cea06e1SXiang Huang ierr = VecPointwiseMult(gn->y_work, gn->y, gn->y);CHKERRQ(ierr); 1027cea06e1SXiang Huang ierr = VecShift(gn->y_work, gn->epsilon*gn->epsilon);CHKERRQ(ierr); 1037cea06e1SXiang Huang ierr = VecCopy(gn->y_work, gn->diag);CHKERRQ(ierr); /* gn->diag = y.^2+epsilon^2 */ 1047cea06e1SXiang Huang ierr = VecSqrtAbs(gn->y_work);CHKERRQ(ierr); /* gn->y_work = sqrt(y.^2+epsilon^2) */ 1057cea06e1SXiang 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; 2007cea06e1SXiang Huang PetscInt i, nx, Nx, Ny; /* XH: added Ny for size of y=D*x*/ 2017cea06e1SXiang 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 } 2227cea06e1SXiang Huang 2237cea06e1SXiang Huang 2247cea06e1SXiang 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 */ 2257cea06e1SXiang Huang ierr = VecGetSize(tao->solution, &Nx);CHKERRQ(ierr); 2267cea06e1SXiang Huang /* Ny = Nx; */ /* for identity matrix */ 2277cea06e1SXiang Huang Ny = Nx - 1; /* for gradient matrix */ 2287cea06e1SXiang Huang if (!gn->y){ 2297cea06e1SXiang Huang ierr = VecCreate(PETSC_COMM_SELF,&gn->y);CHKERRQ(ierr); 2307cea06e1SXiang Huang ierr = VecSetSizes(gn->y,PETSC_DECIDE,Ny);CHKERRQ(ierr); 2317cea06e1SXiang Huang ierr = VecSetFromOptions(gn->y);CHKERRQ(ierr); 2327cea06e1SXiang Huang ierr = VecSet(gn->y,0.0);CHKERRQ(ierr); 2337cea06e1SXiang Huang 2347cea06e1SXiang Huang } 2357cea06e1SXiang Huang if (!gn->y_work){ 2367cea06e1SXiang Huang ierr = VecDuplicate(gn->y, &gn->y_work);CHKERRQ(ierr); 2377cea06e1SXiang Huang } 2388ac80d48SXiang Huang if (!gn->diag){ 2397cea06e1SXiang Huang ierr = VecDuplicate(gn->y, &gn->diag);CHKERRQ(ierr); 2408ac80d48SXiang Huang ierr = VecSet(gn->diag, 0.0);CHKERRQ(ierr); 2418ac80d48SXiang Huang } 2420d71dc2bSXiang Huang 2437cea06e1SXiang Huang /* XH: hack: set gn->D as identity/gradient matrix here for text , how to set D matrix from user data?*/ 2447cea06e1SXiang Huang if (!gn->D){ 2457cea06e1SXiang Huang ierr = MatCreate(PETSC_COMM_SELF,&gn->D);CHKERRQ(ierr); 2467cea06e1SXiang Huang ierr = MatSetSizes(gn->D,PETSC_DECIDE,PETSC_DECIDE,Ny,Nx);CHKERRQ(ierr); 2477cea06e1SXiang Huang ierr = MatSetFromOptions(gn->D);CHKERRQ(ierr); 2487cea06e1SXiang Huang ierr = MatSetUp(gn->D);CHKERRQ(ierr); 2497cea06e1SXiang Huang /* identity matrix */ 2507cea06e1SXiang Huang /* 2517cea06e1SXiang Huang for (i=0; i<Ny; i++) { 2527cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); 2537cea06e1SXiang Huang } 2547cea06e1SXiang Huang */ 2557cea06e1SXiang Huang /* gradient matrix */ 2567cea06e1SXiang Huang /* [-1, 1, 0,...; 0, -1, 1, 0, ...] */ 2577cea06e1SXiang Huang for (i=0; i<Ny; i++) { 2587cea06e1SXiang Huang v = 1.0; 2597cea06e1SXiang Huang nx = i+1; 2607cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&nx,&v,INSERT_VALUES);CHKERRQ(ierr); 2617cea06e1SXiang Huang v = -1.0; 2627cea06e1SXiang Huang ierr = MatSetValues(gn->D,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); 2637cea06e1SXiang Huang } 2647cea06e1SXiang Huang ierr = MatAssemblyBegin(gn->D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2657cea06e1SXiang Huang ierr = MatAssemblyEnd(gn->D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2667cea06e1SXiang Huang } 2677cea06e1SXiang Huang 2687cea06e1SXiang Huang /* XH: debug: check matrix */ 2697cea06e1SXiang Huang PetscPrintf(PETSC_COMM_SELF, "-------- Check D matrix. -------- \n"); 2707cea06e1SXiang Huang ierr = MatView(gn->D,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 271*20fe612cSXiang Huang 2727cea06e1SXiang 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); 3177cea06e1SXiang Huang ierr = VecDestroy(&gn->y);CHKERRQ(ierr); 3187cea06e1SXiang Huang ierr = VecDestroy(&gn->y_work);CHKERRQ(ierr); 319737f463aSAlp Dener } 320737f463aSAlp Dener ierr = MatDestroy(&gn->H);CHKERRQ(ierr); 3217cea06e1SXiang 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. 4357cea06e1SXiang Huang maybe change the name of Tikhonov in TaoBRGNSetTikhonovLambda() etc, as lambda is no longer the Tikhonov regularizer weight but the L1 regularizer weight 4367cea06e1SXiang Huang Maybe change D*x to D(x), and A*x to A(x) as function handle 4377cea06e1SXiang Huang Maybe need to also keep y = D*x, to avoid duplicate frequent computation of D*x 4387cea06e1SXiang Huang */ 439