qml.grouping¶

Overview¶

This subpackage defines functions and classes for generating and manipulating elements of the Pauli group. It also contains Pauli-word partitioning functionality used in measurement optimization.

Functions¶

 are_identical_pauli_words(pauli_1, pauli_2) Performs a check if two Pauli words have the same wires and name attributes. binary_to_pauli(binary_vector[, wire_map]) Converts a binary vector of even dimension to an Observable instance. diagonalize_pauli_word(pauli_word) Transforms the Pauli word to diagonal form in the computational basis. diagonalize_qwc_groupings(qwc_groupings) Diagonalizes a list of qubit-wise commutative groupings of Pauli strings. diagonalize_qwc_pauli_words(qwc_grouping) Diagonalizes a list of mutually qubit-wise commutative Pauli words. group_observables(observables[, …]) Partitions a list of observables (Pauli operations and tensor products thereof) into groupings according to a binary relation (qubit-wise commuting, fully-commuting, or anticommuting). is_commuting(pauli_word_1, pauli_word_2[, …]) Checks if two Pauli words commute. is_pauli_word(observable) Checks if an observable instance is a Pauli word. is_qwc(pauli_vec_1, pauli_vec_2) Checks if two Pauli words in the binary vector representation are qubit-wise commutative. observables_to_binary_matrix(observables[, …]) Converts a list of Pauli words to the binary vector representation and yields a row matrix of the binary vectors. optimize_measurements(observables[, …]) Partitions then diagonalizes a list of Pauli words, facilitating simultaneous measurement of all observables within a partition. pauli_group(n_qubits[, wire_map]) Generate the $$n$$-qubit Pauli group. pauli_mult(pauli_1, pauli_2[, wire_map]) Multiply two Pauli words together and return the product as a Pauli word. pauli_mult_with_phase(pauli_1, pauli_2[, …]) Multiply two Pauli words together, and return both their product as a Pauli word and the global phase. pauli_to_binary(pauli_word[, n_qubits, wire_map]) Converts a Pauli word to the binary vector representation. pauli_word_to_matrix(pauli_word[, wire_map]) Convert a Pauli word from a tensor to its matrix representation. pauli_word_to_string(pauli_word[, wire_map]) Convert a Pauli word from a tensor to a string. qwc_complement_adj_matrix(binary_observables) Obtains the adjacency matrix for the complementary graph of the qubit-wise commutativity graph for a given set of observables in the binary representation. qwc_rotation(pauli_operators) Performs circuit implementation of diagonalizing unitary for a Pauli word. string_to_pauli_word(pauli_string[, wire_map]) Convert a string in terms of 'I', 'X', 'Y', and 'Z' into a Pauli word for the given wire map.

Classes¶

 PauliGroupingStrategy(observables[, …]) Class for partitioning a list of Pauli words according to some binary symmetric relation.

Graph colouring¶

A module for heuristic algorithms for colouring Pauli graphs.

A Pauli graph is a graph where vertices represent Pauli words and edges denote if a specified symmetric binary relation (e.g., commutation) is satisfied for the corresponding Pauli words. The graph-colouring problem is to assign a colour to each vertex such that no vertices of the same colour are connected, using the fewest number of colours (lowest “chromatic number”) as possible.

Functions¶

 largest_first(binary_observables, adj) Performs graph-colouring using the Largest Degree First heuristic. recursive_largest_first(binary_observables, adj) Performs graph-colouring using the Recursive Largest Degree First heuristic.

Pauli group¶

The single-qubit Pauli group consists of the four single-qubit Pauli operations Identity, PauliX, PauliY , and PauliZ. The $$n$$-qubit Pauli group is constructed by taking all possible $$N$$-fold tensor products of these elements. Elements of the $$n$$-qubit Pauli group are often known as Pauli words, and have the form $$P_J = \otimes_{i=1}^{n}\sigma_i^{(J)}$$, where $$\sigma_i^{(J)}$$ is one of the Pauli operators (PauliX, PauliY, PauliZ) or identity (Identity) acting on the $$i^{th}$$ qubit. The full $$n$$-qubit Pauli group has size $$4^n$$ (neglecting the four possible global phases that may arise from multiplication of its elements).

The Pauli group can be constructed using the pauli_group() function. To construct the group, it is recommended to provide a wire map in order to indicate the names and indices of the wires. (If none is provided, a default mapping of integers will be used.)

>>> from pennylane.grouping import pauli_group
>>> pg_3 = list(pauli_group(3))

Multiplication of Pauli group elements can be performed using pauli_mult() or pauli_mult_with_phase():

>>> from pennylane.grouping import pauli_mult
>>> wire_map = {'a' : 0, 'b' : 1, 'c' : 2}
>>> pg = list(pauli_group(3, wire_map=wire_map))
>>> pg[3]
PauliZ(wires=['b']) @ PauliZ(wires=['c'])
>>> pg[55]
PauliY(wires=['a']) @ PauliY(wires=['b']) @ PauliZ(wires=['c'])
>>> pauli_mult(pg[3], pg[55], wire_map=wire_map)
PauliY(wires=['a']) @ PauliX(wires=['b'])

Pauli observables can be converted to strings (and vice versa):

>>> from pennylane.grouping import pauli_word_to_string, string_to_pauli_word
>>> pauli_word_to_string(pg[55], wire_map=wire_map)
'YYZ'
>>> string_to_pauli_word('ZXY', wire_map=wire_map)
PauliZ(wires=['a']) @ PauliX(wires=['b']) @ PauliY(wires=['c'])

The matrix representation for arbitrary Paulis and wire maps can also be performed.

>>> pennylane.grouping import pauli_word_to_matrix
>>> wire_map = {'a' : 0, 'b' : 1}
>>> pauli_word = qml.PauliZ('b')  # corresponds to Pauli 'IZ'
>>> pauli_word_to_matrix(pauli_word, wire_map=wire_map)
array([[ 1.,  0.,  0.,  0.],
[ 0., -1.,  0., -0.],
[ 0.,  0.,  1.,  0.],
[ 0., -0.,  0., -1.]])

Grouping observables¶

Pauli words can be used for expressing a qubit Hamiltonian. A qubit Hamiltonian has the form $$H_{q} = \sum_{J} C_J P_J$$ where $$C_{J}$$ are numerical coefficients, and $$P_J$$ are Pauli words.

A list of Pauli words can be partitioned according to certain grouping strategies. As an example, the group_observables() function partitions a list of observables (Pauli operations and tensor products thereof) into groupings according to a binary relation (e.g., qubit-wise commuting):

>>> observables = [qml.PauliY(0), qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(1)]
>>> obs_groupings = group_observables(observables)
>>> obs_groupings
[[Tensor(PauliX(wires=[0]), PauliX(wires=[1]))],
[PauliY(wires=[0]), PauliZ(wires=[1])]]

The $$C_{J}$$ coefficients for each $$P_J$$ Pauli word making up a Hamiltonian can also be specified along with further options, such as the Pauli-word grouping method (e.g., qubit-wise commuting) and the underlying graph-colouring algorithm (e.g., recursive largest first) used for creating the groups of observables:

>>> obs = [qml.PauliY(0), qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(1)]
>>> coeffs = [1.43, 4.21, 0.97]
>>> obs_groupings, coeffs_groupings = group_observables(obs, coeffs, 'qwc', 'rlf')
>>> obs_groupings
[[Tensor(PauliX(wires=[0]), PauliX(wires=[1]))],
[PauliY(wires=[0]), PauliZ(wires=[1])]]
>>> coeffs_groupings
[[4.21], [1.43, 0.97]]