pyquil.paulis module

Module for working with Pauli algebras.

pyquil.paulis.HASH_PRECISION = 1000000.0

The precision used when hashing terms to check equality. The simplify() method uses np.isclose() for coefficient comparisons to 0 which has its own default precision. We can’t use np.isclose() for hashing terms though.

pyquil.paulis.ID() PauliTerm[source]

The identity operator.

class pyquil.paulis.PauliSum(terms: Sequence[PauliTerm])[source]

Bases: object

A sum of one or more PauliTerms.

Parameters:

terms (Sequence) – A Sequence of PauliTerms.

compact_str() str[source]

A string representation of the PauliSum that is more compact than str(pauli_sum)

>>> pauli_sum = 2.0 * sX(1)* sZ(2) + 1.5 * sY(2)
>>> str(pauli_sum)
'(2+0j)*X1*Z2 + (1.5+0j)*Y2'
>>> pauli_sum.compact_str()
'(2+0j)*X1Z2+(1.5+0j)*Y2'
classmethod from_compact_str(str_pauli_sum: str) PauliSum[source]

Construct a PauliSum from the result of str(pauli_sum)

get_programs() Tuple[List[Program], ndarray][source]

Get a Pyquil Program corresponding to each term in the PauliSum and a coefficient for each program

Returns:

(programs, coefficients)

get_qubits() List[int | FormalArgument | Qubit | QubitPlaceholder][source]

The support of all the operators in the PauliSum object.

Returns:

A list of all the qubits in the sum of terms.

simplify() PauliSum[source]

Simplifies the sum of Pauli operators according to Pauli algebra rules.

class pyquil.paulis.PauliTerm(op: str, index: int | FormalArgument | Qubit | QubitPlaceholder | None, coefficient: Expression | int | float | complex = 1.0)[source]

Bases: object

A term is a product of Pauli operators operating on different qubits.

Create a new Pauli Term with a Pauli operator at a particular index and a leading coefficient.

Parameters:
  • op – The Pauli operator as a string “X”, “Y”, “Z”, or “I”

  • index – The qubit index that that operator is applied to.

  • coefficient – The coefficient multiplying the operator, e.g. 1.5 * Z_1

compact_str() str[source]

A string representation of the Pauli term that is more compact than str(term)

>>> term = 2.0 * sX(1)* sZ(2)
>>> str(term)
'(2+0j)*X1*Z2'
>>> term.compact_str()
'(2+0j)*X1Z2'
copy() PauliTerm[source]

Properly creates a new PauliTerm, with a completely new dictionary of operators

classmethod from_compact_str(str_pauli_term: str) PauliTerm[source]

Construct a PauliTerm from the result of str(pauli_term)

classmethod from_list(terms_list: Sequence[Tuple[str, int | FormalArgument | Qubit | QubitPlaceholder]], coefficient: Expression | int | float | complex = 1.0) PauliTerm[source]

Allocates a Pauli Term from a list of operators and indices. This is more efficient than multiplying together individual terms.

Parameters:

terms_list (list) – A list of tuples, e.g. [(“X”, 0), (“Y”, 1)]

Returns:

PauliTerm

get_qubits() List[int | FormalArgument | Qubit | QubitPlaceholder][source]

Gets all the qubits that this PauliTerm operates on.

id(sort_ops: bool = True) str[source]

Returns an identifier string for the PauliTerm (ignoring the coefficient).

Don’t use this to compare terms. This function will not work with qubits that aren’t sortable.

Parameters:

sort_ops – Whether to sort operations by qubit. This is True by default for backwards compatibility but will change in a future version. Callers should never rely on comparing id’s for testing equality. See operations_as_set instead.

Returns:

A string representation of this term’s operations.

operations_as_set() FrozenSet[Tuple[int | FormalArgument | Qubit | QubitPlaceholder, str]][source]

Return a frozenset of operations in this term.

Use this in place of id() if the order of operations in the term does not matter.

Returns:

frozenset of (qubit, op_str) representing Pauli operations

pauli_string(qubits: Iterable[int] | None = None) str[source]

Return a string representation of this PauliTerm without its coefficient and with implicit qubit indices.

If an iterable of qubits is provided, each character in the resulting string represents a Pauli operator on the corresponding qubit.

>>> p = PauliTerm("X", 0) * PauliTerm("Y", 1, 1.j)
>>> p.pauli_string()
'XY'
>>> p.pauli_string(qubits=[0])
'X'
>>> p.pauli_string(qubits=[0, 2])
'XI'
Parameters:

qubits (iterable of) – The iterable of qubits to represent, given as ints.

Returns:

The string representation of this PauliTerm, sans coefficient

property program: Program
exception pyquil.paulis.UnequalLengthWarning(*args: object, **kwargs: object)[source]

Bases: Warning

pyquil.paulis.ZERO() PauliTerm[source]

The zero operator.

pyquil.paulis.check_commutation(pauli_list: Sequence[PauliTerm], pauli_two: PauliTerm) bool[source]

Check if commuting a PauliTerm commutes with a list of other terms by natural calculation. Uses the result in Section 3 of arXiv:1405.5749v2, modified slightly here to check for the number of anti-coincidences (which must always be even for commuting PauliTerms) instead of the no. of coincidences, as in the paper.

Parameters:
  • pauli_list – A list of PauliTerm objects

  • pauli_two_term – A PauliTerm object

Returns:

True if pauli_two object commutes with pauli_list, False otherwise

pyquil.paulis.commuting_sets(pauli_terms: PauliSum) List[List[PauliTerm]][source]

Gather the Pauli terms of pauli_terms variable into commuting sets

Uses algorithm defined in (Raeisi, Wiebe, Sanders, arXiv:1108.4318, 2011) to find commuting sets. Except uses commutation check from arXiv:1405.5749v2

Parameters:

pauli_terms – A PauliSum object

Returns:

List of lists where each list contains a commuting set

pyquil.paulis.exponential_map(term: PauliTerm) Callable[[float | MemoryReference], Program][source]

Returns a function f(alpha) that constructs the Program corresponding to exp(-1j*alpha*term).

Parameters:

term – A pauli term to exponentiate

Returns:

A function that takes an angle parameter and returns a program.

pyquil.paulis.exponentiate(term: PauliTerm) Program[source]

Creates a pyQuil program that simulates the unitary evolution exp(-1j * term)

Parameters:

term – A pauli term to exponentiate

Returns:

A Program object

pyquil.paulis.exponentiate_commuting_pauli_sum(pauli_sum: PauliSum) Callable[[float | MemoryReference], Program][source]

Returns a function that maps all substituent PauliTerms and sums them into a program. NOTE: Use this function with care. Substituent PauliTerms should commute.

Parameters:

pauli_sum – PauliSum to exponentiate.

Returns:

A function that parametrizes the exponential.

pyquil.paulis.exponentiate_pauli_sum(pauli_sum: PauliSum | PauliTerm) ndarray[Any, dtype[complex128]][source]

Exponentiates a sequence of PauliTerms, which may or may not commute. The Pauliterms must have fixed (non-parametric) coefficients. The coefficients are interpreted in cycles rather than radians or degrees.

e^{-ipisum_i theta_i P_i}

Thus, 1.0 corresponds to one full rotation.

To produce a CZ gate:

>>> from numpy import pi
>>> phi = pi
>>> coeff = phi/(-4*pi) # -0.25
>>> hamiltonian = PauliTerm("Z", 0) * PauliTerm("Z", 1) - 1*PauliTerm("Z", 0) - 1*PauliTerm("Z", 1)
>>> exponentiate_pauli_sum(coeff*hamiltonian)
array([[...]])

To produce the Quil XY(theta) gate, you can use:

>>> theta = pi/2
>>> coeff = theta/(-4*pi)
>>> hamiltonian = PauliTerm("X", 0) * PauliTerm("X", 1) + PauliTerm("Y", 0) * PauliTerm("Y", 1)
>>> exponentiate_pauli_sum(coeff*hamiltonian)
array([[...]])

A global phase is applied to the unitary such that the [0,0] element is always real.

Parameters:

pauli_sum – PauliSum to exponentiate.

Returns:

The matrix exponetial of the PauliSum

pyquil.paulis.integer_types = (<class 'int'>, <class 'numpy.int64'>, <class 'numpy.int32'>, <class 'numpy.int16'>, <class 'numpy.int8'>)

Explicitly include numpy integer dtypes (for python 3).

pyquil.paulis.is_identity(term: PauliTerm | PauliSum) bool[source]

Tests to see if a PauliTerm or PauliSum is a scalar multiple of identity

Parameters:

term – Either a PauliTerm or PauliSum

Returns:

True if the PauliTerm or PauliSum is a scalar multiple of identity, False otherwise

pyquil.paulis.is_zero(pauli_object: PauliTerm | PauliSum) bool[source]

Tests to see if a PauliTerm or PauliSum is zero.

Parameters:

pauli_object – Either a PauliTerm or PauliSum

Returns:

True if PauliTerm is zero, False otherwise

pyquil.paulis.sI(q: int | None = None) PauliTerm[source]

A function that returns the identity operator, optionally on a particular qubit.

This can be specified without a qubit.

Parameters:

qubit_index – The optional index of a qubit.

Returns:

A PauliTerm object

pyquil.paulis.sX(q: int) PauliTerm[source]

A function that returns the sigma_X operator on a particular qubit.

Parameters:

qubit_index – The index of the qubit

Returns:

A PauliTerm object

pyquil.paulis.sY(q: int) PauliTerm[source]

A function that returns the sigma_Y operator on a particular qubit.

Parameters:

qubit_index – The index of the qubit

Returns:

A PauliTerm object

pyquil.paulis.sZ(q: int) PauliTerm[source]

A function that returns the sigma_Z operator on a particular qubit.

Parameters:

qubit_index – The index of the qubit

Returns:

A PauliTerm object

pyquil.paulis.simplify_pauli_sum(pauli_sum: PauliSum) PauliSum[source]

Simplify the sum of Pauli operators according to Pauli algebra rules.

Warning: The simplified expression may re-order pauli operations, and may impact the observed performance when running on the QPU.

pyquil.paulis.suzuki_trotter(trotter_order: int, trotter_steps: int) List[Tuple[float, int]][source]

Generate trotterization coefficients for a given number of Trotter steps.

U = exp(A + B) is approximated as exp(w1*o1)exp(w2*o2)… This method returns a list [(w1, o1), (w2, o2), … , (wm, om)] of tuples where o=0 corresponds to the A operator, o=1 corresponds to the B operator, and w is the coefficient in the exponential. For example, a second order Suzuki-Trotter approximation to exp(A + B) results in the following [(0.5/trotter_steps, 0), (1/trotter_steps, 1), (0.5/trotter_steps, 0)] * trotter_steps.

Parameters:
  • trotter_order – order of Suzuki-Trotter approximation

  • trotter_steps – number of steps in the approximation

Returns:

List of tuples corresponding to the coefficient and operator type: o=0 is A and o=1 is B.

pyquil.paulis.term_with_coeff(term: PauliTerm, coeff: Expression | int | float | complex) PauliTerm[source]

Change the coefficient of a PauliTerm.

Parameters:
  • term – A PauliTerm object

  • coeff – The coefficient to set on the PauliTerm

Returns:

A new PauliTerm that duplicates term but sets coeff

pyquil.paulis.trotterize(first_pauli_term: PauliTerm, second_pauli_term: PauliTerm, trotter_order: int = 1, trotter_steps: int = 1) Program[source]

Create a Quil program that approximates exp( (A + B)t) where A and B are PauliTerm operators.

Parameters:
  • first_pauli_term – PauliTerm denoted A

  • second_pauli_term – PauliTerm denoted B

  • trotter_order – Optional argument indicating the Suzuki-Trotter approximation order–only accepts orders 1, 2, 3, 4.

  • trotter_steps – Optional argument indicating the number of products to decompose the exponential into.

Returns:

Quil program