Actual source code: taolinesearch.c

  1: #include <petsctaolinesearch.h>
  2: #include <petsc/private/taolinesearchimpl.h>

  4: PetscFunctionList TaoLineSearchList = NULL;

  6: PetscClassId TAOLINESEARCH_CLASSID = 0;

  8: PetscLogEvent TAOLINESEARCH_Apply;
  9: PetscLogEvent TAOLINESEARCH_Eval;

 11: /*@C
 12:    TaoLineSearchViewFromOptions - View from Options

 14:    Collective

 16:    Input Parameters:
 17: +  A - the Tao context
 18: .  obj - Optional object
 19: -  name - command line option

 21:    Level: intermediate
 22: .seealso: `TaoLineSearch`, `TaoLineSearchView`, `PetscObjectViewFromOptions()`, `TaoLineSearchCreate()`
 23: @*/
 24: PetscErrorCode TaoLineSearchViewFromOptions(TaoLineSearch A, PetscObject obj, const char name[])
 25: {
 27:   PetscObjectViewFromOptions((PetscObject)A, obj, name);
 28:   return 0;
 29: }

 31: /*@C
 32:   TaoLineSearchView - Prints information about the TaoLineSearch

 34:   Collective

 36:   InputParameters:
 37: + ls - the Tao context
 38: - viewer - visualization context

 40:   Options Database Key:
 41: . -tao_ls_view - Calls TaoLineSearchView() at the end of each line search

 43:   Notes:
 44:   The available visualization contexts include
 45: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 46: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 47:          output where only the first processor opens
 48:          the file.  All other processors send their
 49:          data to the first processor to print.

 51:   Level: beginner

 53: .seealso: `PetscViewerASCIIOpen()`
 54: @*/

 56: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
 57: {
 58:   PetscBool         isascii, isstring;
 59:   TaoLineSearchType type;

 62:   if (!viewer) PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);

 66:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
 67:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
 68:   if (isascii) {
 69:     PetscObjectPrintClassNamePrefixType((PetscObject)ls, viewer);
 70:     PetscViewerASCIIPushTab(viewer);
 71:     PetscTryTypeMethod(ls, view, viewer);
 72:     PetscViewerASCIIPopTab(viewer);
 73:     PetscViewerASCIIPushTab(viewer);
 74:     PetscViewerASCIIPrintf(viewer, "maximum function evaluations=%" PetscInt_FMT "\n", ls->max_funcs);
 75:     PetscViewerASCIIPrintf(viewer, "tolerances: ftol=%g, rtol=%g, gtol=%g\n", (double)ls->ftol, (double)ls->rtol, (double)ls->gtol);
 76:     PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT "\n", ls->nfeval);
 77:     PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT "\n", ls->ngeval);
 78:     PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT "\n", ls->nfgeval);

 80:     if (ls->bounded) PetscViewerASCIIPrintf(viewer, "using variable bounds\n");
 81:     PetscViewerASCIIPrintf(viewer, "Termination reason: %d\n", (int)ls->reason);
 82:     PetscViewerASCIIPopTab(viewer);
 83:   } else if (isstring) {
 84:     TaoLineSearchGetType(ls, &type);
 85:     PetscViewerStringSPrintf(viewer, " %-3.3s", type);
 86:   }
 87:   return 0;
 88: }

 90: /*@C
 91:   TaoLineSearchCreate - Creates a TAO Line Search object.  Algorithms in TAO that use
 92:   line-searches will automatically create one.

 94:   Collective

 96:   Input Parameter:
 97: . comm - MPI communicator

 99:   Output Parameter:
100: . newls - the new TaoLineSearch context

102:   Available methods include:
103: + more-thuente - the More-Thuente method
104: . gpcg - the GPCG method
105: - unit - Do not perform any line search

107:    Options Database Keys:
108: .   -tao_ls_type - select which method TAO should use

110:    Level: beginner

112: .seealso: `TaoLineSearchSetType()`, `TaoLineSearchApply()`, `TaoLineSearchDestroy()`
113: @*/

115: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
116: {
117:   TaoLineSearch ls;

120:   TaoLineSearchInitializePackage();

122:   PetscHeaderCreate(ls, TAOLINESEARCH_CLASSID, "TaoLineSearch", "Linesearch", "Tao", comm, TaoLineSearchDestroy, TaoLineSearchView);
123:   ls->max_funcs = 30;
124:   ls->ftol      = 0.0001;
125:   ls->gtol      = 0.9;
126: #if defined(PETSC_USE_REAL_SINGLE)
127:   ls->rtol = 1.0e-5;
128: #else
129:   ls->rtol = 1.0e-10;
130: #endif
131:   ls->stepmin  = 1.0e-20;
132:   ls->stepmax  = 1.0e+20;
133:   ls->step     = 1.0;
134:   ls->initstep = 1.0;
135:   *newls       = ls;
136:   return 0;
137: }

139: /*@
140:   TaoLineSearchSetUp - Sets up the internal data structures for the later use
141:   of a Tao solver

143:   Collective

145:   Input Parameters:
146: . ls - the TaoLineSearch context

148:   Notes:
149:   The user will not need to explicitly call TaoLineSearchSetUp(), as it will
150:   automatically be called in TaoLineSearchSolve().  However, if the user
151:   desires to call it explicitly, it should come after TaoLineSearchCreate()
152:   but before TaoLineSearchApply().

154:   Level: developer

156: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchApply()`
157: @*/

159: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
160: {
161:   const char *default_type = TAOLINESEARCHMT;
162:   PetscBool   flg;

165:   if (ls->setupcalled) return 0;
166:   if (!((PetscObject)ls)->type_name) TaoLineSearchSetType(ls, default_type);
167:   PetscTryTypeMethod(ls, setup);
168:   if (ls->usetaoroutines) {
169:     TaoIsObjectiveDefined(ls->tao, &flg);
170:     ls->hasobjective = flg;
171:     TaoIsGradientDefined(ls->tao, &flg);
172:     ls->hasgradient = flg;
173:     TaoIsObjectiveAndGradientDefined(ls->tao, &flg);
174:     ls->hasobjectiveandgradient = flg;
175:   } else {
176:     if (ls->ops->computeobjective) {
177:       ls->hasobjective = PETSC_TRUE;
178:     } else {
179:       ls->hasobjective = PETSC_FALSE;
180:     }
181:     if (ls->ops->computegradient) {
182:       ls->hasgradient = PETSC_TRUE;
183:     } else {
184:       ls->hasgradient = PETSC_FALSE;
185:     }
186:     if (ls->ops->computeobjectiveandgradient) {
187:       ls->hasobjectiveandgradient = PETSC_TRUE;
188:     } else {
189:       ls->hasobjectiveandgradient = PETSC_FALSE;
190:     }
191:   }
192:   ls->setupcalled = PETSC_TRUE;
193:   return 0;
194: }

196: /*@
197:   TaoLineSearchReset - Some line searches may carry state information
198:   from one TaoLineSearchApply() to the next.  This function resets this
199:   state information.

201:   Collective

203:   Input Parameter:
204: . ls - the TaoLineSearch context

206:   Level: developer

208: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchApply()`
209: @*/
210: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
211: {
213:   PetscTryTypeMethod(ls, reset);
214:   return 0;
215: }

217: /*@
218:   TaoLineSearchDestroy - Destroys the TAO context that was created with
219:   TaoLineSearchCreate()

221:   Collective

223:   Input Parameter:
224: . ls - the TaoLineSearch context

226:   Level: beginner

228: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
229: @*/
230: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
231: {
232:   if (!*ls) return 0;
234:   if (--((PetscObject)*ls)->refct > 0) {
235:     *ls = NULL;
236:     return 0;
237:   }
238:   VecDestroy(&(*ls)->stepdirection);
239:   VecDestroy(&(*ls)->start_x);
240:   VecDestroy(&(*ls)->upper);
241:   VecDestroy(&(*ls)->lower);
242:   if ((*ls)->ops->destroy) (*(*ls)->ops->destroy)(*ls);
243:   if ((*ls)->usemonitor) PetscViewerDestroy(&(*ls)->viewer);
244:   PetscHeaderDestroy(ls);
245:   return 0;
246: }

248: /*@
249:   TaoLineSearchApply - Performs a line-search in a given step direction.  Criteria for acceptable step length depends on the line-search algorithm chosen

251:   Collective

253:   Input Parameters:
254: + ls - the Tao context
255: - s - search direction

257:   Input/Output Parameters:

259:   Output Parameters:
260: + x - On input the current solution, on output x contains the new solution determined by the line search
261: . f - On input the objective function value at current solution, on output contains the objective function value at new solution
262: . g - On input the gradient evaluated at x, on output contains the gradient at new solution
263: . steplength - scalar multiplier of s used ( x = x0 + steplength * x)
264: - reason - reason why the line-search stopped

266:   Notes:
267:   reason will be set to one of:

269: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
270: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
271: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
272: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
273: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
274: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
275: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
276: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
277: . TAOLINESEARCH_HALTED_OTHER - any other reason
278: - TAOLINESEARCH_SUCCESS - successful line search

280:   The algorithm developer must set up the TaoLineSearch with calls to
281:   TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()

283:   You may or may not need to follow this with a call to
284:   TaoAddLineSearchCounts(), depending on whether you want these
285:   evaluations to count toward the total function/gradient evaluations.

287:   Level: beginner

289:   .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetType()`, `TaoLineSearchSetInitialStepLength()`, `TaoAddLineSearchCounts()`
290:  @*/

292: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
293: {
294:   PetscInt low1, low2, low3, high1, high2, high3;

305:   VecGetOwnershipRange(x, &low1, &high1);
306:   VecGetOwnershipRange(g, &low2, &high2);
307:   VecGetOwnershipRange(s, &low3, &high3);

310:   *reason = TAOLINESEARCH_CONTINUE_ITERATING;
311:   PetscObjectReference((PetscObject)s);
312:   VecDestroy(&ls->stepdirection);
313:   ls->stepdirection = s;

315:   TaoLineSearchSetUp(ls);
316:   ls->nfeval  = 0;
317:   ls->ngeval  = 0;
318:   ls->nfgeval = 0;
319:   /* Check parameter values */
320:   if (ls->ftol < 0.0) {
321:     PetscInfo(ls, "Bad Line Search Parameter: ftol (%g) < 0\n", (double)ls->ftol);
322:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
323:   }
324:   if (ls->rtol < 0.0) {
325:     PetscInfo(ls, "Bad Line Search Parameter: rtol (%g) < 0\n", (double)ls->rtol);
326:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
327:   }
328:   if (ls->gtol < 0.0) {
329:     PetscInfo(ls, "Bad Line Search Parameter: gtol (%g) < 0\n", (double)ls->gtol);
330:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
331:   }
332:   if (ls->stepmin < 0.0) {
333:     PetscInfo(ls, "Bad Line Search Parameter: stepmin (%g) < 0\n", (double)ls->stepmin);
334:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
335:   }
336:   if (ls->stepmax < ls->stepmin) {
337:     PetscInfo(ls, "Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n", (double)ls->stepmin, (double)ls->stepmax);
338:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
339:   }
340:   if (ls->max_funcs < 0) {
341:     PetscInfo(ls, "Bad Line Search Parameter: max_funcs (%" PetscInt_FMT ") < 0\n", ls->max_funcs);
342:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
343:   }
344:   if (PetscIsInfOrNanReal(*f)) {
345:     PetscInfo(ls, "Initial Line Search Function Value is Inf or Nan (%g)\n", (double)*f);
346:     *reason = TAOLINESEARCH_FAILED_INFORNAN;
347:   }

349:   PetscObjectReference((PetscObject)x);
350:   VecDestroy(&ls->start_x);
351:   ls->start_x = x;

353:   PetscLogEventBegin(TAOLINESEARCH_Apply, ls, 0, 0, 0);
354:   PetscUseTypeMethod(ls, apply, x, f, g, s);
355:   PetscLogEventEnd(TAOLINESEARCH_Apply, ls, 0, 0, 0);
356:   *reason   = ls->reason;
357:   ls->new_f = *f;

359:   if (steplength) *steplength = ls->step;

361:   TaoLineSearchViewFromOptions(ls, NULL, "-tao_ls_view");
362:   return 0;
363: }

365: /*@C
366:    TaoLineSearchSetType - Sets the algorithm used in a line search

368:    Collective

370:    Input Parameters:
371: +  ls - the TaoLineSearch context
372: -  type - the TaoLineSearchType selection

374:   Available methods include:
375: +  more-thuente - line search with a cubic model enforcing the strong Wolfe/curvature condition
376: .  armijo - simple backtracking line search enforcing only the sufficient decrease condition
377: -  unit - do not perform a line search and always accept unit step length

379:   Options Database Keys:
380: .  -tao_ls_type <more-thuente, armijo, unit> - select which method TAO should use at runtime

382:   Level: beginner

384: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchGetType()`, `TaoLineSearchApply()`

386: @*/

388: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, TaoLineSearchType type)
389: {
390:   PetscErrorCode (*r)(TaoLineSearch);
391:   PetscBool flg;

395:   PetscObjectTypeCompare((PetscObject)ls, type, &flg);
396:   if (flg) return 0;

398:   PetscFunctionListFind(TaoLineSearchList, type, (void (**)(void)) & r);
400:   PetscTryTypeMethod(ls, destroy);
401:   ls->max_funcs = 30;
402:   ls->ftol      = 0.0001;
403:   ls->gtol      = 0.9;
404: #if defined(PETSC_USE_REAL_SINGLE)
405:   ls->rtol = 1.0e-5;
406: #else
407:   ls->rtol = 1.0e-10;
408: #endif
409:   ls->stepmin = 1.0e-20;
410:   ls->stepmax = 1.0e+20;

412:   ls->nfeval              = 0;
413:   ls->ngeval              = 0;
414:   ls->nfgeval             = 0;
415:   ls->ops->setup          = NULL;
416:   ls->ops->apply          = NULL;
417:   ls->ops->view           = NULL;
418:   ls->ops->setfromoptions = NULL;
419:   ls->ops->destroy        = NULL;
420:   ls->setupcalled         = PETSC_FALSE;
421:   (*r)(ls);
422:   PetscObjectChangeTypeName((PetscObject)ls, type);
423:   return 0;
424: }

426: /*@C
427:   TaoLineSearchMonitor - Monitor the line search steps. This routine will otuput the
428:   iteration number, step length, and function value before calling the implementation
429:   specific monitor.

431:    Input Parameters:
432: +  ls - the TaoLineSearch context
433: .  its - the current iterate number (>=0)
434: .  f - the current objective function value
435: -  step - the step length

437:    Options Database Key:
438: .  -tao_ls_monitor - Use the default monitor, which prints statistics to standard output

440:    Level: developer

442: @*/
443: PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
444: {
445:   PetscInt tabs;

448:   if (ls->usemonitor) {
449:     PetscViewerASCIIGetTab(ls->viewer, &tabs);
450:     PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel);
451:     PetscViewerASCIIPrintf(ls->viewer, "%3" PetscInt_FMT " LS", its);
452:     PetscViewerASCIIPrintf(ls->viewer, "  Function value: %g,", (double)f);
453:     PetscViewerASCIIPrintf(ls->viewer, "  Step length: %g\n", (double)step);
454:     if (ls->ops->monitor && its > 0) {
455:       PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel + 3);
456:       PetscUseTypeMethod(ls, monitor);
457:     }
458:     PetscViewerASCIISetTab(ls->viewer, tabs);
459:   }
460:   return 0;
461: }

463: /*@
464:   TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
465:   options.

467:   Collective

469:   Input Parameter:
470: . ls - the TaoLineSearch context

472:   Options Database Keys:
473: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
474: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
475: . -tao_ls_gtol <tol> - tolerance for curvature condition
476: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
477: . -tao_ls_stepinit <step> - initial steplength allowed
478: . -tao_ls_stepmin <step> - minimum steplength allowed
479: . -tao_ls_stepmax <step> - maximum steplength allowed
480: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
481: - -tao_ls_view - display line-search results to standard output

483:   Level: beginner
484: @*/
485: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
486: {
487:   const char *default_type = TAOLINESEARCHMT;
488:   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
489:   PetscViewer monviewer;
490:   PetscBool   flg;

493:   PetscObjectOptionsBegin((PetscObject)ls);
494:   if (((PetscObject)ls)->type_name) default_type = ((PetscObject)ls)->type_name;
495:   /* Check for type from options */
496:   PetscOptionsFList("-tao_ls_type", "Tao Line Search type", "TaoLineSearchSetType", TaoLineSearchList, default_type, type, 256, &flg);
497:   if (flg) {
498:     TaoLineSearchSetType(ls, type);
499:   } else if (!((PetscObject)ls)->type_name) {
500:     TaoLineSearchSetType(ls, default_type);
501:   }

503:   PetscOptionsInt("-tao_ls_max_funcs", "max function evals in line search", "", ls->max_funcs, &ls->max_funcs, NULL);
504:   PetscOptionsReal("-tao_ls_ftol", "tol for sufficient decrease", "", ls->ftol, &ls->ftol, NULL);
505:   PetscOptionsReal("-tao_ls_gtol", "tol for curvature condition", "", ls->gtol, &ls->gtol, NULL);
506:   PetscOptionsReal("-tao_ls_rtol", "relative tol for acceptable step", "", ls->rtol, &ls->rtol, NULL);
507:   PetscOptionsReal("-tao_ls_stepmin", "lower bound for step", "", ls->stepmin, &ls->stepmin, NULL);
508:   PetscOptionsReal("-tao_ls_stepmax", "upper bound for step", "", ls->stepmax, &ls->stepmax, NULL);
509:   PetscOptionsReal("-tao_ls_stepinit", "initial step", "", ls->initstep, &ls->initstep, NULL);
510:   PetscOptionsString("-tao_ls_monitor", "enable the basic monitor", "TaoLineSearchSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
511:   if (flg) {
512:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ls), monfilename, &monviewer);
513:     ls->viewer     = monviewer;
514:     ls->usemonitor = PETSC_TRUE;
515:   }
516:   PetscTryTypeMethod(ls, setfromoptions, PetscOptionsObject);
517:   PetscOptionsEnd();
518:   return 0;
519: }

521: /*@C
522:   TaoLineSearchGetType - Gets the current line search algorithm

524:   Not Collective

526:   Input Parameter:
527: . ls - the TaoLineSearch context

529:   Output Parameter:
530: . type - the line search algorithm in effect

532:   Level: developer

534: @*/
535: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
536: {
539:   *type = ((PetscObject)ls)->type_name;
540:   return 0;
541: }

543: /*@
544:   TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
545:   routines used by the line search in last application (not cumulative).

547:   Not Collective

549:   Input Parameter:
550: . ls - the TaoLineSearch context

552:   Output Parameters:
553: + nfeval   - number of function evaluations
554: . ngeval   - number of gradient evaluations
555: - nfgeval  - number of function/gradient evaluations

557:   Level: intermediate

559:   Note:
560:   If the line search is using the Tao objective and gradient
561:   routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
562:   is already counting the number of evaluations.

564: @*/
565: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
566: {
568:   *nfeval  = ls->nfeval;
569:   *ngeval  = ls->ngeval;
570:   *nfgeval = ls->nfgeval;
571:   return 0;
572: }

574: /*@
575:   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
576:   Tao evaluation routines.

578:   Not Collective

580:   Input Parameter:
581: . ls - the TaoLineSearch context

583:   Output Parameter:
584: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
585:         otherwise PETSC_FALSE

587:   Level: developer
588: @*/
589: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
590: {
592:   *flg = ls->usetaoroutines;
593:   return 0;
594: }

596: /*@C
597:   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search

599:   Logically Collective

601:   Input Parameters:
602: + ls - the TaoLineSearch context
603: . func - the objective function evaluation routine
604: - ctx - the (optional) user-defined context for private data

606:   Calling sequence of func:
607: $      func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);

609: + x - input vector
610: . f - function value
611: - ctx (optional) user-defined context

613:   Level: beginner

615:   Note:
616:   Use this routine only if you want the line search objective
617:   evaluation routine to be different from the Tao's objective
618:   evaluation routine. If you use this routine you must also set
619:   the line search gradient and/or function/gradient routine.

621:   Note:
622:   Some algorithms (lcl, gpcg) set their own objective routine for the
623:   line search, application programmers should be wary of overriding the
624:   default objective routine.

626: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetGradientRoutine()`, `TaoLineSearchSetObjectiveAndGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
627: @*/
628: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, PetscReal *, void *), void *ctx)
629: {

632:   ls->ops->computeobjective = func;
633:   if (ctx) ls->userctx_func = ctx;
634:   ls->usetaoroutines = PETSC_FALSE;
635:   return 0;
636: }

638: /*@C
639:   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search

641:   Logically Collective

643:   Input Parameters:
644: + ls - the TaoLineSearch context
645: . func - the gradient evaluation routine
646: - ctx - the (optional) user-defined context for private data

648:   Calling sequence of func:
649: $      func (TaoLinesearch ls, Vec x, Vec g, void *ctx);

651: + x - input vector
652: . g - gradient vector
653: - ctx (optional) user-defined context

655:   Level: beginner

657:   Note:
658:   Use this routine only if you want the line search gradient
659:   evaluation routine to be different from the Tao's gradient
660:   evaluation routine. If you use this routine you must also set
661:   the line search function and/or function/gradient routine.

663:   Note:
664:   Some algorithms (lcl, gpcg) set their own gradient routine for the
665:   line search, application programmers should be wary of overriding the
666:   default gradient routine.

668: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetObjectiveRoutine()`, `TaoLineSearchSetObjectiveAndGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
669: @*/
670: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, Vec g, void *), void *ctx)
671: {
673:   ls->ops->computegradient = func;
674:   if (ctx) ls->userctx_grad = ctx;
675:   ls->usetaoroutines = PETSC_FALSE;
676:   return 0;
677: }

679: /*@C
680:   TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search

682:   Logically Collective

684:   Input Parameters:
685: + ls - the TaoLineSearch context
686: . func - the objective and gradient evaluation routine
687: - ctx - the (optional) user-defined context for private data

689:   Calling sequence of func:
690: $      func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);

692: + x - input vector
693: . f - function value
694: . g - gradient vector
695: - ctx (optional) user-defined context

697:   Level: beginner

699:   Note:
700:   Use this routine only if you want the line search objective and gradient
701:   evaluation routines to be different from the Tao's objective
702:   and gradient evaluation routines.

704:   Note:
705:   Some algorithms (lcl, gpcg) set their own objective routine for the
706:   line search, application programmers should be wary of overriding the
707:   default objective routine.

709: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetObjectiveRoutine()`, `TaoLineSearchSetGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
710: @*/
711: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void *), void *ctx)
712: {
714:   ls->ops->computeobjectiveandgradient = func;
715:   if (ctx) ls->userctx_funcgrad = ctx;
716:   ls->usetaoroutines = PETSC_FALSE;
717:   return 0;
718: }

720: /*@C
721:   TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
722:   (gradient'*stepdirection) evaluation routine for the line search.
723:   Sometimes it is more efficient to compute the inner product of the gradient
724:   and the step direction than it is to compute the gradient, and this is all
725:   the line search typically needs of the gradient.

727:   Logically Collective

729:   Input Parameters:
730: + ls - the TaoLineSearch context
731: . func - the objective and gradient evaluation routine
732: - ctx - the (optional) user-defined context for private data

734:   Calling sequence of func:
735: $      func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);

737: + x - input vector
738: . s - step direction
739: . f - function value
740: . gts - inner product of gradient and step direction vectors
741: - ctx (optional) user-defined context

743:   Note: The gradient will still need to be computed at the end of the line
744:   search, so you will still need to set a line search gradient evaluation
745:   routine

747:   Note: Bounded line searches (those used in bounded optimization algorithms)
748:   don't use g's directly, but rather (g'x - g'x0)/steplength.  You can get the
749:   x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()

751:   Level: advanced

753:   Note:
754:   Some algorithms (lcl, gpcg) set their own objective routine for the
755:   line search, application programmers should be wary of overriding the
756:   default objective routine.

758: .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetObjective()`, `TaoLineSearchSetGradient()`, `TaoLineSearchUseTaoRoutines()`
759: @*/
760: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void *), void *ctx)
761: {
763:   ls->ops->computeobjectiveandgts = func;
764:   if (ctx) ls->userctx_funcgts = ctx;
765:   ls->usegts         = PETSC_TRUE;
766:   ls->usetaoroutines = PETSC_FALSE;
767:   return 0;
768: }

770: /*@C
771:   TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
772:   objective and gradient evaluation routines from the given Tao object.

774:   Logically Collective

776:   Input Parameters:
777: + ls - the TaoLineSearch context
778: - ts - the Tao context with defined objective/gradient evaluation routines

780:   Level: developer

782: .seealso: `TaoLineSearchCreate()`
783: @*/
784: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
785: {
788:   ls->tao            = ts;
789:   ls->usetaoroutines = PETSC_TRUE;
790:   return 0;
791: }

793: /*@
794:   TaoLineSearchComputeObjective - Computes the objective function value at a given point

796:   Collective

798:   Input Parameters:
799: + ls - the TaoLineSearch context
800: - x - input vector

802:   Output Parameter:
803: . f - Objective value at X

805:   Notes:
806:     TaoLineSearchComputeObjective() is typically used within line searches
807:   so most users would not generally call this routine themselves.

809:   Level: developer

811: .seealso: `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
812: @*/
813: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
814: {
815:   Vec       gdummy;
816:   PetscReal gts;

822:   if (ls->usetaoroutines) {
823:     TaoComputeObjective(ls->tao, x, f);
824:   } else {
826:     PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0);
827:     if (ls->ops->computeobjective) PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjective)(ls, x, f, ls->userctx_func));
828:     else if (ls->ops->computeobjectiveandgradient) {
829:       VecDuplicate(x, &gdummy);
830:       PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgradient)(ls, x, f, gdummy, ls->userctx_funcgrad));
831:       VecDestroy(&gdummy);
832:     } else PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgts)(ls, x, ls->stepdirection, f, &gts, ls->userctx_funcgts));
833:     PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0);
834:   }
835:   ls->nfeval++;
836:   return 0;
837: }

839: /*@
840:   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point

842:   Collective

844:   Input Parameters:
845: + ls - the TaoLineSearch context
846: - x - input vector

848:   Output Parameters:
849: + f - Objective value at X
850: - g - Gradient vector at X

852:   Notes:
853:     TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
854:   so most users would not generally call this routine themselves.

856:   Level: developer

858: .seealso: `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
859: @*/
860: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
861: {
868:   if (ls->usetaoroutines) {
869:     TaoComputeObjectiveAndGradient(ls->tao, x, f, g);
870:   } else {
871:     PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0);
872:     if (ls->ops->computeobjectiveandgradient) PetscCallBack("TaoLineSearch callback objective/gradient", (*ls->ops->computeobjectiveandgradient)(ls, x, f, g, ls->userctx_funcgrad));
873:     else {
874:       PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjective)(ls, x, f, ls->userctx_func));
875:       PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computegradient)(ls, x, g, ls->userctx_grad));
876:     }
877:     PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0);
878:     PetscInfo(ls, "TaoLineSearch Function evaluation: %14.12e\n", (double)(*f));
879:   }
880:   ls->nfgeval++;
881:   return 0;
882: }

884: /*@
885:   TaoLineSearchComputeGradient - Computes the gradient of the objective function

887:   Collective

889:   Input Parameters:
890: + ls - the TaoLineSearch context
891: - x - input vector

893:   Output Parameter:
894: . g - gradient vector

896:   Notes:
897:     TaoComputeGradient() is typically used within line searches
898:   so most users would not generally call this routine themselves.

900:   Level: developer

902: .seealso: `TaoLineSearchComputeObjective()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetGradient()`
903: @*/
904: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
905: {
906:   PetscReal fdummy;

913:   if (ls->usetaoroutines) {
914:     TaoComputeGradient(ls->tao, x, g);
915:   } else {
916:     PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0);
917:     if (ls->ops->computegradient) PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computegradient)(ls, x, g, ls->userctx_grad));
918:     else PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computeobjectiveandgradient)(ls, x, &fdummy, g, ls->userctx_funcgrad));
919:     PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0);
920:   }
921:   ls->ngeval++;
922:   return 0;
923: }

925: /*@
926:   TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point

928:   Collective

930:   Input Parameters:
931: + ls - the TaoLineSearch context
932: - x - input vector

934:   Output Parameters:
935: + f - Objective value at X
936: - gts - inner product of gradient and step direction at X

938:   Notes:
939:     TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
940:   so most users would not generally call this routine themselves.

942:   Level: developer

944: .seealso: `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
945: @*/
946: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
947: {
953:   PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0);
954:   PetscCallBack("TaoLineSearch callback objective/gts", (*ls->ops->computeobjectiveandgts)(ls, x, ls->stepdirection, f, gts, ls->userctx_funcgts));
955:   PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0);
956:   PetscInfo(ls, "TaoLineSearch Function evaluation: %14.12e\n", (double)(*f));
957:   ls->nfeval++;
958:   return 0;
959: }

961: /*@
962:   TaoLineSearchGetSolution - Returns the solution to the line search

964:   Collective

966:   Input Parameter:
967: . ls - the TaoLineSearch context

969:   Output Parameters:
970: + x - the new solution
971: . f - the objective function value at x
972: . g - the gradient at x
973: . steplength - the multiple of the step direction taken by the line search
974: - reason - the reason why the line search terminated

976:   reason will be set to one of:

978: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
979: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
980: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
981: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
982: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
983: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
984: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance

986: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
987: . TAOLINESEARCH_HALTED_OTHER - any other reason

989: - TAOLINESEARCH_SUCCESS - successful line search

991:   Level: developer

993: @*/
994: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
995: {
1001:   if (ls->new_x) VecCopy(ls->new_x, x);
1002:   *f = ls->new_f;
1003:   if (ls->new_g) VecCopy(ls->new_g, g);
1004:   if (steplength) *steplength = ls->step;
1005:   *reason = ls->reason;
1006:   return 0;
1007: }

1009: /*@
1010:   TaoLineSearchGetStartingVector - Gets a the initial point of the line
1011:   search.

1013:   Not Collective

1015:   Input Parameter:
1016: . ls - the TaoLineSearch context

1018:   Output Parameter:
1019: . x - The initial point of the line search

1021:   Level: intermediate
1022: @*/
1023: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1024: {
1026:   if (x) *x = ls->start_x;
1027:   return 0;
1028: }

1030: /*@
1031:   TaoLineSearchGetStepDirection - Gets the step direction of the line
1032:   search.

1034:   Not Collective

1036:   Input Parameter:
1037: . ls - the TaoLineSearch context

1039:   Output Parameter:
1040: . s - the step direction of the line search

1042:   Level: advanced
1043: @*/
1044: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1045: {
1047:   if (s) *s = ls->stepdirection;
1048:   return 0;
1049: }

1051: /*@
1052:   TaoLineSearchGetFullStepObjective - Returns the objective function value at the full step.  Useful for some minimization algorithms.

1054:   Not Collective

1056:   Input Parameter:
1057: . ls - the TaoLineSearch context

1059:   Output Parameter:
1060: . f - the objective value at the full step length

1062:   Level: developer
1063: @*/

1065: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1066: {
1068:   *f_fullstep = ls->f_fullstep;
1069:   return 0;
1070: }

1072: /*@
1073:   TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.

1075:   Logically Collective

1077:   Input Parameters:
1078: + ls - the TaoLineSearch context
1079: . xl  - vector of lower bounds
1080: - xu  - vector of upper bounds

1082:   Note: If the variable bounds are not set with this routine, then
1083:   PETSC_NINFINITY and PETSC_INFINITY are assumed

1085:   Level: beginner

1087: .seealso: `TaoSetVariableBounds()`, `TaoLineSearchCreate()`
1088: @*/
1089: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls, Vec xl, Vec xu)
1090: {
1094:   PetscObjectReference((PetscObject)xl);
1095:   PetscObjectReference((PetscObject)xu);
1096:   VecDestroy(&ls->lower);
1097:   VecDestroy(&ls->upper);
1098:   ls->lower   = xl;
1099:   ls->upper   = xu;
1100:   ls->bounded = (PetscBool)(xl || xu);
1101:   return 0;
1102: }

1104: /*@
1105:   TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1106:   search.  If this value is not set then 1.0 is assumed.

1108:   Logically Collective

1110:   Input Parameters:
1111: + ls - the TaoLineSearch context
1112: - s - the initial step size

1114:   Level: intermediate

1116: .seealso: `TaoLineSearchGetStepLength()`, `TaoLineSearchApply()`
1117: @*/
1118: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls, PetscReal s)
1119: {
1122:   ls->initstep = s;
1123:   return 0;
1124: }

1126: /*@
1127:   TaoLineSearchGetStepLength - Get the current step length

1129:   Not Collective

1131:   Input Parameters:
1132: . ls - the TaoLineSearch context

1134:   Output Parameters:
1135: . s - the current step length

1137:   Level: beginner

1139: .seealso: `TaoLineSearchSetInitialStepLength()`, `TaoLineSearchApply()`
1140: @*/
1141: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls, PetscReal *s)
1142: {
1144:   *s = ls->step;
1145:   return 0;
1146: }

1148: /*@C
1149:    TaoLineSearchRegister - Adds a line-search algorithm to the registry

1151:    Not collective

1153:    Input Parameters:
1154: +  sname - name of a new user-defined solver
1155: -  func - routine to Create method context

1157:    Notes:
1158:    TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.

1160:    Sample usage:
1161: .vb
1162:    TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1163: .ve

1165:    Then, your solver can be chosen with the procedural interface via
1166: $     TaoLineSearchSetType(ls,"my_linesearch")
1167:    or at runtime via the option
1168: $     -tao_ls_type my_linesearch

1170:    Level: developer

1172: @*/
1173: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1174: {
1175:   TaoLineSearchInitializePackage();
1176:   PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1177:   return 0;
1178: }

1180: /*@C
1181:    TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1182:    for all TaoLineSearch options in the database.

1184:    Collective

1186:    Input Parameters:
1187: +  ls - the TaoLineSearch solver context
1188: -  prefix - the prefix string to prepend to all line search requests

1190:    Notes:
1191:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1192:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1194:    Level: advanced

1196: .seealso: `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
1197: @*/
1198: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1199: {
1200:   return PetscObjectAppendOptionsPrefix((PetscObject)ls, p);
1201: }

1203: /*@C
1204:   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1205:   TaoLineSearch options in the database

1207:   Not Collective

1209:   Input Parameters:
1210: . ls - the TaoLineSearch context

1212:   Output Parameters:
1213: . prefix - pointer to the prefix string used is returned

1215:   Notes:
1216:     On the fortran side, the user should pass in a string 'prefix' of
1217:   sufficient length to hold the prefix.

1219:   Level: advanced

1221: .seealso: `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchAppendOptionsPrefix()`
1222: @*/
1223: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1224: {
1225:   return PetscObjectGetOptionsPrefix((PetscObject)ls, p);
1226: }

1228: /*@C
1229:    TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1230:    TaoLineSearch options in the database.

1232:    Logically Collective

1234:    Input Parameters:
1235: +  ls - the TaoLineSearch context
1236: -  prefix - the prefix string to prepend to all TAO option requests

1238:    Notes:
1239:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1240:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1242:    For example, to distinguish between the runtime options for two
1243:    different line searches, one could call
1244: .vb
1245:       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1246:       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1247: .ve

1249:    This would enable use of different options for each system, such as
1250: .vb
1251:       -sys1_tao_ls_type mt
1252:       -sys2_tao_ls_type armijo
1253: .ve

1255:    Level: advanced

1257: .seealso: `TaoLineSearchAppendOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
1258: @*/

1260: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1261: {
1262:   return PetscObjectSetOptionsPrefix((PetscObject)ls, p);
1263: }