Actual source code: taolinesearch.c
petsc-dev 2014-02-02
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;
42: PetscBool destroyviewer = PETSC_FALSE;
46: if (!viewer) {
47: destroyviewer = PETSC_TRUE;
48: PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);
49: }
53: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
54: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
55: if (isascii) {
56: if (((PetscObject)ls)->prefix) {
57: PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:(%s)\n",((PetscObject)ls)->prefix);
58: } else {
59: PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:\n");
60: }
61: PetscViewerASCIIPushTab(viewer);
62: TaoLineSearchGetType(ls,&type);
63: if (type) {
64: PetscViewerASCIIPrintf(viewer,"type: %s\n",type);
65: } else {
66: PetscViewerASCIIPrintf(viewer,"type: not set yet\n");
67: }
68: if (ls->ops->view) {
69: PetscViewerASCIIPushTab(viewer);
70: (*ls->ops->view)(ls,viewer);
71: PetscViewerASCIIPopTab(viewer);
72: }
73: PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);
74: PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);
75: PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);
76: PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);
77: PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);
79: if (ls->bounded) {
80: PetscViewerASCIIPrintf(viewer,"using variable bounds\n");
81: }
82: PetscViewerASCIIPrintf(viewer,"Termination reason: %D\n",(int)ls->reason);
83: PetscViewerASCIIPopTab(viewer);
85: } else if (isstring) {
86: TaoLineSearchGetType(ls,&type);
87: PetscViewerStringSPrintf(viewer," %-3.3s",type);
88: }
89: if (destroyviewer) {
90: PetscViewerDestroy(&viewer);
91: }
92: return(0);
93: }
97: /*@C
98: TaoLineSearchCreate - Creates a TAO Line Search object. Algorithms in TAO that use
99: line-searches will automatically create one.
101: Collective on MPI_Comm
103: Input Parameter:
104: . comm - MPI communicator
106: Output Parameter:
107: . newls - the new TaoLineSearch context
109: Available methods include:
110: + more-thuente
111: . gpcg
112: - unit - Do not perform any line search
115: Options Database Keys:
116: . -tao_ls_type - select which method TAO should use
118: Level: beginner
120: .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
121: @*/
123: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
124: {
126: TaoLineSearch ls;
130: *newls = NULL;
132: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
133: TaoLineSearchInitializePackage();
134: #endif
136: PetscHeaderCreate(ls,_p_TaoLineSearch,struct _TaoLineSearchOps,TAOLINESEARCH_CLASSID,"TaoLineSearch",0,0,comm,TaoLineSearchDestroy,TaoLineSearchView);
137: ls->bounded = 0;
138: ls->max_funcs=30;
139: ls->ftol = 0.0001;
140: ls->gtol = 0.9;
141: #if defined(PETSC_USE_REAL_SINGLE)
142: ls->rtol = 1.0e-5;
143: #else
144: ls->rtol = 1.0e-10;
145: #endif
146: ls->stepmin=1.0e-20;
147: ls->stepmax=1.0e+20;
148: ls->step=1.0;
149: ls->nfeval=0;
150: ls->ngeval=0;
151: ls->nfgeval=0;
153: ls->ops->computeobjective=0;
154: ls->ops->computegradient=0;
155: ls->ops->computeobjectiveandgradient=0;
156: ls->ops->computeobjectiveandgts=0;
157: ls->ops->setup=0;
158: ls->ops->apply=0;
159: ls->ops->view=0;
160: ls->ops->setfromoptions=0;
161: ls->ops->reset=0;
162: ls->ops->destroy=0;
163: ls->setupcalled=PETSC_FALSE;
164: ls->usetaoroutines=PETSC_FALSE;
165: *newls = ls;
166: return(0);
167: }
171: /*@
172: TaoLineSearchSetUp - Sets up the internal data structures for the later use
173: of a Tao solver
175: Collective on ls
177: Input Parameters:
178: . ls - the TaoLineSearch context
180: Notes:
181: The user will not need to explicitly call TaoLineSearchSetUp(), as it will
182: automatically be called in TaoLineSearchSolve(). However, if the user
183: desires to call it explicitly, it should come after TaoLineSearchCreate()
184: but before TaoLineSearchApply().
186: Level: developer
188: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
189: @*/
191: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
192: {
194: const char *default_type=TAOLINESEARCH_MT;
195: PetscBool flg;
199: if (ls->setupcalled) return(0);
200: if (!((PetscObject)ls)->type_name) {
201: TaoLineSearchSetType(ls,default_type);
202: }
203: if (ls->ops->setup) {
204: (*ls->ops->setup)(ls);
205: }
206: if (ls->usetaoroutines) {
207: TaoIsObjectiveDefined(ls->tao,&flg);
208: ls->hasobjective = flg;
209: TaoIsGradientDefined(ls->tao,&flg);
210: ls->hasgradient = flg;
211: TaoIsObjectiveAndGradientDefined(ls->tao,&flg);
212: ls->hasobjectiveandgradient = flg;
213: } else {
214: if (ls->ops->computeobjective) {
215: ls->hasobjective = PETSC_TRUE;
216: } else {
217: ls->hasobjective = PETSC_FALSE;
218: }
219: if (ls->ops->computegradient) {
220: ls->hasgradient = PETSC_TRUE;
221: } else {
222: ls->hasgradient = PETSC_FALSE;
223: }
224: if (ls->ops->computeobjectiveandgradient) {
225: ls->hasobjectiveandgradient = PETSC_TRUE;
226: } else {
227: ls->hasobjectiveandgradient = PETSC_FALSE;
228: }
229: }
230: ls->setupcalled = PETSC_TRUE;
231: return(0);
232: }
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: }
264: /*@
265: TaoLineSearchDestroy - Destroys the TAO context that was created with
266: TaoLineSearchCreate()
268: Collective on TaoLineSearch
270: Input Parameter
271: . ls - the TaoLineSearch context
273: Level: beginner
275: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
276: @*/
277: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
278: {
282: if (!*ls) return(0);
284: if (--((PetscObject)*ls)->refct > 0) {*ls=0; return(0);}
285: VecDestroy(&(*ls)->stepdirection);
286: VecDestroy(&(*ls)->start_x);
287: if ((*ls)->ops->destroy) {
288: (*(*ls)->ops->destroy)(*ls);
289: }
290: PetscHeaderDestroy(ls);
291: return(0);
292: }
296: /*@
297: TaoLineSearchApply - Performs a line-search in a given step direction. Criteria for acceptable step length depends on the line-search algorithm chosen
299: Collective on TaoLineSearch
301: Input Parameters:
302: + ls - the Tao context
303: . x - The current solution (on output x contains the new solution determined by the line search)
304: . f - objective function value at current solution (on output contains the objective function value at new solution)
305: . g - gradient evaluated at x (on output contains the gradient at new solution)
306: - s - search direction
308: Output Parameters:
309: + x - new solution
310: . f - objective function value at x
311: . g - gradient vector at x
312: . steplength - scalar multiplier of s used ( x = x0 + steplength * x )
313: - reason - reason why the line-search stopped
315: reason will be set to one of:
317: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
318: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
319: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
320: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
321: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
322: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
323: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
324: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
325: . TAOLINESEARCH_HALTED_OTHER - any other reason
326: - TAOLINESEARCH_SUCCESS - successful line search
328: Note:
329: The algorithm developer must set up the TaoLineSearch with calls to
330: TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()
332: Note:
333: You may or may not need to follow this with a call to
334: TaoAddLineSearchCounts(), depending on whether you want these
335: evaluations to count toward the total function/gradient evaluations.
337: Level: beginner
339: .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
340: @*/
342: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchTerminationReason *reason)
343: {
345: PetscViewer viewer;
346: PetscInt low1,low2,low3,high1,high2,high3;
347: PetscBool flg;
348: char filename[PETSC_MAX_PATH_LEN];
351: *reason = TAOLINESEARCH_CONTINUE_ITERATING;
361: VecGetOwnershipRange(x, &low1, &high1);
362: VecGetOwnershipRange(g, &low2, &high2);
363: VecGetOwnershipRange(s, &low3, &high3);
364: if ( low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,1,"InCompatible vector local lengths");
366: PetscObjectReference((PetscObject)s);
367: VecDestroy(&ls->stepdirection);
368: ls->stepdirection = s;
370: TaoLineSearchSetUp(ls);
371: if (!ls->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
372: ls->nfeval=0;
373: ls->ngeval=0;
374: ls->nfgeval=0;
375: /* Check parameter values */
376: if (ls->ftol < 0.0) {
377: PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);
378: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
379: }
380: if (ls->rtol < 0.0) {
381: PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);
382: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
383: }
384: if (ls->gtol < 0.0) {
385: PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);
386: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
387: }
388: if (ls->stepmin < 0.0) {
389: PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);
390: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
391: }
392: if (ls->stepmax < ls->stepmin) {
393: PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);
394: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
395: }
396: if (ls->max_funcs < 0) {
397: PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);
398: *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
399: }
400: if (PetscIsInfOrNanReal(*f)) {
401: PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);
402: *reason=TAOLINESEARCH_FAILED_INFORNAN;
403: }
405: PetscObjectReference((PetscObject)x);
406: VecDestroy(&ls->start_x);
407: ls->start_x = x;
409: PetscLogEventBegin(TaoLineSearch_ApplyEvent,ls,0,0,0);
410: (*ls->ops->apply)(ls,x,f,g,s);
411: PetscLogEventEnd(TaoLineSearch_ApplyEvent, ls, 0,0,0);
412: *reason=ls->reason;
413: ls->new_f = *f;
415: if (steplength) {
416: *steplength=ls->step;
417: }
419: PetscOptionsGetString(((PetscObject)ls)->prefix,"-tao_ls_view",filename,PETSC_MAX_PATH_LEN,&flg);
420: if (ls->viewls && !PetscPreLoadingOn) {
421: PetscViewerASCIIOpen(((PetscObject)ls)->comm,filename,&viewer);
422: TaoLineSearchView(ls,viewer);
423: PetscViewerDestroy(&viewer);
424: }
425: return(0);
426: }
430: /*@C
431: TaoLineSearchSetType - Sets the algorithm used in a line search
433: Collective on TaoLineSearch
435: Input Parameters:
436: + ls - the TaoLineSearch context
437: - type - a known method
439: Available methods include:
440: + more-thuente
441: . gpcg
442: - unit - Do not perform any line search
445: Options Database Keys:
446: . -tao_ls_type - select which method TAO should use
448: Level: beginner
451: .seealso: TaoLineSearchCreate(), TaoLineSearchGetType(), TaoLineSearchApply()
453: @*/
455: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, const TaoLineSearchType type)
456: {
458: PetscErrorCode (*r)(TaoLineSearch);
459: PetscBool flg;
464: PetscObjectTypeCompare((PetscObject)ls, type, &flg);
465: if (flg) return(0);
467: PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);
468: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
469: if (ls->ops->destroy) {
470: (*(ls)->ops->destroy)(ls);
471: }
472: ls->max_funcs=30;
473: ls->ftol = 0.0001;
474: ls->gtol = 0.9;
475: #if defined(PETSC_USE_REAL_SINGLE)
476: ls->rtol = 1.0e-5;
477: #else
478: ls->rtol = 1.0e-10;
479: #endif
480: ls->stepmin=1.0e-20;
481: ls->stepmax=1.0e+20;
483: ls->nfeval=0;
484: ls->ngeval=0;
485: ls->nfgeval=0;
486: ls->ops->setup=0;
487: ls->ops->apply=0;
488: ls->ops->view=0;
489: ls->ops->setfromoptions=0;
490: ls->ops->destroy=0;
491: ls->setupcalled = PETSC_FALSE;
492: (*r)(ls);
493: PetscObjectChangeTypeName((PetscObject)ls, type);
494: return(0);
495: }
499: /*@
500: TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
501: options.
503: Collective on TaoLineSearch
505: Input Paremeter:
506: . ls - the TaoLineSearch context
508: Options Database Keys:
509: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
510: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
511: . -tao_ls_gtol <tol> - tolerance for curvature condition
512: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
513: . -tao_ls_stepmin <step> - minimum steplength allowed
514: . -tao_ls_stepmax <step> - maximum steplength allowed
515: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
516: - -tao_ls_view - display line-search results to standard output
518: Level: beginner
519: @*/
520: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
521: {
523: const char *default_type=TAOLINESEARCH_MT;
524: char type[256];
525: PetscBool flg;
529: PetscObjectOptionsBegin((PetscObject)ls);
530: if (!TaoLineSearchInitialized) {
531: TaoLineSearchInitializePackage();
532: }
533: if (((PetscObject)ls)->type_name) {
534: default_type = ((PetscObject)ls)->type_name;
535: }
536: /* Check for type from options */
537: PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);
538: if (flg) {
539: TaoLineSearchSetType(ls,type);
540: } else if (!((PetscObject)ls)->type_name) {
541: TaoLineSearchSetType(ls,default_type);
542: }
544: PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,0);
545: PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,0);
546: PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,0);
547: PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,0);
548: PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,0);
549: PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,0);
550: PetscOptionsBool("-tao_ls_view","view TaoLineSearch info after each line search has completed","TaoLineSearchView",PETSC_FALSE,&ls->viewls,NULL);
551: if (ls->ops->setfromoptions) {
552: (*ls->ops->setfromoptions)(ls);
553: }
554: PetscOptionsEnd();
555: return(0);
556: }
560: /*@C
561: TaoLineSearchGetType - Gets the current line search algorithm
563: Not Collective
565: Input Parameter:
566: . ls - the TaoLineSearch context
568: Output Paramter:
569: . type - the line search algorithm in effect
571: Level: developer
573: @*/
574: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, const TaoLineSearchType *type)
575: {
579: *type = ((PetscObject)ls)->type_name;
580: return(0);
581: }
585: /*@
586: TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
587: routines used by the line search in last application (not cumulative).
589: Not Collective
591: Input Parameter:
592: . ls - the TaoLineSearch context
594: Output Parameters:
595: + nfeval - number of function evaluations
596: . ngeval - number of gradient evaluations
597: - nfgeval - number of function/gradient evaluations
599: Level: intermediate
601: Note:
602: If the line search is using the Tao objective and gradient
603: routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
604: is already counting the number of evaluations.
606: @*/
607: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
608: {
611: *nfeval = ls->nfeval;
612: *ngeval = ls->ngeval;
613: *nfgeval = ls->nfgeval;
614: return(0);
615: }
619: /*@
620: TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
621: Tao evaluation routines.
623: Not Collective
625: Input Parameter:
626: . ls - the TaoLineSearch context
628: Output Parameter:
629: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
630: otherwise PETSC_FALSE
632: Level: developer
633: @*/
634: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
635: {
638: *flg = ls->usetaoroutines;
639: return(0);
640: }
644: /*@C
645: TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search
647: Logically Collective on TaoLineSearch
649: Input Parameter:
650: + ls - the TaoLineSearch context
651: . func - the objective function evaluation routine
652: - ctx - the (optional) user-defined context for private data
654: Calling sequence of func:
655: $ func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);
657: + x - input vector
658: . f - function value
659: - ctx (optional) user-defined context
661: Level: beginner
663: Note:
664: Use this routine only if you want the line search objective
665: evaluation routine to be different from the Tao's objective
666: evaluation routine. If you use this routine you must also set
667: the line search gradient and/or function/gradient routine.
669: Note:
670: Some algorithms (lcl, gpcg) set their own objective routine for the
671: line search, application programmers should be wary of overriding the
672: default objective routine.
674: .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
675: @*/
676: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
677: {
681: ls->ops->computeobjective=func;
682: if (ctx) ls->userctx_func=ctx;
683: ls->usetaoroutines=PETSC_FALSE;
684: return(0);
685: }
689: /*@C
690: TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search
692: Logically Collective on TaoLineSearch
694: Input Parameter:
695: + ls - the TaoLineSearch context
696: . func - the gradient evaluation routine
697: - ctx - the (optional) user-defined context for private data
699: Calling sequence of func:
700: $ func (TaoLinesearch ls, Vec x, Vec g, void *ctx);
702: + x - input vector
703: . g - gradient vector
704: - ctx (optional) user-defined context
706: Level: beginner
708: Note:
709: Use this routine only if you want the line search gradient
710: evaluation routine to be different from the Tao's gradient
711: evaluation routine. If you use this routine you must also set
712: the line search function and/or function/gradient routine.
714: Note:
715: Some algorithms (lcl, gpcg) set their own gradient routine for the
716: line search, application programmers should be wary of overriding the
717: default gradient routine.
719: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
720: @*/
721: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
722: {
725: ls->ops->computegradient=func;
726: if (ctx) ls->userctx_grad=ctx;
727: ls->usetaoroutines=PETSC_FALSE;
728: return(0);
729: }
733: /*@C
734: TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search
736: Logically Collective on TaoLineSearch
738: Input Parameter:
739: + ls - the TaoLineSearch context
740: . func - the objective and gradient evaluation routine
741: - ctx - the (optional) user-defined context for private data
743: Calling sequence of func:
744: $ func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);
746: + x - input vector
747: . f - function value
748: . g - gradient vector
749: - ctx (optional) user-defined context
751: Level: beginner
753: Note:
754: Use this routine only if you want the line search objective and gradient
755: evaluation routines to be different from the Tao's objective
756: and gradient evaluation routines.
758: Note:
759: Some algorithms (lcl, gpcg) set their own objective routine for the
760: line search, application programmers should be wary of overriding the
761: default objective routine.
763: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetGradientRoutine(), TaoLineSearchUseTaoRoutines()
764: @*/
765: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void*), void *ctx)
766: {
769: ls->ops->computeobjectiveandgradient=func;
770: if (ctx) ls->userctx_funcgrad=ctx;
771: ls->usetaoroutines = PETSC_FALSE;
772: return(0);
773: }
777: /*@C
778: TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
779: (gradient'*stepdirection) evaluation routine for the line search.
780: Sometimes it is more efficient to compute the inner product of the gradient
781: and the step direction than it is to compute the gradient, and this is all
782: the line search typically needs of the gradient.
784: Logically Collective on TaoLineSearch
786: Input Parameter:
787: + ls - the TaoLineSearch context
788: . func - the objective and gradient evaluation routine
789: - ctx - the (optional) user-defined context for private data
791: Calling sequence of func:
792: $ func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);
794: + x - input vector
795: . s - step direction
796: . f - function value
797: . gts - inner product of gradient and step direction vectors
798: - ctx (optional) user-defined context
800: Note: The gradient will still need to be computed at the end of the line
801: search, so you will still need to set a line search gradient evaluation
802: routine
804: Note: Bounded line searches (those used in bounded optimization algorithms)
805: don't use g's directly, but rather (g'x - g'x0)/steplength. You can get the
806: x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()
808: Level: advanced
810: Note:
811: Some algorithms (lcl, gpcg) set their own objective routine for the
812: line search, application programmers should be wary of overriding the
813: default objective routine.
815: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjective(), TaoLineSearchSetGradient(), TaoLineSearchUseTaoRoutines()
816: @*/
817: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void*), void *ctx)
818: {
821: ls->ops->computeobjectiveandgts=func;
822: if (ctx) ls->userctx_funcgts=ctx;
823: ls->usegts = PETSC_TRUE;
824: ls->usetaoroutines=PETSC_FALSE;
825: return(0);
826: }
830: /*@C
831: TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
832: objective and gradient evaluation routines from the given Tao object.
834: Logically Collective on TaoLineSearch
836: Input Parameter:
837: + ls - the TaoLineSearch context
838: - ts - the Tao context with defined objective/gradient evaluation routines
840: Level: developer
842: .seealso: TaoLineSearchCreate()
843: @*/
844: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
845: {
849: ls->tao = ts;
850: ls->usetaoroutines=PETSC_TRUE;
851: return(0);
852: }
856: /*@
857: TaoLineSearchComputeObjective - Computes the objective function value at a given point
859: Collective on TaoLineSearch
861: Input Parameters:
862: + ls - the TaoLineSearch context
863: - x - input vector
865: Output Parameter:
866: . f - Objective value at X
868: Notes: TaoLineSearchComputeObjective() is typically used within line searches
869: so most users would not generally call this routine themselves.
871: Level: developer
873: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
874: @*/
875: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
876: {
878: Vec gdummy;
879: PetscReal gts;
886: if (ls->usetaoroutines) {
887: TaoComputeObjective(ls->tao,x,f);
888: } else {
889: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
890: 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");
891: PetscStackPush("TaoLineSearch user objective routine");
892: if (ls->ops->computeobjective) {
893: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
894: } else if (ls->ops->computeobjectiveandgradient) {
895: VecDuplicate(x,&gdummy);
896: (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);
897: VecDestroy(&gdummy);
898: } else {
899: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,>s,ls->userctx_funcgts);
900: }
901: PetscStackPop;
902: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
903: }
904: ls->nfeval++;
905: return(0);
906: }
910: /*@
911: TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point
913: Collective on Tao
915: Input Parameters:
916: + ls - the TaoLineSearch context
917: - x - input vector
919: Output Parameter:
920: + f - Objective value at X
921: - g - Gradient vector at X
923: Notes: TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
924: so most users would not generally call this routine themselves.
926: Level: developer
928: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
929: @*/
930: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
931: {
941: if (ls->usetaoroutines) {
942: TaoComputeObjectiveAndGradient(ls->tao,x,f,g);
943: } else {
944: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
945: if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
946: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");
948: PetscStackPush("TaoLineSearch user objective/gradient routine");
949: if (ls->ops->computeobjectiveandgradient) {
950: (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);
951: } else {
952: (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
953: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
954: }
955: PetscStackPop;
956: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
957: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
958: ls->nfgeval++;
959: }
960: return(0);
961: }
965: /*@
966: TaoLineSearchComputeGradient - Computes the gradient of the objective function
968: Collective on TaoLineSearch
970: Input Parameters:
971: + ls - the TaoLineSearch context
972: - x - input vector
974: Output Parameter:
975: . g - gradient vector
977: Notes: TaoComputeGradient() is typically used within line searches
978: so most users would not generally call this routine themselves.
980: Level: developer
982: .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
983: @*/
984: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
985: {
987: PetscReal fdummy;
995: if (ls->usetaoroutines) {
996: TaoComputeGradient(ls->tao,x,g);
997: } else {
998: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
999: if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient functions set");
1000: PetscStackPush("TaoLineSearch user gradient routine");
1001: if (ls->ops->computegradient) {
1002: (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
1003: } else {
1004: (*ls->ops->computeobjectiveandgradient)(ls,x,&fdummy,g,ls->userctx_funcgrad);
1005: }
1006: PetscStackPop;
1007: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
1008: }
1009: ls->ngeval++;
1010: return(0);
1011: }
1015: /*@
1016: TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point
1018: Collective on Tao
1020: Input Parameters:
1021: + ls - the TaoLineSearch context
1022: - x - input vector
1024: Output Parameter:
1025: + f - Objective value at X
1026: - gts - inner product of gradient and step direction at X
1028: Notes: TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
1029: so most users would not generally call this routine themselves.
1031: Level: developer
1033: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1034: @*/
1035: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1036: {
1044: PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
1045: if (!ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1046: PetscStackPush("TaoLineSearch user objective/gts routine");
1047: (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);
1048: PetscStackPop;
1049: PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
1050: PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
1051: ls->nfeval++;
1052: return(0);
1053: }
1057: /*@
1058: TaoLineSearchGetSolution - Returns the solution to the line search
1060: Collective on TaoLineSearch
1062: Input Parameter:
1063: . ls - the TaoLineSearch context
1065: Output Parameter:
1066: + x - the new solution
1067: . f - the objective function value at x
1068: . g - the gradient at x
1069: . steplength - the multiple of the step direction taken by the line search
1070: - reason - the reason why the line search terminated
1072: reason will be set to one of:
1074: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1075: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1076: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1077: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1078: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1079: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1080: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
1082: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
1083: . TAOLINESEARCH_HALTED_OTHER - any other reason
1085: + TAOLINESEARCH_SUCCESS - successful line search
1087: Level: developer
1089: @*/
1090: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchTerminationReason *reason)
1091: {
1100: if (ls->new_x) {
1101: VecCopy(ls->new_x,x);
1102: }
1103: *f = ls->new_f;
1104: if (ls->new_g) {
1105: VecCopy(ls->new_g,g);
1106: }
1107: if (steplength) {
1108: *steplength=ls->step;
1109: }
1110: *reason = ls->reason;
1111: return(0);
1112: }
1116: /*@
1117: TaoLineSearchGetStartingVector - Gets a the initial point of the line
1118: search.
1120: Not Collective
1122: Input Parameter:
1123: . ls - the TaoLineSearch context
1125: Output Parameter:
1126: . x - The initial point of the line search
1128: Level: intermediate
1129: @*/
1130: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1131: {
1134: if (x) {
1135: *x = ls->start_x;
1136: }
1137: return(0);
1138: }
1142: /*@
1143: TaoLineSearchGetStepDirection - Gets the step direction of the line
1144: search.
1146: Not Collective
1148: Input Parameter:
1149: . ls - the TaoLineSearch context
1151: Output Parameter:
1152: . s - the step direction of the line search
1154: Level: advanced
1155: @*/
1156: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1157: {
1160: if (s) {
1161: *s = ls->stepdirection;
1162: }
1163: return(0);
1165: }
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: }
1193: /*@
1194: TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.
1196: Logically Collective on Tao
1198: Input Parameters:
1199: + ls - the TaoLineSearch context
1200: . xl - vector of lower bounds
1201: - xu - vector of upper bounds
1203: Note: If the variable bounds are not set with this routine, then
1204: PETSC_NINFINITY and PETSC_INFINITY are assumed
1206: Level: beginner
1208: .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1209: @*/
1210: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1211: {
1216: ls->lower = xl;
1217: ls->upper = xu;
1218: ls->bounded = 1;
1219: return(0);
1220: }
1224: /*@
1225: TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1226: search. If this value is not set then 1.0 is assumed.
1228: Logically Collective on TaoLineSearch
1230: Input Parameters:
1231: + ls - the TaoLineSearch context
1232: - s - the initial step size
1234: Level: intermediate
1236: .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1237: @*/
1238: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1239: {
1242: ls->initstep = s;
1243: return(0);
1244: }
1248: /*@
1249: TaoLineSearchGetStepLength - Get the current step length
1251: Not Collective
1253: Input Parameters:
1254: . ls - the TaoLineSearch context
1256: Output Parameters
1257: . s - the current step length
1259: Level: beginner
1261: .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1262: @*/
1263: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1264: {
1267: *s = ls->step;
1268: return(0);
1269: }
1273: /*MC
1274: TaoLineSearchRegister - Adds a line-search algorithm to the registry
1276: Not collective
1278: Input Parameters:
1279: + sname - name of a new user-defined solver
1280: - func - routine to Create method context
1282: Notes:
1283: TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.
1285: Sample usage:
1286: .vb
1287: TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1288: .ve
1290: Then, your solver can be chosen with the procedural interface via
1291: $ TaoLineSearchSetType(ls,"my_linesearch")
1292: or at runtime via the option
1293: $ -tao_ls_type my_linesearch
1295: Level: developer
1297: .seealso: TaoLineSearchRegisterDestroy()
1298: M*/
1299: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1300: {
1303: PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1304: return(0);
1305: }
1309: /*@C
1310: TaoLineSearchRegisterDestroy - Frees the list of line-search algorithms that were
1311: registered by TaoLineSearchRegister().
1313: Not Collective
1315: Level: developer
1317: .seealso: TaoLineSearchRegister()
1318: @*/
1319: PetscErrorCode TaoLineSearchRegisterDestroy(void)
1320: {
1323: PetscFunctionListDestroy(&TaoLineSearchList);
1324: TaoLineSearchInitialized = PETSC_FALSE;
1325: return(0);
1326: }
1330: /*@C
1331: TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1332: for all TaoLineSearch options in the database.
1335: Collective on TaoLineSearch
1337: Input Parameters:
1338: + ls - the TaoLineSearch solver context
1339: - prefix - the prefix string to prepend to all line search requests
1341: Notes:
1342: A hyphen (-) must NOT be given at the beginning of the prefix name.
1343: The first character of all runtime options is AUTOMATICALLY the hyphen.
1346: Level: advanced
1348: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1349: @*/
1350: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1351: {
1352: return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1353: }
1357: /*@C
1358: TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1359: TaoLineSearch options in the database
1361: Not Collective
1363: Input Parameters:
1364: . ls - the TaoLineSearch context
1366: Output Parameters:
1367: . prefix - pointer to the prefix string used is returned
1369: Notes: On the fortran side, the user should pass in a string 'prefix' of
1370: sufficient length to hold the prefix.
1372: Level: advanced
1374: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1375: @*/
1376: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1377: {
1378: return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1379: }
1383: /*@C
1384: TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1385: TaoLineSearch options in the database.
1388: Logically Collective on TaoLineSearch
1390: Input Parameters:
1391: + ls - the TaoLineSearch context
1392: - prefix - the prefix string to prepend to all TAO option requests
1394: Notes:
1395: A hyphen (-) must NOT be given at the beginning of the prefix name.
1396: The first character of all runtime options is AUTOMATICALLY the hyphen.
1398: For example, to distinguish between the runtime options for two
1399: different line searches, one could call
1400: .vb
1401: TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1402: TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1403: .ve
1405: This would enable use of different options for each system, such as
1406: .vb
1407: -sys1_tao_ls_type mt
1408: -sys2_tao_ls_type armijo
1409: .ve
1411: Level: advanced
1413: .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1414: @*/
1416: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1417: {
1418: return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1419: }