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, >s, 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: }