Actual source code: taolinesearch.c
petsc-3.7.7 2017-09-25
1: #include <petsctaolinesearch.h> /*I "petsctaolinesearch.h" I*/
2: #include <petsc/private/taolinesearchimpl.h>
4: PetscBool TaoLineSearchInitialized = PETSC_FALSE;
5: PetscFunctionList TaoLineSearchList = NULL;
7: PetscClassId TAOLINESEARCH_CLASSID=0;
8: PetscLogEvent TaoLineSearch_ApplyEvent = 0, TaoLineSearch_EvalEvent=0;
12: /*@C
13: TaoLineSearchView - Prints information about the TaoLineSearch
15: Collective on TaoLineSearch
17: InputParameters:
18: + ls - the Tao context
19: - viewer - visualization context
21: Options Database Key:
22: . -tao_ls_view - Calls TaoLineSearchView() at the end of each line search
24: Notes:
25: The available visualization contexts include
26: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
27: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
28: output where only the first processor opens
29: the file. All other processors send their
30: data to the first processor to print.
32: Level: beginner
34: .seealso: PetscViewerASCIIOpen()
35: @*/
37: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
38: {
39: PetscErrorCode ierr;
40: PetscBool isascii, isstring;
41: const TaoLineSearchType type;
45: if (!viewer) {
46: PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);
47: }
51: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
52: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
53: if (isascii) {
54: if (((PetscObject)ls)->prefix) {
55: PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:(%s)\n",((PetscObject)ls)->prefix);
56: } else {
57: PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:\n");
58: }
59: PetscViewerASCIIPushTab(viewer);
60: TaoLineSearchGetType(ls,&type);
61: if (type) {
62: PetscViewerASCIIPrintf(viewer,"type: %s\n",type);
63: } else {
64: PetscViewerASCIIPrintf(viewer,"type: not set yet\n");
65: }
66: if (ls->ops->view) {
67: PetscViewerASCIIPushTab(viewer);
68: (*ls->ops->view)(ls,viewer);
69: PetscViewerASCIIPopTab(viewer);
70: }
71: PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);
72: PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);
73: PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);
74: PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);
75: PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);
77: if (ls->bounded) {
78: PetscViewerASCIIPrintf(viewer,"using variable bounds\n");
79: }
80: PetscViewerASCIIPrintf(viewer,"Termination reason: %d\n",(int)ls->reason);
81: PetscViewerASCIIPopTab(viewer);
83: } else if (isstring) {
84: TaoLineSearchGetType(ls,&type);
85: PetscViewerStringSPrintf(viewer," %-3.3s",type);
86: }
87: return(0);
88: }
92: /*@C
93: TaoLineSearchCreate - Creates a TAO Line Search object. Algorithms in TAO that use
94: line-searches will automatically create one.
96: Collective on MPI_Comm
98: Input Parameter:
99: . comm - MPI communicator
101: Output Parameter:
102: . newls - the new TaoLineSearch context
104: Available methods include:
105: + more-thuente
106: . gpcg
107: - unit - Do not perform any line search
110: Options Database Keys:
111: . -tao_ls_type - select which method TAO should use
113: Level: beginner
115: .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
116: @*/
118: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
119: {
121: TaoLineSearch ls;
125: *newls = NULL;
127: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
128: TaoLineSearchInitializePackage();
129: #endif
131: PetscHeaderCreate(ls,TAOLINESEARCH_CLASSID,"TaoLineSearch","Linesearch","Tao",comm,TaoLineSearchDestroy,TaoLineSearchView);
132: ls->bounded = 0;
133: ls->max_funcs=30;
134: ls->ftol = 0.0001;
135: ls->gtol = 0.9;
136: #if defined(PETSC_USE_REAL_SINGLE)
137: ls->rtol = 1.0e-5;
138: #else
139: ls->rtol = 1.0e-10;
140: #endif
141: ls->stepmin=1.0e-20;
142: ls->stepmax=1.0e+20;
143: ls->step=1.0;
144: ls->nfeval=0;
145: ls->ngeval=0;
146: ls->nfgeval=0;
148: ls->ops->computeobjective=0;
149: ls->ops->computegradient=0;
150: ls->ops->computeobjectiveandgradient=0;
151: ls->ops->computeobjectiveandgts=0;
152: ls->ops->setup=0;
153: ls->ops->apply=0;
154: ls->ops->view=0;
155: ls->ops->setfromoptions=0;
156: ls->ops->reset=0;
157: ls->ops->destroy=0;
158: ls->setupcalled=PETSC_FALSE;
159: ls->usetaoroutines=PETSC_FALSE;
160: *newls = ls;
161: return(0);
162: }
166: /*@
167: TaoLineSearchSetUp - Sets up the internal data structures for the later use
168: of a Tao solver
170: Collective on ls
172: Input Parameters:
173: . ls - the TaoLineSearch context
175: Notes:
176: The user will not need to explicitly call TaoLineSearchSetUp(), as it will
177: automatically be called in TaoLineSearchSolve(). However, if the user
178: desires to call it explicitly, it should come after TaoLineSearchCreate()
179: but before TaoLineSearchApply().
181: Level: developer
183: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
184: @*/
186: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
187: {
189: const char *default_type=TAOLINESEARCHMT;
190: PetscBool flg;
194: if (ls->setupcalled) return(0);
195: if (!((PetscObject)ls)->type_name) {
196: TaoLineSearchSetType(ls,default_type);
197: }
198: if (ls->ops->setup) {
199: (*ls->ops->setup)(ls);
200: }
201: if (ls->usetaoroutines) {
202: TaoIsObjectiveDefined(ls->tao,&flg);
203: ls->hasobjective = flg;
204: TaoIsGradientDefined(ls->tao,&flg);
205: ls->hasgradient = flg;
206: TaoIsObjectiveAndGradientDefined(ls->tao,&flg);
207: ls->hasobjectiveandgradient = flg;
208: } else {
209: if (ls->ops->computeobjective) {
210: ls->hasobjective = PETSC_TRUE;
211: } else {
212: ls->hasobjective = PETSC_FALSE;
213: }
214: if (ls->ops->computegradient) {
215: ls->hasgradient = PETSC_TRUE;
216: } else {
217: ls->hasgradient = PETSC_FALSE;
218: }
219: if (ls->ops->computeobjectiveandgradient) {
220: ls->hasobjectiveandgradient = PETSC_TRUE;
221: } else {
222: ls->hasobjectiveandgradient = PETSC_FALSE;
223: }
224: }
225: ls->setupcalled = PETSC_TRUE;
226: return(0);
227: }
231: /*@
232: TaoLineSearchReset - Some line searches may carry state information
233: from one TaoLineSearchApply() to the next. This function resets this
234: state information.
236: Collective on TaoLineSearch
238: Input Parameter:
239: . ls - the TaoLineSearch context
241: Level: developer
243: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
244: @*/
245: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
246: {
251: if (ls->ops->reset) {
252: (*ls->ops->reset)(ls);
253: }
254: return(0);
255: }
259: /*@
260: TaoLineSearchDestroy - Destroys the TAO context that was created with
261: TaoLineSearchCreate()
263: Collective on TaoLineSearch
265: Input Parameter
266: . ls - the TaoLineSearch context
268: Level: beginner
270: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
271: @*/
272: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
273: {
277: if (!*ls) return(0);
279: if (--((PetscObject)*ls)->refct > 0) {*ls=0; return(0);}
280: VecDestroy(&(*ls)->stepdirection);
281: VecDestroy(&(*ls)->start_x);
282: if ((*ls)->ops->destroy) {
283: (*(*ls)->ops->destroy)(*ls);
284: }
285: PetscHeaderDestroy(ls);
286: return(0);
287: }
291: /*@
292: TaoLineSearchApply - Performs a line-search in a given step direction. Criteria for acceptable step length depends on the line-search algorithm chosen
294: Collective on TaoLineSearch
296: Input Parameters:
297: + ls - the Tao context
298: . x - The current solution (on output x contains the new solution determined by the line search)
299: . f - objective function value at current solution (on output contains the objective function value at new solution)
300: . g - gradient evaluated at x (on output contains the gradient at new solution)
301: - s - search direction
303: Output Parameters:
304: + x - new solution
305: . f - objective function value at x
306: . g - gradient vector at x
307: . steplength - scalar multiplier of s used ( x = x0 + steplength * x )
308: - reason - reason why the line-search stopped
310: reason will be set to one of:
312: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
313: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
314: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
315: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
316: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
317: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
318: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
319: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
320: . TAOLINESEARCH_HALTED_OTHER - any other reason
321: - TAOLINESEARCH_SUCCESS - successful line search
323: Note:
324: The algorithm developer must set up the TaoLineSearch with calls to
325: TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()
327: Note:
328: You may or may not need to follow this with a call to
329: TaoAddLineSearchCounts(), depending on whether you want these
330: evaluations to count toward the total function/gradient evaluations.
332: Level: beginner
334: .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
335: @*/
337: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
338: {
340: PetscInt low1,low2,low3,high1,high2,high3;
343: *reason = TAOLINESEARCH_CONTINUE_ITERATING;
353: VecGetOwnershipRange(x, &low1, &high1);
354: VecGetOwnershipRange(g, &low2, &high2);
355: VecGetOwnershipRange(s, &low3, &high3);
356: if ( low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,1,"InCompatible vector local lengths");
358: PetscObjectReference((PetscObject)s);
359: VecDestroy(&ls->stepdirection);
360: ls->stepdirection = s;
362: TaoLineSearchSetUp(ls);
363: if (!ls->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
364: ls->nfeval=0;
365: ls->ngeval=0;
366: ls->nfgeval=0;
367: /* Check parameter values */
368: if (ls->ftol < 0.0) {
369: PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);
370: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
371: }
372: if (ls->rtol < 0.0) {
373: PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);
374: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
375: }
376: if (ls->gtol < 0.0) {
377: PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);
378: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
379: }
380: if (ls->stepmin < 0.0) {
381: PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);
382: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
383: }
384: if (ls->stepmax < ls->stepmin) {
385: PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);
386: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
387: }
388: if (ls->max_funcs < 0) {
389: PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);
390: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
391: }
392: if (PetscIsInfOrNanReal(*f)) {
393: PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);
394: *reason=TAOLINESEARCH_FAILED_INFORNAN;
395: }
397: PetscObjectReference((PetscObject)x);
398: VecDestroy(&ls->start_x);
399: ls->start_x = x;
401: PetscLogEventBegin(TaoLineSearch_ApplyEvent,ls,0,0,0);
402: (*ls->ops->apply)(ls,x,f,g,s);
403: PetscLogEventEnd(TaoLineSearch_ApplyEvent, ls, 0,0,0);
404: *reason=ls->reason;
405: ls->new_f = *f;
407: if (steplength) {
408: *steplength=ls->step;
409: }
411: TaoLineSearchViewFromOptions(ls,NULL,"-tao_ls_view");
412: return(0);
413: }
417: /*@C
418: TaoLineSearchSetType - Sets the algorithm used in a line search
420: Collective on TaoLineSearch
422: Input Parameters:
423: + ls - the TaoLineSearch context
424: - type - a known method
426: Available methods include:
427: + more-thuente
428: . gpcg
429: - unit - Do not perform any line search
432: Options Database Keys:
433: . -tao_ls_type - select which method TAO should use
435: Level: beginner
438: .seealso: TaoLineSearchCreate(), TaoLineSearchGetType(), TaoLineSearchApply()
440: @*/
442: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, const TaoLineSearchType type)
443: {
445: PetscErrorCode (*r)(TaoLineSearch);
446: PetscBool flg;
451: PetscObjectTypeCompare((PetscObject)ls, type, &flg);
452: if (flg) return(0);
454: PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);
455: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
456: if (ls->ops->destroy) {
457: (*(ls)->ops->destroy)(ls);
458: }
459: ls->max_funcs=30;
460: ls->ftol = 0.0001;
461: ls->gtol = 0.9;
462: #if defined(PETSC_USE_REAL_SINGLE)
463: ls->rtol = 1.0e-5;
464: #else
465: ls->rtol = 1.0e-10;
466: #endif
467: ls->stepmin=1.0e-20;
468: ls->stepmax=1.0e+20;
470: ls->nfeval=0;
471: ls->ngeval=0;
472: ls->nfgeval=0;
473: ls->ops->setup=0;
474: ls->ops->apply=0;
475: ls->ops->view=0;
476: ls->ops->setfromoptions=0;
477: ls->ops->destroy=0;
478: ls->setupcalled = PETSC_FALSE;
479: (*r)(ls);
480: PetscObjectChangeTypeName((PetscObject)ls, type);
481: return(0);
482: }
486: /*@
487: TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
488: options.
490: Collective on TaoLineSearch
492: Input Paremeter:
493: . ls - the TaoLineSearch context
495: Options Database Keys:
496: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
497: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
498: . -tao_ls_gtol <tol> - tolerance for curvature condition
499: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
500: . -tao_ls_stepmin <step> - minimum steplength allowed
501: . -tao_ls_stepmax <step> - maximum steplength allowed
502: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
503: - -tao_ls_view - display line-search results to standard output
505: Level: beginner
506: @*/
507: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
508: {
510: const char *default_type=TAOLINESEARCHMT;
511: char type[256];
512: PetscBool flg;
516: PetscObjectOptionsBegin((PetscObject)ls);
517: if (!TaoLineSearchInitialized) {
518: TaoLineSearchInitializePackage();
519: }
520: if (((PetscObject)ls)->type_name) {
521: default_type = ((PetscObject)ls)->type_name;
522: }
523: /* Check for type from options */
524: PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);
525: if (flg) {
526: TaoLineSearchSetType(ls,type);
527: } else if (!((PetscObject)ls)->type_name) {
528: TaoLineSearchSetType(ls,default_type);
529: }
531: PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,NULL);
532: PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,NULL);
533: PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,NULL);
534: PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,NULL);
535: PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,NULL);
536: PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,NULL);
537: if (ls->ops->setfromoptions) {
538: (*ls->ops->setfromoptions)(PetscOptionsObject,ls);
539: }
540: PetscOptionsEnd();
541: return(0);
542: }
546: /*@C
547: TaoLineSearchGetType - Gets the current line search algorithm
549: Not Collective
551: Input Parameter:
552: . ls - the TaoLineSearch context
554: Output Paramter:
555: . type - the line search algorithm in effect
557: Level: developer
559: @*/
560: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, const TaoLineSearchType *type)
561: {
565: *type = ((PetscObject)ls)->type_name;
566: return(0);
567: }
571: /*@
572: TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
573: routines used by the line search in last application (not cumulative).
575: Not Collective
577: Input Parameter:
578: . ls - the TaoLineSearch context
580: Output Parameters:
581: + nfeval - number of function evaluations
582: . ngeval - number of gradient evaluations
583: - nfgeval - number of function/gradient evaluations
585: Level: intermediate
587: Note:
588: If the line search is using the Tao objective and gradient
589: routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
590: is already counting the number of evaluations.
592: @*/
593: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
594: {
597: *nfeval = ls->nfeval;
598: *ngeval = ls->ngeval;
599: *nfgeval = ls->nfgeval;
600: return(0);
601: }
605: /*@
606: TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
607: Tao evaluation routines.
609: Not Collective
611: Input Parameter:
612: . ls - the TaoLineSearch context
614: Output Parameter:
615: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
616: otherwise PETSC_FALSE
618: Level: developer
619: @*/
620: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
621: {
624: *flg = ls->usetaoroutines;
625: return(0);
626: }
630: /*@C
631: TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search
633: Logically Collective on TaoLineSearch
635: Input Parameter:
636: + ls - the TaoLineSearch context
637: . func - the objective function evaluation routine
638: - ctx - the (optional) user-defined context for private data
640: Calling sequence of func:
641: $ func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);
643: + x - input vector
644: . f - function value
645: - ctx (optional) user-defined context
647: Level: beginner
649: Note:
650: Use this routine only if you want the line search objective
651: evaluation routine to be different from the Tao's objective
652: evaluation routine. If you use this routine you must also set
653: the line search gradient and/or function/gradient routine.
655: Note:
656: Some algorithms (lcl, gpcg) set their own objective routine for the
657: line search, application programmers should be wary of overriding the
658: default objective routine.
660: .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
661: @*/
662: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
663: {
667: ls->ops->computeobjective=func;
668: if (ctx) ls->userctx_func=ctx;
669: ls->usetaoroutines=PETSC_FALSE;
670: return(0);
671: }
675: /*@C
676: TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search
678: Logically Collective on TaoLineSearch
680: Input Parameter:
681: + ls - the TaoLineSearch context
682: . func - the gradient evaluation routine
683: - ctx - the (optional) user-defined context for private data
685: Calling sequence of func:
686: $ func (TaoLinesearch ls, Vec x, Vec g, void *ctx);
688: + x - input vector
689: . g - gradient vector
690: - ctx (optional) user-defined context
692: Level: beginner
694: Note:
695: Use this routine only if you want the line search gradient
696: evaluation routine to be different from the Tao's gradient
697: evaluation routine. If you use this routine you must also set
698: the line search function and/or function/gradient routine.
700: Note:
701: Some algorithms (lcl, gpcg) set their own gradient routine for the
702: line search, application programmers should be wary of overriding the
703: default gradient routine.
705: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
706: @*/
707: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
708: {
711: ls->ops->computegradient=func;
712: if (ctx) ls->userctx_grad=ctx;
713: ls->usetaoroutines=PETSC_FALSE;
714: return(0);
715: }
719: /*@C
720: TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search
722: Logically Collective on TaoLineSearch
724: Input Parameter:
725: + ls - the TaoLineSearch context
726: . func - the objective and gradient evaluation routine
727: - ctx - the (optional) user-defined context for private data
729: Calling sequence of func:
730: $ func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);
732: + x - input vector
733: . f - function value
734: . g - gradient vector
735: - ctx (optional) user-defined context
737: Level: beginner
739: Note:
740: Use this routine only if you want the line search objective and gradient
741: evaluation routines to be different from the Tao's objective
742: and gradient evaluation routines.
744: Note:
745: Some algorithms (lcl, gpcg) set their own objective routine for the
746: line search, application programmers should be wary of overriding the
747: default objective routine.
749: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetGradientRoutine(), TaoLineSearchUseTaoRoutines()
750: @*/
751: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void*), void *ctx)
752: {
755: ls->ops->computeobjectiveandgradient=func;
756: if (ctx) ls->userctx_funcgrad=ctx;
757: ls->usetaoroutines = PETSC_FALSE;
758: return(0);
759: }
763: /*@C
764: TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
765: (gradient'*stepdirection) evaluation routine for the line search.
766: Sometimes it is more efficient to compute the inner product of the gradient
767: and the step direction than it is to compute the gradient, and this is all
768: the line search typically needs of the gradient.
770: Logically Collective on TaoLineSearch
772: Input Parameter:
773: + ls - the TaoLineSearch context
774: . func - the objective and gradient evaluation routine
775: - ctx - the (optional) user-defined context for private data
777: Calling sequence of func:
778: $ func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);
780: + x - input vector
781: . s - step direction
782: . f - function value
783: . gts - inner product of gradient and step direction vectors
784: - ctx (optional) user-defined context
786: Note: The gradient will still need to be computed at the end of the line
787: search, so you will still need to set a line search gradient evaluation
788: routine
790: Note: Bounded line searches (those used in bounded optimization algorithms)
791: don't use g's directly, but rather (g'x - g'x0)/steplength. You can get the
792: x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()
794: Level: advanced
796: Note:
797: Some algorithms (lcl, gpcg) set their own objective routine for the
798: line search, application programmers should be wary of overriding the
799: default objective routine.
801: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjective(), TaoLineSearchSetGradient(), TaoLineSearchUseTaoRoutines()
802: @*/
803: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void*), void *ctx)
804: {
807: ls->ops->computeobjectiveandgts=func;
808: if (ctx) ls->userctx_funcgts=ctx;
809: ls->usegts = PETSC_TRUE;
810: ls->usetaoroutines=PETSC_FALSE;
811: return(0);
812: }
816: /*@C
817: TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
818: objective and gradient evaluation routines from the given Tao object.
820: Logically Collective on TaoLineSearch
822: Input Parameter:
823: + ls - the TaoLineSearch context
824: - ts - the Tao context with defined objective/gradient evaluation routines
826: Level: developer
828: .seealso: TaoLineSearchCreate()
829: @*/
830: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
831: {
835: ls->tao = ts;
836: ls->usetaoroutines=PETSC_TRUE;
837: return(0);
838: }
842: /*@
843: TaoLineSearchComputeObjective - Computes the objective function value at a given point
845: Collective on TaoLineSearch
847: Input Parameters:
848: + ls - the TaoLineSearch context
849: - x - input vector
851: Output Parameter:
852: . f - Objective value at X
854: Notes: TaoLineSearchComputeObjective() is typically used within line searches
855: so most users would not generally call this routine themselves.
857: Level: developer
859: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
860: @*/
861: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
862: {
864: Vec gdummy;
865: PetscReal gts;
872: if (ls->usetaoroutines) {
873: TaoComputeObjective(ls->tao,x,f);
874: } else {
875: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
876: if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient && !ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
877: PetscStackPush("TaoLineSearch user objective routine");
878: if (ls->ops->computeobjective) {
879: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
880: } else if (ls->ops->computeobjectiveandgradient) {
881: VecDuplicate(x,&gdummy);
882: (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);
883: VecDestroy(&gdummy);
884: } else {
885: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,>s,ls->userctx_funcgts);
886: }
887: PetscStackPop;
888: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
889: }
890: ls->nfeval++;
891: return(0);
892: }
896: /*@
897: TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point
899: Collective on Tao
901: Input Parameters:
902: + ls - the TaoLineSearch context
903: - x - input vector
905: Output Parameter:
906: + f - Objective value at X
907: - g - Gradient vector at X
909: Notes: TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
910: so most users would not generally call this routine themselves.
912: Level: developer
914: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
915: @*/
916: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
917: {
927: if (ls->usetaoroutines) {
928: TaoComputeObjectiveAndGradient(ls->tao,x,f,g);
929: } else {
930: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
931: if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
932: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");
934: PetscStackPush("TaoLineSearch user objective/gradient routine");
935: if (ls->ops->computeobjectiveandgradient) {
936: (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);
937: } else {
938: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
939: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
940: }
941: PetscStackPop;
942: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
943: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
944: }
945: ls->nfgeval++;
946: return(0);
947: }
951: /*@
952: TaoLineSearchComputeGradient - Computes the gradient of the objective function
954: Collective on TaoLineSearch
956: Input Parameters:
957: + ls - the TaoLineSearch context
958: - x - input vector
960: Output Parameter:
961: . g - gradient vector
963: Notes: TaoComputeGradient() is typically used within line searches
964: so most users would not generally call this routine themselves.
966: Level: developer
968: .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
969: @*/
970: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
971: {
973: PetscReal fdummy;
981: if (ls->usetaoroutines) {
982: TaoComputeGradient(ls->tao,x,g);
983: } else {
984: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
985: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient functions set");
986: PetscStackPush("TaoLineSearch user gradient routine");
987: if (ls->ops->computegradient) {
988: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
989: } else {
990: (*ls->ops->computeobjectiveandgradient)(ls,x,&fdummy,g,ls->userctx_funcgrad);
991: }
992: PetscStackPop;
993: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
994: }
995: ls->ngeval++;
996: return(0);
997: }
1001: /*@
1002: TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point
1004: Collective on Tao
1006: Input Parameters:
1007: + ls - the TaoLineSearch context
1008: - x - input vector
1010: Output Parameter:
1011: + f - Objective value at X
1012: - gts - inner product of gradient and step direction at X
1014: Notes: TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
1015: so most users would not generally call this routine themselves.
1017: Level: developer
1019: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1020: @*/
1021: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1022: {
1030: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
1031: if (!ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1032: PetscStackPush("TaoLineSearch user objective/gts routine");
1033: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);
1034: PetscStackPop;
1035: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
1036: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
1037: ls->nfeval++;
1038: return(0);
1039: }
1043: /*@
1044: TaoLineSearchGetSolution - Returns the solution to the line search
1046: Collective on TaoLineSearch
1048: Input Parameter:
1049: . ls - the TaoLineSearch context
1051: Output Parameter:
1052: + x - the new solution
1053: . f - the objective function value at x
1054: . g - the gradient at x
1055: . steplength - the multiple of the step direction taken by the line search
1056: - reason - the reason why the line search terminated
1058: reason will be set to one of:
1060: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1061: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1062: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1063: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1064: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1065: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1066: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
1068: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
1069: . TAOLINESEARCH_HALTED_OTHER - any other reason
1071: + TAOLINESEARCH_SUCCESS - successful line search
1073: Level: developer
1075: @*/
1076: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
1077: {
1086: if (ls->new_x) {
1087: VecCopy(ls->new_x,x);
1088: }
1089: *f = ls->new_f;
1090: if (ls->new_g) {
1091: VecCopy(ls->new_g,g);
1092: }
1093: if (steplength) {
1094: *steplength=ls->step;
1095: }
1096: *reason = ls->reason;
1097: return(0);
1098: }
1102: /*@
1103: TaoLineSearchGetStartingVector - Gets a the initial point of the line
1104: search.
1106: Not Collective
1108: Input Parameter:
1109: . ls - the TaoLineSearch context
1111: Output Parameter:
1112: . x - The initial point of the line search
1114: Level: intermediate
1115: @*/
1116: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1117: {
1120: if (x) {
1121: *x = ls->start_x;
1122: }
1123: return(0);
1124: }
1128: /*@
1129: TaoLineSearchGetStepDirection - Gets the step direction of the line
1130: search.
1132: Not Collective
1134: Input Parameter:
1135: . ls - the TaoLineSearch context
1137: Output Parameter:
1138: . s - the step direction of the line search
1140: Level: advanced
1141: @*/
1142: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1143: {
1146: if (s) {
1147: *s = ls->stepdirection;
1148: }
1149: return(0);
1151: }
1155: /*@
1156: TaoLineSearchGetFullStepObjective - Returns the objective function value at the full step. Useful for some minimization algorithms.
1158: Not Collective
1160: Input Parameter:
1161: . ls - the TaoLineSearch context
1163: Output Parameter:
1164: . f - the objective value at the full step length
1166: Level: developer
1167: @*/
1169: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1170: {
1173: *f_fullstep = ls->f_fullstep;
1174: return(0);
1175: }
1179: /*@
1180: TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.
1182: Logically Collective on Tao
1184: Input Parameters:
1185: + ls - the TaoLineSearch context
1186: . xl - vector of lower bounds
1187: - xu - vector of upper bounds
1189: Note: If the variable bounds are not set with this routine, then
1190: PETSC_NINFINITY and PETSC_INFINITY are assumed
1192: Level: beginner
1194: .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1195: @*/
1196: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1197: {
1202: ls->lower = xl;
1203: ls->upper = xu;
1204: ls->bounded = 1;
1205: return(0);
1206: }
1210: /*@
1211: TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1212: search. If this value is not set then 1.0 is assumed.
1214: Logically Collective on TaoLineSearch
1216: Input Parameters:
1217: + ls - the TaoLineSearch context
1218: - s - the initial step size
1220: Level: intermediate
1222: .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1223: @*/
1224: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1225: {
1228: ls->initstep = s;
1229: return(0);
1230: }
1234: /*@
1235: TaoLineSearchGetStepLength - Get the current step length
1237: Not Collective
1239: Input Parameters:
1240: . ls - the TaoLineSearch context
1242: Output Parameters
1243: . s - the current step length
1245: Level: beginner
1247: .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1248: @*/
1249: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1250: {
1253: *s = ls->step;
1254: return(0);
1255: }
1259: /*MC
1260: TaoLineSearchRegister - Adds a line-search algorithm to the registry
1262: Not collective
1264: Input Parameters:
1265: + sname - name of a new user-defined solver
1266: - func - routine to Create method context
1268: Notes:
1269: TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.
1271: Sample usage:
1272: .vb
1273: TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1274: .ve
1276: Then, your solver can be chosen with the procedural interface via
1277: $ TaoLineSearchSetType(ls,"my_linesearch")
1278: or at runtime via the option
1279: $ -tao_ls_type my_linesearch
1281: Level: developer
1283: .seealso: TaoLineSearchRegisterDestroy()
1284: M*/
1285: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1286: {
1289: PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1290: return(0);
1291: }
1295: /*@C
1296: TaoLineSearchRegisterDestroy - Frees the list of line-search algorithms that were
1297: registered by TaoLineSearchRegister().
1299: Not Collective
1301: Level: developer
1303: .seealso: TaoLineSearchRegister()
1304: @*/
1305: PetscErrorCode TaoLineSearchRegisterDestroy(void)
1306: {
1309: PetscFunctionListDestroy(&TaoLineSearchList);
1310: TaoLineSearchInitialized = PETSC_FALSE;
1311: return(0);
1312: }
1316: /*@C
1317: TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1318: for all TaoLineSearch options in the database.
1321: Collective on TaoLineSearch
1323: Input Parameters:
1324: + ls - the TaoLineSearch solver context
1325: - prefix - the prefix string to prepend to all line search requests
1327: Notes:
1328: A hyphen (-) must NOT be given at the beginning of the prefix name.
1329: The first character of all runtime options is AUTOMATICALLY the hyphen.
1332: Level: advanced
1334: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1335: @*/
1336: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1337: {
1338: return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1339: }
1343: /*@C
1344: TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1345: TaoLineSearch options in the database
1347: Not Collective
1349: Input Parameters:
1350: . ls - the TaoLineSearch context
1352: Output Parameters:
1353: . prefix - pointer to the prefix string used is returned
1355: Notes: On the fortran side, the user should pass in a string 'prefix' of
1356: sufficient length to hold the prefix.
1358: Level: advanced
1360: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1361: @*/
1362: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1363: {
1364: return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1365: }
1369: /*@C
1370: TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1371: TaoLineSearch options in the database.
1374: Logically Collective on TaoLineSearch
1376: Input Parameters:
1377: + ls - the TaoLineSearch context
1378: - prefix - the prefix string to prepend to all TAO option requests
1380: Notes:
1381: A hyphen (-) must NOT be given at the beginning of the prefix name.
1382: The first character of all runtime options is AUTOMATICALLY the hyphen.
1384: For example, to distinguish between the runtime options for two
1385: different line searches, one could call
1386: .vb
1387: TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1388: TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1389: .ve
1391: This would enable use of different options for each system, such as
1392: .vb
1393: -sys1_tao_ls_type mt
1394: -sys2_tao_ls_type armijo
1395: .ve
1397: Level: advanced
1399: .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1400: @*/
1402: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1403: {
1404: return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1405: }