mixle.utils.vector module

Vector and sorted-array utilities used by Mixle estimators.

The helpers cover special functions, sorted merges, count aggregation, and linear-algebra conveniences shared by legacy estimation and evaluation code.

owned_backend_parameter(value)[source]

Return a defensive copy of a distribution parameter for either array backend.

Backend scoring hands its own parameters to an engine and copies first so engine ops cannot alias distribution state. .copy() alone assumes NumPy: under gradient fitting the parameter IS a live torch tensor, which has no .copy() and raised AttributeError: 'Tensor' object has no attribute 'copy'. clone() is the tensor equivalent AND keeps the autograd graph intact – detach() would silently sever it and stop the fit learning. For a NumPy array this is exactly the previous .copy().

exception ImpossibleEvidenceError[source]

Bases: ValueError

Raised when log evidence has zero mass and no posterior exists.

require_possible_log_evidence(log_evidence, *, context)[source]

Return validated log evidence or raise before posterior/statistic construction.

Batch latent-variable updates must not silently discard a zero-probability record or replace its undefined posterior with synthetic responsibilities. This helper gives those implementations one transactional failure contract.

Parameters:
Return type:

ndarray

validate_initialization_probability(p)[source]

Return a finite Bernoulli initialization probability in [0, 1].

Parameters:

p (object)

Return type:

float

validated_initialized_observations(nobs)[source]

Return a finite non-negative selected-observation count, permitting zero.

Zero is a legitimate per-shard/per-restart outcome, not an error: random initialization can hand a shard (or a component within one) no rows, and estimators already handle a zero count through their prior/pseudo-count path. Use require_initialized_observations() instead for a count aggregated across every shard, where zero really does mean no evidence anywhere.

Parameters:

nobs (object)

Return type:

float

require_initialized_observations(nobs)[source]

Return a positive selected-observation count or raise typed impossible evidence.

Only appropriate where nobs is a total across all shards: a global zero means the initialization saw no evidence at all. A single shard selecting nothing is ordinary and must go through validated_initialized_observations().

Parameters:

nobs (object)

Return type:

float

gammaln(x: ndarray) → ndarray[source]
gammaln(x: float) → float

Return logrithm of the gamma function.

Returns np.log(.np.abs(Gamma(x)))

Parameters:

x (Union[np.ndarray, float, int])) – Takes numeric value of np.ndarray of float/int.

Returns:

log(Gamma(x)) as float if x is a float/int, or np.ndarray[np.float] if x is a numpy array.

Return type:

ndarray | float

sorted_merge(a, b)[source]

Performs the merge-step of merge sort on sorted np.ndarray’s a and b, returning sorted array.

Parameters:
  • a (ndarray) – Sorted numpy array.

  • b (ndarray) – Sorted numpy array.

Returns:

Sorted numpy array containing merge sorted a and b. Array len = len(a)+len(b).

Return type:

ndarray

sorted_dict_merge_add(k_vec1, c_vec1, k_vec2, c_vec2)[source]

Performs a merge on two sorted arrays of dictionary keys and the counts for their respective keys.

Returns the merge sorted keys and corresponding counts.

Parameters:
  • k_vec1 (ndarray) – Numpy array of sorted dictionary keys.

  • c_vec1 (ndarray) – Numpy array of counts for keys in vector k_vec1.

  • k_vec2 (ndarray) – Numpy array of sorted dictionary keys.

  • c_vec2 (ndarray) – Numpy array of counts for keys in vector k_vec2.

Returns:

Tuple of numpy arrays containing the merge sorted dictionary keys and corresponding counts.

Return type:

tuple[ndarray, ndarray]

make(x)[source]

Convert the array x into a numpy array.

Parameters:
  • x (Union[np.ndarray, Sequence[Union[int, float, str]]) – Array like object that can be converted to a numpy

  • lists (array. E.g.)

  • tuples (tuples of)

  • tuples

  • tuples

  • ndarrays. (tuples of lists and)

Returns:

Numpy array conversion of x.

Return type:

ndarray

make_pdf(x)[source]

Takes log density values and normalizes on the log-scale, returning an ndarray that s.t. np.exp(rv).sum() == 1.0.

Arg data type for x: Union[np.ndarray, Sequence[float], List[np.ndarray]]). :param x: Array like object with float data type that can be converted to a numpy array. E.g. lists, lists :type x: See above :param of tuples: :param tuples: :param tuples of tuples: :param tuples of lists and ndarrays.:

Returns:

Returns an ndarray that s.t. np.exp(rv).sum() == 1.0.

Parameters:

x (ndarray | Sequence[float] | list[ndarray])

zeros(n)[source]

Return numpy array of shape n, with default dtype=float64.

Parameters:

n (Union[int, Iterable, Tuple[int]]) – Shape tuple of ints, Iterable, or int.

Returns:

Return numpy array of shape n, with default dtype=float64.

Return type:

ndarray

mat_inv(x)[source]

Computes the inverse of a square matrix x.

Arg x data type Union[List[List[Union[float, int]]],List[np.ndarray], np.ndarray]). :param x: List of List[float/int], List of np.ndarray, or 2-d np.ndarray of square matrix. :type x: See above

Returns:

Inverse of x as 2-d numpy array.

Parameters:

x (list[list[float | int]] | list[ndarray] | ndarray)

Return type:

ndarray

dot(x, y)[source]

Performs call to numpy.dot().

Parameters:
Returns:

Returns float/int if x and y are both 1d vectors, returns 1d vector if x xor y is scalar, and matrix else.

Return type:

ndarray | float

outer(x, y)[source]

Compute the outer product of two vectors

Parameters:
Return type:

ndarray

Returns: (M, N) ndarray.

diag(x)[source]

Extract a diagonal or construct a diagonal array.

Note: If x is 2-D return np.ndarray with diagonal. If x is 1-D returns 2-d diagonal matrix with x on diagonal.

See the more detailed documentation for numpy.diagonal if you use this function to extract a diagonal and wish to write to the resulting array; whether it returns a copy or a view depends on what version of numpy you are using.

Parameters:

x (ndarray) – 2-D array, or 1-D array.

Returns:

The extracted diagonal or constructed diagonal array.

Return type:

ndarray

reshape(x, sz)[source]

Gives a new shape to an array without changing its data.

Parameters:
  • x (np.ndarray) – Array to be reshaped.

  • sz (Tuple[int,...]) – Shape compatible with size of array x.

Returns:

Reshaped array containing elements of x with shape = sz.

Return type:

ndarray

cholesky(x_mat)[source]

Compute the Cholesky decomposition of a matrix, to use in cho_solve.

Returns a matrix containing the Cholesky decomposition, x_mat = L L* or x_mat = U* U of a Hermitian positive-definite matrix x_mat. The return value can be directly used as the first parameter to cho_solve.

Parameters:

x_mat (np.ndarray) – Square np.ndarray of matrix to be decomposed.

Returns:

Square np.ndarray matrix whose upper or lower triangle contains the Cholesky factor of x. If Cholesky

factor cannot be found None is returned.

Return type:

tuple[ndarray, bool] | None

cho_solve(a_mat, b)[source]

Solve the linear equations a_mat x = b, given the Cholesky factorization of a_mat.

Parameters:
  • a_mat (Tuple[np.ndarray, bool]) – Cholesky factorization of a, as given by cho_factor.

  • b (np.ndarray) – Right-hand side np.ndarray in a_mat*x = b.

Returns:

The solution to the system a_mat*x = b.

Return type:

ndarray

cholesky_logdet(mat)[source]

Attempt a Cholesky factorization of mat, returning its log-determinant, or None if mat is not positive definite.

This is the correct way to test positive-definiteness of a symmetric matrix. Determinant sign (e.g. from np.linalg.slogdet) is not sufficient: a matrix can have positive determinant while being negative definite or indefinite (e.g. -I in an even dimension has determinant (-1)^d = +1 while every eigenvalue is negative). Cholesky fails on exactly the matrices that are not positive definite, and its diagonal gives the log-determinant as a free byproduct. Callers that also require symmetry (e.g. correlation/covariance matrices) must check that separately – cho_factor only reads one triangle and does not itself verify the other.

Parameters:

mat (np.ndarray) – Square matrix to factor.

Returns:

The log-determinant of mat if it is positive definite, else None.

Return type:

float | None

batched_pd_logdet(x)[source]

Vectorized positive-definite check and log-determinant for a stack of symmetric matrices, shape (…, p, p).

Analogous to np.linalg.slogdet’s (sign, logdet) return, but with a correct positive-definite test in place of a sign check (see cholesky_logdet for why sign is not sufficient). Cholesky does not vectorize usefully here: np.linalg.cholesky on a stacked batch raises LinAlgError for the whole batch if even one matrix fails, instead of flagging just that one. eigvalsh has no such issue – it never raises for a symmetric input, definite or not.

Parameters:

x (np.ndarray) – Stack of symmetric matrices, shape (…, p, p).

Returns:

-2]. is_pd[i] is True iff x[i] is positive definite (every eigenvalue > 0). logdet[i] is log(|det(x[i])|) regardless of definiteness (finite whenever x[i] is nonsingular) – combine with is_pd via np.where the same way slogdet’s sign output is used, discarding logdet where is_pd is False.

Return type:

Tuple (is_pd, logdet), each shape x.shape[

maximum(x, y, output=None)[source]

Element-wise maximum of array elements.

Compare two arrays and returns a new array containing the element-wise maxima. If one of the elements being compared is a NaN, then that element is returned. If both elements are NaNs then the first is returned. The latter distinction is important for complex NaNs, which are defined as at least one of the real or imaginary parts being a NaN. The net effect is that NaNs are propagated.

Parameters:
  • x (array-like) – Array-like holding values to be compared. If x.shape != y.shape, they must be broadcastable to a common shape (which becomes the shape of the output).

  • y (array-like) – Array-like holding values to be compared. If x.shape != y.shape, they must be broadcastable to a common shape (which becomes the shape of the output).

  • output (float | int | ndarray | None) – Optional np.ndarray of float to output results to.

Returns:

ndarray or scalar. The maximum of x and y, element-wise. This is a scalar if both x and y are scalars.

Return type:

float | int | ndarray

log_sum(x)[source]

Performs log(sum(exp(x)) on 1-d numpy array. E.g. for x_i = log(y_i), log(sum(exp(x)) = log(sum(y)).

Parameters:

x (ndarray) – Numpy array on log-scale. E.g. x_i = log(y_i).

Returns:

Float value log(sum(exp(x)), or -np.inf if max(x) is -np.inf.

Return type:

float

weighted_log_sum(x, w)[source]

Computes numerically stable log-sum-of-exponentials with weights=exp(w), on the observation values y=exp(x), returning log(sum(exp(x)*exp(w))).

Note: The weights are on the log-scale.

Parameters:
  • x (ndarray) – Numpy array on log-scale. E.g. x_i = log(y_i).

  • w (ndarray) – Numpy array on of weights for y_i = exp(x_i) on the log-scale. E.g. w_i = log(weight_i).

Returns:

Float value log(sum(exp(x)*exp(w))), or -np.inf if any x or w are -np.inf. Inputs are log-densities and log-weights (<= 0); +inf terms are not supported (this is a hot EM path).

Return type:

float

log_posterior(x)[source]

Computes posterior density for vector of log-likelihood evaluated at each parameter component.

I.e. if,

x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))],

then returned value is,

[log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))],

where,

log(p_mat(theta_j| obs_i)) = log(p_mat(obs_i| theta_j)) - log(p_mat(obs_i)).

Parameters:

x (np.ndarray) – Numpy array of log-density values for each component/parameter value x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))].

Returns:

Numpy array of log-posterior for each component/parameter value

[log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))]. Returns numpy array of [-log(len(x))] if nan or inf detected in x.

Return type:

ndarray

posterior(log_x, out=None, log_sum=False)[source]

Computes posterior density for vector of log-likelihood evaluated at each parameter component.

I.e. if, log_x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))],

then returned value is,

[p_mat(theta_0| obs_i),…,p_mat(theta_{n-1}|obs_i)],

where,

p_mat(theta_j| obs_i) = p_mat(obs_i| theta_j) / p_mat(obs_i).

Parameters:
  • log_x (ndarray) – Numpy array of log-density values for each component/parameter value log_x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))].

  • out (Optional[ndarray]) – Optional numpy array to store returned value.

  • log_sum (Optional[bool]) – If true returns Tuple with ([p_mat(obs_i|theta_j)], log(p_mat(obs_i))).

Returns:

Numpy array of posterior for each component/parameter value [p_mat(theta_0| obs_i),…,p_mat(theta_{n-1}|obs_i)]. Optional tuple with ([p_mat(obs_i|theta_j)], log(p_mat(obs_i))) if log_sum true.

Return type:

ndarray | tuple[ndarray, float]

log_posterior_sum(x)[source]

Computes posterior density for vector of log-likelihood evaluated at each parameter component.

I.e. if,

log_x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))],

then returned value is a Tuple containing,

[log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))] and log(p_mat(obs_i)),

where, p_mat(theta_j| obs_i) = p_mat(obs_i| theta_j) / p_mat(obs_i).

Parameters:

x (np.ndarray) – Numpy array of log-density values for each component/parameter value log_x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))].

Returns:

Tuple of numpy array containing log-posterior for each component/parameter value

[log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))], and log(p_mat(obs_i))). The log-posterior value is [-log(len(x)),…,-log(len(x))] if x contains a nan or -np.inf value.

Return type:

tuple[ndarray, float]

weighted_log_posterior(x, w)[source]

Computes weighted posterior density for vector of log-likelihood evaluated at each parameter component.

I.e. if, x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))], and w = [log(weight_0),log(weight_1),…,log(weight_{n-1})],

then returned value is a list of floats,

[log(p_mat(theta_0| obs_i))+log(weight_0),…,log(p_mat(theta_{n-1}|obs_i))+log(weight_{n-1})].

Parameters:
  • x (ndarray) – Numpy array of log-density values for each component/parameter value

  • w (ndarray) – Numpy array of log weights for each parameter value.

Returns:

List[float] containing log-posterior for each component/parameter value [log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))].

Return type:

list[float]

weighted_log_posterior_sum(x, w)[source]

Computes weighted posterior density for vector of log-likelihood evaluated at each parameter component.

I.e. if,

x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))], and w = [log(weight_0),log(weight_1),…,log(weight_{n-1})],

then returned value is a Tuple of List[float] and float, containing

[log(p_mat(theta_0| obs_i))+log(weight_0),…,log(p_mat(theta_{n-1}|obs_i))+log(weight_{n-1})], and log(p_mat(obs_i)),

where, p_mat(theta_j| obs_i) = p_mat(obs_i| theta_j) / p_mat(obs_i).

Parameters:
  • x (ndarray) – (np.ndarray): numpy array of log-density values for each component/parameter value log_x = [log(p_mat(obs_i | theta_0)), log(p_mat(obs_i | theta_1)),…, log(p_mat(obs_i | theta_{n-1}))].

  • w (np.ndarray) – List[float] or numpy array of log weights for each parameter value.

Returns:

Tuple of List[float] containing log-posterior for each component/parameter value [log(p_mat(theta_0| obs_i)),…,log(p_mat(theta_{n-1}|obs_i))] and log(p_mat(obs_i).

Return type:

tuple[list[float], float]

matrix_log_posteriors(x, u_mat, u)[source]
Parameters:
Returns:

Return type:

tuple[ndarray, ndarray, float]

row_choice(p_mat, rng)[source]

Vectorized choice call for varying sampling weights on contained in the rows of p_mat.

N, S = p_mat.shape

Choice is called on range [0,S), where the rows of p_mat are the sample weights.

An N dim np.ndarray of ints is returned.

Parameters:
  • p_mat (np.ndarray) – N by S matrix with weights

  • rng (Optional[RandomState]) – Set see for sampling.

Returns:

N dim numpy array of ints.

Return type:

ndarray