Skip to main content

General Operator Transformations

At a glance

  • Operator transformations manipulate quantum expressions symbolically.
  • General transformations apply to any operator expression.
  • All transformations have both in-place and out-of-place versions
  • Transformations are designed to prepare operator expressions for efficient numerical calculations
Prerequisites

Before working with transformations, you should be familiar with the operator sums and products that are generated from the factory functions operator_sum and operator_prod. We encourage you to review these types first to understand how operator expressions are structured and constructed.

Design Philosophy

Our transformation system follows a "nothing is automatic" principle - all operations are explicit, transparent, and user-controlled. This deliberate design decision ensures that:

  • Users have full visibility into each transformation step
  • Complex simplifications don't happen unexpectedly
  • The transformations remain predictable and debuggable
  • Users can selectively apply only the transformations they need

This approach prioritizes transparency, giving users complete control over how the expressions are processed.

Overview of transformations

When building quantum operator expressions through composition, the resulting expressions can become unwieldy with redundant terms, nested structures, and numerical artifacts. Operator transformations convert these expressions into cleaner and canonical forms that are ready for calculations. If no transformations are employed, no simplifications of the expressions are done.

Each operation serves a specific purpose:

  1. flatten expands nested products into a flat sum
  2. merge combines identical operator terms
  3. prune removes negligible contributions.

In-place vs. out-of-place transformations

Every transformation comes in two versions. Out-of-place versions (merged, pruned, flattened) preserve the original expression and return a transformed copy, while in-place versions (merge, prune, flatten) modify it directly.

var cleaned = merged(original);  // original unchanged
merge(original); // original is modified

In Aleph, methods in the past tense return copies while those in the present tense denote in-place modification. Use in-place transformations when working with large expressions to save memory, and chain them for efficiency:

flatten(S);
merge(S);
prune(S);
note

Not all transformations have in-place versions. reorder_by_site and simplify_paulis always return new copies, so you must assign the result back to a variable:

var reorderS = reorder_by_site(S);
var simpleS = simplify_paulis(S);

Using transformations

Flatten nested structures

Flattening distributes multiplication over addition, expanding nested expressions into a flat sum of products. A generic flattened operator_sum SS is one that has the form

S=nMcnO1Omn, cnCS = \sum_n^M c_n O_1 \dots O_{m_n}, \ c_n \in \mathbb{C}

Such a sum has MM total terms, each with a possibly different number of non-nested operators OO in a product. Given some operator expression, the flatten function transforms it into the form shown above.

var S = operator_sum(2.0 * Z(0) * (X(1) + Y(2)), as_real)
flatten(S);
// Result: 2 * Z(0) * X(1) + 2 * Z(0) * Y(2)

In the above example a sum is made using operator_sum consisting of a single term 2Z0(X1+Y2)2Z_0(X_1 + Y_2). The flatten function then modifies the sum object in-place by expanding the sum into 2Z0X1+2Z0Y22Z_0X_1 + 2Z_0Y_2.

tip

Use flatten before doing any other kind of transformations as hidden duplicate terms and similat simplfications only become visible after flattening.

warning

Only use flatten on operator_sum types where you've built nested structures.

Flattening a single operator like X(0) or clear operator_prod type is pointless.

Merge like terms

One simplification we can perform on a flattened sum is to merge like terms. Merging identifies identical operators and combines their coefficients and removes terms near-zero coefficients (below machine precision).

tip

Merging before computing expectation values, time evolution, or other operations can increase performance from removing redundant terms.

var S = (2.0 + 1.0i)*X(0) + 3.0*Y(1) + 1.5*X(0)
merge(S); // Result: (3.5 + 1.0i)*X(0) + 3.0*Y(0)
warning

merge will not commute terms when checking if terms are equal. It is possible that further manipulations are required to merge terms that are equivalent algebraically. There is support for both fermionic and spin-1/2 reordering transformations, they should be called before merge to ensure more terms get combined.

Prune negligible contributions

As operator_sum expressions get complex, terms may accrue small coefficients or the operators themselves may have small norms. By pruning the sum, terms whose effective norms fall below a threshold are removed. Here, the effective norm is computed as:

coefficient×operator norm|\text{coefficient}| \times \text{operator norm}

where operator norm\text{operator norm} represents the spectral norm, i.e., the absolute value of the largest eigenvalue of the operator.

var S = X(0) + 0.5*Y(1) + 1e-14*Z(2) + 1e-15*X(3);
prune(S); // Removes 1e-14*Z(2) and 1e-15*X(3)

Default thresholds are 101310^{-13} for double precision and 10410^{-4} for single precision.

Use prune(expr, tolerance) for custom cutoffs:

var S = 0.1*X(0) + 0.05*Y(1) + 1e-6*Z(2);
prune(S, 1e-5); // Removes 1e-6*Z(2) with custom tolerance
tip

Use prune after merging to catch near-zero coefficients created when terms nearly cancel.

warning

Be careful with custom prune tolerances. Setting the tolerance too high can remove physically important terms. Understand your physical scale before using custom tolerances.

Detailed documentation

To check out more detailed documentation see Transformations in the Library Reference.

Documentation Contributors

Eunji Yoo

Sebastien J. Avakian

Jonathon Riddell