Actual source code: tron.c

  1: /*$Id$*/

  3: #include "tron.h"       /*I "tao_solver.h" I*/

  5: /* TRON Routines */
  6: static int TaoGradProjections(TAO_SOLVER,TAO_TRON *);
  7: static int TronCheckOptimalFace(TaoVec*, TaoVec*, TaoVec*, TaoVec*, TaoVec*, 
  8:                                 TaoIndexSet*, TaoIndexSet*, TaoTruth *optimal);

 10: /*------------------------------------------------------------*/
 13: static int TaoSetDown_TRON(TAO_SOLVER tao, void*solver)
 14: {
 15:   TAO_TRON *tron = (TAO_TRON *)solver;
 16:   int      info;
 17:   /* Free allocated memory in TRON structure */
 18:   TaoFunctionBegin;
 19:   
 20:   info = TaoVecDestroy(tron->X_New);CHKERRQ(info);
 21:   info = TaoVecDestroy(tron->G_New);CHKERRQ(info);
 22:   info = TaoVecDestroy(tron->DX);CHKERRQ(info);tron->DX=0;
 23:   info = TaoVecDestroy(tron->Work);CHKERRQ(info);
 24:   info = TaoVecDestroy(tron->DXFree);CHKERRQ(info);
 25:   info = TaoVecDestroy(tron->R);CHKERRQ(info);
 26:   info = TaoVecDestroy(tron->G);CHKERRQ(info);
 27:   info = TaoVecDestroy(tron->PG);CHKERRQ(info);
 28:   info = TaoVecDestroy(tron->XL);CHKERRQ(info);
 29:   info = TaoVecDestroy(tron->XU);CHKERRQ(info);
 30:   
 31:   info = TaoIndexSetDestroy(tron->Free_Local);CHKERRQ(info);
 32:   info = TaoIndexSetDestroy(tron->TT);CHKERRQ(info);
 33:   info = TaoMatDestroy(tron->Hsub);CHKERRQ(info);

 35:   info = TaoSetLagrangianGradientVector(tao,0);CHKERRQ(info);
 36:   info = TaoSetStepDirectionVector(tao,0);CHKERRQ(info);
 37:   info = TaoSetVariableBounds(tao,0,0);CHKERRQ(info);

 39:   TaoFunctionReturn(0);
 40: }

 42: /*------------------------------------------------------------*/
 45: static int TaoSetOptions_TRON(TAO_SOLVER tao, void*solver)
 46: {
 47:   TAO_TRON  *tron = (TAO_TRON *)solver;
 48:   int        info,ival;
 49:   TaoTruth flg;

 51:   TaoFunctionBegin;

 53:   info = TaoOptionsHead("Newton Trust Region Method for bound constrained optimization");CHKERRQ(info);

 55:   info = TaoOptionInt("-tron_maxgpits","maximum number of gradient projections per TRON iterate","TaoSetMaxGPIts",tron->maxgpits,&tron->maxgpits,&flg);
 56:   CHKERRQ(info);

 58:   info = TaoOptionInt("-redistribute","Redistribute Free variables (> 1 processors, only)","TaoPetscISType",1,&ival,&flg); CHKERRQ(info);

 60:   info = TaoOptionName("-submatrixfree","Mask full matrix instead of extract submatrices","TaoPetscISType",&flg); CHKERRQ(info);

 62:   info = TaoOptionsTail();CHKERRQ(info);
 63:   info = TaoLineSearchSetFromOptions(tao);CHKERRQ(info);

 65:   TaoFunctionReturn(0);
 66: }

 68: /*------------------------------------------------------------*/
 71: static int TaoView_TRON(TAO_SOLVER tao,void*solver)
 72: {
 73:   TAO_TRON  *tron = (TAO_TRON *)solver;
 74:   int        info;

 76:   TaoFunctionBegin;
 77:   /*
 78:   info = TaoPrintf1(tao," Variables, Total: %d,",tron->n);
 79:   info = TaoPrintf3(tao,"Free: %d,  Binding: %d \n",
 80:                     tron->n_free, tron->n - tron->n_free,
 81:                     tron->n_bind);CHKERRQ(info);
 82:   info = TaoPrintf1(tao,"            Equal lower bound: %d,",
 83:                     tron->n_lower);CHKERRQ(info);
 84:   info = TaoPrintf1(tao,"  Equal upper bound: %d \n",
 85:                     tron->n_upper);CHKERRQ(info);
 86:   */
 87:   info = TaoPrintInt(tao," Total PG its: %d,",tron->total_gp_its);CHKERRQ(info);
 88:   info = TaoPrintDouble(tao," PG tolerance: %4.3f \n",tron->pg_ftol);CHKERRQ(info);
 89:   info = TaoLineSearchView(tao);CHKERRQ(info);
 90:   info = TaoPrintStatement(tao,"  Linear Solver minimizes quadratic over Trust Region: \n");CHKERRQ(info);

 92:   TaoFunctionReturn(0);
 93: }


 96: /* ---------------------------------------------------------- */
 99: static int TaoSetUp_TRON(TAO_SOLVER tao, void*solver){

101:   int info;
102:   TAO_TRON *tron = (TAO_TRON *)solver;
103:   TaoVec* X;
104:   TaoMat *HH;
105:   TaoIndexSet *TIS;

107:   TaoFunctionBegin;
108:   info = TaoGetSolution(tao,&tron->X);CHKERRQ(info); X=tron->X;
109:   info = TaoGetHessian(tao,&tron->H);CHKERRQ(info);  HH=tron->H;

111:   /* Allocate some arrays */
112:   info = X->Clone(&tron->DX); CHKERRQ(info);
113:   info = X->Clone(&tron->X_New); CHKERRQ(info);
114:   info = X->Clone(&tron->G_New); CHKERRQ(info);
115:   info = X->Clone(&tron->Work); CHKERRQ(info);
116:   info = X->Clone(&tron->DXFree); CHKERRQ(info);
117:   info = X->Clone(&tron->R); CHKERRQ(info);
118:   info = X->Clone(&tron->G); CHKERRQ(info);
119:   info = X->Clone(&tron->PG); CHKERRQ(info);
120:   info = X->Clone(&tron->XL); CHKERRQ(info);
121:   info = X->Clone(&tron->XU); CHKERRQ(info);

123:   info = TaoSetLagrangianGradientVector(tao,tron->PG);CHKERRQ(info);
124:   info = TaoSetStepDirectionVector(tao,tron->DX);CHKERRQ(info);
125:   info = TaoSetVariableBounds(tao,tron->XL,tron->XU);CHKERRQ(info);

127:   info = X->GetDimension(&tron->n); CHKERRQ(info);
128:   
129:   info = X->CreateIndexSet(&tron->Free_Local); CHKERRQ(info);
130:   info = tron->Free_Local->Duplicate(&tron->TT); CHKERRQ(info);

132:   TIS=tron->Free_Local;
133:   info = tron->H->CreateReducedMatrix(TIS,TIS,&tron->Hsub); CHKERRQ(info);
134:   info = TaoCreateLinearSolver(tao,HH,220,0); CHKERRQ(info);

136:   info = TaoCheckFGH(tao);CHKERRQ(info);

138:   TaoFunctionReturn(0);
139: }



145: static int TaoSolve_TRON(TAO_SOLVER tao, void*solver){

147:   TAO_TRON *tron = (TAO_TRON *)solver;
148:   int info,lsflag,iter=0;
149:   TaoTerminateReason reason;
150:   TaoTruth optimal_face=TAO_FALSE,success;
151:   double prered,actred,delta,f,f_new,f_full,rhok,gnorm,gdx,xdiff,stepsize;
152:   TaoVec *XU, *XL;
153:   TaoVec *X,  *G;
154:   TaoVec *PG=tron->PG;
155:   TaoVec *R=tron->R, *DXFree=tron->DXFree;
156:   TaoVec *X_New=tron->X_New, *G_New=tron->G_New;
157:   TaoVec *DX=tron->DX, *Work=tron->Work;
158:   TaoMat *H, *Hsub=tron->Hsub;
159:   TaoIndexSet *Free_Local = tron->Free_Local, *TIS=tron->TT;

161:   TaoFunctionBegin;

163:   // Get initial trust region radius
164:   info = TaoGetInitialTrustRegionRadius(tao, &tron->delta); CHKERRQ(info);
165:   if (tron->delta <= 0) {
166:     SETERRQ(1, "Initial trust region radius must be positive");
167:   }

169:   // Get vectors we will need
170:   info = TaoGetSolution(tao, &X); CHKERRQ(info);
171:   info = TaoGetGradient(tao, &G); CHKERRQ(info);
172:   info = TaoGetHessian(tao, &H); CHKERRQ(info);
173:   info = TaoGetVariableBounds(tao, &XL, &XU); CHKERRQ(info);

175:   // Check that upper bound greater than lower bound
176:   info = TaoEvaluateVariableBounds(tao, XL, XU); CHKERRQ(info);

178:   tron->pgstepsize=1.0;

180:   /*   Project the current point onto the feasible set */
181:   info = X->Median(XL,X,XU); CHKERRQ(info);
182:   
183:   info = TaoComputeMeritFunctionGradient(tao,X,&tron->f,G);CHKERRQ(info);
184:   info = Free_Local->WhichBetween(XL,X,XU); CHKERRQ(info);
185:   
186:   /* Project the gradient and calculate the norm */
187:   //  info = G_New->CopyFrom(G);CHKERRQ(info);
188:   info = PG->BoundGradientProjection(G,XL,X,XU);CHKERRQ(info);
189:   info = PG->Norm2(&tron->gnorm); CHKERRQ(info);

191:   if (tron->delta <= 0.0){
192:     tron->delta=TaoMax(tron->gnorm*tron->gnorm,1.0);
193:     //    tron->delta = TAO_INFINITY;
194:   }

196:   tron->stepsize=tron->delta;

198:   info = TaoMonitor(tao,iter++,tron->f,tron->gnorm,0.0,tron->delta,&reason);
199:   CHKERRQ(info);

201:   while (reason==TAO_CONTINUE_ITERATING){
202:     
203:     info = TaoGradProjections(tao,tron); CHKERRQ(info);

205:     info = Free_Local->WhichBetween(XL,X,XU); CHKERRQ(info);
206:     info = Free_Local->GetSize(&tron->n_free); CHKERRQ(info);
207:     f=tron->f; delta=tron->delta; gnorm=tron->gnorm; 

209:     if (tron->n_free > 0){
210:       
211:       info = TaoComputeHessian(tao,X,H);CHKERRQ(info);

213:       /* Create a reduced linear system */
214:       info = R->SetReducedVec(G,Free_Local);CHKERRQ(info);
215:       info = R->Negate(); CHKERRQ(info);
216:       info = DXFree->SetReducedVec(DX,Free_Local);CHKERRQ(info);
217:       info = DXFree->SetToZero(); CHKERRQ(info);

219:       info = Hsub->SetReducedMatrix(H,Free_Local,Free_Local);CHKERRQ(info);

221:       info = TaoPreLinearSolve(tao,Hsub);CHKERRQ(info);

223:       while (1) {

225:          /* Approximately solve the reduced linear system */

227:         info = TaoLinearSolveTrustRegion(tao, Hsub, R, DXFree, delta, &success); CHKERRQ(info);

229:         info=DX->SetToZero(); CHKERRQ(info);
230:         info=DX->ReducedXPY(DXFree,Free_Local);CHKERRQ(info);

232:         info = G->Dot(DX,&gdx); CHKERRQ(info);
233:         info = PetscInfo1(tao,"Expected decrease in function value: %14.12e\n",gdx); CHKERRQ(info);

235:         stepsize=1.0; f_new=f;
236:         info = X_New->CopyFrom(X); CHKERRQ(info);
237:         info = G_New->CopyFrom(G); CHKERRQ(info);
238:         
239:         info = TaoLineSearchApply(tao,X_New,G_New,DX,Work,
240:                                   &f_new,&f_full,&stepsize,&lsflag);
241:         CHKERRQ(info);
242:         info = H->Multiply(DX,Work); CHKERRQ(info);
243:         info = Work->Aypx(0.5,G); CHKERRQ(info);
244:         info = Work->Dot(DX,&prered); CHKERRQ(info);
245:         actred = f_new - f;
246:         
247:         if (actred<0) rhok=TaoAbsScalar(-actred/prered);
248:         else rhok=0.0;

250:         /* Compare actual improvement to the quadratic model */
251:         if (rhok > tron->eta1) { /* Accept the point */

253:           info = DX->Waxpby(1.0,X_New,-1.0, X); CHKERRQ(info);
254:           info = DX->Norm2(&xdiff); CHKERRQ(info);
255:           xdiff*=stepsize;

257:           /* Adjust trust region size */
258:           if (rhok < tron->eta2 ){
259:             delta = TaoMin(xdiff,delta)*tron->sigma1;
260:           } else if (rhok > tron->eta4 ){
261:             delta= TaoMin(xdiff,delta)*tron->sigma3;
262:           } else if (rhok > tron->eta3 ){
263:             delta=TaoMin(xdiff,delta)*tron->sigma2;
264:           }

266:           info =  PG->BoundGradientProjection(G_New,XL,X_New,XU);
267:           CHKERRQ(info);
268:           info = PG->Norm2(&gnorm);  CHKERRQ(info);
269:           info = TronCheckOptimalFace(X_New,XL,XU,G_New,PG, Free_Local, TIS,
270:                                       &optimal_face); CHKERRQ(info);          
271:           if (stepsize < 1 || optimal_face==TAO_FALSE || reason!=TAO_CONTINUE_ITERATING ){
272:             f=f_new;
273:             info = X->CopyFrom(X_New); CHKERRQ(info);
274:             info = G->CopyFrom(G_New); CHKERRQ(info);
275:             break;
276:           }
277:           if (delta<=1e-30){
278:             break;
279:           }
280:         } 
281:         else if (delta <= 1e-30) {
282:           break;
283:         }
284:         else {
285:           delta /= 4.0;
286:         }
287:       } /* end linear solve loop */
288:       
289:     } else {
290:       
291:       actred=0;
292:       info =  Work->BoundGradientProjection(G,XL,X,XU);
293:       CHKERRQ(info);
294:       info = Work->Norm2(&gnorm);  CHKERRQ(info);
295:       /* if there were no free variables, no cg method */

297:     }

299:     tron->f=f;tron->gnorm=gnorm; tron->actred=actred; tron->delta=delta;
300:     info = TaoMonitor(tao,iter,f,gnorm,0.0,delta,&reason); CHKERRQ(info);
301:     if (reason!=TAO_CONTINUE_ITERATING) break;
302:     iter++;
303:     
304:   }  /* END MAIN LOOP  */

306:   TaoFunctionReturn(0);
307: }


312: static int TaoGradProjections(TAO_SOLVER tao,TAO_TRON *tron)
313: {
314:   int i,lsflag=0,info;
315:   TaoTruth sameface=TAO_FALSE;
316:   double actred=-1.0,actred_max=0.0;
317:   double f_new, f_full;
318:   TaoVec *DX=tron->DX,*XL=tron->XL,*XU=tron->XU,*Work=tron->Work;
319:   TaoVec *X=tron->X,*G=tron->G;
320:   TaoIndexSet *TT1=tron->Free_Local, *TT2=tron->TT, *TT3;
321:   /*
322:      The gradient and function value passed into and out of this
323:      routine should be current and correct.
324:      
325:      The free, active, and binding variables should be already identified
326:   */
327:   
328:   TaoFunctionBegin;
329:   
330:   info = TaoGetSolution(tao,&X);CHKERRQ(info);
331:   info = TaoGetGradient(tao,&G);CHKERRQ(info);
332:   info = TaoGetVariableBounds(tao,&XL,&XU);CHKERRQ(info);

334:   info = TT1->WhichBetween(XL,X,XU); CHKERRQ(info);

336:   for (i=0;i<tron->maxgpits;i++){

338:     if ( -actred <= (tron->pg_ftol)*actred_max) break;
339:   
340:     tron->gp_iterates++; tron->total_gp_its++;      
341:     f_new=tron->f;

343:     info = DX->ScaleCopyFrom(-1.0,G); CHKERRQ(info);

345:     info = TaoLineSearchApply(tao,X,G,DX,Work,
346:                               &f_new,&f_full,&tron->pgstepsize,&lsflag);
347:     CHKERRQ(info);

349:     /* Update the iterate */
350:     actred = f_new - tron->f;
351:     actred_max = TaoMax(actred_max,-(f_new - tron->f));
352:     tron->f = f_new;

354:     info = TT2->WhichBetween(XL,X,XU); CHKERRQ(info);
355:     info = TT2->IsSame(TT1,&sameface);  CHKERRQ(info);
356:     if (sameface==TAO_TRUE) {
357:       break;
358:     } else {
359:       //      info = TT1->WhichBetween(XL,X,XU); CHKERRQ(info);
360:       TT3=TT2;
361:       TT2=TT1;
362:       TT1=TT3;
363:     }

365:   }
366:   
367:   TaoFunctionReturn(0);
368: }


373: static int TronCheckOptimalFace(TaoVec *X,TaoVec *XL,TaoVec*XU,TaoVec *PG,TaoVec*W,
374:                                 TaoIndexSet*Free_Local, TaoIndexSet*TT,
375:                                 TaoTruth *optimal)
376: {
377:   int info,n_free;
378:   double rr;
379:   TaoTruth same;

381:   TaoFunctionBegin;
382:   *optimal = TAO_FALSE;

384:   /* Also check to see if the active set is the same */

386:   info = TT->WhichBetween(XL,X,XU); CHKERRQ(info);
387:   info = Free_Local->IsSame(TT,&same); CHKERRQ(info);
388:   info = Free_Local->GetSize(&n_free); CHKERRQ(info);
389:   if (same == TAO_FALSE){
390:     info = Free_Local->WhichBetween(XL,X,XU); CHKERRQ(info);
391:     *optimal = TAO_FALSE;
392:     TaoFunctionReturn(0);
393:   } else {
394:     *optimal = TAO_TRUE;
395:   }

397:   info = W->CopyFrom(PG); CHKERRQ(info);
398:   info = W->Negate(); CHKERRQ(info);

400:   info = W->BoundGradientProjection(W,XL,X,XU); CHKERRQ(info);
401:   info = W->Axpy(1.0,PG); CHKERRQ(info);

403:   info = W->Norm2(&rr); CHKERRQ(info);
404:   if (rr>0) *optimal = TAO_FALSE;

406:   *optimal = TAO_FALSE;
407:   /*
408:     info = tron->TT->whichNonNegative(W); CHKERRQ(info);
409:     info = tron->TT->GetSize(&n); CHKERRQ(info);
410:     if (n==0) *optimal = TAO_TRUE;
411:   */
412:   TaoFunctionReturn(0);
413: }



419: int TaoDefaultMonitor_TRON(TAO_SOLVER tao,void *dummy)
420: {
421:   int info;
422:   int its,nfree,nbind;
423:   double fct,gnorm;
424:   TAO_TRON *tron;

426:   TaoFunctionBegin;
427:   info = TaoGetSolutionStatus(tao,&its,&fct,&gnorm,0,0,0);CHKERRQ(info);
428:   info = TaoGetSolverContext(tao,"tao_tron",(void**)&tron); CHKERRQ(info);
429:   if (tron){
430:     nfree=tron->n_free;
431:     nbind=tron->n_bind;
432:     info=TaoPrintInt(tao,"iter = %d,",its); CHKERRQ(info);
433:     info=TaoPrintDouble(tao," Function value: %g,",fct); CHKERRQ(info);
434:     info=TaoPrintDouble(tao,"  Residual: %g \n",gnorm);CHKERRQ(info);
435:     
436:     info=TaoPrintInt(tao," free vars = %d,",nfree); CHKERRQ(info);
437:     info=TaoPrintInt(tao," binding vars = %d\n",nbind); CHKERRQ(info);
438:   }
439:   TaoFunctionReturn(0);
440: }

442: int TaoSetMaxGPIts(TAO_SOLVER tao, int its){
443:   int info;
444:   TAO_TRON  *tron;

446:   TaoFunctionBegin;

448:   info = TaoGetSolverContext(tao,"tao_tron",(void**)&tron); CHKERRQ(info);
449:   if (tron){
450:     tron->maxgpits     = its;
451:   }
452:   TaoFunctionReturn(0);
453: }


458: static int TaoGetDualVariables_TRON(TAO_SOLVER tao, TaoVec* DXL, TaoVec* DXU, void *solver){

460:   TAO_TRON *tron = (TAO_TRON *) solver;
461:   TaoVec  *G=tron->G,*GP=tron->Work;
462:   TaoVec  *X,*XL,*XU;
463:   int       info;

465:   TaoFunctionBegin;
466:   info = TaoGetSolution(tao,&X); CHKERRQ(info);
467:   info = TaoGetVariableBounds(tao,&XL,&XU); CHKERRQ(info);
468:   info = GP->BoundGradientProjection(G,XL,X,XU); CHKERRQ(info);

470:   info = DXL->Waxpby(-1.0,G,1.0,GP); CHKERRQ(info);
471:   info = DXU->SetToZero(); CHKERRQ(info);
472:   info = DXL->PointwiseMaximum(DXL,DXU); CHKERRQ(info);

474:   info = DXU->Waxpby(-1.0,GP,1.0,G); CHKERRQ(info);
475:   info = GP->SetToZero(); CHKERRQ(info);
476:   info = DXU->PointwiseMinimum(GP,DXU); CHKERRQ(info);

478:   TaoFunctionReturn(0);
479: }

481: /*------------------------------------------------------------*/
485: int TaoCreate_TRON(TAO_SOLVER tao)
486: {
487:   TAO_TRON *tron;
488:   int      info;

490:   TaoFunctionBegin;

492:   info = TaoNew(TAO_TRON,&tron); CHKERRQ(info);
493:   info = PetscLogObjectMemory(tao,sizeof(TAO_TRON)); CHKERRQ(info);

495:   info=TaoSetTaoSolveRoutine(tao,TaoSolve_TRON,(void*)tron); CHKERRQ(info);
496:   info=TaoSetTaoSetUpDownRoutines(tao,TaoSetUp_TRON,TaoSetDown_TRON); CHKERRQ(info);
497:   info=TaoSetTaoOptionsRoutine(tao,TaoSetOptions_TRON); CHKERRQ(info);
498:   info=TaoSetTaoViewRoutine(tao,TaoView_TRON); CHKERRQ(info);
499:   info=TaoSetTaoDualVariablesRoutine(tao,TaoGetDualVariables_TRON); CHKERRQ(info);

501:   info = TaoSetMaximumIterates(tao, 50); CHKERRQ(info);
502:   info = TaoSetTolerances(tao, 1e-10, 1e-10, 0, 0); CHKERRQ(info);

504:   info = TaoSetTrustRegionRadius(tao, 1.0); CHKERRQ(info);
505:   info = TaoSetTrustRegionTolerance(tao, 1.0e-12); CHKERRQ(info);

507:   /* Initialize pointers and variables */
508:   tron->n            = 0;
509:   tron->delta        = -1.0;
510:   tron->maxgpits     = 3;
511:   tron->pg_ftol      = 0.001;

513:   tron->eta1         = 1.0e-4;
514:   tron->eta2         = 0.25;
515:   tron->eta3         = 0.50;
516:   tron->eta4         = 0.90;

518:   tron->sigma1       = 0.5;
519:   tron->sigma2       = 2.0;
520:   tron->sigma3       = 4.0;

522:   tron->gp_iterates  = 0; /* Cumulative number */
523:   tron->cgits        = 0; /* Current iteration */
524:   tron->total_gp_its = 0;
525:   tron->cg_iterates  = 0;
526:   tron->total_cgits  = 0;
527:  
528:   tron->n_bind       = 0;
529:   tron->n_free       = 0;
530:   tron->n_upper      = 0;
531:   tron->n_lower      = 0;

533:   tron->DX=0;
534:   tron->DXFree=0;
535:   tron->R=0;
536:   tron->X_New=0;
537:   tron->G_New=0;
538:   tron->Work=0;
539:   tron->Free_Local=0;
540:   tron->TT=0;
541:   tron->Hsub=0;

543:   info = TaoCreateMoreThuenteBoundLineSearch(tao, 0 , 0); CHKERRQ(info);
544:   TaoFunctionReturn(0);
545: }