qpots.utils.utils

General utility functions for multi-objective Bayesian optimization, including standardization helpers, hypervolume calculations, candidate selection, partial information helpers, and command-line argument parsing.

qpots.utils.utils._augment_X_with_tasks(X: Tensor, num_tasks: int, task_feature: int) Tensor[source]

Build long-format MultiTaskGP inputs from task-free design points.

Parameters:
  • X (torch.Tensor) – Base design matrix with shape n x d and no task feature.

  • num_tasks (int) – Number of task/output indices to append.

  • task_feature (int) – Position where the task index should be inserted in the augmented d + 1 dimensional input. Negative indices follow Python indexing.

Returns:

Augmented tensor with shape (n * num_tasks) x (d + 1). Rows are grouped by task index.

Return type:

torch.Tensor

Raises:

ValueError – If X is not two-dimensional or task_feature is invalid for the augmented input dimension.

qpots.utils.utils._stable_logdet(A: ndarray, jitter: float = 1e-10, max_tries: int = 8) float[source]

Numerically stable log(det(A)) for (near) PSD matrices by adding diagonal jitter if needed. Raises if it cannot make the matrix numerically positive definite.

qpots.utils.utils.arg_parser()[source]

Parses command-line arguments for the multi-objective Bayesian optimization script.

This function provides default values for each argument, allowing customization for different optimization setups, including high-performance computing (HPC) environments.

Returns:

Parsed command-line arguments.

Return type:

argparse.Namespace

qpots.utils.utils.argmax_mi_subset_bruteforce(cov_or_samples: ndarray, *, subset_size: int | None = None, jitter: float = 1e-10, base: float = 2.718281828459045, assume_samples: bool | None = None, deduplicate_complements: bool = True, return_all_scores: bool = False) Dict[str, Any][source]

Brute-force search over output subsets under a Gaussian assumption.

You can pass either:
  • cov_or_samples as a (K,K) covariance matrix, OR

  • cov_or_samples as (N,K) samples (rows=samples), from which we estimate covariance.

Parameters:
  • cov_or_samples (np.ndarray) – (K,K) covariance OR (N,K) samples.

  • subset_size (int or None) – If provided, restrict search to subsets whose size equals subset_size. If None, searches all non-trivial subsets (excluding empty/full).

  • jitter (see above)

  • base (see above)

  • assume_samples (bool or None) – If None, auto-detect: (K,K) => covariance; otherwise => samples.

  • deduplicate_complements (bool) – If subset_size is None, avoid evaluating both a subset and its complement by restricting the search to subsets of size at most floor(K / 2). This is safe because the split mutual information is symmetric.

  • return_all_scores (bool) – If True, returns a dict mapping subset tuples -> MI score (can be large: O(2^K)).

Returns:

result

  • “S”: tuple of indices for the best subset

  • ”Sc”: tuple of indices for the complement

  • ”mi”: best MI value

  • ”cov”: covariance used

  • optionally “scores”: dict[(tuple)->float] if return_all_scores=True

Return type:

dict with keys

qpots.utils.utils.compute_true_hypervolume(Y: Tensor, ref_point, nobj, ncons, maximize) Tensor[source]

Compute true hypervolume .

Parameters:
  • Y – (n, d) evaluated y values.

  • ref_point – reference point in objective space, length K (K inferred from this).

  • maximize – if False, treats objectives as minimization (internally negates).

Returns:

hypervolume of the non-dominated posterior-mean outcomes.

Return type:

A scalar tensor

qpots.utils.utils.corr_and_total_correlation(cov: Tensor, jitter: float = 1e-06, eps: float = 1e-12)[source]

Compute task correlation matrix R and total correlation TC from an inter-task covariance matrix.

Parameters:
  • cov – (…, m, m) symmetric covariance matrix across m tasks (e.g., posterior Cov[f(x)]).

  • jitter – diagonal jitter added to R before Cholesky/logdet for numerical stability.

  • eps – clamp floor for variances to avoid divide-by-zero.

Returns:

(…, m, m) correlation matrix. TC: (…) total correlation in nats, TC = -0.5 * logdet(R).

Return type:

R

qpots.utils.utils.expected_hypervolume(gps: ModelObject, ref_point: Tensor | None = None, min: bool = False) Tuple[float, Tensor][source]

Compute the expected hypervolume and Pareto front based on GP model predictions.

Parameters:
  • gps (ModelObject) – The multi-objective GP models.

  • ref_point (torch.Tensor, optional) – Reference point for hypervolume calculation.

  • min (bool, optional) – If True, minimizes the objectives instead of maximizing them.

Returns:

  • hypervolume_value (float): The computed hypervolume.

  • pareto_front (torch.Tensor): The Pareto front tensor.

Return type:

tuple

qpots.utils.utils.gen_filtered_cands(gps: ModelObject, cands: Tensor, ref_point: Tensor | None = None, kernel_bandwidth: float = 0.05) Tensor[source]

Generate filtered candidate points based on the current Pareto front using Kernel Density Estimation (KDE).

Parameters:
  • gps (ModelObject) – The multi-objective GP models.

  • cands (torch.Tensor) – Candidate points to filter.

  • ref_point (torch.Tensor, optional) – Reference point for the Pareto front.

  • kernel_bandwidth (float, optional) – Bandwidth for the KDE filter.

Returns:

Filtered candidate points.

Return type:

torch.Tensor

qpots.utils.utils.hypervolume_from_posterior_mean_mtgp(mt_model, X: Tensor, task_feature: int, *, ref_point, maximize) Tensor[source]

Compute hypervolume of the posterior mean vectors produced by a MultiTaskGP.

Parameters:
  • mt_model – fitted MultiTaskGP (task encoded as input feature).

  • X – (n, d) points at which to compute posterior mean for each task.

  • task_feature – index where the task column lives in the augmented input (d+1).

  • ref_point – reference point in objective space, length K (K inferred from this).

  • maximize – if False, treats objectives as minimization (internally negates).

Returns:

hypervolume of the non-dominated posterior-mean outcomes.

Return type:

A scalar tensor

qpots.utils.utils.minmax_scale(x, dim=None, eps=1e-12)[source]

Rescale a tensor to the [0, 1] interval.

Parameters:
  • x (torch.Tensor) – Input tensor of any shape.

  • dim (int or None, optional) – Dimension along which to compute the minimum and maximum. If None, scale globally across the whole tensor.

  • eps (float, optional) – Small denominator floor that prevents division by zero when all values along a slice are equal.

Returns:

Tensor with the same shape as x and values scaled to [0, 1] up to numerical precision.

Return type:

torch.Tensor

qpots.utils.utils.mtgp_posterior_mean_hypervolume(gps: ModelObject, ref_point: Tensor | None = None)[source]

Compute the expected hypervolume based ONLY on MTGP model predictions.

Parameters:
  • gps (ModelObject) – The multi-objective GP models.

  • ref_point (torch.Tensor, optional) – Reference point for hypervolume calculation.

qpots.utils.utils.mutual_information_split_gaussian(cov: ndarray, S: Sequence[int], *, jitter: float = 1e-10, base: float = 2.718281828459045) float[source]

Compute I(Y_S ; Y_{Sc}) under a multivariate Gaussian with covariance cov.

Parameters:
  • cov ((K, K) array) – Covariance matrix of Y.

  • S (sequence of ints) – Indices in the subset S.

  • jitter (float) – Diagonal jitter used for stable log-determinants.

  • base (float) – Log base. Use base=2.0 for bits, base=np.e for nats.

Returns:

mi – Mutual information I(Y_S ; Y_{Sc}) in the chosen log base.

Return type:

float

qpots.utils.utils.posterior_mean_fill(gps: ModelObject)[source]

Fill missing values in training targets using the GP posterior mean.

After partial-information updates, gps.train_y may contain NaN entries, which makes it impossible to compute metrics like the true Pareto front directly. This function replaces all NaN entries with the corresponding posterior mean predicted by the MultiTaskGP model for that input and task.

Parameters:

gps (ModelObject) – Object containing the MultiTaskGP model(s) and training data, including train_x, train_y, number of objectives (nobj), and constraints (ncons).

Returns:

A tensor of the same shape as gps.train_y with NaNs replaced by the posterior mean for each missing entry.

Return type:

torch.Tensor

qpots.utils.utils.select_candidates(gps: ModelObject, pareto_set: ndarray, device: device, q: int = 1, seed: int | None = None) Tensor[source]

Select candidates from the Pareto-optimal set.

Parameters:
  • gps (ModelObject) – Gaussian Process models.

  • pareto_set (numpy.ndarray) – Pareto-optimal set of solutions.

  • device (torch.device) – Device to store the selected candidates.

  • q (int, optional) – Number of candidates to select. Defaults to 1.

  • seed (int, optional) – Random seed for sampling.

Returns:

Selected candidate points.

Return type:

torch.Tensor

qpots.utils.utils.select_candidates_partial_info(gps: ModelObject, pareto_set: ndarray, device: device, q: int = 1, seed: int | None = None, thresh: float | None = None, rescaling: str = '_') Tensor[source]

Select candidates from the Pareto-optimal set using partial information.

This function selects q candidate points from a given Pareto-optimal set and assigns tasks for evaluation. Task selection can be either random or based on a variance threshold. If thresh is provided, tasks with posterior variance above the threshold are chosen. Otherwise, tasks are selected randomly. Any candidates with all-NaN task assignments are removed.

Parameters:
  • gps (ModelObject) – Object containing Gaussian Process models, including training data and number of objectives/constraints.

  • pareto_set (numpy.ndarray) – Pareto-optimal set of solutions. Shape [num_points, num_variables].

  • device (torch.device) – Device to store the selected candidates (CPU or GPU).

  • q (int, optional) – Number of candidates to select. Defaults to 1.

  • seed (int, optional) – Random seed for reproducibility when selecting tasks randomly or applying variance thresholding.

  • thresh (float, optional) – Variance threshold for selecting tasks. If None, tasks are chosen randomly.

  • rescaling (str, optional) – Method to rescale variance for thresholding. Options are: - “_” : no rescaling (raw variance) - “std” : standardize to mean 0, std 1 - “norm” : normalize to [0, 1]

Returns:

  • selected_candidates: Tensor of shape [num_selected, num_variables] containing the chosen candidate points.

  • task_ids: Tensor of shape [num_selected, num_tasks] indicating which tasks are selected for each candidate.

Return type:

Tuple[torch.Tensor, torch.Tensor]

qpots.utils.utils.select_candidates_total_correlation(gps: ModelObject, pareto_set: ndarray, device: device, q: int = 1, seed: int | None = None, thresh: float | None = None) Tensor[source]

Select Pareto-set candidates and choose which outputs to evaluate.

Candidate locations are chosen from the sampled Pareto set using the same maximin-distance heuristic as select_candidates. If thresh is None, each selected location receives a random subset of outputs. If a threshold is provided, the posterior output covariance at each candidate is converted to total correlation. Highly coupled candidates are assigned the subset of outputs that maximizes Gaussian mutual information; weakly coupled candidates are assigned all outputs.

Parameters:
  • gps (ModelObject) – Fitted model container. This routine expects gps.models[0] to be a multi-output model whose posterior exposes the joint covariance across outputs.

  • pareto_set (numpy.ndarray) – Candidate Pareto-optimal design points returned by NSGA-II, with shape n_pareto x d.

  • device (torch.device) – Device used for the returned candidate tensor.

  • q (int, optional) – Maximum number of design points to select.

  • seed (int, optional) – Reserved for reproducible random task selection.

  • thresh (float, optional) – Total-correlation threshold. None enables random task selection; otherwise candidates with abs(TC) > thresh use the mutual information split and candidates below the threshold evaluate all outputs.

Returns:

Selected candidates and a task-id matrix. Task entries contain the output index to evaluate or NaN when that output is skipped.

Return type:

tuple[torch.Tensor, torch.Tensor]

Notes

The feasibility/objective convention follows the rest of qPOTS: objectives and constraints are modeled together, with constraints stored after the objective columns.

qpots.utils.utils.unstandardize(Y: Tensor, train_y: Tensor) Tensor[source]

Reverse the standardization of output Y using the mean and standard deviation computed from the training data.

Parameters:
  • Y (torch.Tensor) – The standardized output tensor.

  • train_y (torch.Tensor) – The training output data used to compute the mean and standard deviation.

Returns:

The unstandardized output tensor.

Return type:

torch.Tensor

qpots.utils.utils.unstandardize_ignore_nan(Y: Tensor, train_y: Tensor, correction: int = 1) Tensor[source]

Reverse the standardization of output Y using the mean and standard deviation computed from the training data, works when NaN values are in the train_y tensor.

Parameters:
  • Y (torch.Tensor) – The standardized output tensor.

  • train_y (torch.Tensor) – The training output data used to compute the mean and standard deviation.

Returns:

The unstandardized output tensor.

Return type:

torch.Tensor