xref: /petsc/src/ml/regressor/impls/linear/linear.c (revision 789736e13dc7600624280f2f1d112db076e5d354)
134b254c5SRichard Tran Mills #include <../src/ml/regressor/impls/linear/linearimpl.h> /*I "petscregressor.h" I*/
234b254c5SRichard Tran Mills 
334b254c5SRichard Tran Mills const char *const PetscRegressorLinearTypes[] = {"ols", "lasso", "ridge", "RegressorLinearType", "REGRESSOR_LINEAR_", NULL};
434b254c5SRichard Tran Mills 
534b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearSetFitIntercept_Linear(PetscRegressor regressor, PetscBool flg)
634b254c5SRichard Tran Mills {
734b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
834b254c5SRichard Tran Mills 
934b254c5SRichard Tran Mills   PetscFunctionBegin;
1034b254c5SRichard Tran Mills   linear->fit_intercept = flg;
1134b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
1234b254c5SRichard Tran Mills }
1334b254c5SRichard Tran Mills 
1434b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearSetType_Linear(PetscRegressor regressor, PetscRegressorLinearType type)
1534b254c5SRichard Tran Mills {
1634b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
1734b254c5SRichard Tran Mills 
1834b254c5SRichard Tran Mills   PetscFunctionBegin;
1934b254c5SRichard Tran Mills   linear->type = type;
2034b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
2134b254c5SRichard Tran Mills }
2234b254c5SRichard Tran Mills 
2334b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearGetType_Linear(PetscRegressor regressor, PetscRegressorLinearType *type)
2434b254c5SRichard Tran Mills {
2534b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
2634b254c5SRichard Tran Mills 
2734b254c5SRichard Tran Mills   PetscFunctionBegin;
2834b254c5SRichard Tran Mills   *type = linear->type;
2934b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
3034b254c5SRichard Tran Mills }
3134b254c5SRichard Tran Mills 
3234b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearGetIntercept_Linear(PetscRegressor regressor, PetscScalar *intercept)
3334b254c5SRichard Tran Mills {
3434b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
3534b254c5SRichard Tran Mills 
3634b254c5SRichard Tran Mills   PetscFunctionBegin;
3734b254c5SRichard Tran Mills   *intercept = linear->intercept;
3834b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
3934b254c5SRichard Tran Mills }
4034b254c5SRichard Tran Mills 
4134b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearGetCoefficients_Linear(PetscRegressor regressor, Vec *coefficients)
4234b254c5SRichard Tran Mills {
4334b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
4434b254c5SRichard Tran Mills 
4534b254c5SRichard Tran Mills   PetscFunctionBegin;
4634b254c5SRichard Tran Mills   *coefficients = linear->coefficients;
4734b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
4834b254c5SRichard Tran Mills }
4934b254c5SRichard Tran Mills 
5034b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearGetKSP_Linear(PetscRegressor regressor, KSP *ksp)
5134b254c5SRichard Tran Mills {
5234b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
5334b254c5SRichard Tran Mills 
5434b254c5SRichard Tran Mills   PetscFunctionBegin;
5534b254c5SRichard Tran Mills   if (!linear->ksp) {
5634b254c5SRichard Tran Mills     PetscCall(KSPCreate(PetscObjectComm((PetscObject)regressor), &linear->ksp));
5734b254c5SRichard Tran Mills     PetscCall(PetscObjectIncrementTabLevel((PetscObject)linear->ksp, (PetscObject)regressor, 1));
5834b254c5SRichard Tran Mills     PetscCall(PetscObjectSetOptions((PetscObject)linear->ksp, ((PetscObject)regressor)->options));
5934b254c5SRichard Tran Mills   }
6034b254c5SRichard Tran Mills   *ksp = linear->ksp;
6134b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
6234b254c5SRichard Tran Mills }
6334b254c5SRichard Tran Mills 
6434b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorLinearSetUseKSP_Linear(PetscRegressor regressor, PetscBool flg)
6534b254c5SRichard Tran Mills {
6634b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
6734b254c5SRichard Tran Mills 
6834b254c5SRichard Tran Mills   PetscFunctionBegin;
6934b254c5SRichard Tran Mills   linear->use_ksp = flg;
7034b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
7134b254c5SRichard Tran Mills }
7234b254c5SRichard Tran Mills 
7334b254c5SRichard Tran Mills static PetscErrorCode EvaluateResidual(Tao tao, Vec x, Vec f, void *ptr)
7434b254c5SRichard Tran Mills {
7534b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)ptr;
7634b254c5SRichard Tran Mills 
7734b254c5SRichard Tran Mills   PetscFunctionBegin;
7834b254c5SRichard Tran Mills   /* Evaluate f = A * x - b */
7934b254c5SRichard Tran Mills   PetscCall(MatMult(linear->X, x, f));
8034b254c5SRichard Tran Mills   PetscCall(VecAXPY(f, -1.0, linear->rhs));
8134b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
8234b254c5SRichard Tran Mills }
8334b254c5SRichard Tran Mills 
8434b254c5SRichard Tran Mills static PetscErrorCode EvaluateJacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *ptr)
8534b254c5SRichard Tran Mills {
86540f39e1SHansol Suh   /* The TAOBRGN API expects us to pass an EvaluateJacobian() routine to it, but in this case it is a dummy function.
87540f39e1SHansol Suh      Denoting our data matrix as X, for linear least squares J[m][n] = df[m]/dx[n] = X[m][n]. */
8834b254c5SRichard Tran Mills   PetscFunctionBegin;
8934b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
9034b254c5SRichard Tran Mills }
9134b254c5SRichard Tran Mills 
9234b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorSetUp_Linear(PetscRegressor regressor)
9334b254c5SRichard Tran Mills {
9434b254c5SRichard Tran Mills   PetscInt               M, N;
9534b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
9634b254c5SRichard Tran Mills   KSP                    ksp;
9734b254c5SRichard Tran Mills   Tao                    tao;
9834b254c5SRichard Tran Mills 
9934b254c5SRichard Tran Mills   PetscFunctionBegin;
10034b254c5SRichard Tran Mills   PetscCall(MatGetSize(regressor->training, &M, &N));
10134b254c5SRichard Tran Mills 
10234b254c5SRichard Tran Mills   if (linear->fit_intercept) {
10334b254c5SRichard Tran Mills     /* If we are fitting the intercept, we need to make A a composite matrix using MATCENTERING to preserve sparsity.
10434b254c5SRichard Tran Mills      * Though there might be some cases we don't want to do this for, depending on what kind of matrix is passed in. (Probably bad idea for dense?)
10534b254c5SRichard Tran Mills      * We will also need to ensure that the right-hand side passed to the KSP is also mean-centered, since we
10634b254c5SRichard Tran Mills      * intend to compute the intercept separately from regression coefficients (that is, we will not be adding a
10734b254c5SRichard Tran Mills      * column of all 1s to our design matrix). */
10834b254c5SRichard Tran Mills     PetscCall(MatCreateCentering(PetscObjectComm((PetscObject)regressor), PETSC_DECIDE, M, &linear->C));
10934b254c5SRichard Tran Mills     PetscCall(MatCreate(PetscObjectComm((PetscObject)regressor), &linear->X));
11034b254c5SRichard Tran Mills     PetscCall(MatSetSizes(linear->X, PETSC_DECIDE, PETSC_DECIDE, M, N));
11134b254c5SRichard Tran Mills     PetscCall(MatSetType(linear->X, MATCOMPOSITE));
11234b254c5SRichard Tran Mills     PetscCall(MatCompositeSetType(linear->X, MAT_COMPOSITE_MULTIPLICATIVE));
11334b254c5SRichard Tran Mills     PetscCall(MatCompositeAddMat(linear->X, regressor->training));
11434b254c5SRichard Tran Mills     PetscCall(MatCompositeAddMat(linear->X, linear->C));
11534b254c5SRichard Tran Mills     PetscCall(VecDuplicate(regressor->target, &linear->rhs));
11634b254c5SRichard Tran Mills     PetscCall(MatMult(linear->C, regressor->target, linear->rhs));
11734b254c5SRichard Tran Mills   } else {
11834b254c5SRichard Tran Mills     // When not fitting intercept, we assume that the input data are already centered.
11934b254c5SRichard Tran Mills     linear->X   = regressor->training;
12034b254c5SRichard Tran Mills     linear->rhs = regressor->target;
12134b254c5SRichard Tran Mills 
12234b254c5SRichard Tran Mills     PetscCall(PetscObjectReference((PetscObject)linear->X));
12334b254c5SRichard Tran Mills     PetscCall(PetscObjectReference((PetscObject)linear->rhs));
12434b254c5SRichard Tran Mills   }
12534b254c5SRichard Tran Mills 
12634b254c5SRichard Tran Mills   if (linear->coefficients) PetscCall(VecDestroy(&linear->coefficients));
12734b254c5SRichard Tran Mills 
12834b254c5SRichard Tran Mills   if (linear->use_ksp) {
12934b254c5SRichard Tran Mills     PetscCheck(linear->type == REGRESSOR_LINEAR_OLS, PetscObjectComm((PetscObject)regressor), PETSC_ERR_ARG_WRONGSTATE, "KSP can be used to fit a linear regressor only when its type is OLS");
13034b254c5SRichard Tran Mills 
13134b254c5SRichard Tran Mills     if (!linear->ksp) PetscCall(PetscRegressorLinearGetKSP(regressor, &linear->ksp));
13234b254c5SRichard Tran Mills     ksp = linear->ksp;
13334b254c5SRichard Tran Mills 
13434b254c5SRichard Tran Mills     PetscCall(MatCreateVecs(linear->X, &linear->coefficients, NULL));
13534b254c5SRichard Tran Mills     /* Set up the KSP to solve the least squares problem (without solving for intercept, as this is done separately) using KSPLSQR. */
13634b254c5SRichard Tran Mills     PetscCall(MatCreateNormal(linear->X, &linear->XtX));
13734b254c5SRichard Tran Mills     PetscCall(KSPSetType(ksp, KSPLSQR));
13834b254c5SRichard Tran Mills     PetscCall(KSPSetOperators(ksp, linear->X, linear->XtX));
13934b254c5SRichard Tran Mills     PetscCall(KSPSetOptionsPrefix(ksp, ((PetscObject)regressor)->prefix));
14034b254c5SRichard Tran Mills     PetscCall(KSPAppendOptionsPrefix(ksp, "regressor_linear_"));
14134b254c5SRichard Tran Mills     PetscCall(KSPSetFromOptions(ksp));
14234b254c5SRichard Tran Mills   } else {
14334b254c5SRichard Tran Mills     /* Note: Currently implementation creates TAO inside of implementations.
14434b254c5SRichard Tran Mills       * Thus, all the prefix jobs are done inside implementations, not in interface */
14534b254c5SRichard Tran Mills     const char *prefix;
14634b254c5SRichard Tran Mills 
14734b254c5SRichard Tran Mills     if (!regressor->tao) PetscCall(PetscRegressorGetTao(regressor, &tao));
14834b254c5SRichard Tran Mills 
14934b254c5SRichard Tran Mills     PetscCall(MatCreateVecs(linear->X, &linear->coefficients, &linear->residual));
15034b254c5SRichard Tran Mills     /* Set up the TAO object to solve the (regularized) least squares problem (without solving for intercept, which is done separately) using TAOBRGN. */
15134b254c5SRichard Tran Mills     PetscCall(TaoSetType(tao, TAOBRGN));
15234b254c5SRichard Tran Mills     PetscCall(TaoSetSolution(tao, linear->coefficients));
15334b254c5SRichard Tran Mills     PetscCall(TaoSetResidualRoutine(tao, linear->residual, EvaluateResidual, linear));
15434b254c5SRichard Tran Mills     PetscCall(TaoSetJacobianResidualRoutine(tao, linear->X, linear->X, EvaluateJacobian, linear));
15534b254c5SRichard Tran Mills     if (!linear->use_ksp) PetscCall(TaoBRGNSetRegularizerWeight(tao, regressor->regularizer_weight));
15634b254c5SRichard Tran Mills     // Set the regularization type and weight for the BRGN as linear->type dictates:
15734b254c5SRichard Tran Mills     // TODO BRGN needs to be BRGNSetRegularizationType
15834b254c5SRichard Tran Mills     // PetscOptionsSetValue no longer works due to functioning prefix system
15934b254c5SRichard Tran Mills     PetscCall(PetscRegressorGetOptionsPrefix(regressor, &prefix));
16034b254c5SRichard Tran Mills     PetscCall(TaoSetOptionsPrefix(regressor->tao, prefix));
16134b254c5SRichard Tran Mills     PetscCall(TaoAppendOptionsPrefix(tao, "regressor_linear_"));
16234b254c5SRichard Tran Mills     switch (linear->type) {
16334b254c5SRichard Tran Mills     case REGRESSOR_LINEAR_OLS:
16434b254c5SRichard Tran Mills       regressor->regularizer_weight = 0.0; // OLS, by definition, uses a regularizer weight of 0
16534b254c5SRichard Tran Mills       break;
16634b254c5SRichard Tran Mills     case REGRESSOR_LINEAR_LASSO:
167c0b7dd19SHansol Suh       PetscCall(TaoBRGNSetRegularizationType(regressor->tao, TAOBRGN_REGULARIZATION_L1DICT));
16834b254c5SRichard Tran Mills       break;
16934b254c5SRichard Tran Mills     case REGRESSOR_LINEAR_RIDGE:
170c0b7dd19SHansol Suh       PetscCall(TaoBRGNSetRegularizationType(regressor->tao, TAOBRGN_REGULARIZATION_L2PURE));
17134b254c5SRichard Tran Mills       break;
17234b254c5SRichard Tran Mills     default:
17334b254c5SRichard Tran Mills       break;
17434b254c5SRichard Tran Mills     }
17534b254c5SRichard Tran Mills     PetscCall(TaoSetFromOptions(tao));
17634b254c5SRichard Tran Mills   }
17734b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
17834b254c5SRichard Tran Mills }
17934b254c5SRichard Tran Mills 
18034b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorReset_Linear(PetscRegressor regressor)
18134b254c5SRichard Tran Mills {
18234b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
18334b254c5SRichard Tran Mills 
18434b254c5SRichard Tran Mills   PetscFunctionBegin;
18534b254c5SRichard Tran Mills   /* Destroy the PETSc objects associated with the linear regressor implementation. */
18634b254c5SRichard Tran Mills   linear->ksp_its     = 0;
18734b254c5SRichard Tran Mills   linear->ksp_tot_its = 0;
18834b254c5SRichard Tran Mills 
18934b254c5SRichard Tran Mills   PetscCall(MatDestroy(&linear->X));
19034b254c5SRichard Tran Mills   PetscCall(MatDestroy(&linear->XtX));
19134b254c5SRichard Tran Mills   PetscCall(MatDestroy(&linear->C));
19234b254c5SRichard Tran Mills   PetscCall(KSPDestroy(&linear->ksp));
19334b254c5SRichard Tran Mills   PetscCall(VecDestroy(&linear->coefficients));
19434b254c5SRichard Tran Mills   PetscCall(VecDestroy(&linear->rhs));
19534b254c5SRichard Tran Mills   PetscCall(VecDestroy(&linear->residual));
19634b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
19734b254c5SRichard Tran Mills }
19834b254c5SRichard Tran Mills 
19934b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorDestroy_Linear(PetscRegressor regressor)
20034b254c5SRichard Tran Mills {
20134b254c5SRichard Tran Mills   PetscFunctionBegin;
20234b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetFitIntercept_C", NULL));
20334b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetUseKSP_C", NULL));
20434b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetKSP_C", NULL));
20534b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetCoefficients_C", NULL));
20634b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetIntercept_C", NULL));
20734b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetType_C", NULL));
20834b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetType_C", NULL));
20934b254c5SRichard Tran Mills   PetscCall(PetscRegressorReset_Linear(regressor));
21034b254c5SRichard Tran Mills   PetscCall(PetscFree(regressor->data));
21134b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
21234b254c5SRichard Tran Mills }
21334b254c5SRichard Tran Mills 
21434b254c5SRichard Tran Mills /*@
21534b254c5SRichard Tran Mills   PetscRegressorLinearSetFitIntercept - Set a flag to indicate that the intercept (also known as the "bias" or "offset") should
21634b254c5SRichard Tran Mills   be calculated; data are assumed to be mean-centered if false.
21734b254c5SRichard Tran Mills 
21834b254c5SRichard Tran Mills   Logically Collective
21934b254c5SRichard Tran Mills 
22034b254c5SRichard Tran Mills   Input Parameters:
22134b254c5SRichard Tran Mills + regressor - the `PetscRegressor` context
22234b254c5SRichard Tran Mills - flg       - `PETSC_TRUE` to calculate the intercept, `PETSC_FALSE` to assume mean-centered data (default is `PETSC_TRUE`)
22334b254c5SRichard Tran Mills 
22434b254c5SRichard Tran Mills   Level: intermediate
22534b254c5SRichard Tran Mills 
22634b254c5SRichard Tran Mills   Options Database Key:
22734b254c5SRichard Tran Mills . regressor_linear_fit_intercept <true,false> - fit the intercept
22834b254c5SRichard Tran Mills 
22934b254c5SRichard Tran Mills   Note:
23034b254c5SRichard Tran Mills   If the user indicates that the intercept should not be calculated, the intercept will be set to zero.
23134b254c5SRichard Tran Mills 
23234b254c5SRichard Tran Mills .seealso: `PetscRegressor`, `PetscRegressorFit()`
23334b254c5SRichard Tran Mills @*/
23434b254c5SRichard Tran Mills PetscErrorCode PetscRegressorLinearSetFitIntercept(PetscRegressor regressor, PetscBool flg)
23534b254c5SRichard Tran Mills {
23634b254c5SRichard Tran Mills   PetscFunctionBegin;
23734b254c5SRichard Tran Mills   /* TODO: Add companion PetscRegressorLinearGetFitIntercept(), and put it in the .seealso: */
23834b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
23934b254c5SRichard Tran Mills   PetscValidLogicalCollectiveBool(regressor, flg, 2);
24034b254c5SRichard Tran Mills   PetscTryMethod(regressor, "PetscRegressorLinearSetFitIntercept_C", (PetscRegressor, PetscBool), (regressor, flg));
24134b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
24234b254c5SRichard Tran Mills }
24334b254c5SRichard Tran Mills 
24434b254c5SRichard Tran Mills /*@
24534b254c5SRichard Tran Mills   PetscRegressorLinearSetUseKSP - Set a flag to indicate that a `KSP` object, instead of a `Tao` one, should be used
246*789736e1SBarry Smith   to fit the linear regressor
24734b254c5SRichard Tran Mills 
24834b254c5SRichard Tran Mills   Logically Collective
24934b254c5SRichard Tran Mills 
25034b254c5SRichard Tran Mills   Input Parameters:
25134b254c5SRichard Tran Mills + regressor - the `PetscRegressor` context
25234b254c5SRichard Tran Mills - flg       - `PETSC_TRUE` to use a `KSP`, `PETSC_FALSE` to use a `Tao` object (default is false)
25334b254c5SRichard Tran Mills 
25434b254c5SRichard Tran Mills   Options Database Key:
25534b254c5SRichard Tran Mills . regressor_linear_use_ksp <true,false> - use `KSP`
25634b254c5SRichard Tran Mills 
25734b254c5SRichard Tran Mills   Level: intermediate
25834b254c5SRichard Tran Mills 
259*789736e1SBarry Smith   Notes:
260*789736e1SBarry Smith   `KSPLSQR` with no preconditioner is used to solve the normal equations by default.
261*789736e1SBarry Smith 
262*789736e1SBarry Smith   For sequential `MATSEQAIJ` sparse matrices QR factorization a `PCType` of `PCQR` can be used to solve the least-squares system with a `MatSolverType` of
263*789736e1SBarry Smith   `MATSOLVERSPQR`, using, for example,
264*789736e1SBarry Smith .vb
265*789736e1SBarry Smith   -ksp_type none -pc_type qr -pc_factor_mat_solver_type sp
266*789736e1SBarry Smith .ve
267*789736e1SBarry Smith   if centering, `PetscRegressorLinearSetFitIntercept()`, is not used.
268*789736e1SBarry Smith 
269*789736e1SBarry Smith   Developer Notes:
270*789736e1SBarry Smith   It should be possible to use Cholesky (and any other preconditioners) to solve the normal equations.
271*789736e1SBarry Smith 
272*789736e1SBarry Smith   It should be possible to use QR if centering is used. See ml/regressor/ex1.c and ex2.c
273*789736e1SBarry Smith 
274*789736e1SBarry Smith   It should be possible to use dense SVD `PCSVD` and dense qr directly on the rectangular matrix to solve the least squares problem.
275*789736e1SBarry Smith 
276*789736e1SBarry Smith   Adding the above support seems to require a refactorization of how least squares problems are solved with PETSc in `KSPLSQR`
277*789736e1SBarry Smith 
278*789736e1SBarry Smith .seealso: `PetscRegressor`, `PetscRegressorLinearGetKSP()`, `KSPLSQR`, `PCQR`, `MATSOLVERSPQR`, `MatSolverType`, `MATSEQDENSE`, `PCSVD`
27934b254c5SRichard Tran Mills @*/
28034b254c5SRichard Tran Mills PetscErrorCode PetscRegressorLinearSetUseKSP(PetscRegressor regressor, PetscBool flg)
28134b254c5SRichard Tran Mills {
28234b254c5SRichard Tran Mills   PetscFunctionBegin;
28334b254c5SRichard Tran Mills   /* TODO: Add companion PetscRegressorLinearGetUseKSP(), and put it in the .seealso: */
28434b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
28534b254c5SRichard Tran Mills   PetscValidLogicalCollectiveBool(regressor, flg, 2);
28634b254c5SRichard Tran Mills   PetscTryMethod(regressor, "PetscRegressorLinearSetUseKSP_C", (PetscRegressor, PetscBool), (regressor, flg));
28734b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
28834b254c5SRichard Tran Mills }
28934b254c5SRichard Tran Mills 
29034b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorSetFromOptions_Linear(PetscRegressor regressor, PetscOptionItems PetscOptionsObject)
29134b254c5SRichard Tran Mills {
29234b254c5SRichard Tran Mills   PetscBool              set, flg = PETSC_FALSE;
29334b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
29434b254c5SRichard Tran Mills 
29534b254c5SRichard Tran Mills   PetscFunctionBegin;
29634b254c5SRichard Tran Mills   PetscOptionsHeadBegin(PetscOptionsObject, "PetscRegressor options for linear regressors");
29734b254c5SRichard Tran Mills   PetscCall(PetscOptionsBool("-regressor_linear_fit_intercept", "Calculate intercept for linear model", "PetscRegressorLinearSetFitIntercept", flg, &flg, &set));
29834b254c5SRichard Tran Mills   if (set) PetscCall(PetscRegressorLinearSetFitIntercept(regressor, flg));
29934b254c5SRichard Tran Mills   PetscCall(PetscOptionsBool("-regressor_linear_use_ksp", "Use KSP instead of TAO for linear model fitting problem", "PetscRegressorLinearSetFitIntercept", flg, &flg, &set));
30034b254c5SRichard Tran Mills   if (set) PetscCall(PetscRegressorLinearSetUseKSP(regressor, flg));
30134b254c5SRichard Tran Mills   PetscCall(PetscOptionsEnum("-regressor_linear_type", "Linear regression method", "PetscRegressorLinearTypes", PetscRegressorLinearTypes, (PetscEnum)linear->type, (PetscEnum *)&linear->type, NULL));
30234b254c5SRichard Tran Mills   PetscOptionsHeadEnd();
30334b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
30434b254c5SRichard Tran Mills }
30534b254c5SRichard Tran Mills 
30634b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorView_Linear(PetscRegressor regressor, PetscViewer viewer)
30734b254c5SRichard Tran Mills {
30834b254c5SRichard Tran Mills   PetscBool              isascii;
30934b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
31034b254c5SRichard Tran Mills 
31134b254c5SRichard Tran Mills   PetscFunctionBegin;
31234b254c5SRichard Tran Mills   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
31334b254c5SRichard Tran Mills   if (isascii) {
31434b254c5SRichard Tran Mills     PetscCall(PetscViewerASCIIPushTab(viewer));
31534b254c5SRichard Tran Mills     PetscCall(PetscViewerASCIIPrintf(viewer, "PetscRegressor Linear Type: %s\n", PetscRegressorLinearTypes[linear->type]));
31634b254c5SRichard Tran Mills     if (linear->ksp) {
31734b254c5SRichard Tran Mills       PetscCall(KSPView(linear->ksp, viewer));
31834b254c5SRichard Tran Mills       PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", linear->ksp_tot_its));
31934b254c5SRichard Tran Mills     }
32034b254c5SRichard Tran Mills     if (linear->fit_intercept) PetscCall(PetscViewerASCIIPrintf(viewer, "Intercept=%g\n", (double)linear->intercept));
32134b254c5SRichard Tran Mills     PetscCall(PetscViewerASCIIPopTab(viewer));
32234b254c5SRichard Tran Mills   }
32334b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
32434b254c5SRichard Tran Mills }
32534b254c5SRichard Tran Mills 
32634b254c5SRichard Tran Mills /*@
32734b254c5SRichard Tran Mills   PetscRegressorLinearGetKSP - Returns the `KSP` context for a `PETSCREGRESSORLINEAR` object.
32834b254c5SRichard Tran Mills 
32934b254c5SRichard Tran Mills   Not Collective, but if the `PetscRegressor` is parallel, then the `KSP` object is parallel
33034b254c5SRichard Tran Mills 
33134b254c5SRichard Tran Mills   Input Parameter:
33234b254c5SRichard Tran Mills . regressor - the `PetscRegressor` context
33334b254c5SRichard Tran Mills 
33434b254c5SRichard Tran Mills   Output Parameter:
33534b254c5SRichard Tran Mills . ksp - the `KSP` context
33634b254c5SRichard Tran Mills 
33734b254c5SRichard Tran Mills   Level: beginner
33834b254c5SRichard Tran Mills 
33934b254c5SRichard Tran Mills   Note:
34034b254c5SRichard Tran Mills   This routine will always return a `KSP`, but, depending on the type of the linear regressor and the options that are set, the regressor may actually use a `Tao` object instead of this `KSP`.
34134b254c5SRichard Tran Mills 
34234b254c5SRichard Tran Mills .seealso: `PetscRegressorGetTao()`
34334b254c5SRichard Tran Mills @*/
34434b254c5SRichard Tran Mills PetscErrorCode PetscRegressorLinearGetKSP(PetscRegressor regressor, KSP *ksp)
34534b254c5SRichard Tran Mills {
34634b254c5SRichard Tran Mills   PetscFunctionBegin;
34734b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
34834b254c5SRichard Tran Mills   PetscAssertPointer(ksp, 2);
34934b254c5SRichard Tran Mills   PetscUseMethod(regressor, "PetscRegressorLinearGetKSP_C", (PetscRegressor, KSP *), (regressor, ksp));
35034b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
35134b254c5SRichard Tran Mills }
35234b254c5SRichard Tran Mills 
35334b254c5SRichard Tran Mills /*@
35434b254c5SRichard Tran Mills   PetscRegressorLinearGetCoefficients - Get a vector of the fitted coefficients from a linear regression model
35534b254c5SRichard Tran Mills 
35634b254c5SRichard Tran Mills   Not Collective but the vector is parallel
35734b254c5SRichard Tran Mills 
35834b254c5SRichard Tran Mills   Input Parameter:
35934b254c5SRichard Tran Mills . regressor - the `PetscRegressor` context
36034b254c5SRichard Tran Mills 
36134b254c5SRichard Tran Mills   Output Parameter:
36234b254c5SRichard Tran Mills . coefficients - the vector of the coefficients
36334b254c5SRichard Tran Mills 
36434b254c5SRichard Tran Mills   Level: beginner
36534b254c5SRichard Tran Mills 
36634b254c5SRichard Tran Mills .seealso: `PetscRegressor`, `PetscRegressorLinearGetIntercept()`, `PETSCREGRESSORLINEAR`, `Vec`
36734b254c5SRichard Tran Mills @*/
36834b254c5SRichard Tran Mills PETSC_EXTERN PetscErrorCode PetscRegressorLinearGetCoefficients(PetscRegressor regressor, Vec *coefficients)
36934b254c5SRichard Tran Mills {
37034b254c5SRichard Tran Mills   PetscFunctionBegin;
37134b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
37234b254c5SRichard Tran Mills   PetscAssertPointer(coefficients, 2);
37334b254c5SRichard Tran Mills   PetscUseMethod(regressor, "PetscRegressorLinearGetCoefficients_C", (PetscRegressor, Vec *), (regressor, coefficients));
37434b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
37534b254c5SRichard Tran Mills }
37634b254c5SRichard Tran Mills 
37734b254c5SRichard Tran Mills /*@
37834b254c5SRichard Tran Mills   PetscRegressorLinearGetIntercept - Get the intercept from a linear regression model
37934b254c5SRichard Tran Mills 
38034b254c5SRichard Tran Mills   Not Collective
38134b254c5SRichard Tran Mills 
38234b254c5SRichard Tran Mills   Input Parameter:
38334b254c5SRichard Tran Mills . regressor - the `PetscRegressor` context
38434b254c5SRichard Tran Mills 
38534b254c5SRichard Tran Mills   Output Parameter:
38634b254c5SRichard Tran Mills . intercept - the intercept
38734b254c5SRichard Tran Mills 
38834b254c5SRichard Tran Mills   Level: beginner
38934b254c5SRichard Tran Mills 
39034b254c5SRichard Tran Mills .seealso: `PetscRegressor`, `PetscRegressorLinearSetFitIntercept()`, `PetscRegressorLinearGetCoefficients()`, `PETSCREGRESSORLINEAR`
39134b254c5SRichard Tran Mills @*/
39234b254c5SRichard Tran Mills PETSC_EXTERN PetscErrorCode PetscRegressorLinearGetIntercept(PetscRegressor regressor, PetscScalar *intercept)
39334b254c5SRichard Tran Mills {
39434b254c5SRichard Tran Mills   PetscFunctionBegin;
39534b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
39634b254c5SRichard Tran Mills   PetscAssertPointer(intercept, 2);
39734b254c5SRichard Tran Mills   PetscUseMethod(regressor, "PetscRegressorLinearGetIntercept_C", (PetscRegressor, PetscScalar *), (regressor, intercept));
39834b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
39934b254c5SRichard Tran Mills }
40034b254c5SRichard Tran Mills 
40134b254c5SRichard Tran Mills /*@C
40234b254c5SRichard Tran Mills   PetscRegressorLinearSetType - Sets the type of linear regression to be performed
40334b254c5SRichard Tran Mills 
40434b254c5SRichard Tran Mills   Logically Collective
40534b254c5SRichard Tran Mills 
40634b254c5SRichard Tran Mills   Input Parameters:
40734b254c5SRichard Tran Mills + regressor - the `PetscRegressor` context (should be of type `PETSCREGRESSORLINEAR`)
40834b254c5SRichard Tran Mills - type      - a known linear regression method
40934b254c5SRichard Tran Mills 
41034b254c5SRichard Tran Mills   Options Database Key:
41134b254c5SRichard Tran Mills . -regressor_linear_type - Sets the linear regression method; use -help for a list of available methods
41234b254c5SRichard Tran Mills    (for instance "-regressor_linear_type ols" or "-regressor_linear_type lasso")
41334b254c5SRichard Tran Mills 
41434b254c5SRichard Tran Mills   Level: intermediate
41534b254c5SRichard Tran Mills 
416*789736e1SBarry Smith .seealso: `PetscRegressorLinearGetType()`, `PetscRegressorLinearType`, `PetscRegressorSetType()`, `REGRESSOR_LINEAR_OLS`,
417*789736e1SBarry Smith           `REGRESSOR_LINEAR_LASSO`, `REGRESSOR_LINEAR_RIDGE`
41834b254c5SRichard Tran Mills @*/
41934b254c5SRichard Tran Mills PetscErrorCode PetscRegressorLinearSetType(PetscRegressor regressor, PetscRegressorLinearType type)
42034b254c5SRichard Tran Mills {
42134b254c5SRichard Tran Mills   PetscFunctionBegin;
42234b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
42334b254c5SRichard Tran Mills   PetscValidLogicalCollectiveEnum(regressor, type, 2);
42434b254c5SRichard Tran Mills   PetscTryMethod(regressor, "PetscRegressorLinearSetType_C", (PetscRegressor, PetscRegressorLinearType), (regressor, type));
42534b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
42634b254c5SRichard Tran Mills }
42734b254c5SRichard Tran Mills 
42834b254c5SRichard Tran Mills /*@
42934b254c5SRichard Tran Mills   PetscRegressorLinearGetType - Return the type for the `PETSCREGRESSORLINEAR` solver
43034b254c5SRichard Tran Mills 
43134b254c5SRichard Tran Mills   Input Parameter:
43234b254c5SRichard Tran Mills . regressor - the `PetscRegressor` solver context
43334b254c5SRichard Tran Mills 
43434b254c5SRichard Tran Mills   Output Parameter:
43534b254c5SRichard Tran Mills . type - `PETSCREGRESSORLINEAR` type
43634b254c5SRichard Tran Mills 
43734b254c5SRichard Tran Mills   Level: advanced
43834b254c5SRichard Tran Mills 
43934b254c5SRichard Tran Mills .seealso: `PetscRegressor`, `PETSCREGRESSORLINEAR`, `PetscRegressorLinearSetType()`, `PetscRegressorLinearType`
44034b254c5SRichard Tran Mills @*/
44134b254c5SRichard Tran Mills PetscErrorCode PetscRegressorLinearGetType(PetscRegressor regressor, PetscRegressorLinearType *type)
44234b254c5SRichard Tran Mills {
44334b254c5SRichard Tran Mills   PetscFunctionBegin;
44434b254c5SRichard Tran Mills   PetscValidHeaderSpecific(regressor, PETSCREGRESSOR_CLASSID, 1);
44534b254c5SRichard Tran Mills   PetscAssertPointer(type, 2);
44634b254c5SRichard Tran Mills   PetscUseMethod(regressor, "PetscRegressorLinearGetType_C", (PetscRegressor, PetscRegressorLinearType *), (regressor, type));
44734b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
44834b254c5SRichard Tran Mills }
44934b254c5SRichard Tran Mills 
45034b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorFit_Linear(PetscRegressor regressor)
45134b254c5SRichard Tran Mills {
45234b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
45334b254c5SRichard Tran Mills   KSP                    ksp;
45434b254c5SRichard Tran Mills   PetscScalar            target_mean, *column_means_global, *column_means_local, column_means_dot_coefficients;
45534b254c5SRichard Tran Mills   Vec                    column_means;
45634b254c5SRichard Tran Mills   PetscInt               m, N, istart, i, kspits;
45734b254c5SRichard Tran Mills 
45834b254c5SRichard Tran Mills   PetscFunctionBegin;
45934b254c5SRichard Tran Mills   if (linear->use_ksp) PetscCall(PetscRegressorLinearGetKSP(regressor, &linear->ksp));
46034b254c5SRichard Tran Mills   ksp = linear->ksp;
46134b254c5SRichard Tran Mills 
46234b254c5SRichard Tran Mills   /* Solve the least-squares problem (previously set up in PetscRegressorSetUp_Linear()) without finding the intercept. */
46334b254c5SRichard Tran Mills   if (linear->use_ksp) {
46434b254c5SRichard Tran Mills     PetscCall(KSPSolve(ksp, linear->rhs, linear->coefficients));
46534b254c5SRichard Tran Mills     PetscCall(KSPGetIterationNumber(ksp, &kspits));
46634b254c5SRichard Tran Mills     linear->ksp_its += kspits;
46734b254c5SRichard Tran Mills     linear->ksp_tot_its += kspits;
46834b254c5SRichard Tran Mills   } else {
46934b254c5SRichard Tran Mills     PetscCall(TaoSolve(regressor->tao));
47034b254c5SRichard Tran Mills   }
47134b254c5SRichard Tran Mills 
47234b254c5SRichard Tran Mills   /* Calculate the intercept. */
47334b254c5SRichard Tran Mills   if (linear->fit_intercept) {
47434b254c5SRichard Tran Mills     PetscCall(MatGetSize(regressor->training, NULL, &N));
47534b254c5SRichard Tran Mills     PetscCall(PetscMalloc1(N, &column_means_global));
47634b254c5SRichard Tran Mills     PetscCall(VecMean(regressor->target, &target_mean));
47734b254c5SRichard Tran Mills     /* We need the means of all columns of regressor->training, placed into a Vec compatible with linear->coefficients.
47834b254c5SRichard Tran Mills      * Note the potential scalability issue: MatGetColumnMeans() computes means of ALL colummns. */
47934b254c5SRichard Tran Mills     PetscCall(MatGetColumnMeans(regressor->training, column_means_global));
48034b254c5SRichard Tran Mills     /* TODO: Calculation of the Vec and matrix column means should probably go into the SetUp phase, and also be placed
48134b254c5SRichard Tran Mills      *       into a routine that is callable from outside of PetscRegressorFit_Linear(), because we'll want to do the same
48234b254c5SRichard Tran Mills      *       thing for other models, such as ridge and LASSO regression, and should avoid code duplication.
48334b254c5SRichard Tran Mills      *       What we are calling 'target_mean' and 'column_means' should be stashed in the base linear regressor struct,
48434b254c5SRichard Tran Mills      *       and perhaps renamed to make it clear they are offsets that should be applied (though the current naming
48534b254c5SRichard Tran Mills      *       makes sense since it makes it clear where these come from.) */
48634b254c5SRichard Tran Mills     PetscCall(VecDuplicate(linear->coefficients, &column_means));
48734b254c5SRichard Tran Mills     PetscCall(VecGetLocalSize(column_means, &m));
48834b254c5SRichard Tran Mills     PetscCall(VecGetOwnershipRange(column_means, &istart, NULL));
48934b254c5SRichard Tran Mills     PetscCall(VecGetArrayWrite(column_means, &column_means_local));
49034b254c5SRichard Tran Mills     for (i = 0; i < m; i++) column_means_local[i] = column_means_global[istart + i];
49134b254c5SRichard Tran Mills     PetscCall(VecRestoreArrayWrite(column_means, &column_means_local));
49234b254c5SRichard Tran Mills     PetscCall(VecDot(column_means, linear->coefficients, &column_means_dot_coefficients));
49334b254c5SRichard Tran Mills     PetscCall(VecDestroy(&column_means));
49434b254c5SRichard Tran Mills     PetscCall(PetscFree(column_means_global));
49534b254c5SRichard Tran Mills     linear->intercept = target_mean - column_means_dot_coefficients;
49634b254c5SRichard Tran Mills   } else {
49734b254c5SRichard Tran Mills     linear->intercept = 0.0;
49834b254c5SRichard Tran Mills   }
49934b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
50034b254c5SRichard Tran Mills }
50134b254c5SRichard Tran Mills 
50234b254c5SRichard Tran Mills static PetscErrorCode PetscRegressorPredict_Linear(PetscRegressor regressor, Mat X, Vec y)
50334b254c5SRichard Tran Mills {
50434b254c5SRichard Tran Mills   PetscRegressor_Linear *linear = (PetscRegressor_Linear *)regressor->data;
50534b254c5SRichard Tran Mills 
50634b254c5SRichard Tran Mills   PetscFunctionBegin;
50734b254c5SRichard Tran Mills   PetscCall(MatMult(X, linear->coefficients, y));
50834b254c5SRichard Tran Mills   PetscCall(VecShift(y, linear->intercept));
50934b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
51034b254c5SRichard Tran Mills }
51134b254c5SRichard Tran Mills 
51234b254c5SRichard Tran Mills /*MC
51334b254c5SRichard Tran Mills      PETSCREGRESSORLINEAR - Linear regression model (ordinary least squares or regularized variants)
51434b254c5SRichard Tran Mills 
51534b254c5SRichard Tran Mills    Options Database:
51634b254c5SRichard Tran Mills +  -regressor_linear_fit_intercept - Calculate the intercept for the linear model
51734b254c5SRichard Tran Mills -  -regressor_linear_use_ksp       - Use `KSP` instead of `Tao` for linear model fitting (non-regularized variants only)
51834b254c5SRichard Tran Mills 
51934b254c5SRichard Tran Mills    Level: beginner
52034b254c5SRichard Tran Mills 
52134b254c5SRichard Tran Mills    Note:
52234b254c5SRichard Tran Mills    This is the default regressor in `PetscRegressor`.
52334b254c5SRichard Tran Mills 
52434b254c5SRichard Tran Mills .seealso: `PetscRegressorCreate()`, `PetscRegressor`, `PetscRegressorSetType()`
52534b254c5SRichard Tran Mills M*/
52634b254c5SRichard Tran Mills PETSC_EXTERN PetscErrorCode PetscRegressorCreate_Linear(PetscRegressor regressor)
52734b254c5SRichard Tran Mills {
52834b254c5SRichard Tran Mills   PetscRegressor_Linear *linear;
52934b254c5SRichard Tran Mills 
53034b254c5SRichard Tran Mills   PetscFunctionBegin;
53134b254c5SRichard Tran Mills   PetscCall(PetscNew(&linear));
53234b254c5SRichard Tran Mills   regressor->data = (void *)linear;
53334b254c5SRichard Tran Mills 
53434b254c5SRichard Tran Mills   regressor->ops->setup          = PetscRegressorSetUp_Linear;
53534b254c5SRichard Tran Mills   regressor->ops->reset          = PetscRegressorReset_Linear;
53634b254c5SRichard Tran Mills   regressor->ops->destroy        = PetscRegressorDestroy_Linear;
53734b254c5SRichard Tran Mills   regressor->ops->setfromoptions = PetscRegressorSetFromOptions_Linear;
53834b254c5SRichard Tran Mills   regressor->ops->view           = PetscRegressorView_Linear;
53934b254c5SRichard Tran Mills   regressor->ops->fit            = PetscRegressorFit_Linear;
54034b254c5SRichard Tran Mills   regressor->ops->predict        = PetscRegressorPredict_Linear;
54134b254c5SRichard Tran Mills 
54234b254c5SRichard Tran Mills   linear->intercept     = 0.0;
54334b254c5SRichard Tran Mills   linear->fit_intercept = PETSC_TRUE;  /* Default to calculating the intercept. */
54434b254c5SRichard Tran Mills   linear->use_ksp       = PETSC_FALSE; /* Do not default to using KSP for solving the model-fitting problem (use TAO instead). */
54534b254c5SRichard Tran Mills   linear->type          = REGRESSOR_LINEAR_OLS;
54634b254c5SRichard Tran Mills   /* Above, manually set the default linear regressor type.
54734b254c5SRichard Tran Mills        We don't use PetscRegressorLinearSetType() here, because that expects the SetUp event to already have happened. */
54834b254c5SRichard Tran Mills 
54934b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetFitIntercept_C", PetscRegressorLinearSetFitIntercept_Linear));
55034b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetUseKSP_C", PetscRegressorLinearSetUseKSP_Linear));
55134b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetKSP_C", PetscRegressorLinearGetKSP_Linear));
55234b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetCoefficients_C", PetscRegressorLinearGetCoefficients_Linear));
55334b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetIntercept_C", PetscRegressorLinearGetIntercept_Linear));
55434b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearSetType_C", PetscRegressorLinearSetType_Linear));
55534b254c5SRichard Tran Mills   PetscCall(PetscObjectComposeFunction((PetscObject)regressor, "PetscRegressorLinearGetType_C", PetscRegressorLinearGetType_Linear));
55634b254c5SRichard Tran Mills   PetscFunctionReturn(PETSC_SUCCESS);
55734b254c5SRichard Tran Mills }
558