For a serious C++ PLS/NIRS library, I would not make a class by acronym. I would rather make a composable PLS engine with several axes: task type, solver, deflection, regularization, orthogonalization, blocks, variable selection, preprocessing, validation, domain adaptation, then possibly GPU/batch backend.

The existing structure confirms this structure: scikit-learn already exposes PLSRegression, PLSCanonical, CCA and PLSSVD, with logic around cross covariance and NIPALS/SVD; the R package pls exposes PLSR, PCR, CPPLS, NIPALS/orthogonal scores, SIMPLS, kernel PLS and wide-kernel PLS; ropls covers PLS(-DA)/OPLS(-DA) with diagnostics; mixOmics covers sPLS and MB-sPLS; and plsVarSel / auswahl show the enormous importance of variable selection wrappers around the PLS. (Scikit-learn)

Current Status (May 2026)

Snapshot of what is delivered in the phase-49-vissa-pls tag (0.97.0+abi.1.14.0). The detailed roadmap is in ROADMAP.md ; phase notes are in roadmap/phase-*.md. Details of parity gates by method are in benchmarks/results/parity_gate/.

Overview Section

Status

Detail

§1 Core family (PLS1/PLS2/PLSRegression/PLSSVD/PCR/CPPLS)

delivered except CPPLS

PLS1/PLS2, PLSRegression, PLSCanonical, PLSSVD, PCR — CPPLS postponed.

§2 Numerical solvers (NIPALS, OrthScores, SIMPLS, Kernel, WideKernel, SVD, Power, Randomized-SVD)

delivered

all 8 solvers are active in n4m_model_fit.

§3 Deflection modes (regression, canonical, orthogonal)

delivered for already active models

X-only / Y-only / symmetric deflection pushed back.

§4–§5 PLS-DA / PLS-LDA / PLS-logistic

delivered

dummy-coding PLS-DA, deterministic LDA/logistic heads in NumPy.

§6 OPLS / OPLS-DA / shared predictive multi-response

delivered

orthogonal deflection, shared predictive scores.

§7 Sparse / penalized

delivered (internal)

Sparse SIMPLS via soft-thresholding (N4M_ALGO_SPARSE_PLS), fit_sparse_pls_da, fit_group_sparse_pls, fit_fused_sparse_pls.

§8 Multi-blocks

delivered (internal)

MB-PLS delivered; Added fit_o2pls, fit_so_pls, fit_on_pls, fit_rosa. sPLS-DA in §7.

§9 Multiway / tensor PLS

delivered (internal)

fit_n_pls + predict_n_pls (Bro 3-way). PARAFAC-PLS / Tucker-PLS as future variants.

§10.1 Kernel linear algorithm / wide-kernel

delivered

solvers KERNEL_ALGORITHM and WIDE_KERNEL.

§10.2 RBF/polynomial non-linear kernel

delivered (internal)

fit_kernel_pls / predict_kernel_pls for RBF, polynomial, sigmoid via Gram dual.

§11 LW-PLS / local PLS

delivered (internal)

LW-PLS delivered (uniform-weight) — covers JIT-PLS. Adaptive PLS / weighted kernel postponed.

§12 Dynamic / recursive PLS

delivered (internal)

Recursive PLS moving-window via fit_predict_recursive_pls. Strict incremental update postponed.

§13 Domain adaptation (supervised DI-PLS, PDS, EPO/OSC)

partial

OSC, EPO and DI-PLS delivered (internal DI-PLS); PDS and DS postponed.

§14 Selection of variables

delivered for 5a–5u

rangers, intervals, biPLS, siPLS, stability, UVE, EMCUVE, randomization, SPA, CARS, Random Frog, SCARS, GA, Shaving, REP, IPW, ST, BVE, T2, WVC, WVC-threshold.

§15 AOM-PLS / POP-PLS

delivered 6a–6f

strict-linear AOM operators (identity, detrend, SG, fd, NW, Whittaker, FCK), AOM-SIMPLS global selection, POP-SIMPLS covariance per-component selection, public C ABI surface.

§16 NIRS Preprocessing

delivered

identity/center/autoscale/Pareto/SNV/MSC/EMSC/Detrend/SG/SG-derivative/Norris-Williams/ASLS/Wavelet(Haar)/OSC/EPO.

§17 PLS diagnostics / chemometrics

delivered (internal)

VIP, selectivity ratio, regression/classification metrics, T² Hotelling, Q-residuals, DModX (cpp/src/core/pls_diagnostics.{hpp,cpp}). Approximate-PRESS still to port.

§18 Validation and choice of components

delivered

splitters, CV engines, SIMPLS component selection, one-SE rule (select_one_se_components), approximate_press (PRESS + selection). Bayesian rules still to port.

§19 Monitoring / process control

delivered (internal)

Empirical thresholds T² / Q at configurable α + alarm flags (pls_monitoring_fit / pls_monitoring_evaluate).

§20 PLS Sets

delivered (internal)

fit_bagging_pls, fit_boosting_pls, fit_random_subspace_pls.

§20 PLS Sets

not delivered

postponed.

§21 GPU/batch variants

not delivered

Acceleration Roadmap (BLAS, OpenMP, CUDA) remains optional, never on the ABI critical path.

§22 Models to exclude

n/a

nothing to deliver.

§23 Realistic prioritization v0.1–v0.7

v0.1–v0.6 mostly covered

v0.7 batch/GPU postponed.

Performance benchmarks (multi-language: native C++, Python, R, etc., multi-size: 200/500/1000/2000/10000 samples × 100/1000/10000 variables) are being instrumented under benchmarks/ — see ROADMAP.md “Benchmark Roadmap” section for details of phases 7a (delivered), 7b, 7c, 7d, 7e (in preparation).

1. Core family: the basic PLS models

To be offered from the base.

PLS1
PLS2
PLSRegression
PLSCanonical
PLSSVD
CCA / PLS mode B
PCR
CPPLS / powered PLS

Detail :

Variant

Role

PLS1

PLS regression with a single variable Y.

PLS2

Multi-output PLS regression.

PLSRegression

Generic PLS1/PLS2 API according to the dimension of Y.

PLSCanonical

Symmetric relationship between two blocks X and Y.

PLSSVD

Direct SVD of the cross covariance XᵀY.

CCA / PLS mode B

Very close to certain canonical variants.

PCR

Not strictly PLS, but essential baseline in chemometrics.

CPPLS

Canonical Powered PLS, useful as an intermediate variant between regression and discrimination.

In the library, I would do at least:

PLSRegressor
PLSCanonical
PLSSVD
PCRRegressor
CPPLSRegressor

2. Variants of numerical solvers

Here, we must distinguish the statistical model and the calculation algorithm.

NIPALS
Orthogonal Scores PLS
SIMPLS
Kernel algorithm PLS
Wide-kernel PLS
SVD PLS
Power-method PLS
Randomized SVD PLS
QR/SVD-stabilized PLS
Missing-aware NIPALS
Batched PLS

Detail :

Solveur

Pourquoi l’avoir

NIPALS

Historical reference, handles large p well, extensible, compatible missing values.

OrthogonalScoresPLS

NIPALS/orthogonal scores version widely used in R packages.

SIMPLS

Fast, direct, elegant, often good for classic PLSR.

KernelPLSAlgorithm

Warning: here “kernel” in the sense of an efficient linear algorithm, not RBF kernel.

WideKernelPLS

Variant adapted to large matrices, a frequent case in spectroscopy.

PLSSVD

Very useful for transformation/covariance, less so for all iterative regression logic.

PowerMethodPLS

Alternative to complete SVD, useful for big problems.

RandomizedSVDPLS

For very large matrices or GPU/batch backend.

StableSIMPLS

SIMPLS with digital guardrails, because SIMPLS can be unstable in some cases.

MissingNIPALS

Management of NaN without complete imputation.

To be provided in the code:

enum class PLSSolver {
    Nipals,
    OrthogonalScores,
    Simpls,
    KernelAlgorithm,
    WideKernel,
    SVD,
    PowerMethod,
    RandomizedSVD
};

3. Deflection modes

It’s fundamental. Many “PLS variants” are actually different choices of deflection.

Regression deflation
Canonical deflation
Symmetric deflation
X-only deflation
Y-only deflation
X-and-Y deflation
Orthogonal score deflation
Residual deflation
Block-wise deflation
Sequential deflation

To expose explicitly:

enum class DeflationMode {
    Regression,
    Canonical,
    Symmetric,
    XOnly,
    YOnly,
    XY,
    OrthogonalScores,
    BlockWise,
    Sequential
};

Also important:

- score normalization;
- weight normalization;
- sign convention;
- rotation calculation mode;
- cumulative coefficients by number of components;
- saved intercepts and scalings;
- optional X / Y reconstruction.

4. Regression PLS and loss variants

To be proposed to cover real NIRS cases.

Standard PLSR
Weighted PLS
Sample-weighted PLS
Robust PLS
Ridge-regularized PLS
Penalized PLS
Continuum regression
Monotonic inner relation PLS / MIR-PLS
Heteroscedastic PLS
Quantile PLS
Bayesian / probabilistic PLS

Priority :

Variant

Priority

Standard PLSR

indispensable

Weighted PLS

indispensable

Robust PLS

very useful

Ridge/regularized PLS

useful

Continuum regression

useful but secondary

MIR-PLS

interesting for you, especially if you have already explored it

Bayesian/probabilistic PLS

recherche / optionnel

Quantile PLS

niche

For NIRS, WeightedPLS is important: sample weights make it possible to manage unbalanced games, batches, local distances, or confidence measures.

5. PLS discriminante / classification

To propose because many NIRS papers do classification.

PLS-DA
OPLS-DA
sPLS-DA
MB-PLS-DA
MB-sPLS-DA
PLS-LDA
PLS-QDA
PLS-logistic
PLS-GLM
PLS-Cox / survival PLS
One-vs-rest PLS-DA
Multiclass PLS-DA
Multilabel PLS-DA

Detail :

Variant

Principle

PLSDA

Y one-hot or dummy, then PLS regression + decision rule.

OPLSDA

Orthogonalized version for separation/interpretation.

SparsePLSDA

Integrated variable selection.

PLSLDA

PLS then LDA scores. Very useful and robust.

PLSLogistic

PLS scores then logistic regression.

PLSGLM

Extension aux familles binomiale, Poisson, etc.

PLSCox

For survival data, rather outside classic NIRS.

I would put PLSDA, OPLSDA, PLSLDA and SparsePLSDA in the advanced base.

6. Orthogonal PLS and interpretable variants

Essential for chemometrics, omics, spectroscopy.

OPLS
OPLS-DA
O2PLS
OSC-PLS
DOSC-PLS
EPO-PLS
OnPLS
Orthogonalized PLS
Predictive-orthogonal decomposition

Detail :

Variant

Role

OPLS

Separates predictive variation and orthogonal variation to Y.

OPLSDA

Classification with predictive/orthogonal components.

O2PLS

Models common and specific variation of two blocks.

OSCPLS

Orthogonal Signal Correction avant ou pendant PLS.

DOSCPLS

Direct Orthogonal Signal Correction.

EPOPLS

External Parameter Orthogonalization, useful for temperature, humidity, instrument, etc.

OnPLS

Multi-blocks with global/local/single variation separation.

For your NIRS context, I would prioritize:

OPLS
OPLS-DA
OSC-PLS
EPO-PLS
O2PLS

7. Sparse PLS, penalized and integrated selection

To be offered early, but not necessarily from the MVP.

sPLS
sPLS-DA
Group sparse PLS
Block sparse PLS
Fused sparse PLS
Elastic-net PLS
Ridge PLS
Lasso-loading PLS
Sparse kernel PLS
Sparse OPLS
Sparse MB-PLS

Detail :

Variant

NIRS Utility

SparsePLS

Selection of wavelengths directly in the model.

GroupSparsePLS

Selection of spectral bands rather than isolated points.

FusedSparsePLS

Favors contiguous wavelengths. Very spectrally relevant.

ElasticNetPLS

Combines sparsity and stability on correlated variables.

SparseOPLS

Interpretation + selection.

SparseMBPLS

Multi-blocks + selection.

For NIRS, GroupSparsePLS and FusedSparsePLS are more coherent than pure point-to-point Lasso, because neighboring wavelengths are strongly correlated.

8. Multi-block/multi-table PLS

To be planned as a major axis of the bookstore.

MB-PLS
MB-PLS-DA
MB-sPLS
MB-sPLS-DA
SO-PLS
SO-PLS-DA
ROSA
Hierarchical MB-PLS
Consensus PLS
Block-wise PLS
O2PLS multiblock
OnPLS
DIABLO-like MB-sPLS-DA

Detail :

Variant

Role

MBPLS

Several X blocks aligned on the same samples.

MBSparsePLS

Multi-blocks + variable selection.

MBPLSDA

Multi-block classification.

SOPLS

Sequential Orthogonalized PLS, blocks processed sequentially.

ROSA

Response-Oriented Sequential Alternation.

HierarchicalMBPLS

Scores by block then higher model.

ConsensusPLS

Merging multiple models/blocks.

OnPLS

Common/local/unique variation decomposition.

DIABLO-like

Supervised multi-omics/multi-block classification version.

To be expected on the API side:

struct Block {
    Matrix X;
    std::string name;
    std::vector<double> wavelengths;
    double block_weight;
};

MBPLSModel fit(const std::vector<Block>& blocks, const Matrix& Y);

9. Multiway / tensor PLS

Very useful if you want to cover spectral imaging, EEM, time series, hyperspectral cubes.

N-PLS
Tri-PLS
Multiway PLS
Tensor PLS
PARAFAC-PLS
Tucker-PLS
N-way PLS-DA
Multiway MB-PLS

Example entries:

samples × wavelengths × time
samples × x_pixels × y_pixels × wavelengths
samples × excitation × emission
samples × wavelengths × instruments

In my opinion, it’s not MVP, but you have to predict the data structure.

10. Kernel and non-linear

Two families to clearly distinguish.

10.1 Kernel linear PLS algorithm

This is the historic “kernel PLS” algorithm to efficiently calculate linear PLS on large matrices. To be included.

Kernel algorithm PLS
Wide-kernel PLS

10.2 Non-linear PLS kernel

Here we are talking about machine learning type kernels.

RBF Kernel PLS
Polynomial Kernel PLS
Sigmoid Kernel PLS
Linear Kernel PLS
Precomputed Kernel PLS
Multiple Kernel PLS
Sparse Kernel PLS
Local Kernel PLS

To propose as an API:

enum class KernelType {
    Linear,
    RBF,
    Polynomial,
    Sigmoid,
    Precomputed
};

But I would put that after the linear core, because validation and tuning quickly become cumbersome.

11. Local PLS, adaptive PLS, just-in-time PLS

Very important for large heterogeneous NIRS games.

Local PLS
kNN-PLS
LW-PLS
Just-in-time PLS
Moving-window local PLS
Cluster-wise PLS
Mixture-of-PLS
Recursive local PLS
Adaptive local PLS
Local kernel PLS
Wavelet local PLS

Principle:

For each prediction:
    1. find the relevant neighbors or samples ;
    2. weight the samples ;
    3. fit a local PLS ;
    4. predict the new sample.

It’s expensive, but it’s exactly the kind of thing a C++/batch/GPU backend can speed up.

To expect:

LocalPLSRegressor
LWPLSRegressor
KNNPLSRegressor
ClusterPLSRegressor
MixturePLSRegressor

12. Dynamic PLS / process PLS / time-aware PLS

To be suggested if you want to cover processes, monitoring, time series, temporal phenotyping.

Dynamic PLS
Lagged PLS
Time-lagged PLS
Recursive PLS
Moving-window PLS
Adaptive PLS
Online PLS
Exponentially weighted PLS
Dynamic OPLS
Dynamic MB-PLS
State-space PLS

Be careful with the name DiPLS: in recent NIRS literature, di-PLS can also refer to domain-invariant PLS, so I would separate:

DPLS  = Dynamic PLS
diPLS = Domain-invariant PLS

13. Domain adaptation / calibration transfer

Very important in real NIRS: instrument, batch, temperature, humidity, site, species, matrix, physical form of the sample.

Domain-invariant PLS / di-PLS
Transfer PLS
Calibration-transfer PLS
Instrument-transfer PLS
Standard-free transfer PLS
Spiked PLS
Slope/bias updated PLS
Direct Standardization + PLS
Piecewise Direct Standardization + PLS
EPO + PLS
OSC/EPO transfer PLS
Batch-corrected PLS

di-PLS is explicitly presented as a domain adaptation technique to reduce differences between related domains, for example to adapt an NIR calibration from one physical form of sample to another without new reference measurements. (ScienceDirect)

I would put in the library:

DomainInvariantPLS
TransferPLS
EPOPLS
PDSAdapter
SlopeBiasAdapter
SpikingAdapter

14. Selection of variables / wavelengths around the PLS

It is not always a “PLS variant” in the strict sense, but for a NIRS library, it is essential.

14.1 Scores/filter simples

VIP
Regression coefficients
Absolute regression coefficients
Loading weights
Selectivity ratio
Significance Multivariate Correlation / sMC
Covariance selection / CovSel
T²-based selection
Q-residual-based selection
Jackknife coefficients
Bootstrap coefficients
Permutation importance

14.2 UVE / Monte Carlo / stability

UVE-PLS
MCUVE-PLS
EMCUVE-PLS
Randomization test PLS
Stability selection PLS
Bootstrap UVE
Jackknife UVE

14.3 Interval / spectral band methods

iPLS
biPLS
siPLS
mwPLS
moving-window PLS
interval random frog
recursive interval PLS
band selection PLS
windowed VIP
windowed CARS

14.4 Wrapper / metaheuristic methods

GA-PLS
PSO-PLS
ACO-PLS
Simulated annealing PLS
Random Frog PLS
CARS-PLS
SCARS-PLS
CARS-SPA-PLS
SPA-PLS
VISSA-PLS
IRIV-PLS
VCPA-PLS
BOSS-PLS

14.5 Methods explicitly listed in plsVarSel

To integrate or reproduce properly:

BVE-PLS
GA-PLS
IPW-PLS
MCUVE-PLS
REP-PLS
SPA-PLS
ST-PLS
Shaving
Truncation
FilterPLSR
PVR
PVS
T2-PLS
WVC-PLS
LDA-from-PLS
LDA-from-PLS-CV

plsVarSel lists precisely this type of functions around PLS variable selection, including bve_pls, ga_pls, ipw_pls, mcuve_pls, rep_pls, spa_pls, stpls, VIP, T2_pls and WVC_pls. (CRAN)

C++ side:

class VariableSelector {
public:
    virtual SelectionResult select(const Matrix& X, const Matrix& Y) = 0;
};

class VIPSelector;
class MCUVESelector;
class CARSSelector;
class SPASelector;
class IPLSSelector;
class GeneticPLSSelector;
class RandomFrogSelector;

15. AOM-PLS and variants linked to your axis

For you, this is probably the most differentiating thing.

AOM-PLS
AOM-PLS1
AOM-PLS2
AOM-NIPALS
AOM-SIMPLS
AOM-KernelPLS
AOM-OPLS
AOM-PLS-DA
AOM-MB-PLS
AOM-sPLS
AOM-LWPLS
AOM-DomainInvariantPLS
POP-PLS
Hard-gated AOM-PLS
Soft-gated AOM-PLS
Sparse-gated AOM-PLS
Per-component AOM-PLS
Per-block AOM-PLS
Per-target AOM-PLS

I would clearly separate:

Variant

Principle

AOMPLS

Weighted mixture of preprocessing operators in PLS.

POPPLS

Discrete choice of an operator per component.

SoftAOMPLS

Differentiable or weighted mixture.

HardAOMPLS

Selection of a single operator.

SparseAOMPLS

Penalty for forcing few operators.

BlockAOMPLS

Different operators depending on the blocks.

AOMOPLS

AOM + predictive/orthogonal separation.

AOMMBPLS

AOM + multi-blocks.

AOMLWPLS

AOM + local model.

For a C++ library, I would represent this with linear operators:

class SpectralOperator {
public:
    virtual void apply(const Matrix& X, Matrix& out) const = 0;
};

class AOMPLSRegressor {
    std::vector<std::shared_ptr<SpectralOperator>> operators_;
    PLSSolver solver_;
    GatingMode gating_;
};

16. NIRS preprocessing to include in the library

Even if they are not PLS variants, a PLS/NIRS library must have them, otherwise it will not be standalone.

Mean centering
Autoscaling
Pareto scaling
Robust scaling
SNV
MSC
EMSC
Detrend
Savitzky-Golay smoothing
Savitzky-Golay derivatives
Finite-difference derivatives
Norris-Williams derivatives
Wavelet transforms
Baseline correction
ASLS baseline
airPLS / arPLS / Whittaker baseline
Normalization by area
Min-max normalization
Vector normalization
Wavelength alignment
Spectral resampling
Splice correction
Dead-band removal
Saturation masking
Outlier masking
OSC
EPO
DOSC

For AOM, all these preprocessings should ideally be represented as reusable operators.

17. PLS diagnostics / chemometrics

To propose as a diagnostic API, not just plots.

Scores
Loadings
Weights
Rotations
Y-loadings
Explained variance X
Explained variance Y
Regression coefficients per component
VIP
Selectivity ratio
Leverage
Hotelling T²
Q residuals / SPE
DModX
Score distance
Orthogonal distance
Residual distance
Contribution plots
Outlier flags
Applicability domain

ropls highlights R²/Q², permutation testing, outlier detection, VIP and regression coefficients as important elements of PLS/OPLS analysis. (Bioconductor)

18. Validation, selection of the number of components, uncertainty

To be included very early. Otherwise the models will not be comparable.

K-fold CV
LOO CV
Repeated K-fold
Monte Carlo CV
Bootstrap CV
Nested CV
Grouped CV
Blocked CV
Stratified CV
Time-series split
Venetian blinds CV
Kennard-Stone split
SPXY split
Duplex split
Permutation tests
Y-scrambling
Jackknife
Bootstrap confidence intervals
Coefficient confidence intervals
Prediction intervals

Metrics to expose:

RMSEC
RMSECV
RMSEP
MSEC
MSECV
MSEP
R² calibration
R² validation
Q²
Bias
SEP
RPD
RPIQ
MAE
Median AE
Slope/intercept observed-vs-predicted
Sensitivity
Specificity
Balanced accuracy
AUC
MCC

The R package pls already exposes CV, LOO, MSEP/RMSEP/R² and jackknife; we must at least reproduce this level properly. (CRAN)

19. Monitoring / process control avec PLS

For industrial applications or time series.

PLS monitoring
PCA/PLS score charts
Hotelling T² chart
SPE/Q chart
Contribution plots
Fault detection PLS
Fault diagnosis PLS
Dynamic PLS monitoring
Recursive PLS monitoring
Batch process PLS
Multiblock process monitoring

This is not a priority for classic NIRS calibration, but very useful for “soft sensors”.

20. Ensembles de PLS

Interesting for robustness and large benchmarks.

Bagging PLS
Boosting PLS
Random subspace PLS
Variable-space boosting PLS
Ensemble MCUVE
Ensemble CARS
Consensus PLS
Stacked PLS
Mixture-of-experts PLS
Cluster ensemble PLS

To use as wrappers:

BaggingPLS
BoostingPLS
RandomSubspacePLS
ConsensusPLS
MixturePLS

21. GPU/batch variants to plan for in C++ design

Even if you start CPU C++ now, the API must allow it later:

Batched PLS fit
Batched PLS predict
Batched CV
Batched preprocessing
Batched variable selection
Batched AOM-PLS
Batched local PLS
Batched bootstrap
Batched permutation tests

Ce n’est pas juste :

fit_one_pls_on_gpu()

The real GPU gain will instead be:

fit 10 000 PLS sur des combinaisons :
    preprocessing × variables × folds × n_components × targets

So plan now:

struct PLSBatchJob {
    MatrixView X;
    MatrixView Y;
    PLSConfig config;
    Split split;
    PreprocessingPipeline pipeline;
};

std::vector<PLSResult> fit_batch(const std::vector<PLSBatchJob>& jobs);

22. Models to exclude or reject

I wouldn’t put them in the initial core:

PLS-SEM / Partial Least Squares Structural Equation Modeling
PLS path modeling
Neural PLS
Deep PLS
Highly specialized survival PLS

Note Phase 47 (2026-05-16): Gaussian-process PLS is now implemented (gpr_pls_fit, parity sklearn rmse_rel ~ 2.3e-10). There GP head is exposed as standalone primitive (fit_gp_on_scores) to allow a future GPR-on-AOMPLS.

Note Phase 48-49 (2026-05-16): in the §14.4 list of wrapper metaheuristics, PSO-PLS (pso_select, Kennedy & Eberhart 1997, paper-only) and VISSA-PLS (vissa_select, Deng et al. 2014, paper-only) are now delivered. The other exotic metaheuristics (ACO, simulated annealing, IRIV, VCPA, BOSS, CARS-SPA) remain postponed.

PLS-SEM is another world: sociometry, structural equation models, causal/latent graphs. It risks polluting a NIRS library.

23. Realistic prioritization

MVP C++ v0.1

PLS1
PLS2
PLSRegression
NIPALS
SIMPLS
PLSSVD
PCR
VIP
RMSE/R²/Q²
K-fold/LOO CV
predict/transform
coefficients per component
mean/scale/intercept serialization

v0.2 chemometrics/NIRS

SNV
MSC
EMSC
Detrend
Savitzky-Golay
derivatives
ASLS baseline
OSC
EPO
PLS-DA
PLS-LDA
OPLS
OPLS-DA
Hotelling T²
Q residuals
DModX

v0.3 variable selection

VIP selector
Coefficient selector
Selectivity ratio
iPLS
biPLS
moving-window PLS
UVE-PLS
MCUVE-PLS
CARS-PLS
SPA-PLS
GA-PLS
Random Frog
Shaving
BVE-PLS

v0.4 advanced

sPLS
sPLS-DA
Group sparse PLS
Fused sparse PLS
Kernel PLS
LW-PLS
Local PLS
Recursive/adaptive PLS
Domain-invariant PLS
Transfer PLS

v0.5 multi-block

MB-PLS
MB-PLS-DA
MB-sPLS
SO-PLS
ROSA
O2PLS
OnPLS
Hierarchical MB-PLS

v0.6 AOM

AOM-PLS
POP-PLS
AOM-SIMPLS
AOM-NIPALS
AOM-OPLS
AOM-MBPLS
Sparse AOM-PLS
AOM-LWPLS

v0.7 GPU/batch

batched PLS
batched CV
batched preprocessing
batched variable selection
batched AOM
batched local PLS
CUDA/cuBLAS or vendor backend

Summary

The library should eventually offer these major families:

1. PLS1 / PLS2 / PLSRegression
2. PLSCanonical / CCA-like / PLSSVD
3. PCR / CPPLS / continuum variants
4. NIPALS / SIMPLS / kernel algorithm / wide-kernel / SVD solvers
5. PLS-DA / OPLS-DA / sPLS-DA / PLS-LDA
6. OPLS / O2PLS / OSC-PLS / EPO-PLS
7. Sparse / group sparse / fused sparse / penalized PLS
8. MB-PLS / SO-PLS / MB-sPLS / OnPLS / ROSA
9. N-way / tensor PLS
10. Kernel nonlinear PLS
11. LW-PLS / local PLS / adaptive PLS
12. Dynamic / recursive / online PLS
13. Domain-invariant / transfer PLS
14. Variable selection : VIP, MCUVE, CARS, SPA, iPLS, GA, Random Frog, etc.
15. AOM-PLS and variants by component/block/operator
16. Diagnostics, validation, monitoring, and uncertainty
17. Batch/GPU-ready implementations

The C++ core must therefore be thought of as:

PLS engine
+ solver strategy
+ deflation strategy
+ preprocessing operators
+ variable selectors
+ validation engine
+ diagnostics engine
+ serialization
+ batch execution

Not like a flat collection of 150 independent classes.