InstanceSpace Python v0.4.1

instancespace.stages

Stages of instance space.

Class for handling the preprocessing stage of the pipeline.

This stage includes tasks such as feature selection, algorithm selection, and removing instances or features with too many missing values.

Methods

select_features_and_algorithms(x, y, feat_labels, algo_labels, selvars) Selects features and algorithms from the dataset based on user options. remove_instances_with_many_missing_values(x, y, s, feat_labels, inst_labels) Removes instances (rows) and features (columns) with excessive missing values.

PreprocessingStage( feature_names: list[str], algorithm_names: list[str], instance_labels: pandas.core.series.Series, instance_sources: pandas.core.series.Series | None, features: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], algorithms: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], selvars: instancespace.data.options.SelvarsOptions)

Initialize the Preprocessing stage.

feature_names
algorithm_names
instance_labels
instance_sources
features
algorithms
selvars
@staticmethod
def select_features_and_algorithms( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], feat_labels: list[str], algo_labels: list[str], selvars: instancespace.data.options.SelvarsOptions) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], list[str], list[str]]:

Select features and algorithms from the dataset.

Based on the user's configuration, this method filters the features and algorithms that should be used in subsequent stages.

Parameters
  • x (NDArray[np.double]): 2D numpy array representing the feature matrix (instances x features).
  • y (NDArray[np.double]): 2D numpy array representing the algorithm matrix (instances y algorithms).
  • feat_labels (list[str]): List of labels corresponding to the features in 'x'.
  • algo_labels (list[str]): List of labels corresponding to the algorithms in 'y'.
  • selvars (SelvarsOptions): An instance of SelvarsOptions that contains settings of the prefered algorithms and instances.
Returns
  • tuple[NDArray[np.double], NDArray[np.double], list[str], list[str]]: A tuple containing:
    • Modified feature matrix after feature selection and instance removal.
    • Modified algorithm matrix after algorithm selection and instance removal.
    • List of selected feature labels.
    • List of selected algorithm labels.
@staticmethod
def remove_instances_with_many_missing_values( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], s: pandas.core.series.Series | None, feat_labels: list[str], inst_labels: pandas.core.series.Series, nan_threshold: float = 0.2) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], pandas.core.series.Series, list[str], pandas.core.series.Series | None]:

Remove instances and features with excessive missing values.

Instances (rows) with too many missing values are removed. Additionally, features (columns) that exceed a missing value threshold are also removed. Washing criterion: 1. For any row, if that row in both X and Y are NaN, remove 2. For X columns, if that column's 20% grids are filled with NaN, remove

Parameters
  • x (NDArray[np.double]): 2D numpy array representing the feature matrix (instances x features).
  • y (NDArray[np.double]): 2D numpy array representing the algorithm matrix (instances y algorithms).
  • s (pd.Series | None): Optional series containing the source of instances.
  • feat_labels (list[str]): List of labels corresponding to the features in 'x'.
  • inst_labels (pd.Series): Series containing labels for each instance.
  • nan_threshold (float): Fraction of missing values at which a feature is removed.
Returns
  • tuple[NDArray[np.double], NDArray[np.double],
  • pd.Series, list[str], pd.Series | None]: A tuple containing the modified feature matrix 'x', the modified algorithm matrix 'y',updated instance labels, list of feature labels that remain after removal, and optionally modified series 's' if provided.

See file docstring.

PrelimStage( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], s: pandas.core.series.Series | None, inst_labels: pandas.core.series.Series, prelim_opts: instancespace.data.options.PrelimOptions, selvars_opts: instancespace.data.options.SelvarsOptions, general_opts: instancespace.data.options.GeneralOptions)

See file docstring.

x
y
prelim_opts
selvars_opts
general_opts
x_raw
y_raw
s
inst_labels
@staticmethod
def predict( inputs: instancespace.stages.prelim.PrelimPredictInput, fitted: instancespace.data.model.PrelimOut) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]:

Apply fitted bounds and normalisation without re-fitting PRELIM.

@staticmethod
def prelim( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], s: pandas.core.series.Series | None, inst_labels: pandas.core.series.Series, prelim_opts: instancespace.data.options.PrelimOptions, selvars_opts: instancespace.data.options.SelvarsOptions, general_opts: instancespace.data.options.GeneralOptions) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], float, numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]:

Perform preliminary processing on the input data 'x' and 'y'.

Parameters
  • x (NDArray[np.double]): The feature matrix (instances x features) to process.
  • y (NDArray[np.double]): The performance matrix (instances x algorithms) to process.
  • x_raw (NDArray[np.double]): The raw feature matrix.
  • y_raw (NDArray[np.double]): The raw performance matrix.
  • s (pd.Series | None): The instance source labels, or None.
  • inst_labels (pd.Series): The instance labels.
  • prelim_opts (PrelimOptions): The options for the preliminary processing.
  • selvars_opts (SelvarsOptions): The options for the instance and feature selection.
  • general_opts (GeneralOptions): The general options for all stages.
Returns
  • tuple: The first items are the processed data: x, y, y_bin, y_best, p, num_good_algos, and beta. The remaining items are the fitted bound and normalization parameters: med_val, iq_range, hi_bound, lo_bound, min_x, lambda_x, mu_x, sigma_x, min_y, lambda_y, sigma_y, and mu_y.

Stage in the processing pipeline for feature selection and instance filtering.

Attributes
  • MIN_FEAT_REQUIRED (int): Minimum number of features required for selection (default is 3).
  • KFOLDS (int): Number of folds for cross-validation (default is 5).
  • parallel_options (ParallelOptions): Options for parallel processing.
Methods

__init__(x: NDArray[np.double], y: NDArray[np.double], y_bin: NDArray[np.bool_], x_raw: NDArray[np.double], y_raw: NDArray[np.double], beta: NDArray[np.bool_], num_good_algos: NDArray[np.double], y_best: NDArray[np.double], p: NDArray[np.int_], inst_labels: pd.Series, s: pd.Series | None, feat_labels: list[str], opts: SiftedOptions, parallel_options: ParallelOptions) -> None: Initializes the SiftedStage with provided parameters.

_inputs() -> type[SiftedInput]: Returns the input type for the SIFTED stage.

_outputs() -> type[SiftedOutput]: Returns the output type for the SIFTED stage.

_compute_correlation(x: NDArray[np.double], y: NDArray[np.double]) -> tuple[NDArray[np.double], NDArray[np.double]]: Calculate the Pearson correlation coefficients between features and performance metrics.

evaluate_cluster(x_aux: NDArray[np.double], rng: np.random.Generator) -> tuple[list[float], NDArray[np.intc]]: Evaluates clusters based on silhouette scores for different cluster configurations.

_find_best_combination(x_aux: NDArray[np.double], clust: NDArray[np.bool_], selvars: NDArray[np.intc], rng: np.random.Generator) -> tuple[NDArray[np.double], NDArray[np.intc]]: Finds the best combination of features using a genetic algorithm.

cost_fcn(instance: pygad.GA, solutions: NDArray[np.intc], _solution_idx: int) -> float: Fitness function to evaluate the quality of a solution in the genetic algorithm

select_features_by_clustering(x_aux: NDArray[np.double], rng: np.random.Generator) -> tuple[NDArray[np.bool_], NDArray[np.intc]]: Selects features based on clustering results.

select_features_by_performance() -> tuple[NDArray[np.double], NDArray[np.double] , NDArray[np.double], NDArray[np.intc]]: Selects features based on correlation with performance metrics.

_sifted(opts_selvars: SelvarsOptions, data_dense: DataDense | None) -> SiftedOutput: Executes feature selection and optional instance filtering based on provided options.

sifted(x: NDArray[np.double], y: NDArray[np.double], y_bin: NDArray[np.bool_], x_raw: NDArray[np.double], y_raw: NDArray[np.double], beta: NDArray[np.bool_], num_good_algos: NDArray[np.double], y_best: NDArray[np.double], p: NDArray[np.int_], inst_labels: pd.Series, s: pd.Series | None, feat_labels: list[str], opts: SiftedOptions, opts_selvars: SelvarsOptions, data_dense: DataDense | None, parallel_options: ParallelOptions) -> SiftedOutput: Executes the core functionality of the Sifted stage for processing feature selection.

_run(inputs: SiftedInput) -> SiftedOutput: Executes the SIFTED stage of the pipeline using the provided inputs.

SiftedStage( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], x_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], beta: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], num_good_algos: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_best: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], p: numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], inst_labels: pandas.core.series.Series, s: pandas.core.series.Series | None, feat_labels: list[str], opts: instancespace.data.options.SiftedOptions, parallel_options: instancespace.data.options.ParallelOptions, general_opts: instancespace.data.options.GeneralOptions)

Define the input variables for the stage.

Parameters
  • x (NDArray[np.double]): Feature matrix to be processed (instances x features).
  • y (NDArray[np.double]): Algorithm performance matrix (instances x algorithms).
  • y_bin (NDArray[np.bool_]): Binary matrix indicating good algorithm performance.
  • feat_labels (list[str]): List of feature labels.
  • x_raw (NDArray[np.double]): Raw feature matrix.
  • y_raw (NDArray[np.double]): Raw performance matrix.
  • beta (NDArray[np.bool_]): Per-instance beta-easy labels.
  • num_good_algos (NDArray[np.double]): Number of good algorithms for each instance.
  • y_best (NDArray[np.double]): Best algorithm performance for each instance.
  • p (NDArray[np.int_]): One-based best-algorithm index for each instance.
  • inst_labels (pd.Series): Instance labels for the dataset.
  • s (pd.Series | None): The instance source labels, or None.
  • opts (SiftedOptions): The configuration options for the SIFTED stage.
  • parallel_options (ParallelOptions): An instance of ParallelOptions containing parallel processing parameters.
  • general_opts (GeneralOptions): General options (e.g. the RNG seed), not specific to any one stage.
MIN_FEAT_REQUIRED: int = 3
KFOLDS: int = 5
x
y
y_bin
feat_labels
x_raw
y_raw
beta
num_good_algos
y_best
p
inst_labels
s
opts
general_opts
@staticmethod
def predict( inputs: instancespace.stages.sifted.SiftedPredictInput, fitted: instancespace.data.model.SiftedOut) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]:

Apply fitted feature indices without re-running selection.

Public method to access the private _sifted method.

@staticmethod
def sifted( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], x_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], beta: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], num_good_algos: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_best: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], p: numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], inst_labels: pandas.core.series.Series, s: pandas.core.series.Series | None, feat_labels: list[str], opts: instancespace.data.options.SiftedOptions, opts_selvars: instancespace.data.options.SelvarsOptions, data_dense: instancespace.data.model.DataDense | None, parallel_options: instancespace.data.options.ParallelOptions, general_options: instancespace.data.options.GeneralOptions) -> instancespace.stages.sifted.SiftedOutput:

Core Sifted stage to process feature selection and performance.

Parameters
  • x (NDArray[np.double]): Feature matrix (instances x features).
  • y (NDArray[np.double]): Performance matrix of algorithms (instances x algorithms).
  • y_bin (NDArray[np.bool_]): Binary matrix indicating instances with good algorithm performance.
  • x_raw (NDArray[np.double]): Unprocessed feature matrix.
  • y_raw (NDArray[np.double]): Unprocessed performance matrix.
  • beta (NDArray[np.bool_]): Per-instance beta-easy labels.
  • num_good_algos (NDArray[np.double]): Number of good algorithms per instance.
  • y_best (NDArray[np.double]): Best algorithm performance for each instance.
  • p (NDArray[np.int_]): Array of correlation p-values for features.
  • inst_labels (pd.Series): Labels for each instance in the dataset.
  • s (pd.Series | None): Series for optional selection during processing.
  • feat_labels (list[str]): List of feature labels.
  • opts (SiftedOptions): Configuration options for the Sifted stage.
  • opts_selvars (SelvarsOptions): Options for selecting variables within the stage.
  • data_dense (DataDense | None): Dense data representation, if available.
  • parallel_options (ParallelOptions): Options for parallel processing.
  • general_options (GeneralOptions): General options (e.g. the RNG seed), not specific to any one stage.
Returns
  • SiftedOutput: Output of the Sifted stage, including selected feature and algorithm indices,correlation coefficients, performance metrics, silhouette scores, and feature selection flags.
Notes

This static method initialises a SiftedStage instance and calls its _sifted method, which uses the provided options and data to execute the Sifted stage pipeline and generate results.

def select_features_by_performance( self) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]]:

Select features based on correlation with performance.

Returns
  • x_aux (NDArray[np.double]): Filtered feature matrix after selection.
  • rho (NDArray[np.double]): Pearson correlation coefficients between features and performance.
  • pval (NDArray[np.double]): p-values for the correlation coefficients.
  • selvars (NDArray[np.intc]): Indices of the selected features.
def select_features_by_clustering( self, x_aux: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], rng: numpy.random._generator.Generator) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]]:

Select features based on clustering.

Parameters
  • x_aux (NDArray[np.double]): Auxiliary feature matrix used for clustering.
  • rng (np.random.Generator): Random number generator for reproducibility.
Returns
  • clust (NDArray[np.bool_]): Boolean matrix where each column represents a cluster.
  • cluster_labels (NDArray[np.intc]): Labels for the clusters.
@staticmethod
def cost_fcn( instance: pygad.pygad.GA, solutions: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]], _solution_idx: int) -> float:

Fitness function to evaluate the quality of solution in GA.

Parameters
  • instance (pygad.GA): The instance of the genetic algorithm.
  • solutions (NDArray[np.intc]): The array of integer values representing the solution to be evaluated.
  • solution_idx (int): The index of the solution being evaluated.
Returns
  • float: The fitness score of the solution: the worst (lowest) per- algorithm k-NN classification accuracy. pygad.GA always maximizes whatever this returns, so maximizing the minimum per-algorithm accuracy directly is equivalent to MATLAB's fitcknn/kfoldLoss-based costfcn (core/SIFTED.m), which ga() minimizes as max_i(loss_i) - -max_i(1 - acc_i) = min_i(acc_i) - 1, the same optimum up to an additive constant without changing the optimal feature set.
def evaluate_cluster( self, x_aux: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], rng: numpy.random._generator.Generator) -> tuple[list[float], numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]]:

Evaluate cluster based on silhouette scores.

Parameters
  • x_aux (NDArray[np.double]): Auxiliary feature matrix used for clustering.
  • rng (np.random.Generator): Random number generator for reproducibility.
Returns
  • silhouette_scores (list[float]): Silhouette scores for different cluster configurations.
  • cluster_labels (NDArray[np.intc]): Labels for the selected cluster configuration.

Class for PILOT stage.

PilotStage( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], feat_labels: list[str])

Initialize the Pilot stage.

The Initialize functon is used to create a Pilot class.

Parameters
  • x (NDArray[np.double]): The feature matrix (instances x features) to process.
  • y (NDArray[np.double]): The data points for the selected feature.
  • feat_labels (list[str]): The feature names.
Returns
  • None
x
y
feat_labels
@staticmethod
def predict( inputs: instancespace.stages.pilot.PilotPredictInput, fitted: instancespace.data.model.PilotOut) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]:

Project with the fitted PLS mean; older models retain linear inference.

@staticmethod
def pilot( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], feat_labels: list[str], options: instancespace.data.options.PilotOptions, general_options: instancespace.data.options.GeneralOptions, y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]] | None = None, _do_output: bool = True, parallel_options: instancespace.data.options.ParallelOptions | None = None) -> instancespace.stages.pilot.PilotOutput:

Run the PILOT dimensionality reduction algorithm.

Parameters
  • x (NDArray[double]): The feature matrix (instances x features) to process.
  • y (NDArray[double]): The data points for the selected feature.
  • feat_labels (list[str]): List feature names.
  • options (PilotOptions): The options enabled for the Pilot Class.
  • general_options (GeneralOptions): General options for all stages, for example the RNG seed.
  • y_bin (NDArray[np.bool_] | None): Binary matrix (instances x algorithms) indicating good algorithm performance. Required only when options.adjust_rotation is set.
  • parallel_options (ParallelOptions | None): Whether (and how much) to parallelise the numerical solver's ntries restart loop. None (the default for direct callers that don't pass one) runs the restarts sequentially, same as flag=False.
Returns
  • PilotOutput: Outputs from the Pilot stage.
@staticmethod
def adjust_rotation( z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], bad_instances: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], theta: float = 135.0) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]:

Rotate the 2D projection so poorly-solved instances face theta.

Ported from PyISpace's pilot.adjust_rotation() (gitlab.com/ita-ml/pyispace). Rotation preserves all pairwise distances in z, so it only changes the space's visual orientation

  • error, R2, and footprint areas are unaffected. The centroid of the instances flagged by bad_instances is rotated to sit at theta degrees (135 = upper-left quadrant, matching PyISpace's default), so that similar datasets come out consistently oriented across runs.
Parameters
  • z (NDArray[np.double]): The 2D projection (instances x 2) to rotate.
  • bad_instances (NDArray[np.bool_]): Boolean mask selecting the instances whose centroid should be placed at theta.
  • theta (float): Target angle, in degrees, for the bad-instance centroid.
Returns
  • NDArray[np.double]: The rotated projection, same shape as z.
  • NDArray[np.double]: The 2x2 rotation matrix applied.
@staticmethod
def analytic_solve( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_bar: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], n: int, m: int, cost_weight: float = 1.0, _do_output: bool = True, dims: int = 2) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]:

Solve the projection problem analytically.

Parameters
  • x (NDArray[np.double]): The feature matrix (instances x features) to process.
  • x_bar (NDArray[np.double]): Combined matrix of X and Y.
  • n (int): Number of original features.
  • m (int): Total number of features including appended Y.
  • cost_weight (float): Scalar performance-reconstruction weight (MATLAB's costWeight). Scales the performance block relative to the feature block before the eigendecomposition; 1.0 weights both blocks equally.
  • dims (int): Output projection dimensionality, either 2 or 3.
Returns
  • NDArray[np.double]: Matrix A.
  • NDArray[np.double]: Matrix B.
  • NDArray[np.double]: Matrix C.
  • NDArray[np.double]: Matrix Z.
  • NDArray[np.double]: The mean squared error between x_bar and its low-dimensional approximation.
  • NDArray[np.double]: The coefficient of determination between x_bar and its low-dimensional approximation.
@staticmethod
def pls_solve( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_bar: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], m: int, dims: int = 2, _do_output: bool = True) -> tuple[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]:

Solve the projection problem via Partial Least Squares.

MATLAB's method='pls' alternative to the analytic/numeric eigen-decomposition solvers above - a genuinely different algorithm, not a variant of either. dims matches MATLAB's own plsregress(X, Y, d) call.

Implements the SIMPLS routine used by MATLAB R2026a's plsregress. Both inputs are mean-centred but not variance-scaled, matching the default MATLAB call in PILOT.m.

Parameters
  • x (NDArray[np.double]): The feature matrix (instances x features) to process.
  • y (NDArray[np.double]): The performance matrix (instances x algorithms).
  • x_bar (NDArray[np.double]): Combined matrix of X and Y.
  • m (int): Total number of features including appended Y.
  • dims (int): Output projection dimensionality, either 2 or 3.
Returns
  • NDArray[np.double]: Matrix A (dims x n), the projection matrix: Z = (X - mean(X)) @ A.T.
  • NDArray[np.double]: Matrix Z (instances x dims), the projected coordinates.
  • NDArray[np.double]: Matrix C (dims x q), the performance-block reconstruction matrix.
  • NDArray[np.double]: Matrix B (n x dims), the feature-block reconstruction matrix.
  • NDArray[np.double]: The sum of squared reconstruction error between x_bar and its low-dimensional approximation.
  • NDArray[np.double]: The per-column coefficient of determination between x_bar and its low-dimensional approximation.
@staticmethod
def numerical_solve( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], hd: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x0: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_bar: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], n: int, m: int, alpha: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], eoptim: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], perf: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], opts: instancespace.data.options.PilotOptions, general_options: instancespace.data.options.GeneralOptions, _do_output: bool = True, parallel_options: instancespace.data.options.ParallelOptions | None = None) -> tuple[int, numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]:

Solve the projection problem numerically.

Parameters
  • x (NDArray[np.double]): The feature matrix (instances x features) to process.
  • hd (NDArray[np.double]): Condensed pairwise distances between the instances in feature space. The quality of each trial is the Pearson correlation between these distances and the distances in the projected space.
  • x0 (NDArray[np.double]): Initial guess for the solution.
  • x_bar (NDArray[np.double]): Combined matrix of X and Y.
  • n (int): Number of original features.
  • m (int): Total number of features including appended Y.
  • alpha (NDArray[np.double]): Flattened parameter vector containing both A (dimsn size) and B (mdims size) matrices.
  • eoptim (NDArray[np.double]): Optimized error function.
  • perf (NDArray[np.double]): Optimized performance matrix.
  • opts (PilotOptions): Configuration options for PILOT.
  • general_options (GeneralOptions): General options for all stages, for example verbosity.
  • parallel_options (ParallelOptions | None): Whether (and how much) to parallelise the ntries restarts across OS processes (matching MATLAB's parfor). None or flag=False runs the restarts sequentially. Ignored - falls back to sequential - when already running inside another process pool's worker (see multiprocessing.parent_process() check below): SIFTED's GA fitness function calls into pilot() from inside its own ProcessPoolExecutor workers, and opening a second, nested pool there would reintroduce MATLAB's nested-parfor-inside-GA bug. In practice this never triggers today, since SIFTED always calls pilot() with analytic=True (bypassing this numerical branch entirely) - this check guards against that invariant ever changing silently.
Returns
  • int: The index of the trial that has the highest distance correlation.
  • NDArray[np.double]: Flattened parameter vector containing both A (dimsn size) and B (mdims size) matrices.
  • NDArray[np.double]: Optimized error function.
  • NDArray[np.double]: Optimized performance matrix.
@staticmethod
def error_function( alpha: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x_bar: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], n: int, m: int, cost_weight: float = 1.0, d: int = 2) -> float:

Error function used for numerical optimization in the PILOT algorithm.

Parameters
  • alpha (NDArray[np.float64]): Flattened parameter vector containing both A (dn size) and B (md size) matrices.
  • x_bar (NDArray[np.float64]): Combined matrix of X and Y.
  • n (int): Number of original features.
  • m (int): Total number of features including appended Y.
  • cost_weight (float): Scalar weight applied to the performance columns' squared error (MATLAB's pilotErrorFcn costWeight). 1.0 weights every column equally.
  • d (int): Output projection dimensionality, either 2 or 3.
Returns
  • float: The mean squared error between x_bar and its low-dimensional approximation.

Pythia stage for automated algorithm selection.

The PythiaStage class is the main class for the Pythia stage. It contains the main function pythia that runs the Pythia stage.

Methods

_inputs() -> type[PythiaInput] Return the input type for the Pythia stage.

_outputs() -> type[PythiaOutput] Return the output type for the Pythia stage.

_run(inputs: PythiaInput) -> PythiaOutput Run the Pythia stage.

pythia(z: NDArray[np.double], y: NDArray[np.double], y_bin: NDArray[np.bool_], y_best: NDArray[np.double], algo_labels: list[str], opts: PythiaOptions, parallel_options: ParallelOptions) -> PythiaOutput Main method that perform automated algorithm selection.

_fit_classifier(z: NDArray[np.double], y_bin: NDArray[np.bool_], w: NDArray[np.double], skf: StratifiedKFold, classifier_name: str, is_poly_kernel: bool, param_space: dict[str, list[float]] | None, use_weights: bool, parallel_options: ParallelOptions, general_options: GeneralOptions, n_tuning_iter: int) -> _ClassifierResult Train the classifier selected by PythiaOptions.classifier.

_display_overall_perf(precision: list[float], accuracy: list[float]) -> None Output overall performance metrics.

_compute_znorm(z: NDArray[np.double]) -> tuple[NDArray[np.double], NDArray[np.double], NDArray[np.double]] Compute normalized feature matrix.

_check_precalcparams(params: NDArray[np.double] | None, nalgos: int) -> NDArray[np.double] | None Check pre-calculated hyper-parameters.

_determine_selections(nalgos: int, precision: list[float], y_hat: NDArray[np.bool_], y_bin: NDArray[np.bool_]) -> tuple[NDArray[np.int_], NDArray[np.int_]] Determine the selections based on the precision metrics.

_generate_summary(nalgos: int, algo_labels: list[str], y: NDArray[np.double], y_hat: NDArray[np.bool_], y_bin: NDArray[np.bool_], y_best: NDArray[np.double], selection0: NDArray[np.int_], selection1: NDArray[np.int_], accuracy: list[float], precision: list[float], recall: list[float], box_consnt: list[float], k_scale: list[float]) -> pd.DataFrames Generate a summary of the results.

PythiaStage( z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_raw: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], y_best: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], algo_labels: list[str])

Define the input for the Pythia stage.

Parameters
  • z (NDArray[np.double]): The feature matrix.
  • y_raw (NDArray[np.double]): The performance metrics.
  • y_bin (NDArray[np.bool_]): The binary labels.
  • y_best (NDArray[np.double]): The best performance metrics.
  • algo_labels (list[str]): The algorithm labels.
z
y
y_bin
y_best
algo_labels

Apply persisted PYTHIA state without fitting or mutating classifiers.

This is MATLAB's PYTHIAevalMode prediction core: normalize new coordinates with the parameters stored by the training run, apply each fitted classifier, pad test-only algorithms with empty predictions, and make the same precision-weighted recommendation as the build path.

Evaluate predictions with MATLAB's explicit confusion-count formulas.

MATLAB stores confusion counts in column-major order: [TN, FN, FP, TP]. Only observed instance/algorithm pairs contribute. inputs.observed has shape (n_instances, n_trained_algorithms) and must come from raw outcome availability, not binary labels. Accuracy uses the observed count for each algorithm. Missing classifiers, wholly unobserved algorithms and test-only algorithms retain NaN counts and rates.

@staticmethod
def pythia( z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], y_best: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], algo_labels: list[str], opts: instancespace.data.options.PythiaOptions, parallel_options: instancespace.data.options.ParallelOptions, general_options: instancespace.data.options.GeneralOptions) -> instancespace.stages.pythia.PythiaOutput:

Run the Pythia stage.

Parameters
  • z (NDArray[np.double]): The feature matrix.
  • y (NDArray[np.double]): The performance metrics.
  • y_bin (NDArray[np.bool_]): The binary labels.
  • y_best (NDArray[np.double]): The best performance metrics.
  • algo_labels (list[str]): The algorithm labels.
  • opts (PythiaOptions): The options for the Pythia stage.
  • parallel_options (ParallelOptions): The parallel options, specifiy whether run in parallel and number of cores.
  • general_options (GeneralOptions): General options (e.g. the RNG seed), not specific to any one stage.
Returns
  • PythiaOutput: The output of the Pythia stage.

CloisterStage class for Correlation-Based Boundary Estimation.

The CloisterStage class implements the core functionality of the CLOISTER stage, which estimates boundaries in a dataset by analyzing the correlation between features.

The class provides methods to compute Pearson correlation coefficients, filter insignificant correlations, and generate convex hulls to create boundary estimates.

Methods

__init__(x, a) Initializes the CloisterStage with the provided feature matrix x and projection matrix a.

_run(options) Executes the CLOISTER stage to estimate boundaries based on the configuration options.

cloister(x, a, options) Main method that estimates boundaries by analyzing correlations between features and applying convex hull construction.

_inputs() Defines the input parameters required for the CLOISTER stage, which include the feature matrix x and the projection matrix a.

_outputs() Defines the output parameters returned by the CLOISTER stage, which include the estimated boundary points (z_edge) and the correlation-based boundary points (z_ecorr).

_compute_correlation(x, options) Computes the Pearson correlation matrix for the feature matrix x, and filters correlations based on statistical significance using the provided p-value threshold.

_generate_boundaries(x, rho, options) Generates boundary points for the feature matrix x based on the computed correlation matrix rho and configuration options.

_compute_convex_hull(points) Computes the convex hull for a given set of points to estimate the boundary of the dataset.

_decimal_to_binary_matrix(nfeats) Generates a binary matrix representing all possible boundary combinations for a given number of features.

@staticmethod
def cloister( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], a: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], options: instancespace.data.options.CloisterOptions, x_mean: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]] | None = None) -> instancespace.stages.cloister.CloisterOutput:

Estimate a boundary for the space using correlation.

Parameters
  • x (NDArray[np.double]): Feature matrix (instances x features) to process.
  • a (NDArray[np.double]): Projection matrix computed from Pilot.
  • options (CloisterOptions): Configuration options for CLOISTER.
  • x_mean (NDArray[np.double] | None): Fitted PILOT feature mean; None retains the uncentred boundary.
Returns
  • The output of the Cloister stage.

A class to manage the TRACE analysis process for performance footprints.

The TRACE class is designed to analyze the performance of different algorithms by generating geometric footprints that represent areas of good, best, and beta performance. The footprints are constructed based on clustering of instance data and are evaluated for their density and purity relative to specific algorithmic performance metrics.

Attributes
  • z (NDArray[np.double]): The space of instances, represented as an array of data points (features).
  • y_bin (NDArray[np.bool_]): Binary indicators of performance, where each column corresponds to an algorithm's performance.
  • p (NDArray[np.int_]): Performance metrics for algorithms, represented as integers where each value corresponds to the index of an algorithm.
  • beta (NDArray[np.bool_]): Specific binary thresholds for footprint calculation.
  • algo_labels (list[str]): List of labels for each algorithm.
  • opts (TraceOptions): Configuration options for TRACE and its subroutines, controlling the behavior of the analysis.
TraceStage( z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], p: numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], beta: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], algo_labels: list[str], trace_opts: instancespace.data.options.TraceOptions, parallel_opts: instancespace.data.options.ParallelOptions, general_opts: instancespace.data.options.GeneralOptions, executor: concurrent.futures.thread.ThreadPoolExecutor | None = None, y_hat: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]] | None = None, pythia_skipped: bool = False)

Initialise the Trace analysis with provided data and options.

Parameters
  • z (NDArray[np.double]): The space of instances, represented as an array of data points (features).
  • y_bin (NDArray[np.bool_]): Binary indicators of performance for each algorithm.
  • p (NDArray[np.int_]): Performance metrics for algorithms, where each value corresponds to the index of an algorithm.
  • beta (NDArray[np.bool_]): Specific binary thresholds for footprint calculation.
  • algo_labels (list[str]): List of labels for each algorithm.
  • trace_opts (TraceOptions): Configuration options for TRACE and its subroutines.
  • parallel_opts (ParallelOptions): Configuration options for parallel processing in Matilda.
  • general_opts (GeneralOptions): General options (e.g. verbosity), not specific to any one stage.
  • executor (ThreadPoolExecutor | None): A caller-owned, already-running pool to submit footprint work to instead of creating and tearing down a fresh one. None (the default) preserves the previous per-call pool behaviour.
  • y_hat (NDArray[np.bool_] | None): Optional PYTHIA predictions used only by TRACE3.
  • pythia_skipped (bool): Whether PYTHIA intentionally returned placeholder predictions.
z
y_bin
p
beta
algo_labels
opts
parallel_opts
general_opts
executor
y_hat
pythia_skipped

Apply trained TRACE geometry without rebuilding or mutating it.

@staticmethod
def trace( z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], p: numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], beta: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], algo_labels: list[str], trace_opts: instancespace.data.options.TraceOptions, parallel_opts: instancespace.data.options.ParallelOptions, general_opts: instancespace.data.options.GeneralOptions, executor: concurrent.futures.thread.ThreadPoolExecutor | None = None, *, y_hat: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]] | None = None, pythia_skipped: bool = False) -> instancespace.stages.trace.TraceOutputs:

Perform the TRACE footprint analysis.

Parameters
  • z (NDArray[np.double]): The space of instances.
  • y_bin (NDArray[np.bool_]): Binary indicators of performance.
  • p (NDArray[np.int_]): Performance metrics for algorithms.
  • beta (NDArray[np.bool_]): Specific beta threshold for footprint calculation.
  • algo_labels (list[str]): Labels for each algorithm.
  • trace_opts (TraceOptions): Configuration options for TRACE and its subroutines.
  • parallel_opts (ParallelOptions): Configuration options for parallel processing in Matilda.
  • general_opts (GeneralOptions): General options for all stages, for example verbosity.
  • executor (ThreadPoolExecutor | None): A caller-owned pool to reuse instead of creating a fresh one.
  • y_hat (NDArray[np.bool_] | None): Optional PYTHIA predictions used only by TRACE3.
  • pythia_skipped (bool): Whether PYTHIA intentionally returned placeholder predictions.
Returns
  • TraceOutputs: The analysis results. These include the footprints and the summary statistics.
@staticmethod
def rescore( trained: instancespace.data.model.TraceOut, z: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], p: numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]], beta: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], algo_labels: list[str]) -> instancespace.data.model.TraceOut:

Re-evaluate trained geometry against new truth without rebuilding it.

def build( self, y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]]) -> instancespace.data.model.Footprint:

Construct a footprint polygon using DBSCAN clustering.

Parameters
  • y_bin (NDArray[np.bool_]): Binary indicator vector indicating which data points are of interest.
Returns
  • Footprint: The constructed footprint with calculated area, density, and purity.
def contra( self, base: instancespace.data.model.Footprint, test: instancespace.data.model.Footprint, y_base: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], y_test: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]]) -> tuple[instancespace.data.model.Footprint, instancespace.data.model.Footprint]:

Detect and resolve contradictions between two footprint polygons.

Parameters
  • base (Footprint): The base footprint polygon.
  • test (Footprint): The test footprint polygon.
  • y_base (NDArray[np.bool_]): Binary array indicating the points corresponding to the base footprint.
  • y_test (NDArray[np.bool_]): Binary array indicating the points corresponding to the test footprint.
Returns
  • tuple: Updated base and test footprints after resolving contradictions.
def tight( self, polygon: shapely.geometry.polygon.Polygon | shapely.geometry.multipolygon.MultiPolygon, y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]]) -> shapely.geometry.polygon.Polygon | shapely.geometry.multipolygon.MultiPolygon:

Refine an existing polygon by removing slivers and improving its shape.

Parameters
  • polygon (Polygon | MultiPolygon): The polygon or multipolygon to be refined.
  • y_bin (NDArray[np.bool_]): Binary array indicating which data points belong to the polygon.
Returns
  • Polygon | MultiPolygon: The refined polygon, or an empty polygon if refinement fails.
def fit_poly( self, polydata: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]]) -> shapely.geometry.polygon.Polygon | shapely.geometry.multipolygon.MultiPolygon | None:

Fit a polygon to the given data points, following the purity constraints.

Parameters
  • polydata (NDArray[np.double]): The data points to fit the polygon to.
  • y_bin (NDArray[np.bool_]): Binary array indicating which data points should be considered for the polygon.
Returns
  • Polygon | MultiPolygon | None: The fitted polygon, or None if the fitting fails.
@staticmethod
def summary( footprint: instancespace.data.model.Footprint, space_area: float, space_density: float) -> list[float]:

Summarize the footprint metrics.

Parameters
  • footprint (Footprint): The footprint to summarize.
  • space_area (float): The total area of the space being analyzed.
  • space_density (float): The density of the entire space.
Returns
  • list: A list containing summarized metrics such as area, normalized area, density, normalized density, and purity.

Generate a footprint with default values, indicating insufficient data.

Returns
  • Footprint: An instance of Footprint with default values.
@staticmethod
def run_dbscan( y_bin: numpy.ndarray[typing.Any, numpy.dtype[numpy.bool_]], data: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]]:

Perform DBSCAN clustering on the dataset.

Parameters
  • y_bin (NDArray[np.bool_]): Binary indicator vector to filter the data points.
  • data (NDArray[np.double]): The dataset to cluster.
Returns
  • NDArray[np.int_]: Array of cluster labels for each data point.
@staticmethod
def epsilon( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], k: int) -> float:

Analytical way of estimating neighborhood radius for DBSCAN.

Parameters
  • x (NDArray[np.double]): data matrix (m, n); m-objects, n-variables
  • k (int): number of objects in a neighborhood of an object (minimal number of objects considered as a cluster)
Returns
  • float: The estimated neighborhood radius.
@staticmethod
def dist( i: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]:

Calculate the Euclidean distances between objects.

Parameters
  • i (NDArray[np.double]): an object (1, n)
  • x (NDArray[np.double]): data matrix (m, n); m-objects, n-variables
Returns
  • NDArray[np.double]: The Euclidean distances, with shape (m,).
@staticmethod
def dbscan( x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], k: int, eps: float) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.int64]]:

Density-Based Spatial Clustering of Applications with Noise (DBSCAN).

Parameters
  • x (NDArray[np.double]): data matrix (m, n); m-objects, n-variables
  • k (int): minimum number of points to form a cluster
  • eps (float): neighborhood radius; if None, it will be estimated using the epsilon function
Returns
  • NDArray[np.int_]: Cluster assignments for each point (-1 for noise)
def process_algorithm( self, i: int) -> tuple[int, instancespace.data.model.Footprint, instancespace.data.model.Footprint]:

Process an algorithm to calculate its good and best performance footprints.

Parameters
  • i (int): Index of the algorithm to process.
Returns
  • tuple[int, Footprint, Footprint]: The index of the algorithm, and its good and best performance footprints.
def compute_algorithm_qualities( self, n_algos: int) -> tuple[list[instancespace.data.model.Footprint], list[instancespace.data.model.Footprint]]:

Perform parallel processing to calculate footprints for multiple algorithms.

Parameters
  • n_workers (int): Number of worker threads to use.
  • n_algos (int): Number of algorithms to process.
Returns
  • tuple[list[Footprint], list[Footprint]]: Lists of good and best performance footprints for each algorithm.
class PredictiveStage(abc.ABC, typing.Generic[~PREDICT_IN, ~FITTED, ~PREDICT_OUT]):

Optional contract for applying a fitted stage to unseen data.

This is separate from Stage so build-only stages and plugins do not need to implement inference, and so the build-only StageRunner contract remains unchanged.

@staticmethod
@abstractmethod
def predict(inputs: ~PREDICT_IN, fitted: ~FITTED) -> ~PREDICT_OUT:

Apply fitted state without training or mutating it.