Skip to content
Construct PsiQDK Algorithms

paulimask

paulimask

PauliMask

PauliMask(x_mask, z_mask)

Bases: MutableSequence

A PauliMask is representation of a multi-qubit Pauli operator.

Internally, it is represented as a tuple of two ints [x_mask, z_mask] specifying the qubits on which a Pauli acts.

This matches the format for ppr and ppm input in Workbench.

Example

"Z0 I1 Y2 X3" = (0b1100, 0b0101) = (4 + 8, 1 + 4) = (12, 5)

Parameters:

Name Type Description Default
x_mask int

The X mask.

required
z_mask int

The Z mask.

required

mask instance-attribute

mask = (x_mask, z_mask)

from_pauli_string classmethod

from_pauli_string(pauli_string)

Create a PauliMask object given a Pauli string - a string-based representation of the operator.

Parameters:

Name Type Description Default
pauli_string str

A string representing the Pauli operators acting on individual qubits. The expected format includes the character representing the Pauli ('I', 'X', 'Y', 'Z') followed by the qubit index, with whitespace inbetween operators.

required

Returns:

Type Description
PauliMask

The PauliMask object representing the input Pauli string

Example

"Z0 Y2 X3" -> PauliMask(12, 5)

insert

insert(index, value)

Insert a value into the mask.

to_list

to_list()

Casts a PauliMask to a list (for printing).

get_indices

get_indices(pauli_type='full')

Returns indices on which PauliMask acts.

Parameters:

Name Type Description Default
pauli_type str

Which indices to pull. Can either be 'X', 'Y' or 'Z', to pull indices for certain Paulis; or 'full' to pull all indices acted on by Paulis. Defaults to pauli_type='full'.

'full'

Returns:

Type Description
list

The indices acted on by Paulis specified by pauli_type.

get_pauli

get_pauli(index)

Returns the Pauli that acts on qubit labeled by index.

Parameters:

Name Type Description Default
index int

The qubit index to query.

required

Returns:

Type Description
str

The Pauli that acts on the qubit labeled by index.

get_pauli_string

get_pauli_string() -> str

Get a string representing the Pauli operators acting on sequential qubits.

Returns:

Type Description
str

The Pauli string representation of the PauliMask.

Example

PauliMask(12, 5) -> "Z0 Y2 X3"

compressed_length

compressed_length() -> int

Length of Pauli string, without the identity terms.

reverse_masks

reverse_masks(mask_length)

Reverse the qubit order of PauliMasks.

commute_check

commute_check(other)

Check for commutation between two PauliMasks.

Parameters:

Name Type Description Default
other PauliMask

The PauliMask to compare.

required

Returns:

Type Description
bool

Whether the PauliMasks commute.

commutator

commutator(other, drop_phase=True)

Returns the commutator of two PauliMasks.

Parameters:

Name Type Description Default
other PauliMask

The PauliMask to compare.

required
drop_phase bool

Whether the factor of \(2j\varepsilon_{i,j,k}\) in the commutator is retained. Defaults to drop_phase = True.

True

Returns:

Type Description
PauliMask or PauliSum

The commutator without the phase if drop_phase=True (PauliMask) or with the phase if drop_phase=False (PauliSum)

Note

If drop_phase=False, this returns a PauliSum.

Example

For the commutator \([XXY, ZYX]\), the first qubit gives a phase \((-j)\), the second \((j)\), and the third \((-j)\), which totals to 2 negative phases and 1 positive phase. The result is then \(2 \cdot (j)^{1} \cdot (-j)^{2} YZZ = -2j YZZ\).

PauliSum

PauliSum(*mask_tuples)

Bases: MutableSequence

Class for representing Pauli sums.

A PauliSum is a list of two-element lists, where the first element is a numeric coefficient and the second is a PauliMask.

Parameters:

Name Type Description Default
mask_tuples list

The two-element list [coeff, mask].

()

sum instance-attribute

sum = list()

get_mask

get_mask(index)

Returns the mask tuple at position given by index.

get_coefficient

get_coefficient(index)

Returns the real coefficient corresponding to the mask at position given by index.

get_pauli_string

get_pauli_string(index)

Returns the Pauli string corresponding to the mask at position given by index.

get_coefficients

get_coefficients()

Returns all coefficients in the PauliSum.

get_pauli_strings

get_pauli_strings()

Returns all Pauli strings in the PauliSum.

set_mask

set_mask(index, val)

Sets the mask at position index.

set_coefficient

set_coefficient(index, val)

Sets the coefficient at position index.

width

width()

Returns the width of the PauliSum.

The width is the total number of qubits on which the operator acts non-trivially.

wires

wires()

Returns the number of wires on which the PauliSum acts.

Differs from width by including Identity wires.

Example

PauliSum([1.0, PauliMask(10, 10)]) --> Width = 2, Wires = 5

insert

insert(index, term)

Insert a term in the Pauli sum.

add_to_coeff

add_to_coeff(index, addend)

Addition of a scalar to a PauliSum term coefficient.

combine_terms

combine_terms()

Combine all terms that have equivalent masks but inequivalent coefficients.

to_list

to_list()

Casts the PauliSum object to a list, for readability.

stack

stack(addend)

Addition of two PauliSums, without combining terms.

mult_term

mult_term(index, multiplicand)

Multiplication of a particular term by a scalar.

remove_below

remove_below(threshold)

If a term has a coefficient smaller than threshold in absolute value, remove it.

norm

norm()

Calculates a bound on the 1-norm of the PauliSum.

normalize

normalize()

Normalize the PauliSum by dividing all terms by the norm of the PauliSum.

Returns:

Type Description
PauliSum

Normalized PauliSum.

add_identity_offset

add_identity_offset()

Add identity offset term to the PauliSum.

Returns:

Type Description
Tuple[float, PauliMask]

Identity offset (sum of coefficients) to pull eigenvalues into positive reals and PauliSum + Identity term.

get_padded_abs_amplitudes

get_padded_abs_amplitudes()

Extract the weights of each Pauli term and place them in a list.

These will serve as the amplitudes for our auxiliary register.

Note

This function makes the coefficients positive-real valued, assuming the sign is absorbed into the Pauli operators.

Returns:

Type Description
list

List of amplitudes.

commutator

commutator(other)

Compute the commutator of a PauliSum with a PauliSum or PauliMask.

Parameters:

Name Type Description Default
other PauliSum or PauliMask

Second term

required

Returns:

Type Description
PauliSum

Returns the commutator, i.e. [self, other]

Notes

If other is a PauliMask, it assumes a coefficient 1.

pauli_sum_to_numpy

pauli_sum_to_numpy(ham: PauliSum)

Takes a PauliSum Hamiltonian and converts it to a NumPy array representation for easier numerics.

Notes
  • Follows a big-endian bit ordering, where the most significant bit is stored first (on the left) and the least significant bit last (on the right).
  • May need reordering using the Workbench reverse_numpy_op utility function for compatibility with vectors directly extracted from Workbench.
  • Depending on your use case, it might be faster to use pauli_sum_to_sparse(ham).toarray() to get a the numpy representation that would be in the same ordering as Workbench than using reverse_numpy_op(pauli_sum_to_numpy(ham)).

Parameters:

Name Type Description Default
ham PauliSum

PauliSum representation of the operator to be turned into a NumPy representation.

required

Returns:

Type Description
ndarray

Representation of the operator described by ham.

Examples:

ham = PauliSum([0.5, PauliMask(1, 0)], [0.5, PauliMask(1, 1)])
pauli_sum_to_numpy(ham)

>>> np.array([[0., 0.5-0.5j],
            [0.5+0.5j, 0.]])
ham2 = PauliSum([1.0, PauliMask(1, 2)])
# Note the qubit ordering -- this yields XZ not ZX (opposite to Workbench ordering)
pauli_sum_to_numpy(ham2)

>>> np.array([[ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],
            [ 0.+0.j,  0.+0.j,  0.+0.j, -1.+0.j],
            [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
            [ 0.+0.j, -1.+0.j,  0.+0.j,  0.+0.j]])

Example of Workbench ordering (little-endian):

qc = QPU(num_qubits=2)
qc[0].x()
qc.pull_state()

>>> np.array([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j])

pauli_sum_to_sparse

pauli_sum_to_sparse(ham: PauliSum)

Takes a PauliSum Hamiltonian and converts it to a Scipy sparse (csr) representation for easier numerics.

Note

Depending on your use case, it might be faster to use pauli_sum_to_sparse(ham).toarray() to get a the numpy representation that would be in the same ordering as Workbench than using reverse_numpy_op(pauli_sum_to_numpy(ham)).

Parameters:

Name Type Description Default
ham PauliSum

PauliSum representation of the operator to be turned into a sparse matrix representation.

required

Returns:

Type Description
csr_matrix

Representation of the operator described by ham.

Example
ham = PauliSum([0.5, PauliMask(1, 0)], [0.5, PauliMask(1, 1)])
pauli_sum_to_sparse(ham).toarray()

>>> np.array([[0., 0.5-0.5j],
            [0.5+0.5j, 0.]])
ham2 = PauliSum([1.0, PauliMask(1, 2)])
pauli_sum_to_sparse(ham2).toarray()

>>> np.array([[ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],
            [ 0.+0.j,  0.+0.j,  0.+0.j, -1.+0.j],
            [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
            [ 0.+0.j, -1.+0.j,  0.+0.j,  0.+0.j]])

random_pauli_sum

random_pauli_sum(wires: int, num_terms: int, low: float = 0.1, high: float = 180.0, group_like: bool = False, include_identity: bool = True, random_number_generator: Generator | None = None)

Generate a random PauliSum.

Parameters:

Name Type Description Default
wires int

Number of qubits acted on. Must be greater than zero.

required
num_terms int

Number of terms in PauliSum.

required
low float

Smallest coefficient to use. Defaults to 0.1.

0.1
high float

Largest coefficient to use. Defaults to 180.

180.0
group_like bool

Whether or not to group two PauliSum terms if they share the same x_mask and z_mask. Defaults to False.

False
include_identity bool

Whether to allow for identity terms to be included in the PauliSum. Defaults to True.

True
random_number_generator Generator | None

Generator for the random coefficients. Defaults to None.

None

Returns:

Type Description
PauliSum

A random PauliSum instance with num_terms number of terms acting on wires many qubits.

Notes
  • It is possible (but unlikely) to generate a trivial PauliSum where all terms have x_mask == z_mask == 0. In this case, the return of wires() will equal 0, and will not match the input wires arg. To avoid this, we run a while loop until we generate a non-trivial PauliSum.

  • Setting group_like = True means terms with the same masks are grouped into a single term with the sum of those terms' coefficients. This can result in the following (potentially unexpected) behavior:

    • len(psum) <= num_terms.
    • The smallest coefficient may be smaller than low.
    • The largest coefficient may be larger than high.