def test_group_observables_exception(self):
     """Tests that the ``group_observables`` function raises an exception if
     the lengths of coefficients and observables do not agree."""
     observables = [Identity(0), PauliX(1)]
     coefficients = [0.5]
     with pytest.raises(IndexError, match="must be the same length"):
         group_observables(observables, coefficients)
예제 #2
0
 def test_return_list_coefficients(self):
     """Tests that if the coefficients are given as a list, the groups
     are likewise lists."""
     obs = [qml.PauliX(0), qml.PauliX(1)]
     coeffs = [1.0, 2.0]
     _, grouped_coeffs = group_observables(obs, coeffs)
     assert isinstance(grouped_coeffs[0], list)
예제 #3
0
    def test_commuting_partitioning(self, observables, com_partitions_sol):

        com_partitions = group_observables(observables, grouping_type="commuting")

        # assert the correct number of partitions:
        n_partitions = len(com_partitions_sol)
        assert len(com_partitions) == n_partitions
        # assert each partition is of the correct length:
        assert all(
            [len(com_partitions[i]) == len(com_partitions_sol[i]) for i in range(n_partitions)]
        )
        # assert each partition contains the same Pauli terms as the solution partition:
        for i, partition in enumerate(com_partitions):
            for j, pauli in enumerate(partition):
                assert are_identical_pauli_words(pauli, com_partitions_sol[i][j])
예제 #4
0
def optimize_measurements(observables,
                          coefficients=None,
                          grouping="qwc",
                          colouring_method="rlf"):
    """Partitions then diagonalizes a list of Pauli words, facilitating simultaneous measurement of
    all observables within a partition.

    The input list of observables are partitioned into mutually qubit-wise commuting (QWC) or
    mutually commuting partitions by approximately solving minimum clique cover on a graph where
    each observable represents a vertex. The unitaries which diagonalize the
    partitions are then found. See `arXiv:1907.03358
    <https://arxiv.org/abs/1907.03358>`_ and `arXiv:1907.09386
    <https://arxiv.org/abs/1907.09386>`_ for technical details of the QWC and
    fully-commuting measurement-partitioning approaches respectively.

    Args:
        observables (list[Observable]): a list of Pauli words (Pauli operation instances and Tensor
            instances thereof)
        coefficients (list[float]): a list of float coefficients, for instance the weights of
            the Pauli words comprising a Hamiltonian
        grouping (str): the binary symmetric relation to use for operator partitioning
        colouring_method (str): the graph-colouring heuristic to use in obtaining the operator
            partitions

    Returns:
        tuple:

            * list[callable]: a list of the post-rotation templates, one
              for each partition
            * list[list[Observable]]: A list of the obtained groupings. Each
              grouping is itself a list of Pauli words diagonal in the
              measurement basis.
            * list[list[float]]: A list of coefficient groupings. Each
              coefficient grouping is itself a list of the partitions
              corresponding coefficients.  Only output if coefficients are
              specified.

    **Example**

    >>> obs = [qml.PauliY(0), qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(1)]
    >>> coeffs = [1.43, 4.21, 0.97]
    >>> rotations, groupings, grouped_coeffs = optimize_measurements(obs, coeffs, 'qwc', 'rlf')
    >>> print(rotations)
    [[RY(-1.5707963267948966, wires=[0]), RY(-1.5707963267948966, wires=[1])],
     [RX(1.5707963267948966, wires=[0])]]
    >>> print(groupings)
    [[PauliZ(wires=[0]) @ PauliZ(wires=[1])], [PauliZ(wires=[0]), PauliZ(wires=[1])]]
    >>> print(grouped_coeffs)
    [[4.21], [1.43, 0.97]]
    """

    if coefficients is None:
        grouped_obs = group_observables(observables,
                                        grouping_type=grouping,
                                        method=colouring_method)
    else:
        grouped_obs, grouped_coeffs = group_observables(
            observables,
            coefficients,
            grouping_type=grouping,
            method=colouring_method)

    if grouping.lower() == "qwc":
        (
            post_rotations,
            diagonalized_groupings,
        ) = diagonalize_qwc_groupings(grouped_obs)
    else:
        raise NotImplementedError(
            f"Measurement reduction by '{grouping.lower()}' grouping not implemented."
        )

    if coefficients is None:
        return post_rotations, diagonalized_groupings

    return post_rotations, diagonalized_groupings, grouped_coeffs