Actual source code: taolinesearch.c
petsc-3.13.1 2020-05-02
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 on TaoLineSearch
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: {
30: PetscObjectViewFromOptions((PetscObject)A,obj,name);
31: return(0);
32: }
34: /*@C
35: TaoLineSearchView - Prints information about the TaoLineSearch
37: Collective on TaoLineSearch
39: InputParameters:
40: + ls - the Tao context
41: - viewer - visualization context
43: Options Database Key:
44: . -tao_ls_view - Calls TaoLineSearchView() at the end of each line search
46: Notes:
47: The available visualization contexts include
48: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
49: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
50: output where only the first processor opens
51: the file. All other processors send their
52: data to the first processor to print.
54: Level: beginner
56: .seealso: PetscViewerASCIIOpen()
57: @*/
59: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
60: {
61: PetscErrorCode ierr;
62: PetscBool isascii, isstring;
63: TaoLineSearchType type;
67: if (!viewer) {
68: PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);
69: }
73: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
74: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
75: if (isascii) {
76: PetscObjectPrintClassNamePrefixType((PetscObject)ls, viewer);
77: if (ls->ops->view) {
78: PetscViewerASCIIPushTab(viewer);
79: (*ls->ops->view)(ls,viewer);
80: PetscViewerASCIIPopTab(viewer);
81: }
82: PetscViewerASCIIPushTab(viewer);
83: PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);
84: PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);
85: PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);
86: PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);
87: PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);
89: if (ls->bounded) {
90: PetscViewerASCIIPrintf(viewer,"using variable bounds\n");
91: }
92: PetscViewerASCIIPrintf(viewer,"Termination reason: %d\n",(int)ls->reason);
93: PetscViewerASCIIPopTab(viewer);
94: } else if (isstring) {
95: TaoLineSearchGetType(ls,&type);
96: PetscViewerStringSPrintf(viewer," %-3.3s",type);
97: }
98: return(0);
99: }
101: /*@C
102: TaoLineSearchCreate - Creates a TAO Line Search object. Algorithms in TAO that use
103: line-searches will automatically create one.
105: Collective
107: Input Parameter:
108: . comm - MPI communicator
110: Output Parameter:
111: . newls - the new TaoLineSearch context
113: Available methods include:
114: + more-thuente
115: . gpcg
116: - unit - Do not perform any line search
119: Options Database Keys:
120: . -tao_ls_type - select which method TAO should use
122: Level: beginner
124: .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
125: @*/
127: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
128: {
130: TaoLineSearch ls;
134: *newls = NULL;
136: TaoLineSearchInitializePackage();
138: PetscHeaderCreate(ls,TAOLINESEARCH_CLASSID,"TaoLineSearch","Linesearch","Tao",comm,TaoLineSearchDestroy,TaoLineSearchView);
139: ls->bounded = 0;
140: ls->max_funcs=30;
141: ls->ftol = 0.0001;
142: ls->gtol = 0.9;
143: #if defined(PETSC_USE_REAL_SINGLE)
144: ls->rtol = 1.0e-5;
145: #else
146: ls->rtol = 1.0e-10;
147: #endif
148: ls->stepmin=1.0e-20;
149: ls->stepmax=1.0e+20;
150: ls->step=1.0;
151: ls->nfeval=0;
152: ls->ngeval=0;
153: ls->nfgeval=0;
155: ls->ops->computeobjective=0;
156: ls->ops->computegradient=0;
157: ls->ops->computeobjectiveandgradient=0;
158: ls->ops->computeobjectiveandgts=0;
159: ls->ops->setup=0;
160: ls->ops->apply=0;
161: ls->ops->view=0;
162: ls->ops->setfromoptions=0;
163: ls->ops->reset=0;
164: ls->ops->destroy=0;
165: ls->ops->monitor=0;
166: ls->usemonitor=PETSC_FALSE;
167: ls->setupcalled=PETSC_FALSE;
168: ls->usetaoroutines=PETSC_FALSE;
169: *newls = ls;
170: return(0);
171: }
173: /*@
174: TaoLineSearchSetUp - Sets up the internal data structures for the later use
175: of a Tao solver
177: Collective on ls
179: Input Parameters:
180: . ls - the TaoLineSearch context
182: Notes:
183: The user will not need to explicitly call TaoLineSearchSetUp(), as it will
184: automatically be called in TaoLineSearchSolve(). However, if the user
185: desires to call it explicitly, it should come after TaoLineSearchCreate()
186: but before TaoLineSearchApply().
188: Level: developer
190: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
191: @*/
193: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
194: {
196: const char *default_type=TAOLINESEARCHMT;
197: PetscBool flg;
201: if (ls->setupcalled) return(0);
202: if (!((PetscObject)ls)->type_name) {
203: TaoLineSearchSetType(ls,default_type);
204: }
205: if (ls->ops->setup) {
206: (*ls->ops->setup)(ls);
207: }
208: if (ls->usetaoroutines) {
209: TaoIsObjectiveDefined(ls->tao,&flg);
210: ls->hasobjective = flg;
211: TaoIsGradientDefined(ls->tao,&flg);
212: ls->hasgradient = flg;
213: TaoIsObjectiveAndGradientDefined(ls->tao,&flg);
214: ls->hasobjectiveandgradient = flg;
215: } else {
216: if (ls->ops->computeobjective) {
217: ls->hasobjective = PETSC_TRUE;
218: } else {
219: ls->hasobjective = PETSC_FALSE;
220: }
221: if (ls->ops->computegradient) {
222: ls->hasgradient = PETSC_TRUE;
223: } else {
224: ls->hasgradient = PETSC_FALSE;
225: }
226: if (ls->ops->computeobjectiveandgradient) {
227: ls->hasobjectiveandgradient = PETSC_TRUE;
228: } else {
229: ls->hasobjectiveandgradient = PETSC_FALSE;
230: }
231: }
232: ls->setupcalled = PETSC_TRUE;
233: return(0);
234: }
236: /*@
237: TaoLineSearchReset - Some line searches may carry state information
238: from one TaoLineSearchApply() to the next. This function resets this
239: state information.
241: Collective on TaoLineSearch
243: Input Parameter:
244: . ls - the TaoLineSearch context
246: Level: developer
248: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
249: @*/
250: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
251: {
256: if (ls->ops->reset) {
257: (*ls->ops->reset)(ls);
258: }
259: return(0);
260: }
262: /*@
263: TaoLineSearchDestroy - Destroys the TAO context that was created with
264: TaoLineSearchCreate()
266: Collective on TaoLineSearch
268: Input Parameter:
269: . ls - the TaoLineSearch context
271: Level: beginner
273: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
274: @*/
275: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
276: {
280: if (!*ls) return(0);
282: if (--((PetscObject)*ls)->refct > 0) {*ls=0; return(0);}
283: VecDestroy(&(*ls)->stepdirection);
284: VecDestroy(&(*ls)->start_x);
285: if ((*ls)->ops->destroy) {
286: (*(*ls)->ops->destroy)(*ls);
287: }
288: if ((*ls)->usemonitor) {
289: PetscViewerDestroy(&(*ls)->viewer);
290: }
291: PetscHeaderDestroy(ls);
292: return(0);
293: }
295: /*@
296: TaoLineSearchApply - Performs a line-search in a given step direction. Criteria for acceptable step length depends on the line-search algorithm chosen
298: Collective on TaoLineSearch
300: Input Parameters:
301: + ls - the Tao context
302: . x - The current solution (on output x contains the new solution determined by the line search)
303: . f - objective function value at current solution (on output contains the objective function value at new solution)
304: . g - gradient evaluated at x (on output contains the gradient at new solution)
305: - s - search direction
307: Output Parameters:
308: + x - new solution
309: . f - objective function value at x
310: . g - gradient vector at x
311: . steplength - scalar multiplier of s used ( x = x0 + steplength * x )
312: - reason - reason why the line-search stopped
314: reason will be set to one of:
316: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
317: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
318: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
319: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
320: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
321: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
322: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
323: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
324: . TAOLINESEARCH_HALTED_OTHER - any other reason
325: - TAOLINESEARCH_SUCCESS - successful line search
327: Note:
328: The algorithm developer must set up the TaoLineSearch with calls to
329: TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()
331: Note:
332: You may or may not need to follow this with a call to
333: TaoAddLineSearchCounts(), depending on whether you want these
334: evaluations to count toward the total function/gradient evaluations.
336: Level: beginner
338: .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
339: @*/
341: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
342: {
344: PetscInt low1,low2,low3,high1,high2,high3;
347: *reason = TAOLINESEARCH_CONTINUE_ITERATING;
357: VecGetOwnershipRange(x, &low1, &high1);
358: VecGetOwnershipRange(g, &low2, &high2);
359: VecGetOwnershipRange(s, &low3, &high3);
360: if (low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible vector local lengths");
362: PetscObjectReference((PetscObject)s);
363: VecDestroy(&ls->stepdirection);
364: ls->stepdirection = s;
366: TaoLineSearchSetUp(ls);
367: if (!ls->ops->apply) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
368: ls->nfeval=0;
369: ls->ngeval=0;
370: ls->nfgeval=0;
371: /* Check parameter values */
372: if (ls->ftol < 0.0) {
373: PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);
374: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
375: }
376: if (ls->rtol < 0.0) {
377: PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);
378: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
379: }
380: if (ls->gtol < 0.0) {
381: PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);
382: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
383: }
384: if (ls->stepmin < 0.0) {
385: PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);
386: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
387: }
388: if (ls->stepmax < ls->stepmin) {
389: PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);
390: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
391: }
392: if (ls->max_funcs < 0) {
393: PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);
394: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
395: }
396: if (PetscIsInfOrNanReal(*f)) {
397: PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);
398: *reason=TAOLINESEARCH_FAILED_INFORNAN;
399: }
401: PetscObjectReference((PetscObject)x);
402: VecDestroy(&ls->start_x);
403: ls->start_x = x;
405: PetscLogEventBegin(TAOLINESEARCH_Apply,ls,0,0,0);
406: (*ls->ops->apply)(ls,x,f,g,s);
407: PetscLogEventEnd(TAOLINESEARCH_Apply, ls, 0,0,0);
408: *reason=ls->reason;
409: ls->new_f = *f;
411: if (steplength) {
412: *steplength=ls->step;
413: }
415: TaoLineSearchViewFromOptions(ls,NULL,"-tao_ls_view");
416: return(0);
417: }
419: /*@C
420: TaoLineSearchSetType - Sets the algorithm used in a line search
422: Collective on TaoLineSearch
424: Input Parameters:
425: + ls - the TaoLineSearch context
426: - type - a known method
428: Available methods include:
429: + more-thuente
430: . gpcg
431: - unit - Do not perform any line search
434: Options Database Keys:
435: . -tao_ls_type - select which method TAO should use
437: Level: beginner
440: .seealso: TaoLineSearchCreate(), TaoLineSearchGetType(), TaoLineSearchApply()
442: @*/
444: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, TaoLineSearchType type)
445: {
447: PetscErrorCode (*r)(TaoLineSearch);
448: PetscBool flg;
453: PetscObjectTypeCompare((PetscObject)ls, type, &flg);
454: if (flg) return(0);
456: PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);
457: if (!r) SETERRQ1(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
458: if (ls->ops->destroy) {
459: (*(ls)->ops->destroy)(ls);
460: }
461: ls->max_funcs=30;
462: ls->ftol = 0.0001;
463: ls->gtol = 0.9;
464: #if defined(PETSC_USE_REAL_SINGLE)
465: ls->rtol = 1.0e-5;
466: #else
467: ls->rtol = 1.0e-10;
468: #endif
469: ls->stepmin=1.0e-20;
470: ls->stepmax=1.0e+20;
472: ls->nfeval=0;
473: ls->ngeval=0;
474: ls->nfgeval=0;
475: ls->ops->setup=0;
476: ls->ops->apply=0;
477: ls->ops->view=0;
478: ls->ops->setfromoptions=0;
479: ls->ops->destroy=0;
480: ls->setupcalled = PETSC_FALSE;
481: (*r)(ls);
482: PetscObjectChangeTypeName((PetscObject)ls, type);
483: return(0);
484: }
486: /*@C
487: TaoLineSearchMonitor - Monitor the line search steps. This routine will otuput the
488: iteration number, step length, and function value before calling the implementation
489: specific monitor.
491: Input Parameters:
492: + ls - the TaoLineSearch context
493: . its - the current iterate number (>=0)
494: . f - the current objective function value
495: - step - the step length
497: Options Database Key:
498: . -tao_ls_monitor - Use the default monitor, which prints statistics to standard output
500: Level: developer
502: @*/
503: PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
504: {
506: PetscInt tabs;
510: if (ls->usemonitor) {
511: PetscViewerASCIIGetTab(ls->viewer, &tabs);
512: PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel);
513: PetscViewerASCIIPrintf(ls->viewer, "%3D LS", its);
514: PetscViewerASCIIPrintf(ls->viewer, " Function value: %g,", (double)f);
515: PetscViewerASCIIPrintf(ls->viewer, " Step length: %g\n", (double)step);
516: if (ls->ops->monitor && its > 0) {
517: PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel + 3);
518: (*ls->ops->monitor)(ls);
519: }
520: PetscViewerASCIISetTab(ls->viewer, tabs);
521: }
522: return(0);
523: }
525: /*@
526: TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
527: options.
529: Collective on TaoLineSearch
531: Input Paremeter:
532: . ls - the TaoLineSearch context
534: Options Database Keys:
535: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
536: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
537: . -tao_ls_gtol <tol> - tolerance for curvature condition
538: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
539: . -tao_ls_stepmin <step> - minimum steplength allowed
540: . -tao_ls_stepmax <step> - maximum steplength allowed
541: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
542: - -tao_ls_view - display line-search results to standard output
544: Level: beginner
545: @*/
546: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
547: {
549: const char *default_type=TAOLINESEARCHMT;
550: char type[256],monfilename[PETSC_MAX_PATH_LEN];
551: PetscViewer monviewer;
552: PetscBool flg;
556: PetscObjectOptionsBegin((PetscObject)ls);
557: if (((PetscObject)ls)->type_name) {
558: default_type = ((PetscObject)ls)->type_name;
559: }
560: /* Check for type from options */
561: PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);
562: if (flg) {
563: TaoLineSearchSetType(ls,type);
564: } else if (!((PetscObject)ls)->type_name) {
565: TaoLineSearchSetType(ls,default_type);
566: }
568: PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,NULL);
569: PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,NULL);
570: PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,NULL);
571: PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,NULL);
572: PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,NULL);
573: PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,NULL);
574: PetscOptionsString("-tao_ls_monitor","enable the basic monitor","TaoLineSearchSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
575: if (flg) {
576: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ls),monfilename,&monviewer);
577: ls->viewer = monviewer;
578: ls->usemonitor = PETSC_TRUE;
579: }
580: if (ls->ops->setfromoptions) {
581: (*ls->ops->setfromoptions)(PetscOptionsObject,ls);
582: }
583: PetscOptionsEnd();
584: return(0);
585: }
587: /*@C
588: TaoLineSearchGetType - Gets the current line search algorithm
590: Not Collective
592: Input Parameter:
593: . ls - the TaoLineSearch context
595: Output Parameter:
596: . type - the line search algorithm in effect
598: Level: developer
600: @*/
601: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
602: {
606: *type = ((PetscObject)ls)->type_name;
607: return(0);
608: }
610: /*@
611: TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
612: routines used by the line search in last application (not cumulative).
614: Not Collective
616: Input Parameter:
617: . ls - the TaoLineSearch context
619: Output Parameters:
620: + nfeval - number of function evaluations
621: . ngeval - number of gradient evaluations
622: - nfgeval - number of function/gradient evaluations
624: Level: intermediate
626: Note:
627: If the line search is using the Tao objective and gradient
628: routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
629: is already counting the number of evaluations.
631: @*/
632: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
633: {
636: *nfeval = ls->nfeval;
637: *ngeval = ls->ngeval;
638: *nfgeval = ls->nfgeval;
639: return(0);
640: }
642: /*@
643: TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
644: Tao evaluation routines.
646: Not Collective
648: Input Parameter:
649: . ls - the TaoLineSearch context
651: Output Parameter:
652: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
653: otherwise PETSC_FALSE
655: Level: developer
656: @*/
657: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
658: {
661: *flg = ls->usetaoroutines;
662: return(0);
663: }
665: /*@C
666: TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search
668: Logically Collective on TaoLineSearch
670: Input Parameter:
671: + ls - the TaoLineSearch context
672: . func - the objective function evaluation routine
673: - ctx - the (optional) user-defined context for private data
675: Calling sequence of func:
676: $ func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);
678: + x - input vector
679: . f - function value
680: - ctx (optional) user-defined context
682: Level: beginner
684: Note:
685: Use this routine only if you want the line search objective
686: evaluation routine to be different from the Tao's objective
687: evaluation routine. If you use this routine you must also set
688: the line search gradient and/or function/gradient routine.
690: Note:
691: Some algorithms (lcl, gpcg) set their own objective routine for the
692: line search, application programmers should be wary of overriding the
693: default objective routine.
695: .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
696: @*/
697: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
698: {
702: ls->ops->computeobjective=func;
703: if (ctx) ls->userctx_func=ctx;
704: ls->usetaoroutines=PETSC_FALSE;
705: return(0);
706: }
708: /*@C
709: TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search
711: Logically Collective on TaoLineSearch
713: Input Parameter:
714: + ls - the TaoLineSearch context
715: . func - the gradient evaluation routine
716: - ctx - the (optional) user-defined context for private data
718: Calling sequence of func:
719: $ func (TaoLinesearch ls, Vec x, Vec g, void *ctx);
721: + x - input vector
722: . g - gradient vector
723: - ctx (optional) user-defined context
725: Level: beginner
727: Note:
728: Use this routine only if you want the line search gradient
729: evaluation routine to be different from the Tao's gradient
730: evaluation routine. If you use this routine you must also set
731: the line search function and/or function/gradient routine.
733: Note:
734: Some algorithms (lcl, gpcg) set their own gradient routine for the
735: line search, application programmers should be wary of overriding the
736: default gradient routine.
738: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
739: @*/
740: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
741: {
744: ls->ops->computegradient=func;
745: if (ctx) ls->userctx_grad=ctx;
746: ls->usetaoroutines=PETSC_FALSE;
747: return(0);
748: }
750: /*@C
751: TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search
753: Logically Collective on TaoLineSearch
755: Input Parameter:
756: + ls - the TaoLineSearch context
757: . func - the objective and gradient evaluation routine
758: - ctx - the (optional) user-defined context for private data
760: Calling sequence of func:
761: $ func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);
763: + x - input vector
764: . f - function value
765: . g - gradient vector
766: - ctx (optional) user-defined context
768: Level: beginner
770: Note:
771: Use this routine only if you want the line search objective and gradient
772: evaluation routines to be different from the Tao's objective
773: and gradient evaluation routines.
775: Note:
776: Some algorithms (lcl, gpcg) set their own objective routine for the
777: line search, application programmers should be wary of overriding the
778: default objective routine.
780: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetGradientRoutine(), TaoLineSearchUseTaoRoutines()
781: @*/
782: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void*), void *ctx)
783: {
786: ls->ops->computeobjectiveandgradient=func;
787: if (ctx) ls->userctx_funcgrad=ctx;
788: ls->usetaoroutines = PETSC_FALSE;
789: return(0);
790: }
792: /*@C
793: TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
794: (gradient'*stepdirection) evaluation routine for the line search.
795: Sometimes it is more efficient to compute the inner product of the gradient
796: and the step direction than it is to compute the gradient, and this is all
797: the line search typically needs of the gradient.
799: Logically Collective on TaoLineSearch
801: Input Parameter:
802: + ls - the TaoLineSearch context
803: . func - the objective and gradient evaluation routine
804: - ctx - the (optional) user-defined context for private data
806: Calling sequence of func:
807: $ func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);
809: + x - input vector
810: . s - step direction
811: . f - function value
812: . gts - inner product of gradient and step direction vectors
813: - ctx (optional) user-defined context
815: Note: The gradient will still need to be computed at the end of the line
816: search, so you will still need to set a line search gradient evaluation
817: routine
819: Note: Bounded line searches (those used in bounded optimization algorithms)
820: don't use g's directly, but rather (g'x - g'x0)/steplength. You can get the
821: x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()
823: Level: advanced
825: Note:
826: Some algorithms (lcl, gpcg) set their own objective routine for the
827: line search, application programmers should be wary of overriding the
828: default objective routine.
830: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjective(), TaoLineSearchSetGradient(), TaoLineSearchUseTaoRoutines()
831: @*/
832: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void*), void *ctx)
833: {
836: ls->ops->computeobjectiveandgts=func;
837: if (ctx) ls->userctx_funcgts=ctx;
838: ls->usegts = PETSC_TRUE;
839: ls->usetaoroutines=PETSC_FALSE;
840: return(0);
841: }
843: /*@C
844: TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
845: objective and gradient evaluation routines from the given Tao object.
847: Logically Collective on TaoLineSearch
849: Input Parameter:
850: + ls - the TaoLineSearch context
851: - ts - the Tao context with defined objective/gradient evaluation routines
853: Level: developer
855: .seealso: TaoLineSearchCreate()
856: @*/
857: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
858: {
862: ls->tao = ts;
863: ls->usetaoroutines=PETSC_TRUE;
864: return(0);
865: }
867: /*@
868: TaoLineSearchComputeObjective - Computes the objective function value at a given point
870: Collective on TaoLineSearch
872: Input Parameters:
873: + ls - the TaoLineSearch context
874: - x - input vector
876: Output Parameter:
877: . f - Objective value at X
879: Notes:
880: TaoLineSearchComputeObjective() is typically used within line searches
881: so most users would not generally call this routine themselves.
883: Level: developer
885: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
886: @*/
887: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
888: {
890: Vec gdummy;
891: PetscReal gts;
898: if (ls->usetaoroutines) {
899: TaoComputeObjective(ls->tao,x,f);
900: } else {
901: if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient && !ls->ops->computeobjectiveandgts) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
902: PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
903: PetscStackPush("TaoLineSearch user objective routine");
904: if (ls->ops->computeobjective) {
905: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
906: } else if (ls->ops->computeobjectiveandgradient) {
907: VecDuplicate(x,&gdummy);
908: (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);
909: VecDestroy(&gdummy);
910: } else {
911: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,>s,ls->userctx_funcgts);
912: }
913: PetscStackPop;
914: PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
915: }
916: ls->nfeval++;
917: return(0);
918: }
920: /*@
921: TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point
923: Collective on Tao
925: Input Parameters:
926: + ls - the TaoLineSearch context
927: - x - input vector
929: Output Parameter:
930: + f - Objective value at X
931: - g - Gradient vector at X
933: Notes:
934: TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
935: so most users would not generally call this routine themselves.
937: Level: developer
939: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
940: @*/
941: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
942: {
952: if (ls->usetaoroutines) {
953: TaoComputeObjectiveAndGradient(ls->tao,x,f,g);
954: } else {
955: if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
956: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");
957: PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
958: PetscStackPush("TaoLineSearch user objective/gradient routine");
959: if (ls->ops->computeobjectiveandgradient) {
960: (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);
961: } else {
962: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
963: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
964: }
965: PetscStackPop;
966: PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
967: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
968: }
969: ls->nfgeval++;
970: return(0);
971: }
973: /*@
974: TaoLineSearchComputeGradient - Computes the gradient of the objective function
976: Collective on TaoLineSearch
978: Input Parameters:
979: + ls - the TaoLineSearch context
980: - x - input vector
982: Output Parameter:
983: . g - gradient vector
985: Notes:
986: TaoComputeGradient() is typically used within line searches
987: so most users would not generally call this routine themselves.
989: Level: developer
991: .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
992: @*/
993: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
994: {
996: PetscReal fdummy;
1004: if (ls->usetaoroutines) {
1005: TaoComputeGradient(ls->tao,x,g);
1006: } else {
1007: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient functions set");
1008: PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
1009: PetscStackPush("TaoLineSearch user gradient routine");
1010: if (ls->ops->computegradient) {
1011: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
1012: } else {
1013: (*ls->ops->computeobjectiveandgradient)(ls,x,&fdummy,g,ls->userctx_funcgrad);
1014: }
1015: PetscStackPop;
1016: PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
1017: }
1018: ls->ngeval++;
1019: return(0);
1020: }
1022: /*@
1023: TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point
1025: Collective on Tao
1027: Input Parameters:
1028: + ls - the TaoLineSearch context
1029: - x - input vector
1031: Output Parameter:
1032: + f - Objective value at X
1033: - gts - inner product of gradient and step direction at X
1035: Notes:
1036: TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
1037: so most users would not generally call this routine themselves.
1039: Level: developer
1041: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1042: @*/
1043: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1044: {
1052: if (!ls->ops->computeobjectiveandgts) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1053: PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
1054: PetscStackPush("TaoLineSearch user objective/gts routine");
1055: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);
1056: PetscStackPop;
1057: PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
1058: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
1059: ls->nfeval++;
1060: return(0);
1061: }
1063: /*@
1064: TaoLineSearchGetSolution - Returns the solution to the line search
1066: Collective on TaoLineSearch
1068: Input Parameter:
1069: . ls - the TaoLineSearch context
1071: Output Parameter:
1072: + x - the new solution
1073: . f - the objective function value at x
1074: . g - the gradient at x
1075: . steplength - the multiple of the step direction taken by the line search
1076: - reason - the reason why the line search terminated
1078: reason will be set to one of:
1080: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1081: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1082: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1083: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1084: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1085: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1086: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
1088: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
1089: . TAOLINESEARCH_HALTED_OTHER - any other reason
1091: - TAOLINESEARCH_SUCCESS - successful line search
1093: Level: developer
1095: @*/
1096: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
1097: {
1106: if (ls->new_x) {
1107: VecCopy(ls->new_x,x);
1108: }
1109: *f = ls->new_f;
1110: if (ls->new_g) {
1111: VecCopy(ls->new_g,g);
1112: }
1113: if (steplength) {
1114: *steplength=ls->step;
1115: }
1116: *reason = ls->reason;
1117: return(0);
1118: }
1120: /*@
1121: TaoLineSearchGetStartingVector - Gets a the initial point of the line
1122: search.
1124: Not Collective
1126: Input Parameter:
1127: . ls - the TaoLineSearch context
1129: Output Parameter:
1130: . x - The initial point of the line search
1132: Level: intermediate
1133: @*/
1134: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1135: {
1138: if (x) {
1139: *x = ls->start_x;
1140: }
1141: return(0);
1142: }
1144: /*@
1145: TaoLineSearchGetStepDirection - Gets the step direction of the line
1146: search.
1148: Not Collective
1150: Input Parameter:
1151: . ls - the TaoLineSearch context
1153: Output Parameter:
1154: . s - the step direction of the line search
1156: Level: advanced
1157: @*/
1158: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1159: {
1162: if (s) {
1163: *s = ls->stepdirection;
1164: }
1165: return(0);
1167: }
1169: /*@
1170: TaoLineSearchGetFullStepObjective - Returns the objective function value at the full step. Useful for some minimization algorithms.
1172: Not Collective
1174: Input Parameter:
1175: . ls - the TaoLineSearch context
1177: Output Parameter:
1178: . f - the objective value at the full step length
1180: Level: developer
1181: @*/
1183: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1184: {
1187: *f_fullstep = ls->f_fullstep;
1188: return(0);
1189: }
1191: /*@
1192: TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.
1194: Logically Collective on Tao
1196: Input Parameters:
1197: + ls - the TaoLineSearch context
1198: . xl - vector of lower bounds
1199: - xu - vector of upper bounds
1201: Note: If the variable bounds are not set with this routine, then
1202: PETSC_NINFINITY and PETSC_INFINITY are assumed
1204: Level: beginner
1206: .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1207: @*/
1208: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1209: {
1214: ls->lower = xl;
1215: ls->upper = xu;
1216: ls->bounded = 1;
1217: return(0);
1218: }
1220: /*@
1221: TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1222: search. If this value is not set then 1.0 is assumed.
1224: Logically Collective on TaoLineSearch
1226: Input Parameters:
1227: + ls - the TaoLineSearch context
1228: - s - the initial step size
1230: Level: intermediate
1232: .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1233: @*/
1234: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1235: {
1238: ls->initstep = s;
1239: return(0);
1240: }
1242: /*@
1243: TaoLineSearchGetStepLength - Get the current step length
1245: Not Collective
1247: Input Parameters:
1248: . ls - the TaoLineSearch context
1250: Output Parameters:
1251: . s - the current step length
1253: Level: beginner
1255: .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1256: @*/
1257: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1258: {
1261: *s = ls->step;
1262: return(0);
1263: }
1265: /*@C
1266: TaoLineSearchRegister - Adds a line-search algorithm to the registry
1268: Not collective
1270: Input Parameters:
1271: + sname - name of a new user-defined solver
1272: - func - routine to Create method context
1274: Notes:
1275: TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.
1277: Sample usage:
1278: .vb
1279: TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1280: .ve
1282: Then, your solver can be chosen with the procedural interface via
1283: $ TaoLineSearchSetType(ls,"my_linesearch")
1284: or at runtime via the option
1285: $ -tao_ls_type my_linesearch
1287: Level: developer
1289: @*/
1290: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1291: {
1294: TaoLineSearchInitializePackage();
1295: PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1296: return(0);
1297: }
1299: /*@C
1300: TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1301: for all TaoLineSearch options in the database.
1304: Collective on TaoLineSearch
1306: Input Parameters:
1307: + ls - the TaoLineSearch solver context
1308: - prefix - the prefix string to prepend to all line search requests
1310: Notes:
1311: A hyphen (-) must NOT be given at the beginning of the prefix name.
1312: The first character of all runtime options is AUTOMATICALLY the hyphen.
1315: Level: advanced
1317: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1318: @*/
1319: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1320: {
1321: return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1322: }
1324: /*@C
1325: TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1326: TaoLineSearch options in the database
1328: Not Collective
1330: Input Parameters:
1331: . ls - the TaoLineSearch context
1333: Output Parameters:
1334: . prefix - pointer to the prefix string used is returned
1336: Notes:
1337: On the fortran side, the user should pass in a string 'prefix' of
1338: sufficient length to hold the prefix.
1340: Level: advanced
1342: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1343: @*/
1344: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1345: {
1346: return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1347: }
1349: /*@C
1350: TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1351: TaoLineSearch options in the database.
1354: Logically Collective on TaoLineSearch
1356: Input Parameters:
1357: + ls - the TaoLineSearch context
1358: - prefix - the prefix string to prepend to all TAO option requests
1360: Notes:
1361: A hyphen (-) must NOT be given at the beginning of the prefix name.
1362: The first character of all runtime options is AUTOMATICALLY the hyphen.
1364: For example, to distinguish between the runtime options for two
1365: different line searches, one could call
1366: .vb
1367: TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1368: TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1369: .ve
1371: This would enable use of different options for each system, such as
1372: .vb
1373: -sys1_tao_ls_type mt
1374: -sys2_tao_ls_type armijo
1375: .ve
1377: Level: advanced
1379: .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1380: @*/
1382: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1383: {
1384: return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1385: }