Actual source code: regressor.c
1: #include <petsc/private/regressorimpl.h>
3: PetscBool PetscRegressorRegisterAllCalled = PETSC_FALSE;
4: PetscFunctionList PetscRegressorList = NULL;
6: PetscClassId PETSCREGRESSOR_CLASSID;
8: /* Logging support */
9: PetscLogEvent PetscRegressor_SetUp, PetscRegressor_Fit, PetscRegressor_Predict;
11: /*@C
12: PetscRegressorRegister - Adds a method to the `PetscRegressor` package.
14: Not collective
16: Input Parameters:
17: + sname - name of a new user-defined regressor
18: - function - routine to create method context
20: Notes:
21: `PetscRegressorRegister()` may be called multiple times to add several user-defined regressors.
23: Example Usage:
24: .vb
25: PetscRegressorRegister("my_regressor",MyRegressorCreate);
26: .ve
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
37: Level: advanced
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: }
49: /*@
50: PetscRegressorCreate - Creates a `PetscRegressor` object.
52: Collective
54: Input Parameter:
55: . comm - the MPI communicator that will share the `PetscRegressor` object
57: Output Parameter:
58: . newregressor - the new `PetscRegressor` object
60: Level: beginner
62: .seealso: `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressor`
63: @*/
64: PetscErrorCode PetscRegressorCreate(MPI_Comm comm, PetscRegressor *newregressor)
65: {
66: PetscRegressor regressor;
68: PetscFunctionBegin;
69: PetscAssertPointer(newregressor, 2);
70: *newregressor = NULL;
71: PetscCall(PetscRegressorInitializePackage());
73: PetscCall(PetscHeaderCreate(regressor, PETSCREGRESSOR_CLASSID, "PetscRegressor", "Regressor", "PetscRegressor", comm, PetscRegressorDestroy, PetscRegressorView));
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
82: *newregressor = regressor;
83: PetscFunctionReturn(PETSC_SUCCESS);
84: }
86: /*@
87: PetscRegressorView - Prints information about the `PetscRegressor` object
89: Collective
91: Input Parameters:
92: + regressor - the `PetscRegressor` context
93: - viewer - a `PetscViewer` context
95: Options Database Key:
96: . -regressor_view - Calls `PetscRegressorView()` at the end of `PetscRegressorFit()`
98: Level: beginner
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.
108: .seealso: [](ch_regressor), `PetscRegressor`, `PetscViewerASCIIOpen()`
109: @*/
110: PetscErrorCode PetscRegressorView(PetscRegressor regressor, PetscViewer viewer)
111: {
112: PetscBool isascii, isstring;
113: PetscRegressorType type;
115: PetscFunctionBegin;
117: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)regressor)->comm, &viewer));
119: PetscCheckSameComm(regressor, 1, viewer, 2);
121: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
122: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
123: if (isascii) {
124: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)regressor, viewer));
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: }
137: /*@
138: PetscRegressorViewFromOptions - View a `PetscRegressor` object based on values in the options database
140: Collective
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
147: Options Database Key:
148: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments
150: Level: intermediate
152: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorView`, `PetscObjectViewFromOptions()`, `PetscRegressorCreate()`
153: @*/
154: PetscErrorCode PetscRegressorViewFromOptions(PetscRegressor A, PetscObject obj, const char name[])
155: {
156: PetscFunctionBegin;
158: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
159: PetscFunctionReturn(PETSC_SUCCESS);
160: }
162: /*@
163: PetscRegressorSetFromOptions - Sets `PetscRegressor` options from the options database.
165: Collective
167: Input Parameter:
168: . regressor - the `PetscRegressor` context
170: Options Database Keys:
171: . -regressor_type type - the particular type of regressor to be used; see `PetscRegressorType` for complete list
173: Level: beginner
175: Note:
176: This routine must be called before `PetscRegressorSetUp()` (or `PetscRegressorFit()`, which calls
177: the former) if the user is to be allowed to set the regressor type.
179: .seealso: `PetscRegressor`, `PetscRegressorCreate()`
180: @*/
181: PetscErrorCode PetscRegressorSetFromOptions(PetscRegressor regressor)
182: {
183: PetscBool flg;
184: PetscRegressorType default_type = PETSCREGRESSORLINEAR;
185: char type[256];
187: PetscFunctionBegin;
189: if (((PetscObject)regressor)->type_name) default_type = ((PetscObject)regressor)->type_name;
190: PetscObjectOptionsBegin((PetscObject)regressor);
191: /* Check for type from options */
192: PetscCall(PetscOptionsFList("-regressor_type", "PetscRegressor type", "PetscRegressorSetType", PetscRegressorList, default_type, type, 256, &flg));
193: if (flg) {
194: PetscCall(PetscRegressorSetType(regressor, type));
195: } else if (!((PetscObject)regressor)->type_name) {
196: PetscCall(PetscRegressorSetType(regressor, default_type));
197: }
198: PetscCall(PetscOptionsReal("-regressor_regularizer_weight", "Weight for the regularizer", "PetscRegressorSetRegularizerWeight", regressor->regularizer_weight, ®ressor->regularizer_weight, &flg));
199: if (flg) PetscCall(PetscRegressorSetRegularizerWeight(regressor, regressor->regularizer_weight));
200: // 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!
201: PetscTryTypeMethod(regressor, setfromoptions, PetscOptionsObject);
202: PetscOptionsEnd();
203: PetscFunctionReturn(PETSC_SUCCESS);
204: }
206: /*@
207: PetscRegressorSetUp - Sets up the internal data structures for the later use of a regressor.
209: Collective
211: Input Parameter:
212: . regressor - the `PetscRegressor` context
214: Notes:
215: For basic use of the `PetscRegressor` solvers the user need not to explicitly call
216: `PetscRegressorSetUp()`, since these actions will automatically occur during
217: the call to `PetscRegressorFit()`. However, if one wishes to control this
218: phase separately, `PetscRegressorSetUp()` should be called after `PetscRegressorCreate()`,
219: `PetscRegressorSetUp()`, and optional routines of the form `PetscRegressorSetXXX()`,
220: but before `PetscRegressorFit()`.
222: Level: advanced
224: .seealso: `PetscRegressorCreate()`, `PetscRegressorFit()`, `PetscRegressorDestroy()`
225: @*/
226: PetscErrorCode PetscRegressorSetUp(PetscRegressor regressor)
227: {
228: PetscFunctionBegin;
230: if (regressor->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
231: PetscCall(PetscLogEventBegin(PetscRegressor_SetUp, regressor, 0, 0, 0));
232: //TODO is there some mat vec etc that must be set, like TaoSolution?
233: PetscTryTypeMethod(regressor, setup);
234: regressor->setupcalled = PETSC_TRUE;
235: PetscCall(PetscLogEventEnd(PetscRegressor_SetUp, regressor, 0, 0, 0));
236: PetscFunctionReturn(PETSC_SUCCESS);
237: }
239: /* NOTE: I've decided to make this take X and y, like the Scikit-learn Fit routines do.
240: * Am I overlooking some reason that X should be set in a separate function call, a la KSPSetOperators()?. */
241: /*@
242: PetscRegressorFit - Fit, or train, a regressor from a training dataset
244: Collective
246: Input Parameters:
247: + regressor - the `PetscRegressor` context
248: . X - matrix of training data (of dimension [number of samples] x [number of features])
249: - y - vector of target values from the training dataset
251: Level: beginner
253: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorDestroy()`, `PetscRegressorPredict()`
254: @*/
255: PetscErrorCode PetscRegressorFit(PetscRegressor regressor, Mat X, Vec y)
256: {
257: PetscFunctionBegin;
262: if (X) {
263: PetscCall(PetscObjectReference((PetscObject)X));
264: PetscCall(MatDestroy(®ressor->training));
265: regressor->training = X;
266: }
267: if (y) {
268: PetscCall(PetscObjectReference((PetscObject)y));
269: PetscCall(VecDestroy(®ressor->target));
270: regressor->target = y;
271: }
272: PetscCall(PetscRegressorSetUp(regressor));
274: PetscCall(PetscLogEventBegin(PetscRegressor_Fit, regressor, X, y, 0));
275: PetscUseTypeMethod(regressor, fit);
276: PetscCall(PetscLogEventEnd(PetscRegressor_Fit, regressor, X, y, 0));
277: //TODO print convergence data
278: PetscCall(PetscRegressorViewFromOptions(regressor, NULL, "-regressor_view"));
279: regressor->fitcalled = PETSC_TRUE;
280: PetscFunctionReturn(PETSC_SUCCESS);
281: }
283: /*@
284: PetscRegressorPredict - Compute predictions (that is, perform inference) using a fitted regression model.
286: Collective
288: Input Parameters:
289: + regressor - the `PetscRegressor` context (for which `PetscRegressorFit()` must have been called)
290: - X - data matrix of unlabeled observations
292: Output Parameter:
293: . y - vector of predicted labels
295: Level: beginner
297: .seealso: `PetscRegressorFit()`, `PetscRegressorDestroy()`
298: @*/
299: PetscErrorCode PetscRegressorPredict(PetscRegressor regressor, Mat X, Vec y)
300: {
301: PetscFunctionBegin;
305: PetscCheck(regressor->fitcalled == PETSC_TRUE, ((PetscObject)regressor)->comm, PETSC_ERR_ARG_WRONGSTATE, "PetscRegressorFit() must be called before PetscRegressorPredict()");
306: PetscCall(PetscLogEventBegin(PetscRegressor_Predict, regressor, X, y, 0));
307: PetscTryTypeMethod(regressor, predict, X, y);
308: PetscCall(PetscLogEventEnd(PetscRegressor_Predict, regressor, X, y, 0));
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /*@
313: PetscRegressorReset - Resets a `PetscRegressor` context by removing any allocated `Vec` and `Mat`. Any options set in the object remain.
315: Collective
317: Input Parameter:
318: . regressor - context obtained from `PetscRegressorCreate()`
320: Level: intermediate
322: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressorDestroy()`
323: @*/
324: PetscErrorCode PetscRegressorReset(PetscRegressor regressor)
325: {
326: PetscFunctionBegin;
328: if (regressor->ops->reset) PetscTryTypeMethod(regressor, reset);
329: PetscCall(MatDestroy(®ressor->training));
330: PetscCall(VecDestroy(®ressor->target));
331: PetscCall(TaoDestroy(®ressor->tao));
332: regressor->setupcalled = PETSC_FALSE;
333: regressor->fitcalled = PETSC_FALSE;
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: /*@C
338: PetscRegressorDestroy - Destroys the regressor context that was created with `PetscRegressorCreate()`.
340: Collective
342: Input Parameter:
343: . regressor - the `PetscRegressor` context
345: Level: beginner
347: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorReset()`, `PetscRegressor`
348: @*/
349: PetscErrorCode PetscRegressorDestroy(PetscRegressor *regressor)
350: {
351: PetscFunctionBegin;
352: if (!*regressor) PetscFunctionReturn(PETSC_SUCCESS);
354: if (--((PetscObject)*regressor)->refct > 0) {
355: *regressor = NULL;
356: PetscFunctionReturn(PETSC_SUCCESS);
357: }
359: PetscCall(PetscRegressorReset(*regressor));
360: PetscTryTypeMethod(*regressor, destroy);
362: PetscCall(PetscHeaderDestroy(regressor));
363: PetscFunctionReturn(PETSC_SUCCESS);
364: }
366: /*@C
367: PetscRegressorSetType - Sets the type for the regressor.
369: Collective
371: Input Parameters:
372: + regressor - the `PetscRegressor` context
373: - type - a known regression method
375: Options Database Key:
376: . -regressor_type type - Sets the type of regressor; use -help for a list of available types
378: Level: intermediate
380: Notes:
381: See "include/petscregressor.h" for available methods (for instance)
382: . `PETSCREGRESSORLINEAR` - Regression model that is linear in its coefficients; supports ordinary least squares as well as regularized variants
384: Normally, it is best to use the `PetscRegressorSetFromOptions()` command and then
385: set the `PetscRegressor` type from the options database rather than by using
386: this routine, as this provides maximum flexibility.
387: The `PetscRegressorSetType()` routine is provided for those situations where it
388: is necessary to set the nonlinear solver independently of the command
389: line or options database.
391: .seealso: `PetscRegressorType`
392: @*/
393: PetscErrorCode PetscRegressorSetType(PetscRegressor regressor, PetscRegressorType type)
394: {
395: PetscErrorCode (*r)(PetscRegressor);
396: PetscBool match;
398: PetscFunctionBegin;
400: PetscAssertPointer(type, 2);
402: PetscCall(PetscObjectTypeCompare((PetscObject)regressor, type, &match));
403: if (match) PetscFunctionReturn(PETSC_SUCCESS);
405: PetscCall(PetscFunctionListFind(PetscRegressorList, type, &r));
406: PetscCheck(r, PetscObjectComm((PetscObject)regressor), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PetscRegressor type %s", type);
408: /* Destroy the existing solver information */
409: PetscTryTypeMethod(regressor, destroy);
410: PetscCall(TaoDestroy(®ressor->tao));
411: regressor->ops->setup = NULL;
412: regressor->ops->setfromoptions = NULL;
413: regressor->ops->settraining = NULL;
414: regressor->ops->fit = NULL;
415: regressor->ops->predict = NULL;
416: regressor->ops->destroy = NULL;
417: regressor->ops->reset = NULL;
418: regressor->ops->view = NULL;
420: /* Call the PetscRegressorCreate_XXX routine for this particular regressor */
421: regressor->setupcalled = PETSC_FALSE;
422: PetscCall((*r)(regressor));
423: PetscCall(PetscObjectChangeTypeName((PetscObject)regressor, type));
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /*@
428: PetscRegressorGetType - Gets the current `PetscRegressorType` being used in the `PetscRegressor` object
430: Not Collective
432: Input Parameter:
433: . regressor - the `PetscRegressor` solver context
435: Output Parameter:
436: . type - the `PetscRegressorType`
438: Level: intermediate
440: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorType`, `PetscRegressorSetType()`
441: @*/
442: PetscErrorCode PetscRegressorGetType(PetscRegressor regressor, PetscRegressorType *type)
443: {
444: PetscFunctionBegin;
446: PetscAssertPointer(type, 2);
447: *type = ((PetscObject)regressor)->type_name;
448: PetscFunctionReturn(PETSC_SUCCESS);
449: }
451: /*@
452: PetscRegressorSetRegularizerWeight - Sets the weight to be used for the regularizer for a `PetscRegressor` context
454: Logically Collective
456: Input Parameters:
457: + regressor - the `PetscRegressor` context
458: - weight - the regularizer weight
460: Options Database Key:
461: . regressor_regularizer_weight weight - sets the regularizer's weight
463: Level: beginner
465: .seealso: `PetscRegressorSetType`
466: @*/
467: PetscErrorCode PetscRegressorSetRegularizerWeight(PetscRegressor regressor, PetscReal weight)
468: {
469: PetscFunctionBegin;
472: regressor->regularizer_weight = weight;
473: PetscFunctionReturn(PETSC_SUCCESS);
474: }
476: /*@
477: PetscRegressorGetTao - Returns the `Tao` context for a `PetscRegressor` object.
479: Not Collective, but if the `PetscRegressor` is parallel, then the `Tao` object is parallel
481: Input Parameter:
482: . regressor - the regressor context
484: Output Parameter:
485: . tao - the `Tao` context
487: Level: beginner
489: Notes:
490: The `Tao` object will be created if it does not yet exist.
492: The user can directly manipulate the `Tao` context to set various
493: options, etc. Likewise, the user can then extract and manipulate the
494: child contexts such as `KSP` or `TaoLineSearch`as well.
496: Depending on the type of the regressor and the options that are set, the regressor may use not use a `Tao` object.
498: .seealso: `PetscRegressorLinearGetKSP()`
499: @*/
500: PetscErrorCode PetscRegressorGetTao(PetscRegressor regressor, Tao *tao)
501: {
502: PetscFunctionBegin;
504: PetscAssertPointer(tao, 2);
505: // Analogous to how SNESGetKSP() operates, this routine should create the Tao if it doesn't exist.
506: if (!regressor->tao) {
507: PetscCall(TaoCreate(PetscObjectComm((PetscObject)regressor), ®ressor->tao));
508: PetscCall(PetscObjectIncrementTabLevel((PetscObject)regressor->tao, (PetscObject)regressor, 1));
509: PetscCall(PetscObjectSetOptions((PetscObject)regressor->tao, ((PetscObject)regressor)->options));
510: }
511: *tao = regressor->tao;
512: PetscFunctionReturn(PETSC_SUCCESS);
513: }
515: /*@
516: PetscRegressorSetOptionsPrefix - Sets the prefix used for searching for all
517: PetscRegressor options in the database.
519: Logically Collective
521: Input Parameters:
522: + regressor - the `PetscRegressor` context
523: - p - the prefix string to prepend to all PetscRegressor option requests
525: Level: advanced
527: Notes:
528: A hyphen (-) must NOT be given at the beginning of the prefix name.
529: The first character of all runtime options is AUTOMATICALLY the hyphen.
531: For example, to distinguish between the runtime options for two
532: different PetscRegressor solvers, one could call
533: .vb
534: PetscRegressorSetOptionsPrefix(regressor1,"sys1_")
535: PetscRegressorSetOptionsPrefix(regressor2,"sys2_")
536: .ve
538: This would enable use of different options for each system, such as
539: .vb
540: -sys1_regressor_method linear -sys1_regressor_regularizer_weight 1.2
541: -sys2_regressor_method linear -sys2_regressor_regularizer_weight 1.1
542: .ve
544: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorAppendOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
545: @*/
546: PetscErrorCode PetscRegressorSetOptionsPrefix(PetscRegressor regressor, const char p[])
547: {
548: PetscFunctionBegin;
550: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)regressor, p));
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@
555: PetscRegressorAppendOptionsPrefix - Appends to the prefix used for searching for all PetscRegressor options in the database.
557: Logically Collective
559: Input Parameters:
560: + regressor - the `PetscRegressor` solver context
561: - p - the prefix string to prepend to all `PetscRegressor` option requests
563: Level: advanced
565: Note:
566: A hyphen (-) must NOT be given at the beginning of the prefix name.
567: The first character of all runtime options is automatically the hyphen.
569: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
570: @*/
571: PetscErrorCode PetscRegressorAppendOptionsPrefix(PetscRegressor regressor, const char p[])
572: {
573: PetscFunctionBegin;
575: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)regressor, p));
576: PetscFunctionReturn(PETSC_SUCCESS);
577: }
579: /*@
580: PetscRegressorGetOptionsPrefix - Gets the prefix used for searching for all
581: PetscRegressor options in the database
583: Not Collective
585: Input Parameter:
586: . regressor - the `PetscRegressor` context
588: Output Parameter:
589: . p - pointer to the prefix string used is returned
591: Fortran Notes:
592: Pass in a string 'prefix' of sufficient length to hold the prefix.
594: Level: advanced
596: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorAppendOptionsPrefix()`
597: @*/
598: PetscErrorCode PetscRegressorGetOptionsPrefix(PetscRegressor regressor, const char *p[])
599: {
600: PetscFunctionBegin;
602: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)regressor, p));
603: PetscFunctionReturn(PETSC_SUCCESS);
604: }