Spin-½ Operator Transformations
At a glance
- Special transformations can be done on operator expressions comprised exclusively of spin 1/2 operators.
- Spin-1/2 operator expression can be reordered while respecting the bosonic algebra.
- Particular simplifications can be done to operator expressions comprised of single site spin-1/2 operators, namely pauli strings.
This document will assume you are familiar with general operator transformations and spin-1/2 operators. Feel free to consult them before reading this concept if you have not done so already.
Overview of transformations
There are currently three exclusively spin-1/2 operator transformations that are available in aleph:
reorder_by_sitesorts operators by site index for canonical ordering while obeying commutation relationssimplify_paulissimplifies pauli operators according to the pauli algebra.commutatorreturns for two spin-1/2 operators
The first transformation can be useful to put operator expression into a canonical order according to their sites without commuting terms within the local hilbert space. The second one on the other hand will simplify pauli operators according to the pauli algebra
where . The last transformation calculates the commutator of two spin-1/2 operators, which can be further simplified or used in numerical calculations.
Using transformations
Reorder by site
The reorder_by_site function sorts operators in ascending order of site index while preserving quantum commutation rules. That is, given an operator expression
the transformation orders into
where are such that , i.e. they are now ordered. Importantly, in order to respect the bosonic algebra of spin-1/2 operators
no operators are commuted with each other during this process. We can see this with the input operator expression
var S = operator_sum(2.0 * (X(2) * Y(0)) + 3.0 * (Z(1) * X(0)), as_real);
var reordered = reorder_by_site(S);
// Result: 2.0 * Y(0) * X(2) + 3.0 * X(0) * Z(1)
The out of the reordering only occurs between operators with disjoint support (acting on different qubits) so quantum mechanical commutation relationships are preserved. If we instead had a term with X(0) * Y(0) , then it wouldn't be reordered since both operators act on the same site.
var S = operator_sum(2.0 * (X(2) * Y(0)) + 3.0 * (Z(1) * X(0)) + 1.0 * (X(0) * Y(0)), as_real);
var reordered = reorder_by_site(S);
// Result: 2.0 * Y(0) * X(2) + 3.0 * X(0) * Z(1) + 1.0 * X(0) * Y(0)
Further simplifications can be done by calling merge after the operator has been reordered. This reorder ensures that all terms with the same operators but in different orders can be identified with each other and hence simplified.
var S = X(1) * Y(0) + Y(0) * X(1); // Same operators, different order
var reordered = reorder_by_site(S);
// Result: Y(0) * X(1) + Y(0) * X(1)
merge(reordered);
// Result: 2.0 * Y(0) * X(1)
Simplifying pauli strings
Special expressions can be manipulated and simplified utilizing known properties of the operators, namely pauli operators i.e. . General expressions made up of these operators are called pauli strings and are of the form
In this case, simplify_paulis applies Pauli algebra rules to operators in operator expressions on the same site resulting in the simplification of the pauli operators via the following identities,
The function transforms the operator expression in place and returns a complex coefficient, merging like terms together ensuring all terms in the expression are unique. The behaviour of this function depends on the input type:
- If the input is an
OperatorProductcomprised of Pauli operators, the returnedcomplexnumber is the value of the phase accrued from applying the Pauli algebra to the expression. - If the input is a
ComplexOperatorSumcomprised of Pauli operators, the returned number is1.0while the sum is updated.
Since Aleph enforces variable types to be immutable, simplify_paulis cannot modify the type of the object in place so the function is designed to keep the input object the same type, but modifies its contents. RealOperatorSums are not valid for this reason and will throw an error. The interface is the same for both input cases:
// operator as a product
var prod = operator_prod(X(0) * Y(0))
var phase = simplify_paulis(prod) // phase = (0.0,1,0), prod = Z(0)
// operator as a sum
var sum = operator sum(X(0) * Y(0))
var phase = simplify_paulis(sum) // phase = (1.0,0.0), sum = (0.0,1.0) * Z(0)
The variable declaration for the phase does not need to be present for both products and sums and can be called inline as simplify_paulis(input) if the phase information is not needed. An optional real number eps can be passed to prune the sum, discarding all Pauli strings with a coefficient with a norm less than eps:
var sum = operator_sum(X(0)*Y(1) + 1e-12*Z(0))
var eps = 1e-8 // second term will be removed
simplify_paulis(sum,eps) // sum = (1.0,0.0) * X(0) * Y(1)
A more general workflow would involve performing several operations on a spinhalf operator expression with general transformations and then simplify further at the end with simplify_paulis. This may require some casting of the expression in terms of Pauli operators before applying the final simplifications. This way, flatten, merge, and prune can help reduce the number of final terms to fully simplify with simplify_paulis.
When working with Pauli operators, its best practice to apply the general transformations first that potentially reduce the number of terms in the expression and then use simplify_paulis at the end.
var term1 = X(0)*Y(0) + Z(1); // Pauli products
var term2 = X(2) + Y(2);
var S = operator_sum(2.0*term1*term2 + 3.0*X(0)*Y(0)*X(2) + 1e-15*Z(3)); // Nested, duplicates, and noise
// Step 1: Flatten nested structures
flatten(S);
// Result: 2*X(0)*Y(0)*X(2) + 2*X(0)*Y(0)*Y(2) + 2*Z(1)*X(2) + 2*Z(1)*Y(2) + 3*X(0)*Y(0)*X(2) + 1e-15*Z(3)
// Step 2: Merge duplicate terms, can also reorder before if needed
merge(S);
// Result: 5*X(0)*Y(0)*X(2) + 2*X(0)*Y(0)*Y(2) + 2*Z(1)*X(2) + 2*Z(1)*Y(2) + 1e-15*Z(3)
// Step 3: Prune with custom tolerance
prune(S, 1e-10); // Removes 1e-15*Z(3)
// Result: 5*X(0)*Y(0)*X(2) + 2*X(0)*Y(0)*Y(2) + 2*Z(1)*X(2) + 2*Z(1)*Y(2)
// Step 4: Simplify Pauli products (XY -> iZ)
var final = simplify_paulis(S);
// Final: (0+5i) * Z(0) * X(2) + (0+2i) * Z(0) * Y(2) + (2+0i) * Z(1) * X(2) + (2+0i) * Z(1) * Y(2)
In the above example, steps 2,3,4 can be done in one call to simplify_paulis as the input expression is comprised solely of Pauli operators.
Compute commutators
Evaluating the commutator of two operators is a fundamental operation in quantum mechanics. In the case of spin-1/2 degrees of freedom, operators commute with themselves and with those that have disjoint support. The commutator function uses this knowledge when applicable and returns an explicit calculation of the commutator of two spin-1/2 operator expressions.
var comm = commutator(X(0), Y(0)); // Returns (1+0i)*X(0)*Y(0) + (-1+-0i)*Y(0)*X(0)
Like any given operator expresison, the output is not simplified. Using general and spin-1/2 transformations, expressions can be simplified and truncated to suit your numerical needs or symbolic calculation. In the particular case of pauli operators we can simplify the result even further,
var comm = commutator(X(1), Y(1));
// Returns (1) * X(1) * Y(1) + (-1) * Y(1) * X(1)
simplify_paulis(comm);
// Returns (0+2i) * Z(1)
As mentioned above, in the case of the operators being identical or have disjoint support, the commutator automatically returns an empty operator representing zero.
var iden = commutator(X(0), X(0));
// Returns ()
var disJ = commutator(X(0), X(1));
// Returns ()
This is useful for optimization - you can skip expensive commutator calculations for disjoint operators, or identify which operators commute with your system Hamiltonian or circuit!
Detailed documentation
To check out more detailed documentation see Transformations in the Library Reference.