1*a7e14dcfSSatish Balay #include "bmrm.h" 2*a7e14dcfSSatish Balay 3*a7e14dcfSSatish Balay static PetscErrorCode init_df_solver(TAO_DF*); 4*a7e14dcfSSatish Balay static PetscErrorCode ensure_df_space(PetscInt, TAO_DF*); 5*a7e14dcfSSatish Balay static PetscErrorCode destroy_df_solver(TAO_DF*); 6*a7e14dcfSSatish Balay static PetscReal phi(PetscReal*,PetscInt,PetscReal,PetscReal*, 7*a7e14dcfSSatish Balay PetscReal,PetscReal*,PetscReal*,PetscReal*); 8*a7e14dcfSSatish Balay static PetscInt project(PetscInt,PetscReal*,PetscReal,PetscReal*, 9*a7e14dcfSSatish Balay PetscReal*,PetscReal*,PetscReal*,PetscReal*,TAO_DF*); 10*a7e14dcfSSatish Balay 11*a7e14dcfSSatish Balay static PetscErrorCode solve(TAO_DF*); 12*a7e14dcfSSatish Balay 13*a7e14dcfSSatish Balay 14*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 15*a7e14dcfSSatish Balay /* The main solver function 16*a7e14dcfSSatish Balay 17*a7e14dcfSSatish Balay f = Remp(W) This is what the user provides us from the application layer 18*a7e14dcfSSatish Balay So the ComputeGradient function for instance should get us back the subgradient of Remp(W) 19*a7e14dcfSSatish Balay 20*a7e14dcfSSatish Balay Regularizer assumed to be L2 norm = lambda*0.5*W'W () 21*a7e14dcfSSatish Balay */ 22*a7e14dcfSSatish Balay 23*a7e14dcfSSatish Balay #undef __FUNCT__ 24*a7e14dcfSSatish Balay #define __FUNCT__ "make_grad_node" 25*a7e14dcfSSatish Balay static PetscErrorCode make_grad_node(Vec X, Vec_Chain **p) 26*a7e14dcfSSatish Balay { 27*a7e14dcfSSatish Balay PetscErrorCode ierr; 28*a7e14dcfSSatish Balay 29*a7e14dcfSSatish Balay PetscFunctionBegin; 30*a7e14dcfSSatish Balay 31*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(Vec_Chain), p); CHKERRQ(ierr); 32*a7e14dcfSSatish Balay ierr = VecDuplicate(X, &(*p)->V); CHKERRQ(ierr); 33*a7e14dcfSSatish Balay ierr = VecCopy(X, (*p)->V); CHKERRQ(ierr); 34*a7e14dcfSSatish Balay (*p)->next = PETSC_NULL; 35*a7e14dcfSSatish Balay 36*a7e14dcfSSatish Balay PetscFunctionReturn(0); 37*a7e14dcfSSatish Balay } 38*a7e14dcfSSatish Balay 39*a7e14dcfSSatish Balay 40*a7e14dcfSSatish Balay #undef __FUNCT__ 41*a7e14dcfSSatish Balay #define __FUNCT__ "destroy_grad_list" 42*a7e14dcfSSatish Balay static PetscErrorCode destroy_grad_list(Vec_Chain *head) 43*a7e14dcfSSatish Balay { 44*a7e14dcfSSatish Balay PetscErrorCode ierr; 45*a7e14dcfSSatish Balay Vec_Chain *p = head->next, *q; 46*a7e14dcfSSatish Balay 47*a7e14dcfSSatish Balay PetscFunctionBegin; 48*a7e14dcfSSatish Balay while(p) { 49*a7e14dcfSSatish Balay q = p->next; 50*a7e14dcfSSatish Balay ierr = VecDestroy(&p->V); CHKERRQ(ierr); 51*a7e14dcfSSatish Balay ierr = PetscFree(p); CHKERRQ(ierr); 52*a7e14dcfSSatish Balay p = q; 53*a7e14dcfSSatish Balay } 54*a7e14dcfSSatish Balay head->next = PETSC_NULL; 55*a7e14dcfSSatish Balay 56*a7e14dcfSSatish Balay PetscFunctionReturn(0); 57*a7e14dcfSSatish Balay } 58*a7e14dcfSSatish Balay 59*a7e14dcfSSatish Balay 60*a7e14dcfSSatish Balay #undef __FUNCT__ 61*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSolve_BMRM" 62*a7e14dcfSSatish Balay static PetscErrorCode TaoSolve_BMRM(TaoSolver tao) 63*a7e14dcfSSatish Balay { 64*a7e14dcfSSatish Balay PetscErrorCode ierr; 65*a7e14dcfSSatish Balay TaoSolverTerminationReason reason; 66*a7e14dcfSSatish Balay TAO_DF df; 67*a7e14dcfSSatish Balay TAO_BMRM *bmrm = (TAO_BMRM*)tao->data; 68*a7e14dcfSSatish Balay 69*a7e14dcfSSatish Balay /* Values and pointers to parts of the optimization problem */ 70*a7e14dcfSSatish Balay PetscReal f = 0.0; 71*a7e14dcfSSatish Balay Vec W = tao->solution; 72*a7e14dcfSSatish Balay Vec G = tao->gradient; 73*a7e14dcfSSatish Balay PetscReal lambda; 74*a7e14dcfSSatish Balay 75*a7e14dcfSSatish Balay PetscReal bt; 76*a7e14dcfSSatish Balay Vec_Chain grad_list, *tail_glist, *pgrad; 77*a7e14dcfSSatish Balay 78*a7e14dcfSSatish Balay PetscInt iter = 0; 79*a7e14dcfSSatish Balay PetscInt i; 80*a7e14dcfSSatish Balay PetscMPIInt rank; 81*a7e14dcfSSatish Balay 82*a7e14dcfSSatish Balay /* Used in termination criteria check */ 83*a7e14dcfSSatish Balay PetscReal reg; 84*a7e14dcfSSatish Balay PetscReal jtwt, max_jtwt, pre_epsilon, epsilon, jw, min_jw; 85*a7e14dcfSSatish Balay PetscReal innerSolverTol; 86*a7e14dcfSSatish Balay 87*a7e14dcfSSatish Balay PetscFunctionBegin; 88*a7e14dcfSSatish Balay 89*a7e14dcfSSatish Balay ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr); 90*a7e14dcfSSatish Balay lambda = bmrm->lambda; 91*a7e14dcfSSatish Balay 92*a7e14dcfSSatish Balay /* Check Stopping Condition */ 93*a7e14dcfSSatish Balay tao->step = 1.0; 94*a7e14dcfSSatish Balay max_jtwt = -BMRM_INFTY; 95*a7e14dcfSSatish Balay min_jw = BMRM_INFTY; 96*a7e14dcfSSatish Balay innerSolverTol = 1.0; 97*a7e14dcfSSatish Balay epsilon = 0.0; 98*a7e14dcfSSatish Balay 99*a7e14dcfSSatish Balay if (rank == 0) { 100*a7e14dcfSSatish Balay ierr = init_df_solver(&df); CHKERRQ(ierr); 101*a7e14dcfSSatish Balay grad_list.next = NULL; 102*a7e14dcfSSatish Balay tail_glist = &grad_list; 103*a7e14dcfSSatish Balay } 104*a7e14dcfSSatish Balay 105*a7e14dcfSSatish Balay df.tol = 1e-6; 106*a7e14dcfSSatish Balay reason = TAO_CONTINUE_ITERATING; 107*a7e14dcfSSatish Balay 108*a7e14dcfSSatish Balay /*-----------------Algorithm Begins------------------------*/ 109*a7e14dcfSSatish Balay /* make the scatter */ 110*a7e14dcfSSatish Balay ierr = VecScatterCreateToZero(W, &bmrm->scatter, &bmrm->local_w); CHKERRQ(ierr); 111*a7e14dcfSSatish Balay ierr = VecAssemblyBegin(bmrm->local_w); CHKERRQ(ierr); 112*a7e14dcfSSatish Balay ierr = VecAssemblyEnd(bmrm->local_w); CHKERRQ(ierr); 113*a7e14dcfSSatish Balay 114*a7e14dcfSSatish Balay /* NOTE: In application pass the sub-gradient of Remp(W) */ 115*a7e14dcfSSatish Balay ierr = TaoComputeObjectiveAndGradient(tao, W, &f, G); CHKERRQ(ierr); 116*a7e14dcfSSatish Balay ierr = TaoMonitor(tao,iter,f,1.0,0.0,tao->step,&reason); CHKERRQ(ierr); 117*a7e14dcfSSatish Balay while (reason == TAO_CONTINUE_ITERATING) { 118*a7e14dcfSSatish Balay /* compute bt = Remp(Wt-1) - <Wt-1, At> */ 119*a7e14dcfSSatish Balay ierr = VecDot(W, G, &bt); CHKERRQ(ierr); 120*a7e14dcfSSatish Balay bt = f - bt; 121*a7e14dcfSSatish Balay 122*a7e14dcfSSatish Balay /* First gather the gradient to the master node */ 123*a7e14dcfSSatish Balay ierr = VecScatterBegin(bmrm->scatter, G, bmrm->local_w, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr); 124*a7e14dcfSSatish Balay ierr = VecScatterEnd(bmrm->scatter, G, bmrm->local_w, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr); 125*a7e14dcfSSatish Balay 126*a7e14dcfSSatish Balay /* Bring up the inner solver */ 127*a7e14dcfSSatish Balay if (rank == 0) { 128*a7e14dcfSSatish Balay ierr = ensure_df_space(iter+1, &df); CHKERRQ(ierr); 129*a7e14dcfSSatish Balay ierr = make_grad_node(bmrm->local_w, &pgrad); CHKERRQ(ierr); 130*a7e14dcfSSatish Balay tail_glist->next = pgrad; 131*a7e14dcfSSatish Balay tail_glist = pgrad; 132*a7e14dcfSSatish Balay 133*a7e14dcfSSatish Balay df.a[iter] = 1.0; 134*a7e14dcfSSatish Balay df.f[iter] = -bt; 135*a7e14dcfSSatish Balay df.u[iter] = 1.0; 136*a7e14dcfSSatish Balay df.l[iter] = 0.0; 137*a7e14dcfSSatish Balay 138*a7e14dcfSSatish Balay /* set up the Q */ 139*a7e14dcfSSatish Balay pgrad = grad_list.next; 140*a7e14dcfSSatish Balay for (i=0; i<=iter; i++) { 141*a7e14dcfSSatish Balay ierr = VecDot(pgrad->V, bmrm->local_w, ®); CHKERRQ(ierr); 142*a7e14dcfSSatish Balay df.Q[i][iter] = df.Q[iter][i] = reg / lambda; 143*a7e14dcfSSatish Balay pgrad = pgrad->next; 144*a7e14dcfSSatish Balay } 145*a7e14dcfSSatish Balay 146*a7e14dcfSSatish Balay if (iter > 0) { 147*a7e14dcfSSatish Balay df.x[iter] = 0.0; 148*a7e14dcfSSatish Balay ierr = solve(&df); CHKERRQ(ierr); 149*a7e14dcfSSatish Balay } 150*a7e14dcfSSatish Balay else 151*a7e14dcfSSatish Balay df.x[0] = 1.0; 152*a7e14dcfSSatish Balay 153*a7e14dcfSSatish Balay /* now computing Jt*(alpha_t) which should be = Jt(wt) to check convergence */ 154*a7e14dcfSSatish Balay jtwt = 0.0; 155*a7e14dcfSSatish Balay ierr = VecSet(bmrm->local_w, 0.0); CHKERRQ(ierr); 156*a7e14dcfSSatish Balay pgrad = grad_list.next; 157*a7e14dcfSSatish Balay for (i=0; i<=iter; i++) { 158*a7e14dcfSSatish Balay jtwt -= df.x[i] * df.f[i]; 159*a7e14dcfSSatish Balay ierr = VecAXPY(bmrm->local_w, -df.x[i] / lambda, pgrad->V); CHKERRQ(ierr); 160*a7e14dcfSSatish Balay pgrad = pgrad->next; 161*a7e14dcfSSatish Balay } 162*a7e14dcfSSatish Balay 163*a7e14dcfSSatish Balay ierr = VecNorm(bmrm->local_w, NORM_2, ®); CHKERRQ(ierr); 164*a7e14dcfSSatish Balay reg = 0.5*lambda*reg*reg; 165*a7e14dcfSSatish Balay jtwt -= reg; 166*a7e14dcfSSatish Balay } /* end if rank == 0 */ 167*a7e14dcfSSatish Balay 168*a7e14dcfSSatish Balay /* scatter the new W to all nodes */ 169*a7e14dcfSSatish Balay ierr = VecScatterBegin(bmrm->scatter,bmrm->local_w,W,INSERT_VALUES,SCATTER_REVERSE); CHKERRQ(ierr); 170*a7e14dcfSSatish Balay ierr = VecScatterEnd(bmrm->scatter,bmrm->local_w,W,INSERT_VALUES,SCATTER_REVERSE); CHKERRQ(ierr); 171*a7e14dcfSSatish Balay 172*a7e14dcfSSatish Balay ierr = TaoComputeObjectiveAndGradient(tao, W, &f, G); CHKERRQ(ierr); 173*a7e14dcfSSatish Balay 174*a7e14dcfSSatish Balay MPI_Bcast(&jtwt,1,MPI_DOUBLE,0,PETSC_COMM_WORLD); 175*a7e14dcfSSatish Balay MPI_Bcast(®,1,MPI_DOUBLE,0,PETSC_COMM_WORLD); 176*a7e14dcfSSatish Balay 177*a7e14dcfSSatish Balay jw = reg + f; /* J(w) = regularizer + Remp(w) */ 178*a7e14dcfSSatish Balay if (jw < min_jw) 179*a7e14dcfSSatish Balay min_jw = jw; 180*a7e14dcfSSatish Balay if (jtwt > max_jtwt) 181*a7e14dcfSSatish Balay max_jtwt = jtwt; 182*a7e14dcfSSatish Balay 183*a7e14dcfSSatish Balay pre_epsilon = epsilon; 184*a7e14dcfSSatish Balay epsilon = min_jw - jtwt; 185*a7e14dcfSSatish Balay 186*a7e14dcfSSatish Balay if (rank == 0) { 187*a7e14dcfSSatish Balay if (innerSolverTol > epsilon) 188*a7e14dcfSSatish Balay innerSolverTol = epsilon; 189*a7e14dcfSSatish Balay else if (innerSolverTol < 1e-7) 190*a7e14dcfSSatish Balay innerSolverTol = 1e-7; 191*a7e14dcfSSatish Balay 192*a7e14dcfSSatish Balay /* if the annealing doesn't work well, lower the inner solver tolerance */ 193*a7e14dcfSSatish Balay if(pre_epsilon < epsilon) 194*a7e14dcfSSatish Balay innerSolverTol *= 0.2; 195*a7e14dcfSSatish Balay 196*a7e14dcfSSatish Balay df.tol = innerSolverTol*0.5; 197*a7e14dcfSSatish Balay } 198*a7e14dcfSSatish Balay 199*a7e14dcfSSatish Balay iter++; 200*a7e14dcfSSatish Balay ierr = TaoMonitor(tao,iter,min_jw,epsilon,0.0,tao->step,&reason); CHKERRQ(ierr); 201*a7e14dcfSSatish Balay } 202*a7e14dcfSSatish Balay 203*a7e14dcfSSatish Balay /* free all the memory */ 204*a7e14dcfSSatish Balay if (rank == 0) { 205*a7e14dcfSSatish Balay ierr = destroy_grad_list(&grad_list); CHKERRQ(ierr); 206*a7e14dcfSSatish Balay ierr = destroy_df_solver(&df); CHKERRQ(ierr); 207*a7e14dcfSSatish Balay } 208*a7e14dcfSSatish Balay 209*a7e14dcfSSatish Balay ierr = VecDestroy(&bmrm->local_w); CHKERRQ(ierr); 210*a7e14dcfSSatish Balay ierr = VecScatterDestroy(&bmrm->scatter); CHKERRQ(ierr); 211*a7e14dcfSSatish Balay 212*a7e14dcfSSatish Balay PetscFunctionReturn(0); 213*a7e14dcfSSatish Balay } 214*a7e14dcfSSatish Balay 215*a7e14dcfSSatish Balay 216*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 217*a7e14dcfSSatish Balay 218*a7e14dcfSSatish Balay #undef __FUNCT__ 219*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetup_BMRM" 220*a7e14dcfSSatish Balay static PetscErrorCode TaoSetup_BMRM(TaoSolver tao) { 221*a7e14dcfSSatish Balay 222*a7e14dcfSSatish Balay PetscErrorCode ierr; 223*a7e14dcfSSatish Balay 224*a7e14dcfSSatish Balay PetscFunctionBegin; 225*a7e14dcfSSatish Balay 226*a7e14dcfSSatish Balay /* Allocate some arrays */ 227*a7e14dcfSSatish Balay if (!tao->gradient) { 228*a7e14dcfSSatish Balay ierr = VecDuplicate(tao->solution, &tao->gradient); CHKERRQ(ierr); 229*a7e14dcfSSatish Balay } 230*a7e14dcfSSatish Balay 231*a7e14dcfSSatish Balay PetscFunctionReturn(0); 232*a7e14dcfSSatish Balay } 233*a7e14dcfSSatish Balay 234*a7e14dcfSSatish Balay 235*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 236*a7e14dcfSSatish Balay 237*a7e14dcfSSatish Balay #undef __FUNCT__ 238*a7e14dcfSSatish Balay #define __FUNCT__ "TaoDestroy_BMRM" 239*a7e14dcfSSatish Balay static PetscErrorCode TaoDestroy_BMRM(TaoSolver tao) 240*a7e14dcfSSatish Balay { 241*a7e14dcfSSatish Balay PetscErrorCode ierr; 242*a7e14dcfSSatish Balay 243*a7e14dcfSSatish Balay /* Free allocated memory in custom BMRM structure */ 244*a7e14dcfSSatish Balay PetscFunctionBegin; 245*a7e14dcfSSatish Balay ierr = PetscFree(tao->data); CHKERRQ(ierr); 246*a7e14dcfSSatish Balay tao->data = PETSC_NULL; 247*a7e14dcfSSatish Balay 248*a7e14dcfSSatish Balay PetscFunctionReturn(0); 249*a7e14dcfSSatish Balay } 250*a7e14dcfSSatish Balay 251*a7e14dcfSSatish Balay 252*a7e14dcfSSatish Balay #undef __FUNCT__ 253*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetFromOptions_BMRM" 254*a7e14dcfSSatish Balay static PetscErrorCode TaoSetFromOptions_BMRM(TaoSolver tao) 255*a7e14dcfSSatish Balay { 256*a7e14dcfSSatish Balay PetscErrorCode ierr; 257*a7e14dcfSSatish Balay TAO_BMRM* bmrm = (TAO_BMRM*)tao->data; 258*a7e14dcfSSatish Balay PetscBool flg; 259*a7e14dcfSSatish Balay 260*a7e14dcfSSatish Balay PetscFunctionBegin; 261*a7e14dcfSSatish Balay ierr = PetscOptionsHead("BMRM for regularized risk minimization");CHKERRQ(ierr); 262*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_bmrm_lambda", "regulariser weight","", 100,&bmrm->lambda,&flg); CHKERRQ(ierr); 263*a7e14dcfSSatish Balay ierr = PetscOptionsTail();CHKERRQ(ierr); 264*a7e14dcfSSatish Balay PetscFunctionReturn(0); 265*a7e14dcfSSatish Balay } 266*a7e14dcfSSatish Balay 267*a7e14dcfSSatish Balay 268*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 269*a7e14dcfSSatish Balay #undef __FUNCT__ 270*a7e14dcfSSatish Balay #define __FUNCT__ "TaoView_BMRM" 271*a7e14dcfSSatish Balay static PetscErrorCode TaoView_BMRM(TaoSolver tao, PetscViewer viewer) 272*a7e14dcfSSatish Balay { 273*a7e14dcfSSatish Balay PetscBool isascii; 274*a7e14dcfSSatish Balay PetscErrorCode ierr; 275*a7e14dcfSSatish Balay 276*a7e14dcfSSatish Balay PetscFunctionBegin; 277*a7e14dcfSSatish Balay ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 278*a7e14dcfSSatish Balay if (isascii) { 279*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr); 280*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr); 281*a7e14dcfSSatish Balay } 282*a7e14dcfSSatish Balay else{ 283*a7e14dcfSSatish Balay SETERRQ1(((PetscObject)tao)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for TAO BMRM",((PetscObject)viewer)->type_name); 284*a7e14dcfSSatish Balay } 285*a7e14dcfSSatish Balay 286*a7e14dcfSSatish Balay PetscFunctionReturn(0); 287*a7e14dcfSSatish Balay } 288*a7e14dcfSSatish Balay 289*a7e14dcfSSatish Balay 290*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 291*a7e14dcfSSatish Balay EXTERN_C_BEGIN 292*a7e14dcfSSatish Balay #undef __FUNCT__ 293*a7e14dcfSSatish Balay #define __FUNCT__ "TaoCreate_BMRM" 294*a7e14dcfSSatish Balay PetscErrorCode TaoCreate_BMRM(TaoSolver tao) 295*a7e14dcfSSatish Balay { 296*a7e14dcfSSatish Balay TAO_BMRM *bmrm; 297*a7e14dcfSSatish Balay PetscErrorCode ierr; 298*a7e14dcfSSatish Balay 299*a7e14dcfSSatish Balay PetscFunctionBegin; 300*a7e14dcfSSatish Balay tao->ops->setup = TaoSetup_BMRM; 301*a7e14dcfSSatish Balay tao->ops->solve = TaoSolve_BMRM; 302*a7e14dcfSSatish Balay tao->ops->view = TaoView_BMRM; 303*a7e14dcfSSatish Balay tao->ops->setfromoptions = TaoSetFromOptions_BMRM; 304*a7e14dcfSSatish Balay tao->ops->destroy = TaoDestroy_BMRM; 305*a7e14dcfSSatish Balay 306*a7e14dcfSSatish Balay ierr = PetscNewLog(tao,TAO_BMRM,&bmrm); CHKERRQ(ierr); 307*a7e14dcfSSatish Balay bmrm->lambda = 1.0; 308*a7e14dcfSSatish Balay tao->data = (void*)bmrm; 309*a7e14dcfSSatish Balay 310*a7e14dcfSSatish Balay /* Note: May need to be tuned! */ 311*a7e14dcfSSatish Balay tao->max_it = 2048; 312*a7e14dcfSSatish Balay tao->max_funcs = 300000; 313*a7e14dcfSSatish Balay tao->fatol = 1e-20; 314*a7e14dcfSSatish Balay tao->frtol = 1e-25; 315*a7e14dcfSSatish Balay tao->gatol = 1e-25; 316*a7e14dcfSSatish Balay tao->grtol = 1e-25; 317*a7e14dcfSSatish Balay 318*a7e14dcfSSatish Balay PetscFunctionReturn(0); 319*a7e14dcfSSatish Balay } 320*a7e14dcfSSatish Balay EXTERN_C_END 321*a7e14dcfSSatish Balay 322*a7e14dcfSSatish Balay 323*a7e14dcfSSatish Balay 324*a7e14dcfSSatish Balay #undef __FUNCT__ 325*a7e14dcfSSatish Balay #define __FUNCT__ "init_df_solver" 326*a7e14dcfSSatish Balay PetscErrorCode init_df_solver(TAO_DF *df) 327*a7e14dcfSSatish Balay { 328*a7e14dcfSSatish Balay PetscInt i, n = INCRE_DIM; 329*a7e14dcfSSatish Balay PetscErrorCode ierr; 330*a7e14dcfSSatish Balay 331*a7e14dcfSSatish Balay PetscFunctionBegin; 332*a7e14dcfSSatish Balay 333*a7e14dcfSSatish Balay /* default values */ 334*a7e14dcfSSatish Balay df->maxProjIter = 200; 335*a7e14dcfSSatish Balay df->maxPGMIter = 300000; 336*a7e14dcfSSatish Balay df->b = 1.0; 337*a7e14dcfSSatish Balay 338*a7e14dcfSSatish Balay /* memory space required by Dai-Fletcher */ 339*a7e14dcfSSatish Balay df->cur_num_cp = n; 340*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->f); CHKERRQ(ierr); 341*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->a); CHKERRQ(ierr); 342*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->l); CHKERRQ(ierr); 343*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->u); CHKERRQ(ierr); 344*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->x); CHKERRQ(ierr); 345*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal*)*n, &df->Q); CHKERRQ(ierr); 346*a7e14dcfSSatish Balay 347*a7e14dcfSSatish Balay for (i = 0; i < n; i ++) { 348*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->Q[i]); CHKERRQ(ierr); 349*a7e14dcfSSatish Balay } 350*a7e14dcfSSatish Balay 351*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->g); CHKERRQ(ierr); 352*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->y); CHKERRQ(ierr); 353*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->tempv); CHKERRQ(ierr); 354*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->d); CHKERRQ(ierr); 355*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->Qd); CHKERRQ(ierr); 356*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->t); CHKERRQ(ierr); 357*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->xplus); CHKERRQ(ierr); 358*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->tplus); CHKERRQ(ierr); 359*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->sk); CHKERRQ(ierr); 360*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->yk); CHKERRQ(ierr); 361*a7e14dcfSSatish Balay 362*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->ipt); CHKERRQ(ierr); 363*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->ipt2); CHKERRQ(ierr); 364*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->uv); CHKERRQ(ierr); 365*a7e14dcfSSatish Balay 366*a7e14dcfSSatish Balay PetscFunctionReturn(0); 367*a7e14dcfSSatish Balay } 368*a7e14dcfSSatish Balay 369*a7e14dcfSSatish Balay 370*a7e14dcfSSatish Balay #undef __FUNCT__ 371*a7e14dcfSSatish Balay #define __FUNCT__ "ensure_df_space" 372*a7e14dcfSSatish Balay PetscErrorCode ensure_df_space(PetscInt dim, TAO_DF *df) 373*a7e14dcfSSatish Balay { 374*a7e14dcfSSatish Balay PetscErrorCode ierr; 375*a7e14dcfSSatish Balay PetscReal *tmp, **tmp_Q; 376*a7e14dcfSSatish Balay PetscInt i, n, old_n; 377*a7e14dcfSSatish Balay 378*a7e14dcfSSatish Balay df->dim = dim; 379*a7e14dcfSSatish Balay if (dim <= df->cur_num_cp) 380*a7e14dcfSSatish Balay return 0; 381*a7e14dcfSSatish Balay 382*a7e14dcfSSatish Balay PetscFunctionBegin; 383*a7e14dcfSSatish Balay 384*a7e14dcfSSatish Balay old_n = df->cur_num_cp; 385*a7e14dcfSSatish Balay df->cur_num_cp += INCRE_DIM; 386*a7e14dcfSSatish Balay n = df->cur_num_cp; 387*a7e14dcfSSatish Balay 388*a7e14dcfSSatish Balay /* memory space required by dai-fletcher */ 389*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp); CHKERRQ(ierr); 390*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp, df->f, sizeof(PetscReal)*old_n); CHKERRQ(ierr); 391*a7e14dcfSSatish Balay ierr = PetscFree(df->f); CHKERRQ(ierr); 392*a7e14dcfSSatish Balay df->f = tmp; 393*a7e14dcfSSatish Balay 394*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp); CHKERRQ(ierr); 395*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp, df->a, sizeof(PetscReal)*old_n); CHKERRQ(ierr); 396*a7e14dcfSSatish Balay ierr = PetscFree(df->a); CHKERRQ(ierr); 397*a7e14dcfSSatish Balay df->a = tmp; 398*a7e14dcfSSatish Balay 399*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp); CHKERRQ(ierr); 400*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp, df->l, sizeof(PetscReal)*old_n); CHKERRQ(ierr); 401*a7e14dcfSSatish Balay ierr = PetscFree(df->l); CHKERRQ(ierr); 402*a7e14dcfSSatish Balay df->l = tmp; 403*a7e14dcfSSatish Balay 404*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp); CHKERRQ(ierr); 405*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp, df->u, sizeof(PetscReal)*old_n); CHKERRQ(ierr); 406*a7e14dcfSSatish Balay ierr = PetscFree(df->u); CHKERRQ(ierr); 407*a7e14dcfSSatish Balay df->u = tmp; 408*a7e14dcfSSatish Balay 409*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp); CHKERRQ(ierr); 410*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp, df->x, sizeof(PetscReal)*old_n); CHKERRQ(ierr); 411*a7e14dcfSSatish Balay ierr = PetscFree(df->x); CHKERRQ(ierr); 412*a7e14dcfSSatish Balay df->x = tmp; 413*a7e14dcfSSatish Balay 414*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal*)*n, &tmp_Q); CHKERRQ(ierr); 415*a7e14dcfSSatish Balay for (i = 0; i < n; i ++) 416*a7e14dcfSSatish Balay { 417*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &tmp_Q[i]); CHKERRQ(ierr); 418*a7e14dcfSSatish Balay if (i < old_n) 419*a7e14dcfSSatish Balay { 420*a7e14dcfSSatish Balay ierr = PetscMemcpy(tmp_Q[i], df->Q[i], sizeof(PetscReal)*old_n); CHKERRQ(ierr); 421*a7e14dcfSSatish Balay ierr = PetscFree(df->Q[i]); CHKERRQ(ierr); 422*a7e14dcfSSatish Balay } 423*a7e14dcfSSatish Balay } 424*a7e14dcfSSatish Balay 425*a7e14dcfSSatish Balay ierr = PetscFree(df->Q); CHKERRQ(ierr); 426*a7e14dcfSSatish Balay df->Q = tmp_Q; 427*a7e14dcfSSatish Balay 428*a7e14dcfSSatish Balay ierr = PetscFree(df->g); CHKERRQ(ierr); 429*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->g); CHKERRQ(ierr); 430*a7e14dcfSSatish Balay 431*a7e14dcfSSatish Balay ierr = PetscFree(df->y); CHKERRQ(ierr); 432*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->y); CHKERRQ(ierr); 433*a7e14dcfSSatish Balay 434*a7e14dcfSSatish Balay ierr = PetscFree(df->tempv); CHKERRQ(ierr); 435*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->tempv); CHKERRQ(ierr); 436*a7e14dcfSSatish Balay 437*a7e14dcfSSatish Balay ierr = PetscFree(df->d); CHKERRQ(ierr); 438*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->d); CHKERRQ(ierr); 439*a7e14dcfSSatish Balay 440*a7e14dcfSSatish Balay ierr = PetscFree(df->Qd); CHKERRQ(ierr); 441*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->Qd); CHKERRQ(ierr); 442*a7e14dcfSSatish Balay 443*a7e14dcfSSatish Balay ierr = PetscFree(df->t); CHKERRQ(ierr); 444*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->t); CHKERRQ(ierr); 445*a7e14dcfSSatish Balay 446*a7e14dcfSSatish Balay ierr = PetscFree(df->xplus); CHKERRQ(ierr); 447*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->xplus); CHKERRQ(ierr); 448*a7e14dcfSSatish Balay 449*a7e14dcfSSatish Balay ierr = PetscFree(df->tplus); CHKERRQ(ierr); 450*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->tplus); CHKERRQ(ierr); 451*a7e14dcfSSatish Balay 452*a7e14dcfSSatish Balay ierr = PetscFree(df->sk); CHKERRQ(ierr); 453*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->sk); CHKERRQ(ierr); 454*a7e14dcfSSatish Balay 455*a7e14dcfSSatish Balay ierr = PetscFree(df->yk); CHKERRQ(ierr); 456*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscReal)*n, &df->yk); CHKERRQ(ierr); 457*a7e14dcfSSatish Balay 458*a7e14dcfSSatish Balay ierr = PetscFree(df->ipt); CHKERRQ(ierr); 459*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->ipt); CHKERRQ(ierr); 460*a7e14dcfSSatish Balay 461*a7e14dcfSSatish Balay ierr = PetscFree(df->ipt2); CHKERRQ(ierr); 462*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->ipt2); CHKERRQ(ierr); 463*a7e14dcfSSatish Balay 464*a7e14dcfSSatish Balay ierr = PetscFree(df->uv); CHKERRQ(ierr); 465*a7e14dcfSSatish Balay ierr = PetscMalloc(sizeof(PetscInt)*n, &df->uv); CHKERRQ(ierr); 466*a7e14dcfSSatish Balay 467*a7e14dcfSSatish Balay PetscFunctionReturn(0); 468*a7e14dcfSSatish Balay } 469*a7e14dcfSSatish Balay 470*a7e14dcfSSatish Balay 471*a7e14dcfSSatish Balay #undef __FUNCT__ 472*a7e14dcfSSatish Balay #define __FUNCT__ "destroy_df_solver" 473*a7e14dcfSSatish Balay PetscErrorCode destroy_df_solver(TAO_DF *df) 474*a7e14dcfSSatish Balay { 475*a7e14dcfSSatish Balay PetscErrorCode ierr; 476*a7e14dcfSSatish Balay PetscInt i; 477*a7e14dcfSSatish Balay PetscFunctionBegin; 478*a7e14dcfSSatish Balay 479*a7e14dcfSSatish Balay if (df->f) { 480*a7e14dcfSSatish Balay ierr = PetscFree(df->f); CHKERRQ(ierr); df->f = PETSC_NULL; 481*a7e14dcfSSatish Balay } 482*a7e14dcfSSatish Balay 483*a7e14dcfSSatish Balay if (df->a) { 484*a7e14dcfSSatish Balay ierr = PetscFree(df->a); CHKERRQ(ierr); df->a = PETSC_NULL; 485*a7e14dcfSSatish Balay } 486*a7e14dcfSSatish Balay 487*a7e14dcfSSatish Balay if (df->l) { 488*a7e14dcfSSatish Balay ierr = PetscFree(df->l); CHKERRQ(ierr); df->l = PETSC_NULL; 489*a7e14dcfSSatish Balay } 490*a7e14dcfSSatish Balay 491*a7e14dcfSSatish Balay if (df->u) { 492*a7e14dcfSSatish Balay ierr = PetscFree(df->u); CHKERRQ(ierr); df->u = PETSC_NULL; 493*a7e14dcfSSatish Balay } 494*a7e14dcfSSatish Balay 495*a7e14dcfSSatish Balay if (df->x) { 496*a7e14dcfSSatish Balay ierr = PetscFree(df->x); CHKERRQ(ierr); df->x = PETSC_NULL; 497*a7e14dcfSSatish Balay } 498*a7e14dcfSSatish Balay 499*a7e14dcfSSatish Balay for (i = 0; i < df->cur_num_cp; i ++) 500*a7e14dcfSSatish Balay { 501*a7e14dcfSSatish Balay ierr = PetscFree(df->Q[i]); CHKERRQ(ierr); 502*a7e14dcfSSatish Balay } 503*a7e14dcfSSatish Balay ierr = PetscFree(df->Q); CHKERRQ(ierr); 504*a7e14dcfSSatish Balay 505*a7e14dcfSSatish Balay 506*a7e14dcfSSatish Balay if (df->ipt) { 507*a7e14dcfSSatish Balay ierr = PetscFree(df->ipt); CHKERRQ(ierr); df->ipt = PETSC_NULL; 508*a7e14dcfSSatish Balay } 509*a7e14dcfSSatish Balay if (df->ipt2) { 510*a7e14dcfSSatish Balay ierr = PetscFree(df->ipt2); CHKERRQ(ierr); df->ipt2 = PETSC_NULL; 511*a7e14dcfSSatish Balay } 512*a7e14dcfSSatish Balay if (df->uv) { 513*a7e14dcfSSatish Balay ierr = PetscFree(df->uv); CHKERRQ(ierr); df->uv = PETSC_NULL; 514*a7e14dcfSSatish Balay } 515*a7e14dcfSSatish Balay if (df->g) { 516*a7e14dcfSSatish Balay ierr = PetscFree(df->g); CHKERRQ(ierr); df->g = PETSC_NULL; 517*a7e14dcfSSatish Balay } 518*a7e14dcfSSatish Balay if (df->y) { 519*a7e14dcfSSatish Balay ierr = PetscFree(df->y); CHKERRQ(ierr); df->y = PETSC_NULL; 520*a7e14dcfSSatish Balay } 521*a7e14dcfSSatish Balay if (df->tempv) { 522*a7e14dcfSSatish Balay ierr = PetscFree(df->tempv); CHKERRQ(ierr); df->tempv = PETSC_NULL; 523*a7e14dcfSSatish Balay } 524*a7e14dcfSSatish Balay if (df->d) { 525*a7e14dcfSSatish Balay ierr = PetscFree(df->d); CHKERRQ(ierr); df->d = PETSC_NULL; 526*a7e14dcfSSatish Balay } 527*a7e14dcfSSatish Balay if (df->Qd) { 528*a7e14dcfSSatish Balay ierr = PetscFree(df->Qd); CHKERRQ(ierr); df->Qd = PETSC_NULL; 529*a7e14dcfSSatish Balay } 530*a7e14dcfSSatish Balay if (df->t) { 531*a7e14dcfSSatish Balay ierr = PetscFree(df->t); CHKERRQ(ierr); df->t = PETSC_NULL; 532*a7e14dcfSSatish Balay } 533*a7e14dcfSSatish Balay if (df->xplus) { 534*a7e14dcfSSatish Balay ierr = PetscFree(df->xplus); CHKERRQ(ierr); df->xplus = PETSC_NULL; 535*a7e14dcfSSatish Balay } 536*a7e14dcfSSatish Balay if (df->tplus) { 537*a7e14dcfSSatish Balay ierr = PetscFree(df->tplus); CHKERRQ(ierr); df->tplus = PETSC_NULL; 538*a7e14dcfSSatish Balay } 539*a7e14dcfSSatish Balay if (df->sk) { 540*a7e14dcfSSatish Balay ierr = PetscFree(df->sk); CHKERRQ(ierr); df->sk = PETSC_NULL; 541*a7e14dcfSSatish Balay } 542*a7e14dcfSSatish Balay if (df->yk) { 543*a7e14dcfSSatish Balay ierr = PetscFree(df->yk); CHKERRQ(ierr); df->yk = PETSC_NULL; 544*a7e14dcfSSatish Balay } 545*a7e14dcfSSatish Balay 546*a7e14dcfSSatish Balay PetscFunctionReturn(0); 547*a7e14dcfSSatish Balay } 548*a7e14dcfSSatish Balay 549*a7e14dcfSSatish Balay 550*a7e14dcfSSatish Balay /* Piecewise linear monotone target function for the Dai-Fletcher projector */ 551*a7e14dcfSSatish Balay #undef __FUNCT__ 552*a7e14dcfSSatish Balay #define __FUNCT__ "phi" 553*a7e14dcfSSatish Balay PetscReal phi(PetscReal *x, 554*a7e14dcfSSatish Balay PetscInt n, 555*a7e14dcfSSatish Balay PetscReal lambda, 556*a7e14dcfSSatish Balay PetscReal *a, 557*a7e14dcfSSatish Balay PetscReal b, 558*a7e14dcfSSatish Balay PetscReal *c, 559*a7e14dcfSSatish Balay PetscReal *l, 560*a7e14dcfSSatish Balay PetscReal *u) 561*a7e14dcfSSatish Balay { 562*a7e14dcfSSatish Balay PetscReal r = 0.0; 563*a7e14dcfSSatish Balay PetscInt i; 564*a7e14dcfSSatish Balay 565*a7e14dcfSSatish Balay for (i = 0; i < n; i++){ 566*a7e14dcfSSatish Balay x[i] = -c[i] + lambda*a[i]; 567*a7e14dcfSSatish Balay if (x[i] > u[i]) 568*a7e14dcfSSatish Balay x[i] = u[i]; 569*a7e14dcfSSatish Balay else if(x[i] < l[i]) 570*a7e14dcfSSatish Balay x[i] = l[i]; 571*a7e14dcfSSatish Balay r += a[i]*x[i]; 572*a7e14dcfSSatish Balay } 573*a7e14dcfSSatish Balay return r - b; 574*a7e14dcfSSatish Balay } 575*a7e14dcfSSatish Balay 576*a7e14dcfSSatish Balay 577*a7e14dcfSSatish Balay 578*a7e14dcfSSatish Balay /** Modified Dai-Fletcher QP projector solves the problem: 579*a7e14dcfSSatish Balay * 580*a7e14dcfSSatish Balay * minimise 0.5*x'*x - c'*x 581*a7e14dcfSSatish Balay * subj to a'*x = b 582*a7e14dcfSSatish Balay * l \leq x \leq u 583*a7e14dcfSSatish Balay * 584*a7e14dcfSSatish Balay * \param c The point to be projected onto feasible set 585*a7e14dcfSSatish Balay */ 586*a7e14dcfSSatish Balay #undef __FUNCT__ 587*a7e14dcfSSatish Balay #define __FUNCT__ "project" 588*a7e14dcfSSatish Balay PetscInt project(PetscInt n, 589*a7e14dcfSSatish Balay PetscReal *a, 590*a7e14dcfSSatish Balay PetscReal b, 591*a7e14dcfSSatish Balay PetscReal *c, 592*a7e14dcfSSatish Balay PetscReal *l, 593*a7e14dcfSSatish Balay PetscReal *u, 594*a7e14dcfSSatish Balay PetscReal *x, 595*a7e14dcfSSatish Balay PetscReal *lam_ext, 596*a7e14dcfSSatish Balay TAO_DF *df) 597*a7e14dcfSSatish Balay { 598*a7e14dcfSSatish Balay PetscReal lambda, lambdal, lambdau, dlambda, lambda_new; 599*a7e14dcfSSatish Balay PetscReal r, rl, ru, s; 600*a7e14dcfSSatish Balay PetscInt innerIter; 601*a7e14dcfSSatish Balay PetscBool nonNegativeSlack = PETSC_FALSE; 602*a7e14dcfSSatish Balay /* PetscBool nonNegativeSlack = PETSC_TRUE; */ 603*a7e14dcfSSatish Balay 604*a7e14dcfSSatish Balay *lam_ext = 0; 605*a7e14dcfSSatish Balay lambda = 0; 606*a7e14dcfSSatish Balay dlambda = 0.5; 607*a7e14dcfSSatish Balay innerIter = 1; 608*a7e14dcfSSatish Balay 609*a7e14dcfSSatish Balay /* \phi(x;lambda) := 0.5*x'*x + c'*x - lambda*(a'*x-b) 610*a7e14dcfSSatish Balay * 611*a7e14dcfSSatish Balay * Optimality conditions for \phi: 612*a7e14dcfSSatish Balay * 613*a7e14dcfSSatish Balay * 1. lambda <= 0 614*a7e14dcfSSatish Balay * 2. r <= 0 615*a7e14dcfSSatish Balay * 3. r*lambda == 0 616*a7e14dcfSSatish Balay */ 617*a7e14dcfSSatish Balay 618*a7e14dcfSSatish Balay /* Bracketing Phase */ 619*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 620*a7e14dcfSSatish Balay 621*a7e14dcfSSatish Balay if(nonNegativeSlack) 622*a7e14dcfSSatish Balay { 623*a7e14dcfSSatish Balay /* inequality constraint, i.e., with \xi >= 0 constraint */ 624*a7e14dcfSSatish Balay if (r < TOL_R) 625*a7e14dcfSSatish Balay return 0; 626*a7e14dcfSSatish Balay } 627*a7e14dcfSSatish Balay else 628*a7e14dcfSSatish Balay { 629*a7e14dcfSSatish Balay /* equality constraint ,i.e., without \xi >= 0 constraint */ 630*a7e14dcfSSatish Balay if (fabs(r) < TOL_R) 631*a7e14dcfSSatish Balay return 0; 632*a7e14dcfSSatish Balay } 633*a7e14dcfSSatish Balay 634*a7e14dcfSSatish Balay if (r < 0.0){ 635*a7e14dcfSSatish Balay lambdal = lambda; 636*a7e14dcfSSatish Balay rl = r; 637*a7e14dcfSSatish Balay lambda = lambda + dlambda; 638*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 639*a7e14dcfSSatish Balay while (r < 0.0 && dlambda < BMRM_INFTY) { 640*a7e14dcfSSatish Balay lambdal = lambda; 641*a7e14dcfSSatish Balay s = rl/r - 1.0; 642*a7e14dcfSSatish Balay if (s < 0.1) s = 0.1; 643*a7e14dcfSSatish Balay dlambda = dlambda + dlambda/s; 644*a7e14dcfSSatish Balay lambda = lambda + dlambda; 645*a7e14dcfSSatish Balay rl = r; 646*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 647*a7e14dcfSSatish Balay } 648*a7e14dcfSSatish Balay lambdau = lambda; 649*a7e14dcfSSatish Balay ru = r; 650*a7e14dcfSSatish Balay } 651*a7e14dcfSSatish Balay else { 652*a7e14dcfSSatish Balay lambdau = lambda; 653*a7e14dcfSSatish Balay ru = r; 654*a7e14dcfSSatish Balay lambda = lambda - dlambda; 655*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 656*a7e14dcfSSatish Balay while (r > 0.0 && dlambda > -BMRM_INFTY) { 657*a7e14dcfSSatish Balay lambdau = lambda; 658*a7e14dcfSSatish Balay s = ru/r - 1.0; 659*a7e14dcfSSatish Balay if (s < 0.1) s = 0.1; 660*a7e14dcfSSatish Balay dlambda = dlambda + dlambda/s; 661*a7e14dcfSSatish Balay lambda = lambda - dlambda; 662*a7e14dcfSSatish Balay ru = r; 663*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 664*a7e14dcfSSatish Balay } 665*a7e14dcfSSatish Balay lambdal = lambda; 666*a7e14dcfSSatish Balay rl = r; 667*a7e14dcfSSatish Balay } 668*a7e14dcfSSatish Balay 669*a7e14dcfSSatish Balay if(fabs(dlambda) > BMRM_INFTY) { 670*a7e14dcfSSatish Balay PetscPrintf(PETSC_COMM_SELF, "ERROR: L2N2_DaiFletcherPGM detected Infeasible QP problem!\n"); 671*a7e14dcfSSatish Balay exit(0); 672*a7e14dcfSSatish Balay } 673*a7e14dcfSSatish Balay 674*a7e14dcfSSatish Balay if(ru == 0){ 675*a7e14dcfSSatish Balay lambda = lambdau; 676*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 677*a7e14dcfSSatish Balay return innerIter; 678*a7e14dcfSSatish Balay } 679*a7e14dcfSSatish Balay 680*a7e14dcfSSatish Balay /* Secant Phase */ 681*a7e14dcfSSatish Balay s = 1.0 - rl/ru; 682*a7e14dcfSSatish Balay dlambda = dlambda/s; 683*a7e14dcfSSatish Balay lambda = lambdau - dlambda; 684*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 685*a7e14dcfSSatish Balay 686*a7e14dcfSSatish Balay while (fabs(r) > TOL_R 687*a7e14dcfSSatish Balay && dlambda > TOL_LAM * (1.0 + fabs(lambda)) 688*a7e14dcfSSatish Balay && innerIter < df->maxProjIter){ 689*a7e14dcfSSatish Balay innerIter++; 690*a7e14dcfSSatish Balay if (r > 0.0){ 691*a7e14dcfSSatish Balay if (s <= 2.0){ 692*a7e14dcfSSatish Balay lambdau = lambda; 693*a7e14dcfSSatish Balay ru = r; 694*a7e14dcfSSatish Balay s = 1.0 - rl/ru; 695*a7e14dcfSSatish Balay dlambda = (lambdau - lambdal) / s; 696*a7e14dcfSSatish Balay lambda = lambdau - dlambda; 697*a7e14dcfSSatish Balay } 698*a7e14dcfSSatish Balay else { 699*a7e14dcfSSatish Balay s = ru/r-1.0; 700*a7e14dcfSSatish Balay if (s < 0.1) s = 0.1; 701*a7e14dcfSSatish Balay dlambda = (lambdau - lambda) / s; 702*a7e14dcfSSatish Balay lambda_new = 0.75*lambdal + 0.25*lambda; 703*a7e14dcfSSatish Balay if (lambda_new < (lambda - dlambda)) 704*a7e14dcfSSatish Balay lambda_new = lambda - dlambda; 705*a7e14dcfSSatish Balay lambdau = lambda; 706*a7e14dcfSSatish Balay ru = r; 707*a7e14dcfSSatish Balay lambda = lambda_new; 708*a7e14dcfSSatish Balay s = (lambdau - lambdal) / (lambdau - lambda); 709*a7e14dcfSSatish Balay } 710*a7e14dcfSSatish Balay } 711*a7e14dcfSSatish Balay else { 712*a7e14dcfSSatish Balay if (s >= 2.0){ 713*a7e14dcfSSatish Balay lambdal = lambda; 714*a7e14dcfSSatish Balay rl = r; 715*a7e14dcfSSatish Balay s = 1.0 - rl/ru; 716*a7e14dcfSSatish Balay dlambda = (lambdau - lambdal) / s; 717*a7e14dcfSSatish Balay lambda = lambdau - dlambda; 718*a7e14dcfSSatish Balay } 719*a7e14dcfSSatish Balay else { 720*a7e14dcfSSatish Balay s = rl/r - 1.0; 721*a7e14dcfSSatish Balay if (s < 0.1) s = 0.1; 722*a7e14dcfSSatish Balay dlambda = (lambda-lambdal) / s; 723*a7e14dcfSSatish Balay lambda_new = 0.75*lambdau + 0.25*lambda; 724*a7e14dcfSSatish Balay if (lambda_new > (lambda + dlambda)) 725*a7e14dcfSSatish Balay lambda_new = lambda + dlambda; 726*a7e14dcfSSatish Balay lambdal = lambda; 727*a7e14dcfSSatish Balay rl = r; 728*a7e14dcfSSatish Balay lambda = lambda_new; 729*a7e14dcfSSatish Balay s = (lambdau - lambdal) / (lambdau-lambda); 730*a7e14dcfSSatish Balay } 731*a7e14dcfSSatish Balay } 732*a7e14dcfSSatish Balay r = phi(x, n, lambda, a, b, c, l, u); 733*a7e14dcfSSatish Balay } 734*a7e14dcfSSatish Balay 735*a7e14dcfSSatish Balay *lam_ext = lambda; 736*a7e14dcfSSatish Balay if(innerIter >= df->maxProjIter) 737*a7e14dcfSSatish Balay PetscPrintf(PETSC_COMM_SELF, "WARNING: DaiFletcher max iterations\n"); 738*a7e14dcfSSatish Balay 739*a7e14dcfSSatish Balay return innerIter; 740*a7e14dcfSSatish Balay } 741*a7e14dcfSSatish Balay 742*a7e14dcfSSatish Balay 743*a7e14dcfSSatish Balay #undef __FUNCT__ 744*a7e14dcfSSatish Balay #define __FUNCT__ "solve" 745*a7e14dcfSSatish Balay PetscErrorCode solve(TAO_DF *df) 746*a7e14dcfSSatish Balay { 747*a7e14dcfSSatish Balay PetscErrorCode ierr; 748*a7e14dcfSSatish Balay PetscInt i, j, innerIter, it, it2, luv, info, lscount = 0, projcount = 0; 749*a7e14dcfSSatish Balay PetscReal gd, max, ak, bk, akold, bkold, lamnew, alpha, kktlam=0.0, lam_ext; 750*a7e14dcfSSatish Balay PetscReal DELTAsv, ProdDELTAsv; 751*a7e14dcfSSatish Balay PetscReal c, *tempQ; 752*a7e14dcfSSatish Balay PetscReal *x = df->x, *a = df->a, b = df->b, *l = df->l, *u = df->u, tol = df->tol; 753*a7e14dcfSSatish Balay PetscReal *tempv = df->tempv, *y = df->y, *g = df->g, *d = df->d, *Qd = df->Qd; 754*a7e14dcfSSatish Balay PetscReal *xplus = df->xplus, *tplus = df->tplus, *sk = df->sk, *yk = df->yk; 755*a7e14dcfSSatish Balay PetscReal **Q = df->Q, *f = df->f, *t = df->t; 756*a7e14dcfSSatish Balay PetscInt dim = df->dim, *ipt = df->ipt, *ipt2 = df->ipt2, *uv = df->uv; 757*a7e14dcfSSatish Balay 758*a7e14dcfSSatish Balay /*** variables for the adaptive nonmonotone linesearch ***/ 759*a7e14dcfSSatish Balay PetscInt L, llast; 760*a7e14dcfSSatish Balay PetscReal fr, fbest, fv, fc, fv0; 761*a7e14dcfSSatish Balay c = BMRM_INFTY; 762*a7e14dcfSSatish Balay 763*a7e14dcfSSatish Balay DELTAsv = EPS_SV; 764*a7e14dcfSSatish Balay if (tol <= 1.0e-5 || dim <= 20) 765*a7e14dcfSSatish Balay ProdDELTAsv = 0.0F; 766*a7e14dcfSSatish Balay else 767*a7e14dcfSSatish Balay ProdDELTAsv = EPS_SV; 768*a7e14dcfSSatish Balay 769*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 770*a7e14dcfSSatish Balay tempv[i] = -x[i]; 771*a7e14dcfSSatish Balay 772*a7e14dcfSSatish Balay lam_ext = 0.0; 773*a7e14dcfSSatish Balay 774*a7e14dcfSSatish Balay /* Project the initial solution */ 775*a7e14dcfSSatish Balay projcount += project(dim, a, b, tempv, l, u, x, &lam_ext, df); 776*a7e14dcfSSatish Balay 777*a7e14dcfSSatish Balay /* Compute gradient 778*a7e14dcfSSatish Balay g = Q*x + f; */ 779*a7e14dcfSSatish Balay 780*a7e14dcfSSatish Balay it = 0; 781*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 782*a7e14dcfSSatish Balay if (fabs(x[i]) > ProdDELTAsv) 783*a7e14dcfSSatish Balay ipt[it++] = i; 784*a7e14dcfSSatish Balay 785*a7e14dcfSSatish Balay ierr = PetscMemzero(t, dim*sizeof(PetscReal)); CHKERRQ(ierr); 786*a7e14dcfSSatish Balay for (i = 0; i < it; i++){ 787*a7e14dcfSSatish Balay tempQ = Q[ipt[i]]; 788*a7e14dcfSSatish Balay for (j = 0; j < dim; j++) 789*a7e14dcfSSatish Balay t[j] += (tempQ[j]*x[ipt[i]]); 790*a7e14dcfSSatish Balay } 791*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 792*a7e14dcfSSatish Balay g[i] = t[i] + f[i]; 793*a7e14dcfSSatish Balay } 794*a7e14dcfSSatish Balay 795*a7e14dcfSSatish Balay 796*a7e14dcfSSatish Balay /* y = -(x_{k} - g_{k}) */ 797*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 798*a7e14dcfSSatish Balay y[i] = g[i] - x[i]; 799*a7e14dcfSSatish Balay } 800*a7e14dcfSSatish Balay 801*a7e14dcfSSatish Balay /* Project x_{k} - g_{k} */ 802*a7e14dcfSSatish Balay projcount += project(dim, a, b, y, l, u, tempv, &lam_ext, df); 803*a7e14dcfSSatish Balay 804*a7e14dcfSSatish Balay /* y = P(x_{k} - g_{k}) - x_{k} */ 805*a7e14dcfSSatish Balay max = ALPHA_MIN; 806*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 807*a7e14dcfSSatish Balay y[i] = tempv[i] - x[i]; 808*a7e14dcfSSatish Balay if (fabs(y[i]) > max) 809*a7e14dcfSSatish Balay max = fabs(y[i]); 810*a7e14dcfSSatish Balay } 811*a7e14dcfSSatish Balay 812*a7e14dcfSSatish Balay if (max < tol*1e-3){ 813*a7e14dcfSSatish Balay lscount = 0; 814*a7e14dcfSSatish Balay innerIter = 0; 815*a7e14dcfSSatish Balay return 0; 816*a7e14dcfSSatish Balay } 817*a7e14dcfSSatish Balay 818*a7e14dcfSSatish Balay alpha = 1.0 / max; 819*a7e14dcfSSatish Balay 820*a7e14dcfSSatish Balay /* fv0 = f(x_{0}). Recall t = Q x_{k} */ 821*a7e14dcfSSatish Balay fv0 = 0.0; 822*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 823*a7e14dcfSSatish Balay fv0 += x[i] * (0.5*t[i] + f[i]); 824*a7e14dcfSSatish Balay 825*a7e14dcfSSatish Balay /*** adaptive nonmonotone linesearch ***/ 826*a7e14dcfSSatish Balay L = 2; 827*a7e14dcfSSatish Balay fr = ALPHA_MAX; 828*a7e14dcfSSatish Balay fbest = fv0; 829*a7e14dcfSSatish Balay fc = fv0; 830*a7e14dcfSSatish Balay llast = 0; 831*a7e14dcfSSatish Balay akold = bkold = 0.0; 832*a7e14dcfSSatish Balay 833*a7e14dcfSSatish Balay /*** Iterator begins ***/ 834*a7e14dcfSSatish Balay for (innerIter = 1; innerIter <= df->maxPGMIter; innerIter++) { 835*a7e14dcfSSatish Balay 836*a7e14dcfSSatish Balay /* tempv = -(x_{k} - alpha*g_{k}) */ 837*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 838*a7e14dcfSSatish Balay tempv[i] = alpha*g[i] - x[i]; 839*a7e14dcfSSatish Balay 840*a7e14dcfSSatish Balay /* Project x_{k} - alpha*g_{k} */ 841*a7e14dcfSSatish Balay projcount += project(dim, a, b, tempv, l, u, y, &lam_ext, df); 842*a7e14dcfSSatish Balay 843*a7e14dcfSSatish Balay 844*a7e14dcfSSatish Balay /* gd = \inner{d_{k}}{g_{k}} 845*a7e14dcfSSatish Balay d = P(x_{k} - alpha*g_{k}) - x_{k} 846*a7e14dcfSSatish Balay */ 847*a7e14dcfSSatish Balay gd = 0.0; 848*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 849*a7e14dcfSSatish Balay d[i] = y[i] - x[i]; 850*a7e14dcfSSatish Balay gd += d[i] * g[i]; 851*a7e14dcfSSatish Balay } 852*a7e14dcfSSatish Balay 853*a7e14dcfSSatish Balay /* Gradient computation */ 854*a7e14dcfSSatish Balay 855*a7e14dcfSSatish Balay /* compute Qd = Q*d or Qd = Q*y - t depending on their sparsity */ 856*a7e14dcfSSatish Balay 857*a7e14dcfSSatish Balay it = it2 = 0; 858*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 859*a7e14dcfSSatish Balay if (fabs(d[i]) > (ProdDELTAsv*1.0e-2)) 860*a7e14dcfSSatish Balay ipt[it++] = i; 861*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 862*a7e14dcfSSatish Balay if (fabs(y[i]) > ProdDELTAsv) 863*a7e14dcfSSatish Balay ipt2[it2++] = i; 864*a7e14dcfSSatish Balay 865*a7e14dcfSSatish Balay ierr = PetscMemzero(Qd, dim*sizeof(PetscReal)); CHKERRQ(ierr); 866*a7e14dcfSSatish Balay /* compute Qd = Q*d */ 867*a7e14dcfSSatish Balay if (it < it2){ 868*a7e14dcfSSatish Balay for (i = 0; i < it; i++){ 869*a7e14dcfSSatish Balay tempQ = Q[ipt[i]]; 870*a7e14dcfSSatish Balay for (j = 0; j < dim; j++) 871*a7e14dcfSSatish Balay Qd[j] += (tempQ[j] * d[ipt[i]]); 872*a7e14dcfSSatish Balay } 873*a7e14dcfSSatish Balay } 874*a7e14dcfSSatish Balay else { /* compute Qd = Q*y-t */ 875*a7e14dcfSSatish Balay for (i = 0; i < it2; i++){ 876*a7e14dcfSSatish Balay tempQ = Q[ipt2[i]]; 877*a7e14dcfSSatish Balay for (j = 0; j < dim; j++) 878*a7e14dcfSSatish Balay Qd[j] += (tempQ[j] * y[ipt2[i]]); 879*a7e14dcfSSatish Balay } 880*a7e14dcfSSatish Balay for (j = 0; j < dim; j++) 881*a7e14dcfSSatish Balay Qd[j] -= t[j]; 882*a7e14dcfSSatish Balay } 883*a7e14dcfSSatish Balay 884*a7e14dcfSSatish Balay 885*a7e14dcfSSatish Balay /* ak = inner{d_{k}}{d_{k}} */ 886*a7e14dcfSSatish Balay ak = 0.0; 887*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 888*a7e14dcfSSatish Balay ak += d[i] * d[i]; 889*a7e14dcfSSatish Balay 890*a7e14dcfSSatish Balay bk = 0.0; 891*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 892*a7e14dcfSSatish Balay bk += d[i]*Qd[i]; 893*a7e14dcfSSatish Balay 894*a7e14dcfSSatish Balay if (bk > EPS*ak && gd < 0.0) /* ak is normd */ 895*a7e14dcfSSatish Balay lamnew = -gd/bk; 896*a7e14dcfSSatish Balay else 897*a7e14dcfSSatish Balay lamnew = 1.0; 898*a7e14dcfSSatish Balay 899*a7e14dcfSSatish Balay /* fv is computing f(x_{k} + d_{k}) */ 900*a7e14dcfSSatish Balay fv = 0.0; 901*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 902*a7e14dcfSSatish Balay xplus[i] = x[i] + d[i]; 903*a7e14dcfSSatish Balay tplus[i] = t[i] + Qd[i]; 904*a7e14dcfSSatish Balay fv += xplus[i] * (0.5*tplus[i] + f[i]); 905*a7e14dcfSSatish Balay } 906*a7e14dcfSSatish Balay 907*a7e14dcfSSatish Balay /* fr is fref */ 908*a7e14dcfSSatish Balay if ((innerIter == 1 && fv >= fv0) || (innerIter > 1 && fv >= fr)){ 909*a7e14dcfSSatish Balay lscount++; 910*a7e14dcfSSatish Balay fv = 0.0; 911*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 912*a7e14dcfSSatish Balay xplus[i] = x[i] + lamnew*d[i]; 913*a7e14dcfSSatish Balay tplus[i] = t[i] + lamnew*Qd[i]; 914*a7e14dcfSSatish Balay fv += xplus[i] * (0.5*tplus[i] + f[i]); 915*a7e14dcfSSatish Balay } 916*a7e14dcfSSatish Balay } 917*a7e14dcfSSatish Balay 918*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 919*a7e14dcfSSatish Balay sk[i] = xplus[i] - x[i]; 920*a7e14dcfSSatish Balay yk[i] = tplus[i] - t[i]; 921*a7e14dcfSSatish Balay x[i] = xplus[i]; 922*a7e14dcfSSatish Balay t[i] = tplus[i]; 923*a7e14dcfSSatish Balay g[i] = t[i] + f[i]; 924*a7e14dcfSSatish Balay } 925*a7e14dcfSSatish Balay 926*a7e14dcfSSatish Balay 927*a7e14dcfSSatish Balay /* update the line search control parameters */ 928*a7e14dcfSSatish Balay 929*a7e14dcfSSatish Balay if (fv < fbest){ 930*a7e14dcfSSatish Balay fbest = fv; 931*a7e14dcfSSatish Balay fc = fv; 932*a7e14dcfSSatish Balay llast = 0; 933*a7e14dcfSSatish Balay } 934*a7e14dcfSSatish Balay else { 935*a7e14dcfSSatish Balay fc = (fc > fv ? fc : fv); 936*a7e14dcfSSatish Balay llast++; 937*a7e14dcfSSatish Balay if (llast == L){ 938*a7e14dcfSSatish Balay fr = fc; 939*a7e14dcfSSatish Balay fc = fv; 940*a7e14dcfSSatish Balay llast = 0; 941*a7e14dcfSSatish Balay } 942*a7e14dcfSSatish Balay } 943*a7e14dcfSSatish Balay 944*a7e14dcfSSatish Balay ak = bk = 0.0; 945*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 946*a7e14dcfSSatish Balay ak += sk[i] * sk[i]; 947*a7e14dcfSSatish Balay bk += sk[i] * yk[i]; 948*a7e14dcfSSatish Balay } 949*a7e14dcfSSatish Balay 950*a7e14dcfSSatish Balay if (bk <= EPS*ak) 951*a7e14dcfSSatish Balay alpha = ALPHA_MAX; 952*a7e14dcfSSatish Balay else{ 953*a7e14dcfSSatish Balay if (bkold < EPS*akold) 954*a7e14dcfSSatish Balay alpha = ak/bk; 955*a7e14dcfSSatish Balay else 956*a7e14dcfSSatish Balay alpha = (akold+ak)/(bkold+bk); 957*a7e14dcfSSatish Balay 958*a7e14dcfSSatish Balay if (alpha > ALPHA_MAX) 959*a7e14dcfSSatish Balay alpha = ALPHA_MAX; 960*a7e14dcfSSatish Balay else if (alpha < ALPHA_MIN) 961*a7e14dcfSSatish Balay alpha = ALPHA_MIN; 962*a7e14dcfSSatish Balay } 963*a7e14dcfSSatish Balay 964*a7e14dcfSSatish Balay akold = ak; 965*a7e14dcfSSatish Balay bkold = bk; 966*a7e14dcfSSatish Balay 967*a7e14dcfSSatish Balay 968*a7e14dcfSSatish Balay /*** stopping criterion based on KKT conditions ***/ 969*a7e14dcfSSatish Balay /* at optimal, gradient of lagrangian w.r.t. x is zero */ 970*a7e14dcfSSatish Balay 971*a7e14dcfSSatish Balay bk = 0.0; 972*a7e14dcfSSatish Balay for (i = 0; i < dim; i++) 973*a7e14dcfSSatish Balay bk += x[i] * x[i]; 974*a7e14dcfSSatish Balay 975*a7e14dcfSSatish Balay if (sqrt(ak) < tol*10 * sqrt(bk)){ 976*a7e14dcfSSatish Balay it = 0; 977*a7e14dcfSSatish Balay luv = 0; 978*a7e14dcfSSatish Balay kktlam = 0.0; 979*a7e14dcfSSatish Balay for (i = 0; i < dim; i++){ 980*a7e14dcfSSatish Balay /* x[i] is active hence lagrange multipliers for box constraints 981*a7e14dcfSSatish Balay are zero. The lagrange multiplier for ineq. const. is then 982*a7e14dcfSSatish Balay defined as below 983*a7e14dcfSSatish Balay */ 984*a7e14dcfSSatish Balay if ((x[i] > DELTAsv) && (x[i] < c-DELTAsv)){ 985*a7e14dcfSSatish Balay ipt[it++] = i; 986*a7e14dcfSSatish Balay kktlam = kktlam - a[i]*g[i]; 987*a7e14dcfSSatish Balay } 988*a7e14dcfSSatish Balay else 989*a7e14dcfSSatish Balay uv[luv++] = i; 990*a7e14dcfSSatish Balay } 991*a7e14dcfSSatish Balay 992*a7e14dcfSSatish Balay if (it == 0 && sqrt(ak) < tol*0.5 * sqrt(bk)) 993*a7e14dcfSSatish Balay return 0; 994*a7e14dcfSSatish Balay else { 995*a7e14dcfSSatish Balay kktlam = kktlam/it; 996*a7e14dcfSSatish Balay info = 1; 997*a7e14dcfSSatish Balay for (i = 0; i < it; i++) { 998*a7e14dcfSSatish Balay if (fabs(a[ipt[i]] * g[ipt[i]] + kktlam) > tol) { 999*a7e14dcfSSatish Balay info = 0; 1000*a7e14dcfSSatish Balay break; 1001*a7e14dcfSSatish Balay } 1002*a7e14dcfSSatish Balay } 1003*a7e14dcfSSatish Balay if (info == 1) { 1004*a7e14dcfSSatish Balay for (i = 0; i < luv; i++) { 1005*a7e14dcfSSatish Balay if (x[uv[i]] <= DELTAsv){ 1006*a7e14dcfSSatish Balay /* x[i] == lower bound, hence, lagrange multiplier (say, beta) for lower bound may 1007*a7e14dcfSSatish Balay not be zero. So, the gradient without beta is > 0 1008*a7e14dcfSSatish Balay */ 1009*a7e14dcfSSatish Balay if (g[uv[i]] + kktlam*a[uv[i]] < -tol){ 1010*a7e14dcfSSatish Balay info = 0; 1011*a7e14dcfSSatish Balay break; 1012*a7e14dcfSSatish Balay } 1013*a7e14dcfSSatish Balay } 1014*a7e14dcfSSatish Balay else { 1015*a7e14dcfSSatish Balay /* x[i] == upper bound, hence, lagrange multiplier (say, eta) for upper bound may 1016*a7e14dcfSSatish Balay not be zero. So, the gradient without eta is < 0 1017*a7e14dcfSSatish Balay */ 1018*a7e14dcfSSatish Balay if (g[uv[i]] + kktlam*a[uv[i]] > tol) { 1019*a7e14dcfSSatish Balay info = 0; 1020*a7e14dcfSSatish Balay break; 1021*a7e14dcfSSatish Balay } 1022*a7e14dcfSSatish Balay } 1023*a7e14dcfSSatish Balay } 1024*a7e14dcfSSatish Balay } 1025*a7e14dcfSSatish Balay 1026*a7e14dcfSSatish Balay if (info == 1) 1027*a7e14dcfSSatish Balay return 0; 1028*a7e14dcfSSatish Balay } 1029*a7e14dcfSSatish Balay } 1030*a7e14dcfSSatish Balay } 1031*a7e14dcfSSatish Balay return 0; 1032*a7e14dcfSSatish Balay } 1033*a7e14dcfSSatish Balay 1034*a7e14dcfSSatish Balay 1035