xref: /petsc/src/ml/regressor/interface/regressor.c (revision 174dc0c8cee294b82b85e4dd3b331b29396264fc)
1 #include <petsc/private/regressorimpl.h>
2 
3 PetscBool         PetscRegressorRegisterAllCalled = PETSC_FALSE;
4 PetscFunctionList PetscRegressorList              = NULL;
5 
6 PetscClassId PETSCREGRESSOR_CLASSID;
7 
8 /* Logging support */
9 PetscLogEvent PetscRegressor_SetUp, PetscRegressor_Fit, PetscRegressor_Predict;
10 
11 /*@C
12   PetscRegressorRegister - Adds a method to the `PetscRegressor` package.
13 
14   Not collective
15 
16   Input Parameters:
17 + sname    - name of a new user-defined regressor
18 - function - routine to create method context
19 
20   Notes:
21   `PetscRegressorRegister()` may be called multiple times to add several user-defined regressors.
22 
23   Example Usage:
24 .vb
25    PetscRegressorRegister("my_regressor",MyRegressorCreate);
26 .ve
27 
28   Then, your regressor can be chosen with the procedural interface via
29 .vb
30      PetscRegressorSetType(regressor,"my_regressor")
31 .ve
32   or at runtime via the option
33 .vb
34     -regressor_type my_regressor
35 .ve
36 
37   Level: advanced
38 
39 .seealso: `PetscRegressorRegisterAll()`
40 @*/
41 PetscErrorCode PetscRegressorRegister(const char sname[], PetscErrorCode (*function)(PetscRegressor))
42 {
43   PetscFunctionBegin;
44   PetscCall(PetscRegressorInitializePackage());
45   PetscCall(PetscFunctionListAdd(&PetscRegressorList, sname, function));
46   PetscFunctionReturn(PETSC_SUCCESS);
47 }
48 
49 /*@
50   PetscRegressorCreate - Creates a `PetscRegressor` object.
51 
52   Collective
53 
54   Input Parameter:
55 . comm - the MPI communicator that will share the `PetscRegressor` object
56 
57   Output Parameter:
58 . newregressor - the new `PetscRegressor` object
59 
60   Level: beginner
61 
62 .seealso: `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressor`
63 @*/
64 PetscErrorCode PetscRegressorCreate(MPI_Comm comm, PetscRegressor *newregressor)
65 {
66   PetscRegressor regressor;
67 
68   PetscFunctionBegin;
69   PetscAssertPointer(newregressor, 2);
70   *newregressor = NULL;
71   PetscCall(PetscRegressorInitializePackage());
72 
73   PetscCall(PetscHeaderCreate(regressor, PETSCREGRESSOR_CLASSID, "PetscRegressor", "Regressor", "PetscRegressor", comm, PetscRegressorDestroy, PetscRegressorView));
74 
75   regressor->setupcalled = PETSC_FALSE;
76   regressor->fitcalled   = PETSC_FALSE;
77   regressor->data        = NULL;
78   regressor->training    = NULL;
79   regressor->target      = NULL;
80   PetscObjectParameterSetDefault(regressor, regularizer_weight, 1.0); // Default to regularizer weight of 1.0, usually the default in SciKit-learn
81 
82   *newregressor = regressor;
83   PetscFunctionReturn(PETSC_SUCCESS);
84 }
85 
86 /*@
87   PetscRegressorView - Prints information about the `PetscRegressor` object
88 
89   Collective
90 
91   Input Parameters:
92 + regressor - the `PetscRegressor` context
93 - viewer    - a `PetscViewer` context
94 
95   Options Database Key:
96 . -regressor_view - Calls `PetscRegressorView()` at the end of `PetscRegressorFit()`
97 
98   Level: beginner
99 
100   Notes:
101   The available visualization contexts include
102 +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
103 -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
104   output where only the first processor opens
105   the file.  All other processors send their
106   data to the first processor to print.
107 
108 .seealso: [](ch_regressor), `PetscRegressor`, `PetscViewerASCIIOpen()`
109 @*/
110 PetscErrorCode PetscRegressorView(PetscRegressor regressor, PetscViewer viewer)
111 {
112   PetscBool          isascii, isstring;
113   PetscRegressorType type;
114 
115   PetscFunctionBegin;
116   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
117   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)regressor)->comm, &viewer));
118   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
119   PetscCheckSameComm(regressor, 1, viewer, 2);
120 
121   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
122   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
123   if (isascii) {
124     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)regressor, viewer));
125 
126     PetscCall(PetscViewerASCIIPushTab(viewer));
127     PetscTryTypeMethod(regressor, view, viewer);
128     if (regressor->tao) PetscCall(TaoView(regressor->tao, viewer));
129     PetscCall(PetscViewerASCIIPopTab(viewer));
130   } else if (isstring) {
131     PetscCall(PetscRegressorGetType(regressor, &type));
132     PetscCall(PetscViewerStringSPrintf(viewer, " PetscRegressorType: %-7.7s", type));
133   }
134   PetscFunctionReturn(PETSC_SUCCESS);
135 }
136 
137 /*@
138   PetscRegressorViewFromOptions - View a `PetscRegressor` object based on values in the options database
139 
140   Collective
141 
142   Input Parameters:
143 + A    - the  `PetscRegressor` context
144 . obj  - Optional object that provides the prefix for the options database
145 - name - command line option
146 
147   Level: intermediate
148 
149 .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorView`, `PetscObjectViewFromOptions()`, `PetscRegressorCreate()`
150 @*/
151 PetscErrorCode PetscRegressorViewFromOptions(PetscRegressor A, PetscObject obj, const char name[])
152 {
153   PetscFunctionBegin;
154   PetscValidHeaderSpecific(A, PETSCREGRESSOR_CLASSID, 1);
155   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
156   PetscFunctionReturn(PETSC_SUCCESS);
157 }
158 
159 /*@
160   PetscRegressorSetFromOptions - Sets `PetscRegressor` options from the options database.
161 
162   Collective
163 
164   Input Parameter:
165 . regressor - the `PetscRegressor` context
166 
167   Options Database Keys:
168 . -regressor_type <type> - the particular type of regressor to be used; see `PetscRegressorType` for complete list
169 
170   Level: beginner
171 
172   Note:
173   This routine must be called before `PetscRegressorSetUp()` (or `PetscRegressorFit()`, which calls
174   the former) if the user is to be allowed to set the regressor type.
175 
176 .seealso: `PetscRegressor`, `PetscRegressorCreate()`
177 @*/
178 PetscErrorCode PetscRegressorSetFromOptions(PetscRegressor regressor)
179 {
180   PetscBool          flg;
181   PetscRegressorType default_type = PETSCREGRESSORLINEAR;
182   char               type[256];
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
186   if (((PetscObject)regressor)->type_name) default_type = ((PetscObject)regressor)->type_name;
187   PetscObjectOptionsBegin((PetscObject)regressor);
188   /* Check for type from options */
189   PetscCall(PetscOptionsFList("-regressor_type", "PetscRegressor type", "PetscRegressorSetType", PetscRegressorList, default_type, type, 256, &flg));
190   if (flg) {
191     PetscCall(PetscRegressorSetType(regressor, type));
192   } else if (!((PetscObject)regressor)->type_name) {
193     PetscCall(PetscRegressorSetType(regressor, default_type));
194   }
195   PetscCall(PetscOptionsReal("-regressor_regularizer_weight", "Weight for the regularizer", "PetscRegressorSetRegularizerWeight", regressor->regularizer_weight, &regressor->regularizer_weight, &flg));
196   if (flg) PetscCall(PetscRegressorSetRegularizerWeight(regressor, regressor->regularizer_weight));
197   // The above is a little superfluous, because we have already set regressor->regularizer_weight above, but we also need to set the flag indicating that the user has set the weight!
198   PetscTryTypeMethod(regressor, setfromoptions, PetscOptionsObject);
199   PetscOptionsEnd();
200   PetscFunctionReturn(PETSC_SUCCESS);
201 }
202 
203 /*@
204   PetscRegressorSetUp - Sets up the internal data structures for the later use of a regressor.
205 
206   Collective
207 
208   Input Parameter:
209 . regressor - the `PetscRegressor` context
210 
211   Notes:
212   For basic use of the `PetscRegressor` solvers the user need not to explicitly call
213   `PetscRegressorSetUp()`, since these actions will automatically occur during
214   the call to `PetscRegressorFit()`.  However, if one wishes to control this
215   phase separately, `PetscRegressorSetUp()` should be called after `PetscRegressorCreate()`,
216   `PetscRegressorSetUp()`, and optional routines of the form `PetscRegressorSetXXX()`,
217   but before `PetscRegressorFit()`.
218 
219   Level: advanced
220 
221 .seealso: `PetscRegressorCreate()`, `PetscRegressorFit()`, `PetscRegressorDestroy()`
222 @*/
223 PetscErrorCode PetscRegressorSetUp(PetscRegressor regressor)
224 {
225   PetscFunctionBegin;
226   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
227   if (regressor->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
228   PetscCall(PetscLogEventBegin(PetscRegressor_SetUp, regressor, 0, 0, 0));
229   //TODO is there some mat vec etc that must be set, like TaoSolution?
230   PetscTryTypeMethod(regressor, setup);
231   regressor->setupcalled = PETSC_TRUE;
232   PetscCall(PetscLogEventEnd(PetscRegressor_SetUp, regressor, 0, 0, 0));
233   PetscFunctionReturn(PETSC_SUCCESS);
234 }
235 
236 /* NOTE: I've decided to make this take X and y, like the Scikit-learn Fit routines do.
237  * Am I overlooking some reason that X should be set in a separate function call, a la KSPSetOperators()?. */
238 /*@
239   PetscRegressorFit - Fit, or train, a regressor from a training dataset
240 
241   Collective
242 
243   Input Parameters:
244 + regressor - the `PetscRegressor` context
245 . X         - matrix of training data (of dimension [number of samples] x [number of features])
246 - y         - vector of target values from the training dataset
247 
248   Level: beginner
249 
250 .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorDestroy()`, `PetscRegressorPredict()`
251 @*/
252 PetscErrorCode PetscRegressorFit(PetscRegressor regressor, Mat X, Vec y)
253 {
254   PetscFunctionBegin;
255   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
256   if (X) PetscValidHeaderSpecific(X, MAT_CLASSID, 2);
257   if (y) PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
258 
259   if (X) {
260     PetscCall(PetscObjectReference((PetscObject)X));
261     PetscCall(MatDestroy(&regressor->training));
262     regressor->training = X;
263   }
264   if (y) {
265     PetscCall(PetscObjectReference((PetscObject)y));
266     PetscCall(VecDestroy(&regressor->target));
267     regressor->target = y;
268   }
269   PetscCall(PetscRegressorSetUp(regressor));
270 
271   PetscCall(PetscLogEventBegin(PetscRegressor_Fit, regressor, X, y, 0));
272   PetscUseTypeMethod(regressor, fit);
273   PetscCall(PetscLogEventEnd(PetscRegressor_Fit, regressor, X, y, 0));
274   //TODO print convergence data
275   PetscCall(PetscRegressorViewFromOptions(regressor, NULL, "-regressor_view"));
276   regressor->fitcalled = PETSC_TRUE;
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281   PetscRegressorPredict - Compute predictions (that is, perform inference) using a fitted regression model.
282 
283   Collective
284 
285   Input Parameters:
286 + regressor - the `PetscRegressor` context (for which `PetscRegressorFit()` must have been called)
287 - X         - data matrix of unlabeled observations
288 
289   Output Parameter:
290 . y - vector of predicted labels
291 
292   Level: beginner
293 
294 .seealso: `PetscRegressorFit()`, `PetscRegressorDestroy()`
295 @*/
296 PetscErrorCode PetscRegressorPredict(PetscRegressor regressor, Mat X, Vec y)
297 {
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
300   if (X) PetscValidHeaderSpecific(X, MAT_CLASSID, 2);
301   if (y) PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
302   PetscCheck(regressor->fitcalled == PETSC_TRUE, ((PetscObject)regressor)->comm, PETSC_ERR_ARG_WRONGSTATE, "PetscRegressorFit() must be called before PetscRegressorPredict()");
303   PetscCall(PetscLogEventBegin(PetscRegressor_Predict, regressor, X, y, 0));
304   PetscTryTypeMethod(regressor, predict, X, y);
305   PetscCall(PetscLogEventEnd(PetscRegressor_Predict, regressor, X, y, 0));
306   PetscFunctionReturn(PETSC_SUCCESS);
307 }
308 
309 /*@
310   PetscRegressorReset - Resets a `PetscRegressor` context by removing any allocated `Vec` and `Mat`. Any options set in the object remain.
311 
312   Collective
313 
314   Input Parameter:
315 . regressor - context obtained from `PetscRegressorCreate()`
316 
317   Level: intermediate
318 
319 .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressorDestroy()`
320 @*/
321 PetscErrorCode PetscRegressorReset(PetscRegressor regressor)
322 {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
325   if (regressor->ops->reset) PetscTryTypeMethod(regressor, reset);
326   PetscCall(MatDestroy(&regressor->training));
327   PetscCall(VecDestroy(&regressor->target));
328   PetscCall(TaoDestroy(&regressor->tao));
329   regressor->setupcalled = PETSC_FALSE;
330   regressor->fitcalled   = PETSC_FALSE;
331   PetscFunctionReturn(PETSC_SUCCESS);
332 }
333 
334 /*@C
335   PetscRegressorDestroy - Destroys the regressor context that was created with `PetscRegressorCreate()`.
336 
337   Collective
338 
339   Input Parameter:
340 . regressor - the `PetscRegressor` context
341 
342   Level: beginner
343 
344 .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorReset()`, `PetscRegressor`
345 @*/
346 PetscErrorCode PetscRegressorDestroy(PetscRegressor *regressor)
347 {
348   PetscFunctionBegin;
349   if (!*regressor) PetscFunctionReturn(PETSC_SUCCESS);
350   PetscValidHeaderSpecific((*regressor), PETSCREGRESSOR_CLASSID, 1);
351   if (--((PetscObject)(*regressor))->refct > 0) {
352     *regressor = NULL;
353     PetscFunctionReturn(PETSC_SUCCESS);
354   }
355 
356   PetscCall(PetscRegressorReset(*regressor));
357   PetscTryTypeMethod(*regressor, destroy);
358 
359   PetscCall(PetscHeaderDestroy(regressor));
360   PetscFunctionReturn(PETSC_SUCCESS);
361 }
362 
363 /*@C
364   PetscRegressorSetType - Sets the type for the regressor.
365 
366   Collective
367 
368   Input Parameters:
369 + regressor - the `PetscRegressor` context
370 - type      - a known regression method
371 
372   Options Database Key:
373 . -regressor_type <type> - Sets the type of regressor; use -help for a list of available types
374 
375   Level: intermediate
376 
377   Notes:
378   See "include/petscregressor.h" for available methods (for instance)
379 .    `PETSCREGRESSORLINEAR` - Regression model that is linear in its coefficients; supports ordinary least squares as well as regularized variants
380 
381   Normally, it is best to use the `PetscRegressorSetFromOptions()` command and then
382   set the `PetscRegressor` type from the options database rather than by using
383   this routine, as this provides maximum flexibility.
384   The `PetscRegressorSetType()` routine is provided for those situations where it
385   is necessary to set the nonlinear solver independently of the command
386   line or options database.
387 
388 .seealso: `PetscRegressorType`
389 @*/
390 PetscErrorCode PetscRegressorSetType(PetscRegressor regressor, PetscRegressorType type)
391 {
392   PetscErrorCode (*r)(PetscRegressor);
393   PetscBool match;
394 
395   PetscFunctionBegin;
396   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
397   PetscAssertPointer(type, 2);
398 
399   PetscCall(PetscObjectTypeCompare((PetscObject)regressor, type, &match));
400   if (match) PetscFunctionReturn(PETSC_SUCCESS);
401 
402   PetscCall(PetscFunctionListFind(PetscRegressorList, type, &r));
403   PetscCheck(r, PetscObjectComm((PetscObject)regressor), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PetscRegressor type %s", type);
404 
405   /* Destroy the existing solver information */
406   PetscTryTypeMethod(regressor, destroy);
407   PetscCall(TaoDestroy(&regressor->tao));
408   regressor->ops->setup          = NULL;
409   regressor->ops->setfromoptions = NULL;
410   regressor->ops->settraining    = NULL;
411   regressor->ops->fit            = NULL;
412   regressor->ops->predict        = NULL;
413   regressor->ops->destroy        = NULL;
414   regressor->ops->reset          = NULL;
415   regressor->ops->view           = NULL;
416 
417   /* Call the PetscRegressorCreate_XXX routine for this particular regressor */
418   regressor->setupcalled = PETSC_FALSE;
419   PetscCall((*r)(regressor));
420   PetscCall(PetscObjectChangeTypeName((PetscObject)regressor, type));
421   PetscFunctionReturn(PETSC_SUCCESS);
422 }
423 
424 /*@
425   PetscRegressorGetType - Gets the current `PetscRegressorType` being used in the `PetscRegressor` object
426 
427   Not Collective
428 
429   Input Parameter:
430 . regressor - the `PetscRegressor` solver context
431 
432   Output Parameter:
433 . type - the `PetscRegressorType`
434 
435   Level: intermediate
436 
437 .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorType`, `PetscRegressorSetType()`
438 @*/
439 PetscErrorCode PetscRegressorGetType(PetscRegressor regressor, PetscRegressorType *type)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
443   PetscAssertPointer(type, 2);
444   *type = ((PetscObject)regressor)->type_name;
445   PetscFunctionReturn(PETSC_SUCCESS);
446 }
447 
448 /*@
449   PetscRegressorSetRegularizerWeight - Sets the weight to be used for the regularizer for a `PetscRegressor` context
450 
451   Logically Collective
452 
453   Input Parameters:
454 + regressor - the `PetscRegressor` context
455 - weight    - the regularizer weight
456 
457   Options Database Key:
458 . regressor_regularizer_weight <weight> - sets the regularizer's weight
459 
460   Level: beginner
461 
462 .seealso: `PetscRegressorSetType`
463 @*/
464 PetscErrorCode PetscRegressorSetRegularizerWeight(PetscRegressor regressor, PetscReal weight)
465 {
466   PetscFunctionBegin;
467   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
468   PetscValidLogicalCollectiveReal(regressor, weight, 2);
469   regressor->regularizer_weight = weight;
470   PetscFunctionReturn(PETSC_SUCCESS);
471 }
472 
473 /*@
474   PetscRegressorGetTao - Returns the `Tao` context for a `PetscRegressor` object.
475 
476   Not Collective, but if the `PetscRegressor` is parallel, then the `Tao` object is parallel
477 
478   Input Parameter:
479 . regressor - the regressor context
480 
481   Output Parameter:
482 . tao - the `Tao` context
483 
484   Level: beginner
485 
486   Notes:
487   The `Tao` object will be created if it does not yet exist.
488 
489   The user can directly manipulate the `Tao` context to set various
490   options, etc.  Likewise, the user can then extract and manipulate the
491   child contexts such as `KSP` or `TaoLineSearch`as well.
492 
493   Depending on the type of the regressor and the options that are set, the regressor may use not use a `Tao` object.
494 
495 .seealso: `PetscRegressorLinearGetKSP()`
496 @*/
497 PetscErrorCode PetscRegressorGetTao(PetscRegressor regressor, Tao *tao)
498 {
499   PetscFunctionBegin;
500   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
501   PetscAssertPointer(tao, 2);
502   // Analogous to how SNESGetKSP() operates, this routine should create the Tao if it doesn't exist.
503   if (!regressor->tao) {
504     PetscCall(TaoCreate(PetscObjectComm((PetscObject)regressor), &regressor->tao));
505     PetscCall(PetscObjectIncrementTabLevel((PetscObject)regressor->tao, (PetscObject)regressor, 1));
506     PetscCall(PetscObjectSetOptions((PetscObject)regressor->tao, ((PetscObject)regressor)->options));
507   }
508   *tao = regressor->tao;
509   PetscFunctionReturn(PETSC_SUCCESS);
510 }
511 
512 /*@
513   PetscRegressorSetOptionsPrefix - Sets the prefix used for searching for all
514   PetscRegressor options in the database.
515 
516   Logically Collective
517 
518   Input Parameters:
519 + regressor - the `PetscRegressor` context
520 - p         - the prefix string to prepend to all PetscRegressor option requests
521 
522   Level: advanced
523 
524   Notes:
525   A hyphen (-) must NOT be given at the beginning of the prefix name.
526   The first character of all runtime options is AUTOMATICALLY the hyphen.
527 
528   For example, to distinguish between the runtime options for two
529   different PetscRegressor solvers, one could call
530 .vb
531       PetscRegressorSetOptionsPrefix(regressor1,"sys1_")
532       PetscRegressorSetOptionsPrefix(regressor2,"sys2_")
533 .ve
534 
535   This would enable use of different options for each system, such as
536 .vb
537       -sys1_regressor_method linear -sys1_regressor_regularizer_weight 1.2
538       -sys2_regressor_method linear -sys2_regressor_regularizer_weight 1.1
539 .ve
540 
541 .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorAppendOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
542 @*/
543 PetscErrorCode PetscRegressorSetOptionsPrefix(PetscRegressor regressor, const char p[])
544 {
545   PetscFunctionBegin;
546   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
547   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)regressor, p));
548   PetscFunctionReturn(PETSC_SUCCESS);
549 }
550 
551 /*@
552   PetscRegressorAppendOptionsPrefix - Appends to the prefix used for searching for all PetscRegressor options in the database.
553 
554   Logically Collective
555 
556   Input Parameters:
557 + regressor - the `PetscRegressor` solver context
558 - p         - the prefix string to prepend to all `PetscRegressor` option requests
559 
560   Level: advanced
561 
562   Note:
563   A hyphen (-) must NOT be given at the beginning of the prefix name.
564   The first character of all runtime options is automatically the hyphen.
565 
566 .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
567 @*/
568 PetscErrorCode PetscRegressorAppendOptionsPrefix(PetscRegressor regressor, const char p[])
569 {
570   PetscFunctionBegin;
571   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
572   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)regressor, p));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577   PetscRegressorGetOptionsPrefix - Gets the prefix used for searching for all
578   PetscRegressor options in the database
579 
580   Not Collective
581 
582   Input Parameter:
583 . regressor - the `PetscRegressor` context
584 
585   Output Parameter:
586 . p - pointer to the prefix string used is returned
587 
588   Fortran Notes:
589   Pass in a string 'prefix' of sufficient length to hold the prefix.
590 
591   Level: advanced
592 
593 .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorAppendOptionsPrefix()`
594 @*/
595 PetscErrorCode PetscRegressorGetOptionsPrefix(PetscRegressor regressor, const char *p[])
596 {
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
599   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)regressor, p));
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602