pprop.propagator.utils module

Utility functions for the Propagator class.

Provides: - requires_propagation() – decorator guarding methods until propagation is done. - remove_duplicate_observables() – deduplicates PennyLane observables by hash. - build_arrays() – converts CoeffTerms into dense NumPy arrays. - make_evaluator() – compiles CoeffTerms into fast numeric callables.

pprop.propagator.utils.build_arrays(expr, num_params)[source]

Convert a CoeffTerms list into dense NumPy arrays for vectorised evaluation.

Each term in expr encodes a product of the form:

\[c \prod_{i \in \text{sin\_idx}} \sin(\theta_i) \prod_{j \in \text{cos\_idx}} \cos(\theta_j)\]

where indices may repeat, encoding powers. For example, sin_idx = [2, 2, 3] encodes \(\sin^2(\theta_2)\,\sin(\theta_3)\). The full expression is the sum over all terms:

\[f(\boldsymbol{\theta}) = \sum_k c_k \prod_j \sin^{s_{kj}}(\theta_j) \prod_j \cos^{p_{kj}}(\theta_j)\]

where \(s_{kj}\) and \(p_{kj}\) are the number of times parameter \(j\) appears in sin_idx and cos_idx of term \(k\).

This function unpacks the index lists into integer count arrays of shape (n_terms, num_params) so that the full expression can be evaluated via np.power and NumPy broadcasting instead of Python loops.

Parameters:
  • expr (CoeffTerms) – List of (coeff, sin_indices, cos_indices) tuples. Indices may repeat.

  • num_params (int) – Total number of circuit parameters (length of the θ vector).

Returns:

  • coeffs (ndarray of shape (n_terms,), dtype float64) – Scalar coefficient of each term.

  • sin_counts (ndarray of shape (n_terms, num_params), dtype int32) – sin_counts[i, j] is the number of times parameter j appears in sin_idx of term i, i.e. the power of \(\sin(\theta_j)\).

  • cos_counts (ndarray of shape (n_terms, num_params), dtype int32) – cos_counts[i, j] is the number of times parameter j appears in cos_idx of term i, i.e. the power of \(\cos(\theta_j)\).

Return type:

Tuple[ndarray, ndarray, ndarray]

pprop.propagator.utils.make_evaluator(expr, num_params)[source]

Compile a CoeffTerms expression into fast numeric callables.

Calls build_arrays() once to pre-compute the coefficient vector and integer count arrays, then closes over them in two inner functions that can be called repeatedly with different parameter vectors without rebuilding the arrays.

Parameters:
  • expr (CoeffTerms) – Symbolic expression as a list of (coeff, sin_indices, cos_indices) tuples. Indices may repeat to encode powers.

  • num_params (int) – Total number of circuit parameters.

Returns:

  • eval (Callable[[ndarray], float]) – eval(θ) returns the scalar expectation value at parameters θ.

  • eval_grad (Callable[[ndarray], Tuple[float, ndarray]]) – eval_grad(θ) returns (value, gradient) where gradient has shape (num_params,).

Return type:

Tuple[Callable[[ndarray], float], Callable[[ndarray], Tuple[float, ndarray]]]

Notes

Each term evaluates to:

\[t_k(\boldsymbol{\theta}) = c_k \prod_j \sin^{s_{kj}}(\theta_j) \prod_j \cos^{p_{kj}}(\theta_j)\]

The gradient with respect to \(\theta_j\) follows from the chain rule applied to both power factors:

\[\frac{\partial t_k}{\partial \theta_j} = t_k \left( \frac{s_{kj}\,\cos(\theta_j)}{\sin(\theta_j)} - \frac{p_{kj}\,\sin(\theta_j)}{\cos(\theta_j)} \right)\]

A small epsilon (1e-30) guards against division by zero when a sin or cos factor is exactly zero.

pprop.propagator.utils.remove_duplicate_observables(observables)[source]

Remove duplicate observables from a list of PennyLane observables.

Two observables are considered duplicates if their simplified canonical form has the same hash. This avoids redundant propagations when an ansatz accidentally returns the same observable more than once.

Parameters:

observables (list[Observable]) – Raw list of PennyLane observables as captured from a QuantumTape.

Returns:

  • unique_observables (list[Observable]) – Deduplicated list, each observable in its simplified canonical form.

  • removed_elements (list[Observable]) – Observables that were dropped because an identical hash was already seen.

Return type:

Tuple[List[Observable], List[Observable]]

pprop.propagator.utils.requires_propagation(method)[source]

Decorator that guards a method behind a propagation check.

Wraps any instance method so that it raises RuntimeError when called before propagate() has been run (i.e. before self._propagated is True).

Parameters:

method (Callable) – The instance method to wrap.

Returns:

The wrapped method with the propagation guard applied.

Return type:

Callable

Raises:

RuntimeError – If self._propagated is False at call time.