Exemple #1
0
def test_pauli_string():
    p = PauliTerm("X", 1) * PauliTerm("Z", 5)
    assert p.pauli_string([1, 5]) == "XZ"
    assert p.pauli_string([1]) == "X"
    assert p.pauli_string([5]) == "Z"
    assert p.pauli_string([5, 6]) == "ZI"
    assert p.pauli_string([0, 1]) == "IX"
Exemple #2
0
    def _evaluate_single_term(self, ansatz_circuit: Program,
                              meas_term: PauliTerm) -> np.ndarray:
        """Compute the expectation value of a single PauliTerm , given a quantum circuit to evaluate on.
        
        Args:
            ansatz_circuit: A Program representing the quantum state to evaluate the PauliTerm on.
            
            meas_term: a PauliTerm object to be evaluated.
        
        """
        # First, create the quantum circuit needed for evaluation.

        # concatenate operator (converted to a Program) and ansatz circuit
        expectation_circuit = ansatz_circuit.copy()

        expectation_circuit += meas_term.program

        ro = expectation_circuit.declare('ro', 'BIT',
                                         len(meas_term.get_qubits()))

        # add necessary post-rotations and measurement
        for i, qubit in enumerate(sorted(list(meas_term.get_qubits()))):

            if meas_term.pauli_string([qubit]) == 'X':
                expectation_circuit += H(qubit)
            elif meas_term.pauli_string([qubit]) == 'Y':
                expectation_circuit += H(qubit)
                expectation_circuit += S(qubit)

            expectation_circuit += Program().measure(qubit, ro[i])

        result = self._run(expectation_circuit,
                           num_shots=self._num_shots_evaluation)

        return result
Exemple #3
0
def pauli_term_to_euler_memory_map(
    term: PauliTerm,
    *,
    prefix: str,
    tuple_x: Tuple[float, float, float],
    tuple_y: Tuple[float, float, float],
    tuple_z: Tuple[float, float, float],
    suffix_alpha: str = "alpha",
    suffix_beta: str = "beta",
    suffix_gamma: str = "gamma",
) -> Dict[str, List[float]]:
    """
    Given a ``PauliTerm``, create a memory map corresponding to a collection of ZXZXZ-decomposed
    single-qubit gates. The intent is that these gate are used to prepare an eigenstate of the
    ``PauliTerm`` or measure in the eigenbasis of the ``PauliTerm``, which is more clearly
    discernible from the calling functions ``pauli_term_to_preparation_memory_map`` (for state
    preparation) and ``pauli_term_to_measurement_memory_map`` (for measuring in different bases).
    This function is not really meant to be used by itself, but rather by the aforementioned
    calling functions.

    :param term: The ``PauliTerm`` in question.
    :param prefix: The prefix for the declared memory region labels. For example, if the prefix
        is "preparation" and the alpha, beta, and gamma suffixes are left as default, the labels
        would be "preparation_alpha", "preparation_beta", and "preparation_gamma".
    :param tuple_x: A tuple of Euler angles as (alpha, beta, gamma) to be used for the ``X``
        operators in the ``PauliTerm``.
    :param tuple_y: A tuple of Euler angles as (alpha, beta, gamma) to be used for the ``Y``
        operators in the ``PauliTerm``.
    :param tuple_z: A tuple of Euler angles as (alpha, beta, gamma) to be used for the ``Z``
        and ``I`` operators in the ``PauliTerm``.
    :param suffix_alpha: The suffix for the "alpha" memory region label, which corresponds to the
        first (rightmost) ``Z`` in the ZXZXZ decomposition. Defaults to "alpha".
    :param suffix_beta: The suffix for the "beta" memory region label, which corresponds to the
        second (middle) ``Z`` in the ZXZXZ decomposition. Defaults to "beta".
    :param suffix_gamma: The suffix for the "gamma" memory region label, which corresponds to the
        last (leftmost) ``Z`` in the ZXZXZ decomposition. Defaults to "gamma".
    :return: Memory map dictionary containing three entries (three labels as keys and three lists
        of angles as values).
    """
    # no need to provide a memory map when no rotations are necessary
    if ("X" not in term.pauli_string()) and ("Y" not in term.pauli_string()):
        return {}

    alpha_label = f"{prefix}_{suffix_alpha}"
    beta_label = f"{prefix}_{suffix_beta}"
    gamma_label = f"{prefix}_{suffix_gamma}"

    # assume the pauli indices are equivalent to the memory region
    memory_size = max(term.get_qubits()) + 1

    memory_map = {
        alpha_label: [0.0] * memory_size,
        beta_label: [0.0] * memory_size,
        gamma_label: [0.0] * memory_size,
    }

    tuples = {"X": tuple_x, "Y": tuple_y, "Z": tuple_z, "I": tuple_z}

    for qubit, operator in term:
        if operator not in tuples:
            raise ValueError(f"Unknown operator {operator}")
        memory_map[alpha_label][qubit] = tuples[operator][0]
        memory_map[beta_label][qubit] = tuples[operator][1]
        memory_map[gamma_label][qubit] = tuples[operator][2]

    return memory_map