xref: /petsc/src/tao/quadratic/impls/bqpip/bqpip.c (revision 83c8fe1d2fbb84e46683ab9274628fec4a31c480)
174962610SAlp Dener /*
274962610SAlp Dener     This file implements a Mehrotra predictor-corrector method for
374962610SAlp Dener     bound-constrained quadratic programs.
474962610SAlp Dener 
574962610SAlp Dener  */
674962610SAlp Dener 
774962610SAlp Dener #include <../src/tao/quadratic/impls/bqpip/bqpipimpl.h>
874962610SAlp Dener #include <petscksp.h>
974962610SAlp Dener 
1074962610SAlp Dener static PetscErrorCode QPIPComputeResidual(TAO_BQPIP *qp,Tao tao)
1174962610SAlp Dener {
1274962610SAlp Dener   PetscErrorCode ierr;
1374962610SAlp Dener   PetscReal      dtmp = 1.0 - qp->psteplength;
1474962610SAlp Dener 
1574962610SAlp Dener   PetscFunctionBegin;
1674962610SAlp Dener   /* Compute R3 and R5 */
1774962610SAlp Dener 
1874962610SAlp Dener   ierr = VecScale(qp->R3,dtmp);CHKERRQ(ierr);
1974962610SAlp Dener   ierr = VecScale(qp->R5,dtmp);CHKERRQ(ierr);
2074962610SAlp Dener   qp->pinfeas=dtmp*qp->pinfeas;
2174962610SAlp Dener 
2274962610SAlp Dener   ierr = VecCopy(qp->S,tao->gradient);CHKERRQ(ierr);
2374962610SAlp Dener   ierr = VecAXPY(tao->gradient,-1.0,qp->Z);CHKERRQ(ierr);
2474962610SAlp Dener 
2574962610SAlp Dener   ierr = MatMult(tao->hessian,tao->solution,qp->RHS);CHKERRQ(ierr);
2674962610SAlp Dener   ierr = VecScale(qp->RHS,-1.0);CHKERRQ(ierr);
2774962610SAlp Dener   ierr = VecAXPY(qp->RHS,-1.0,qp->C);CHKERRQ(ierr);
2874962610SAlp Dener   ierr = VecAXPY(tao->gradient,-1.0,qp->RHS);CHKERRQ(ierr);
2974962610SAlp Dener 
3074962610SAlp Dener   ierr = VecNorm(tao->gradient,NORM_1,&qp->dinfeas);CHKERRQ(ierr);
3174962610SAlp Dener   qp->rnorm=(qp->dinfeas+qp->pinfeas)/(qp->m+qp->n);
3274962610SAlp Dener   PetscFunctionReturn(0);
3374962610SAlp Dener }
3474962610SAlp Dener 
3574962610SAlp Dener static PetscErrorCode  QPIPSetInitialPoint(TAO_BQPIP *qp, Tao tao)
3674962610SAlp Dener {
3774962610SAlp Dener   PetscErrorCode ierr;
3874962610SAlp Dener   PetscReal      two=2.0,p01=1;
3974962610SAlp Dener   PetscReal      gap1,gap2,fff,mu;
4074962610SAlp Dener 
4174962610SAlp Dener   PetscFunctionBegin;
4274962610SAlp Dener   /* Compute function, Gradient R=Hx+b, and Hessian */
4374962610SAlp Dener   ierr = MatMult(tao->hessian,tao->solution,tao->gradient);CHKERRQ(ierr);
4474962610SAlp Dener   ierr = VecCopy(qp->C,qp->Work);CHKERRQ(ierr);
4574962610SAlp Dener   ierr = VecAXPY(qp->Work,0.5,tao->gradient);CHKERRQ(ierr);
4674962610SAlp Dener   ierr = VecAXPY(tao->gradient,1.0,qp->C);CHKERRQ(ierr);
4774962610SAlp Dener   ierr = VecDot(tao->solution,qp->Work,&fff);CHKERRQ(ierr);
4874962610SAlp Dener   qp->pobj = fff + qp->d;
4974962610SAlp Dener 
50691b26d3SBarry Smith   if (PetscIsInfOrNanReal(qp->pobj)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER, "User provided data contains Inf or NaN");
5174962610SAlp Dener 
5274962610SAlp Dener   /* Initialize slack vectors */
5374962610SAlp Dener   /* T = XU - X; G = X - XL */
5474962610SAlp Dener   ierr = VecCopy(qp->XU,qp->T);CHKERRQ(ierr);
5574962610SAlp Dener   ierr = VecAXPY(qp->T,-1.0,tao->solution);CHKERRQ(ierr);
5674962610SAlp Dener   ierr = VecCopy(tao->solution,qp->G);CHKERRQ(ierr);
5774962610SAlp Dener   ierr = VecAXPY(qp->G,-1.0,qp->XL);CHKERRQ(ierr);
5874962610SAlp Dener 
5974962610SAlp Dener   ierr = VecSet(qp->GZwork,p01);CHKERRQ(ierr);
6074962610SAlp Dener   ierr = VecSet(qp->TSwork,p01);CHKERRQ(ierr);
6174962610SAlp Dener 
6274962610SAlp Dener   ierr = VecPointwiseMax(qp->G,qp->G,qp->GZwork);CHKERRQ(ierr);
6374962610SAlp Dener   ierr = VecPointwiseMax(qp->T,qp->T,qp->TSwork);CHKERRQ(ierr);
6474962610SAlp Dener 
6574962610SAlp Dener   /* Initialize Dual Variable Vectors */
6674962610SAlp Dener   ierr = VecCopy(qp->G,qp->Z);CHKERRQ(ierr);
6774962610SAlp Dener   ierr = VecReciprocal(qp->Z);CHKERRQ(ierr);
6874962610SAlp Dener 
6974962610SAlp Dener   ierr = VecCopy(qp->T,qp->S);CHKERRQ(ierr);
7074962610SAlp Dener   ierr = VecReciprocal(qp->S);CHKERRQ(ierr);
7174962610SAlp Dener 
7274962610SAlp Dener   ierr = MatMult(tao->hessian,qp->Work,qp->RHS);CHKERRQ(ierr);
7374962610SAlp Dener   ierr = VecAbs(qp->RHS);CHKERRQ(ierr);
7474962610SAlp Dener   ierr = VecSet(qp->Work,p01);CHKERRQ(ierr);
7574962610SAlp Dener   ierr = VecPointwiseMax(qp->RHS,qp->RHS,qp->Work);CHKERRQ(ierr);
7674962610SAlp Dener 
7774962610SAlp Dener   ierr = VecPointwiseDivide(qp->RHS,tao->gradient,qp->RHS);CHKERRQ(ierr);
7874962610SAlp Dener   ierr = VecNorm(qp->RHS,NORM_1,&gap1);CHKERRQ(ierr);
7974962610SAlp Dener   mu = PetscMin(10.0,(gap1+10.0)/qp->m);
8074962610SAlp Dener 
8174962610SAlp Dener   ierr = VecScale(qp->S,mu);CHKERRQ(ierr);
8274962610SAlp Dener   ierr = VecScale(qp->Z,mu);CHKERRQ(ierr);
8374962610SAlp Dener 
8474962610SAlp Dener   ierr = VecSet(qp->TSwork,p01);CHKERRQ(ierr);
8574962610SAlp Dener   ierr = VecSet(qp->GZwork,p01);CHKERRQ(ierr);
8674962610SAlp Dener   ierr = VecPointwiseMax(qp->S,qp->S,qp->TSwork);CHKERRQ(ierr);
8774962610SAlp Dener   ierr = VecPointwiseMax(qp->Z,qp->Z,qp->GZwork);CHKERRQ(ierr);
8874962610SAlp Dener 
8974962610SAlp Dener   qp->mu=0;qp->dinfeas=1.0;qp->pinfeas=1.0;
9074962610SAlp Dener   while ((qp->dinfeas+qp->pinfeas)/(qp->m+qp->n) >= qp->mu) {
9174962610SAlp Dener     ierr = VecScale(qp->G,two);CHKERRQ(ierr);
9274962610SAlp Dener     ierr = VecScale(qp->Z,two);CHKERRQ(ierr);
9374962610SAlp Dener     ierr = VecScale(qp->S,two);CHKERRQ(ierr);
9474962610SAlp Dener     ierr = VecScale(qp->T,two);CHKERRQ(ierr);
9574962610SAlp Dener 
9674962610SAlp Dener     ierr = QPIPComputeResidual(qp,tao);CHKERRQ(ierr);
9774962610SAlp Dener 
9874962610SAlp Dener     ierr = VecCopy(tao->solution,qp->R3);CHKERRQ(ierr);
9974962610SAlp Dener     ierr = VecAXPY(qp->R3,-1.0,qp->G);CHKERRQ(ierr);
10074962610SAlp Dener     ierr = VecAXPY(qp->R3,-1.0,qp->XL);CHKERRQ(ierr);
10174962610SAlp Dener 
10274962610SAlp Dener     ierr = VecCopy(tao->solution,qp->R5);CHKERRQ(ierr);
10374962610SAlp Dener     ierr = VecAXPY(qp->R5,1.0,qp->T);CHKERRQ(ierr);
10474962610SAlp Dener     ierr = VecAXPY(qp->R5,-1.0,qp->XU);CHKERRQ(ierr);
10574962610SAlp Dener 
10674962610SAlp Dener     ierr = VecNorm(qp->R3,NORM_INFINITY,&gap1);CHKERRQ(ierr);
10774962610SAlp Dener     ierr = VecNorm(qp->R5,NORM_INFINITY,&gap2);CHKERRQ(ierr);
10874962610SAlp Dener     qp->pinfeas=PetscMax(gap1,gap2);
10974962610SAlp Dener 
11074962610SAlp Dener     /* Compute the duality gap */
11174962610SAlp Dener     ierr = VecDot(qp->G,qp->Z,&gap1);CHKERRQ(ierr);
11274962610SAlp Dener     ierr = VecDot(qp->T,qp->S,&gap2);CHKERRQ(ierr);
11374962610SAlp Dener 
11474962610SAlp Dener     qp->gap  = gap1+gap2;
11574962610SAlp Dener     qp->dobj = qp->pobj - qp->gap;
11674962610SAlp Dener     if (qp->m>0) {
11774962610SAlp Dener       qp->mu=qp->gap/(qp->m);
11874962610SAlp Dener     } else {
11974962610SAlp Dener       qp->mu=0.0;
12074962610SAlp Dener     }
12174962610SAlp Dener     qp->rgap=qp->gap/(PetscAbsReal(qp->dobj) + PetscAbsReal(qp->pobj) + 1.0);
12274962610SAlp Dener   }
12374962610SAlp Dener   PetscFunctionReturn(0);
12474962610SAlp Dener }
12574962610SAlp Dener 
12674962610SAlp Dener static PetscErrorCode QPIPStepLength(TAO_BQPIP *qp)
12774962610SAlp Dener {
12874962610SAlp Dener   PetscReal      tstep1,tstep2,tstep3,tstep4,tstep;
12974962610SAlp Dener   PetscErrorCode ierr;
13074962610SAlp Dener 
13174962610SAlp Dener   PetscFunctionBegin;
13274962610SAlp Dener   /* Compute stepsize to the boundary */
13374962610SAlp Dener   ierr = VecStepMax(qp->G,qp->DG,&tstep1);CHKERRQ(ierr);
13474962610SAlp Dener   ierr = VecStepMax(qp->T,qp->DT,&tstep2);CHKERRQ(ierr);
13574962610SAlp Dener   ierr = VecStepMax(qp->S,qp->DS,&tstep3);CHKERRQ(ierr);
13674962610SAlp Dener   ierr = VecStepMax(qp->Z,qp->DZ,&tstep4);CHKERRQ(ierr);
13774962610SAlp Dener 
13874962610SAlp Dener   tstep = PetscMin(tstep1,tstep2);
13974962610SAlp Dener   qp->psteplength = PetscMin(0.95*tstep,1.0);
14074962610SAlp Dener 
14174962610SAlp Dener   tstep = PetscMin(tstep3,tstep4);
14274962610SAlp Dener   qp->dsteplength = PetscMin(0.95*tstep,1.0);
14374962610SAlp Dener 
14474962610SAlp Dener   qp->psteplength = PetscMin(qp->psteplength,qp->dsteplength);
14574962610SAlp Dener   qp->dsteplength = qp->psteplength;
14674962610SAlp Dener   PetscFunctionReturn(0);
14774962610SAlp Dener }
14874962610SAlp Dener 
14974962610SAlp Dener static PetscErrorCode QPIPComputeNormFromCentralPath(TAO_BQPIP *qp,PetscReal *norm)
15074962610SAlp Dener {
15174962610SAlp Dener   PetscErrorCode ierr;
15274962610SAlp Dener   PetscReal      gap[2],mu[2],nmu;
15374962610SAlp Dener 
15474962610SAlp Dener   PetscFunctionBegin;
15574962610SAlp Dener   ierr = VecPointwiseMult(qp->GZwork,qp->G,qp->Z);CHKERRQ(ierr);
15674962610SAlp Dener   ierr = VecPointwiseMult(qp->TSwork,qp->T,qp->S);CHKERRQ(ierr);
15774962610SAlp Dener   ierr = VecNorm(qp->TSwork,NORM_1,&mu[0]);CHKERRQ(ierr);
15874962610SAlp Dener   ierr = VecNorm(qp->GZwork,NORM_1,&mu[1]);CHKERRQ(ierr);
15974962610SAlp Dener 
16074962610SAlp Dener   nmu=-(mu[0]+mu[1])/qp->m;
16174962610SAlp Dener 
16274962610SAlp Dener   ierr = VecShift(qp->GZwork,nmu);CHKERRQ(ierr);
16374962610SAlp Dener   ierr = VecShift(qp->TSwork,nmu);CHKERRQ(ierr);
16474962610SAlp Dener 
16574962610SAlp Dener   ierr = VecNorm(qp->GZwork,NORM_2,&gap[0]);CHKERRQ(ierr);
16674962610SAlp Dener   ierr = VecNorm(qp->TSwork,NORM_2,&gap[1]);CHKERRQ(ierr);
16774962610SAlp Dener   gap[0]*=gap[0];
16874962610SAlp Dener   gap[1]*=gap[1];
16974962610SAlp Dener 
17074962610SAlp Dener   qp->pathnorm=PetscSqrtScalar(gap[0]+gap[1]);
17174962610SAlp Dener   *norm=qp->pathnorm;
17274962610SAlp Dener   PetscFunctionReturn(0);
17374962610SAlp Dener }
17474962610SAlp Dener 
17574962610SAlp Dener static PetscErrorCode QPIPComputeStepDirection(TAO_BQPIP *qp,Tao tao)
17674962610SAlp Dener {
17774962610SAlp Dener   PetscErrorCode ierr;
17874962610SAlp Dener 
17974962610SAlp Dener   PetscFunctionBegin;
18074962610SAlp Dener   /* Calculate DG */
18174962610SAlp Dener   ierr = VecCopy(tao->stepdirection,qp->DG);CHKERRQ(ierr);
18274962610SAlp Dener   ierr = VecAXPY(qp->DG,1.0,qp->R3);CHKERRQ(ierr);
18374962610SAlp Dener 
18474962610SAlp Dener   /* Calculate DT */
18574962610SAlp Dener   ierr = VecCopy(tao->stepdirection,qp->DT);CHKERRQ(ierr);
18674962610SAlp Dener   ierr = VecScale(qp->DT,-1.0);CHKERRQ(ierr);
18774962610SAlp Dener   ierr = VecAXPY(qp->DT,-1.0,qp->R5);CHKERRQ(ierr);
18874962610SAlp Dener 
18974962610SAlp Dener   /* Calculate DZ */
19074962610SAlp Dener   ierr = VecAXPY(qp->DZ,-1.0,qp->Z);CHKERRQ(ierr);
19174962610SAlp Dener   ierr = VecPointwiseDivide(qp->GZwork,qp->DG,qp->G);CHKERRQ(ierr);
19274962610SAlp Dener   ierr = VecPointwiseMult(qp->GZwork,qp->GZwork,qp->Z);CHKERRQ(ierr);
19374962610SAlp Dener   ierr = VecAXPY(qp->DZ,-1.0,qp->GZwork);CHKERRQ(ierr);
19474962610SAlp Dener 
19574962610SAlp Dener   /* Calculate DS */
19674962610SAlp Dener   ierr = VecAXPY(qp->DS,-1.0,qp->S);CHKERRQ(ierr);
19774962610SAlp Dener   ierr = VecPointwiseDivide(qp->TSwork,qp->DT,qp->T);CHKERRQ(ierr);
19874962610SAlp Dener   ierr = VecPointwiseMult(qp->TSwork,qp->TSwork,qp->S);CHKERRQ(ierr);
19974962610SAlp Dener   ierr = VecAXPY(qp->DS,-1.0,qp->TSwork);CHKERRQ(ierr);
20074962610SAlp Dener   PetscFunctionReturn(0);
20174962610SAlp Dener }
20274962610SAlp Dener 
20374962610SAlp Dener static PetscErrorCode TaoSetup_BQPIP(Tao tao)
20474962610SAlp Dener {
20574962610SAlp Dener   TAO_BQPIP      *qp =(TAO_BQPIP*)tao->data;
20674962610SAlp Dener   PetscErrorCode ierr;
20774962610SAlp Dener 
20874962610SAlp Dener   PetscFunctionBegin;
20974962610SAlp Dener   /* Set pointers to Data */
21074962610SAlp Dener   ierr = VecGetSize(tao->solution,&qp->n);CHKERRQ(ierr);
21174962610SAlp Dener 
21274962610SAlp Dener   /* Allocate some arrays */
21374962610SAlp Dener   if (!tao->gradient) {
21474962610SAlp Dener     ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);
21574962610SAlp Dener   }
21674962610SAlp Dener   if (!tao->stepdirection) {
21774962610SAlp Dener     ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);
21874962610SAlp Dener   }
21974962610SAlp Dener   if (!tao->XL) {
22074962610SAlp Dener     ierr = VecDuplicate(tao->solution,&tao->XL);CHKERRQ(ierr);
22174962610SAlp Dener     ierr = VecSet(tao->XL,PETSC_NINFINITY);CHKERRQ(ierr);
22274962610SAlp Dener   }
22374962610SAlp Dener   if (!tao->XU) {
22474962610SAlp Dener     ierr = VecDuplicate(tao->solution,&tao->XU);CHKERRQ(ierr);
22574962610SAlp Dener     ierr = VecSet(tao->XU,PETSC_INFINITY);CHKERRQ(ierr);
22674962610SAlp Dener   }
22774962610SAlp Dener 
22874962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->Work);CHKERRQ(ierr);
22974962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->XU);CHKERRQ(ierr);
23074962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->XL);CHKERRQ(ierr);
23174962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->HDiag);CHKERRQ(ierr);
23274962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->DiagAxpy);CHKERRQ(ierr);
23374962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->RHS);CHKERRQ(ierr);
23474962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->RHS2);CHKERRQ(ierr);
23574962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->C);CHKERRQ(ierr);
23674962610SAlp Dener 
23774962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->G);CHKERRQ(ierr);
23874962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->DG);CHKERRQ(ierr);
23974962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->S);CHKERRQ(ierr);
24074962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->Z);CHKERRQ(ierr);
24174962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->DZ);CHKERRQ(ierr);
24274962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->GZwork);CHKERRQ(ierr);
24374962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->R3);CHKERRQ(ierr);
24474962610SAlp Dener 
24574962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->T);CHKERRQ(ierr);
24674962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->DT);CHKERRQ(ierr);
24774962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->DS);CHKERRQ(ierr);
24874962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->TSwork);CHKERRQ(ierr);
24974962610SAlp Dener   ierr = VecDuplicate(tao->solution,&qp->R5);CHKERRQ(ierr);
25074962610SAlp Dener   qp->m=2*qp->n;
25174962610SAlp Dener   PetscFunctionReturn(0);
25274962610SAlp Dener }
25374962610SAlp Dener 
25474962610SAlp Dener static PetscErrorCode TaoSolve_BQPIP(Tao tao)
25574962610SAlp Dener {
25674962610SAlp Dener   TAO_BQPIP          *qp = (TAO_BQPIP*)tao->data;
25774962610SAlp Dener   PetscErrorCode     ierr;
25874962610SAlp Dener   PetscInt           its;
25974962610SAlp Dener   PetscReal          d1,d2,ksptol,sigmamu;
26074962610SAlp Dener   PetscReal          gnorm,dstep,pstep,step=0;
26174962610SAlp Dener   PetscReal          gap[4];
26274962610SAlp Dener   PetscBool          getdiagop;
26374962610SAlp Dener 
26474962610SAlp Dener   PetscFunctionBegin;
26574962610SAlp Dener   qp->dobj        = 0.0;
26674962610SAlp Dener   qp->pobj        = 1.0;
26774962610SAlp Dener   qp->gap         = 10.0;
26874962610SAlp Dener   qp->rgap        = 1.0;
26974962610SAlp Dener   qp->mu          = 1.0;
27074962610SAlp Dener   qp->dinfeas     = 1.0;
27174962610SAlp Dener   qp->psteplength = 0.0;
27274962610SAlp Dener   qp->dsteplength = 0.0;
27374962610SAlp Dener 
27474962610SAlp Dener   /* TODO
27574962610SAlp Dener      - Remove fixed variables and treat them correctly
27674962610SAlp Dener      - Use index sets for the infinite versus finite bounds
27774962610SAlp Dener      - Update remaining code for fixed and free variables
27874962610SAlp Dener      - Fix inexact solves for predictor and corrector
27974962610SAlp Dener   */
28074962610SAlp Dener 
28174962610SAlp Dener   /* Tighten infinite bounds, things break when we don't do this
28274962610SAlp Dener     -- see test_bqpip.c
28374962610SAlp Dener   */
28474962610SAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
28574962610SAlp Dener   ierr = VecSet(qp->XU,1.0e20);CHKERRQ(ierr);
28674962610SAlp Dener   ierr = VecSet(qp->XL,-1.0e20);CHKERRQ(ierr);
28774962610SAlp Dener   ierr = VecPointwiseMax(qp->XL,qp->XL,tao->XL);CHKERRQ(ierr);
28874962610SAlp Dener   ierr = VecPointwiseMin(qp->XU,qp->XU,tao->XU);CHKERRQ(ierr);
28974962610SAlp Dener   ierr = VecMedian(qp->XL,tao->solution,qp->XU,tao->solution);CHKERRQ(ierr);
29074962610SAlp Dener 
29174962610SAlp Dener   /* Evaluate gradient and Hessian at zero to get the correct values
29274962610SAlp Dener      without contaminating them with numerical artifacts.
29374962610SAlp Dener   */
29474962610SAlp Dener   ierr = VecSet(qp->Work,0);CHKERRQ(ierr);
29574962610SAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao,qp->Work,&qp->d,qp->C);CHKERRQ(ierr);
29674962610SAlp Dener   ierr = TaoComputeHessian(tao,qp->Work,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
29774962610SAlp Dener   ierr = MatHasOperation(tao->hessian,MATOP_GET_DIAGONAL,&getdiagop);CHKERRQ(ierr);
29874962610SAlp Dener   if (getdiagop) {
29974962610SAlp Dener     ierr = MatGetDiagonal(tao->hessian,qp->HDiag);CHKERRQ(ierr);
30074962610SAlp Dener   }
30174962610SAlp Dener 
30274962610SAlp Dener   /* Initialize starting point and residuals */
30374962610SAlp Dener   ierr = QPIPSetInitialPoint(qp,tao);CHKERRQ(ierr);
30474962610SAlp Dener   ierr = QPIPComputeResidual(qp,tao);CHKERRQ(ierr);
30574962610SAlp Dener 
30674962610SAlp Dener   /* Enter main loop */
30774962610SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
30874962610SAlp Dener   while (1) {
30974962610SAlp Dener 
31074962610SAlp Dener     /* Check Stopping Condition      */
31174962610SAlp Dener     gnorm = PetscSqrtScalar(qp->gap + qp->dinfeas);
31274962610SAlp Dener     ierr = TaoLogConvergenceHistory(tao,qp->pobj,gnorm,qp->pinfeas,tao->ksp_its);CHKERRQ(ierr);
31374962610SAlp Dener     ierr = TaoMonitor(tao,tao->niter,qp->pobj,gnorm,qp->pinfeas,step);CHKERRQ(ierr);
31474962610SAlp Dener     ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
31574962610SAlp Dener     if (tao->reason != TAO_CONTINUE_ITERATING) break;
316e1e80dc8SAlp Dener     /* Call general purpose update function */
317e1e80dc8SAlp Dener     if (tao->ops->update) {
3188fcddce6SStefano Zampini       ierr = (*tao->ops->update)(tao, tao->niter, tao->user_update);CHKERRQ(ierr);
319e1e80dc8SAlp Dener     }
32074962610SAlp Dener     tao->niter++;
32174962610SAlp Dener     tao->ksp_its = 0;
32274962610SAlp Dener 
32374962610SAlp Dener     /*
32474962610SAlp Dener        Dual Infeasibility Direction should already be in the right
32574962610SAlp Dener        hand side from computing the residuals
32674962610SAlp Dener     */
32774962610SAlp Dener 
32874962610SAlp Dener     ierr = QPIPComputeNormFromCentralPath(qp,&d1);CHKERRQ(ierr);
32974962610SAlp Dener 
33074962610SAlp Dener     ierr = VecSet(qp->DZ,0.0);CHKERRQ(ierr);
33174962610SAlp Dener     ierr = VecSet(qp->DS,0.0);CHKERRQ(ierr);
33274962610SAlp Dener 
33374962610SAlp Dener     /*
33474962610SAlp Dener        Compute the Primal Infeasiblitiy RHS and the
33574962610SAlp Dener        Diagonal Matrix to be added to H and store in Work
33674962610SAlp Dener     */
33774962610SAlp Dener     ierr = VecPointwiseDivide(qp->DiagAxpy,qp->Z,qp->G);CHKERRQ(ierr);
33874962610SAlp Dener     ierr = VecPointwiseMult(qp->GZwork,qp->DiagAxpy,qp->R3);CHKERRQ(ierr);
33974962610SAlp Dener     ierr = VecAXPY(qp->RHS,-1.0,qp->GZwork);CHKERRQ(ierr);
34074962610SAlp Dener 
34174962610SAlp Dener     ierr = VecPointwiseDivide(qp->TSwork,qp->S,qp->T);CHKERRQ(ierr);
34274962610SAlp Dener     ierr = VecAXPY(qp->DiagAxpy,1.0,qp->TSwork);CHKERRQ(ierr);
34374962610SAlp Dener     ierr = VecPointwiseMult(qp->TSwork,qp->TSwork,qp->R5);CHKERRQ(ierr);
34474962610SAlp Dener     ierr = VecAXPY(qp->RHS,-1.0,qp->TSwork);CHKERRQ(ierr);
34574962610SAlp Dener 
34674962610SAlp Dener     /*  Determine the solving tolerance */
34774962610SAlp Dener     ksptol = qp->mu/10.0;
34874962610SAlp Dener     ksptol = PetscMin(ksptol,0.001);
34974962610SAlp Dener     ierr   = KSPSetTolerances(tao->ksp,ksptol,1e-30,1e30,PetscMax(10,qp->n));CHKERRQ(ierr);
35074962610SAlp Dener 
35174962610SAlp Dener     /* Shift the diagonals of the Hessian matrix */
35274962610SAlp Dener     ierr = MatDiagonalSet(tao->hessian,qp->DiagAxpy,ADD_VALUES);CHKERRQ(ierr);
35374962610SAlp Dener     if (!getdiagop) {
35474962610SAlp Dener       ierr = VecCopy(qp->DiagAxpy,qp->HDiag);CHKERRQ(ierr);
35574962610SAlp Dener       ierr = VecScale(qp->HDiag,-1.0);CHKERRQ(ierr);
35674962610SAlp Dener     }
35774962610SAlp Dener     ierr = MatAssemblyBegin(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
35874962610SAlp Dener     ierr = MatAssemblyEnd(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
35974962610SAlp Dener 
36074962610SAlp Dener     ierr = KSPSetOperators(tao->ksp,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
36174962610SAlp Dener     ierr = KSPSolve(tao->ksp,qp->RHS,tao->stepdirection);CHKERRQ(ierr);
36274962610SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
36374962610SAlp Dener     tao->ksp_its += its;
36474962610SAlp Dener     tao->ksp_tot_its += its;
36574962610SAlp Dener 
36674962610SAlp Dener     /* Restore the true diagonal of the Hessian matrix */
36774962610SAlp Dener     if (getdiagop) {
36874962610SAlp Dener       ierr = MatDiagonalSet(tao->hessian,qp->HDiag,INSERT_VALUES);CHKERRQ(ierr);
36974962610SAlp Dener     } else {
37074962610SAlp Dener       ierr = MatDiagonalSet(tao->hessian,qp->HDiag,ADD_VALUES);CHKERRQ(ierr);
37174962610SAlp Dener     }
37274962610SAlp Dener     ierr = MatAssemblyBegin(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37374962610SAlp Dener     ierr = MatAssemblyEnd(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37474962610SAlp Dener     ierr = QPIPComputeStepDirection(qp,tao);CHKERRQ(ierr);
37574962610SAlp Dener     ierr = QPIPStepLength(qp);CHKERRQ(ierr);
37674962610SAlp Dener 
37774962610SAlp Dener     /* Calculate New Residual R1 in Work vector */
37874962610SAlp Dener     ierr = MatMult(tao->hessian,tao->stepdirection,qp->RHS2);CHKERRQ(ierr);
37974962610SAlp Dener     ierr = VecAXPY(qp->RHS2,1.0,qp->DS);CHKERRQ(ierr);
38074962610SAlp Dener     ierr = VecAXPY(qp->RHS2,-1.0,qp->DZ);CHKERRQ(ierr);
38174962610SAlp Dener     ierr = VecAYPX(qp->RHS2,qp->dsteplength,tao->gradient);CHKERRQ(ierr);
38274962610SAlp Dener 
38374962610SAlp Dener     ierr = VecNorm(qp->RHS2,NORM_2,&qp->dinfeas);CHKERRQ(ierr);
38474962610SAlp Dener     ierr = VecDot(qp->DZ,qp->DG,gap);CHKERRQ(ierr);
38574962610SAlp Dener     ierr = VecDot(qp->DS,qp->DT,gap+1);CHKERRQ(ierr);
38674962610SAlp Dener 
38774962610SAlp Dener     qp->rnorm = (qp->dinfeas+qp->psteplength*qp->pinfeas)/(qp->m+qp->n);
38874962610SAlp Dener     pstep     = qp->psteplength;
38974962610SAlp Dener     step      = PetscMin(qp->psteplength,qp->dsteplength);
39074962610SAlp Dener     sigmamu   = (pstep*pstep*(gap[0]+gap[1]) + (1 - pstep)*qp->gap)/qp->m;
39174962610SAlp Dener 
39274962610SAlp Dener     if (qp->predcorr && step < 0.9) {
39374962610SAlp Dener       if (sigmamu < qp->mu) {
39474962610SAlp Dener         sigmamu = sigmamu/qp->mu;
39574962610SAlp Dener         sigmamu = sigmamu*sigmamu*sigmamu;
39674962610SAlp Dener       } else {
39774962610SAlp Dener         sigmamu = 1.0;
39874962610SAlp Dener       }
39974962610SAlp Dener       sigmamu = sigmamu*qp->mu;
40074962610SAlp Dener 
40174962610SAlp Dener       /* Compute Corrector Step */
40274962610SAlp Dener       ierr = VecPointwiseMult(qp->DZ,qp->DG,qp->DZ);CHKERRQ(ierr);
40374962610SAlp Dener       ierr = VecScale(qp->DZ,-1.0);CHKERRQ(ierr);
40474962610SAlp Dener       ierr = VecShift(qp->DZ,sigmamu);CHKERRQ(ierr);
40574962610SAlp Dener       ierr = VecPointwiseDivide(qp->DZ,qp->DZ,qp->G);CHKERRQ(ierr);
40674962610SAlp Dener 
40774962610SAlp Dener       ierr = VecPointwiseMult(qp->DS,qp->DS,qp->DT);CHKERRQ(ierr);
40874962610SAlp Dener       ierr = VecScale(qp->DS,-1.0);CHKERRQ(ierr);
40974962610SAlp Dener       ierr = VecShift(qp->DS,sigmamu);CHKERRQ(ierr);
41074962610SAlp Dener       ierr = VecPointwiseDivide(qp->DS,qp->DS,qp->T);CHKERRQ(ierr);
41174962610SAlp Dener 
41274962610SAlp Dener       ierr = VecCopy(qp->DZ,qp->RHS2);CHKERRQ(ierr);
41374962610SAlp Dener       ierr = VecAXPY(qp->RHS2,-1.0,qp->DS);CHKERRQ(ierr);
41474962610SAlp Dener       ierr = VecAXPY(qp->RHS2,1.0,qp->RHS);CHKERRQ(ierr);
41574962610SAlp Dener 
41674962610SAlp Dener       /* Approximately solve the linear system */
41774962610SAlp Dener       ierr = MatDiagonalSet(tao->hessian,qp->DiagAxpy,ADD_VALUES);CHKERRQ(ierr);
41874962610SAlp Dener       if (!getdiagop) {
41974962610SAlp Dener         ierr = VecCopy(qp->DiagAxpy,qp->HDiag);CHKERRQ(ierr);
42074962610SAlp Dener         ierr = VecScale(qp->HDiag,-1.0);CHKERRQ(ierr);
42174962610SAlp Dener       }
42274962610SAlp Dener       ierr = MatAssemblyBegin(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
42374962610SAlp Dener       ierr = MatAssemblyEnd(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
42474962610SAlp Dener 
42574962610SAlp Dener       /* Solve using the previous tolerances that were set */
42674962610SAlp Dener       ierr = KSPSolve(tao->ksp,qp->RHS2,tao->stepdirection);CHKERRQ(ierr);
42774962610SAlp Dener       ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr);
42874962610SAlp Dener       tao->ksp_its += its;
42974962610SAlp Dener       tao->ksp_tot_its += its;
43074962610SAlp Dener 
43174962610SAlp Dener       if (getdiagop) {
43274962610SAlp Dener         ierr = MatDiagonalSet(tao->hessian,qp->HDiag,INSERT_VALUES);CHKERRQ(ierr);
43374962610SAlp Dener       } else {
43474962610SAlp Dener         ierr = MatDiagonalSet(tao->hessian,qp->HDiag,ADD_VALUES);CHKERRQ(ierr);
43574962610SAlp Dener       }
43674962610SAlp Dener       ierr = MatAssemblyBegin(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
43774962610SAlp Dener       ierr = MatAssemblyEnd(tao->hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
43874962610SAlp Dener       ierr = QPIPComputeStepDirection(qp,tao);CHKERRQ(ierr);
43974962610SAlp Dener       ierr = QPIPStepLength(qp);CHKERRQ(ierr);
44074962610SAlp Dener     }  /* End Corrector step */
44174962610SAlp Dener 
44274962610SAlp Dener 
44374962610SAlp Dener     /* Take the step */
44474962610SAlp Dener     dstep = qp->dsteplength;
44574962610SAlp Dener 
44674962610SAlp Dener     ierr = VecAXPY(qp->Z,dstep,qp->DZ);CHKERRQ(ierr);
44774962610SAlp Dener     ierr = VecAXPY(qp->S,dstep,qp->DS);CHKERRQ(ierr);
44874962610SAlp Dener     ierr = VecAXPY(tao->solution,dstep,tao->stepdirection);CHKERRQ(ierr);
44974962610SAlp Dener     ierr = VecAXPY(qp->G,dstep,qp->DG);CHKERRQ(ierr);
45074962610SAlp Dener     ierr = VecAXPY(qp->T,dstep,qp->DT);CHKERRQ(ierr);
45174962610SAlp Dener 
45274962610SAlp Dener     /* Compute Residuals */
45374962610SAlp Dener     ierr = QPIPComputeResidual(qp,tao);CHKERRQ(ierr);
45474962610SAlp Dener 
45574962610SAlp Dener     /* Evaluate quadratic function */
45674962610SAlp Dener     ierr = MatMult(tao->hessian,tao->solution,qp->Work);CHKERRQ(ierr);
45774962610SAlp Dener 
45874962610SAlp Dener     ierr = VecDot(tao->solution,qp->Work,&d1);CHKERRQ(ierr);
45974962610SAlp Dener     ierr = VecDot(tao->solution,qp->C,&d2);CHKERRQ(ierr);
46074962610SAlp Dener     ierr = VecDot(qp->G,qp->Z,gap);CHKERRQ(ierr);
46174962610SAlp Dener     ierr = VecDot(qp->T,qp->S,gap+1);CHKERRQ(ierr);
46274962610SAlp Dener 
46374962610SAlp Dener     /* Compute the duality gap */
46474962610SAlp Dener     qp->pobj = d1/2.0 + d2+qp->d;
46574962610SAlp Dener     qp->gap  = gap[0]+gap[1];
46674962610SAlp Dener     qp->dobj = qp->pobj - qp->gap;
46774962610SAlp Dener     if (qp->m > 0) {
46874962610SAlp Dener       qp->mu = qp->gap/(qp->m);
46974962610SAlp Dener     }
47074962610SAlp Dener     qp->rgap = qp->gap/(PetscAbsReal(qp->dobj) + PetscAbsReal(qp->pobj) + 1.0);
47174962610SAlp Dener   }  /* END MAIN LOOP  */
47274962610SAlp Dener   PetscFunctionReturn(0);
47374962610SAlp Dener }
47474962610SAlp Dener 
47574962610SAlp Dener static PetscErrorCode TaoView_BQPIP(Tao tao,PetscViewer viewer)
47674962610SAlp Dener {
47774962610SAlp Dener   PetscFunctionBegin;
47874962610SAlp Dener   PetscFunctionReturn(0);
47974962610SAlp Dener }
48074962610SAlp Dener 
48174962610SAlp Dener static PetscErrorCode TaoSetFromOptions_BQPIP(PetscOptionItems *PetscOptionsObject,Tao tao)
48274962610SAlp Dener {
48374962610SAlp Dener   TAO_BQPIP      *qp = (TAO_BQPIP*)tao->data;
48474962610SAlp Dener   PetscErrorCode ierr;
48574962610SAlp Dener 
48674962610SAlp Dener   PetscFunctionBegin;
48774962610SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Interior point method for bound constrained quadratic optimization");CHKERRQ(ierr);
488*83c8fe1dSLisandro Dalcin   ierr = PetscOptionsInt("-tao_bqpip_predcorr","Use a predictor-corrector method","",qp->predcorr,&qp->predcorr,NULL);CHKERRQ(ierr);
48974962610SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
49074962610SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
49174962610SAlp Dener   PetscFunctionReturn(0);
49274962610SAlp Dener }
49374962610SAlp Dener 
49474962610SAlp Dener static PetscErrorCode TaoDestroy_BQPIP(Tao tao)
49574962610SAlp Dener {
49674962610SAlp Dener   TAO_BQPIP      *qp = (TAO_BQPIP*)tao->data;
49774962610SAlp Dener   PetscErrorCode ierr;
49874962610SAlp Dener 
49974962610SAlp Dener   PetscFunctionBegin;
50074962610SAlp Dener   if (tao->setupcalled) {
50174962610SAlp Dener     ierr = VecDestroy(&qp->G);CHKERRQ(ierr);
50274962610SAlp Dener     ierr = VecDestroy(&qp->DG);CHKERRQ(ierr);
50374962610SAlp Dener     ierr = VecDestroy(&qp->Z);CHKERRQ(ierr);
50474962610SAlp Dener     ierr = VecDestroy(&qp->DZ);CHKERRQ(ierr);
50574962610SAlp Dener     ierr = VecDestroy(&qp->GZwork);CHKERRQ(ierr);
50674962610SAlp Dener     ierr = VecDestroy(&qp->R3);CHKERRQ(ierr);
50774962610SAlp Dener     ierr = VecDestroy(&qp->S);CHKERRQ(ierr);
50874962610SAlp Dener     ierr = VecDestroy(&qp->DS);CHKERRQ(ierr);
50974962610SAlp Dener     ierr = VecDestroy(&qp->T);CHKERRQ(ierr);
51074962610SAlp Dener 
51174962610SAlp Dener     ierr = VecDestroy(&qp->DT);CHKERRQ(ierr);
51274962610SAlp Dener     ierr = VecDestroy(&qp->TSwork);CHKERRQ(ierr);
51374962610SAlp Dener     ierr = VecDestroy(&qp->R5);CHKERRQ(ierr);
51474962610SAlp Dener     ierr = VecDestroy(&qp->HDiag);CHKERRQ(ierr);
51574962610SAlp Dener     ierr = VecDestroy(&qp->Work);CHKERRQ(ierr);
51674962610SAlp Dener     ierr = VecDestroy(&qp->XL);CHKERRQ(ierr);
51774962610SAlp Dener     ierr = VecDestroy(&qp->XU);CHKERRQ(ierr);
51874962610SAlp Dener     ierr = VecDestroy(&qp->DiagAxpy);CHKERRQ(ierr);
51974962610SAlp Dener     ierr = VecDestroy(&qp->RHS);CHKERRQ(ierr);
52074962610SAlp Dener     ierr = VecDestroy(&qp->RHS2);CHKERRQ(ierr);
52174962610SAlp Dener     ierr = VecDestroy(&qp->C);CHKERRQ(ierr);
52274962610SAlp Dener   }
52374962610SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
52474962610SAlp Dener   PetscFunctionReturn(0);
52574962610SAlp Dener }
52674962610SAlp Dener 
52774962610SAlp Dener static PetscErrorCode TaoComputeDual_BQPIP(Tao tao,Vec DXL,Vec DXU)
52874962610SAlp Dener {
52974962610SAlp Dener   TAO_BQPIP       *qp = (TAO_BQPIP*)tao->data;
53074962610SAlp Dener   PetscErrorCode  ierr;
53174962610SAlp Dener 
53274962610SAlp Dener   PetscFunctionBegin;
53374962610SAlp Dener   ierr = VecCopy(qp->Z,DXL);CHKERRQ(ierr);
53474962610SAlp Dener   ierr = VecCopy(qp->S,DXU);CHKERRQ(ierr);
53574962610SAlp Dener   ierr = VecScale(DXU,-1.0);CHKERRQ(ierr);
53674962610SAlp Dener   PetscFunctionReturn(0);
53774962610SAlp Dener }
53874962610SAlp Dener 
53974962610SAlp Dener /*MC
54074962610SAlp Dener  TAOBQPIP - interior-point method for quadratic programs with
54174962610SAlp Dener     box constraints.
54274962610SAlp Dener 
54374962610SAlp Dener  Notes:
54474962610SAlp Dener     This algorithms solves quadratic problems only, the Hessian will
54574962610SAlp Dener         only be computed once.
54674962610SAlp Dener 
54774962610SAlp Dener  Options Database Keys:
54874962610SAlp Dener . -tao_bqpip_predcorr - use a predictor/corrector method
54974962610SAlp Dener 
55074962610SAlp Dener   Level: beginner
55174962610SAlp Dener M*/
55274962610SAlp Dener 
55374962610SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BQPIP(Tao tao)
55474962610SAlp Dener {
55574962610SAlp Dener   TAO_BQPIP      *qp;
55674962610SAlp Dener   PetscErrorCode ierr;
55774962610SAlp Dener 
55874962610SAlp Dener   PetscFunctionBegin;
55974962610SAlp Dener   ierr = PetscNewLog(tao,&qp);CHKERRQ(ierr);
56074962610SAlp Dener 
56174962610SAlp Dener   tao->ops->setup = TaoSetup_BQPIP;
56274962610SAlp Dener   tao->ops->solve = TaoSolve_BQPIP;
56374962610SAlp Dener   tao->ops->view = TaoView_BQPIP;
56474962610SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BQPIP;
56574962610SAlp Dener   tao->ops->destroy = TaoDestroy_BQPIP;
56674962610SAlp Dener   tao->ops->computedual = TaoComputeDual_BQPIP;
56774962610SAlp Dener 
56874962610SAlp Dener   /* Override default settings (unless already changed) */
56974962610SAlp Dener   if (!tao->max_it_changed) tao->max_it=100;
57074962610SAlp Dener   if (!tao->max_funcs_changed) tao->max_funcs = 500;
57174962610SAlp Dener #if defined(PETSC_USE_REAL_SINGLE)
57274962610SAlp Dener   if (!tao->catol_changed) tao->catol=1e-6;
57374962610SAlp Dener #else
57474962610SAlp Dener   if (!tao->catol_changed) tao->catol=1e-12;
57574962610SAlp Dener #endif
57674962610SAlp Dener 
57774962610SAlp Dener   /* Initialize pointers and variables */
57874962610SAlp Dener   qp->n = 0;
57974962610SAlp Dener   qp->m = 0;
58074962610SAlp Dener 
58174962610SAlp Dener   qp->predcorr = 1;
58274962610SAlp Dener   tao->data    = (void*)qp;
58374962610SAlp Dener 
58474962610SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
58574962610SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
58674962610SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
58774962610SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCG);CHKERRQ(ierr);
58874962610SAlp Dener   ierr = KSPSetTolerances(tao->ksp,1e-14,1e-30,1e30,PetscMax(10,qp->n));CHKERRQ(ierr);
58974962610SAlp Dener   PetscFunctionReturn(0);
59074962610SAlp Dener }
591