Beispiel #1
0
    def _add_to_qubit_observable_mapping(self,
                                         result_type: ResultType) -> None:
        if isinstance(result_type, ResultType.Probability):
            observable = Observable.Z()  # computational basis
        elif isinstance(result_type, ObservableResultType):
            observable = result_type.observable
        else:
            return

        targets = result_type.target or list(self._qubit_observable_set)
        all_qubits_observable = self._qubit_observable_mapping.get(
            Circuit._ALL_QUBITS)
        for i in range(len(targets)):
            target = targets[i]
            tensor_product_dict = (
                Circuit._tensor_product_index_dict(observable) if isinstance(
                    observable, TensorProduct) else None)
            new_observable = tensor_product_dict[i][
                0] if tensor_product_dict else observable
            current_observable = all_qubits_observable or self._qubit_observable_mapping.get(
                target)

            add_observable = Circuit._validate_observable_to_add_for_qubit(
                current_observable, new_observable, target)

            if result_type.target:
                new_targets = (tuple(result_type.target[
                    tensor_product_dict[i][1][0]:tensor_product_dict[i][1][1]])
                               if tensor_product_dict else tuple(
                                   result_type.target))
                if add_observable:
                    self._qubit_target_mapping[target] = new_targets
                    self._qubit_observable_mapping[target] = new_observable
                elif new_observable.qubit_count > 1 and new_observable != Observable.I(
                ):
                    current_target = self._qubit_target_mapping.get(target)
                    if current_target and current_target != new_targets:
                        raise ValueError(
                            f"Target order {current_target} of existing result type with"
                            f" observable {current_observable} conflicts with order {targets}"
                            " of new result type")

        if not result_type.target:
            if all_qubits_observable and all_qubits_observable != observable:
                raise ValueError(
                    f"Existing result type for observable {all_qubits_observable} for all qubits"
                    f" conflicts with observable {observable} for new result type"
                )
            self._qubit_observable_mapping[Circuit._ALL_QUBITS] = observable
Beispiel #2
0
 def _extract_observable(result_type: ResultType) -> Optional[Observable]:
     if isinstance(result_type, ResultType.Probability):
         return Observable.Z()  # computational basis
     elif isinstance(result_type, ObservableResultType):
         return result_type.observable
     else:
         return None
Beispiel #3
0
 def _validate_observable_to_add_for_qubit(current_observable,
                                           new_observable, target):
     identity = Observable.I()
     add_observable = False
     if not current_observable or (current_observable == identity
                                   and new_observable != identity):
         add_observable = True
     elif (current_observable != identity and new_observable != identity
           and current_observable != new_observable):
         raise ValueError(
             f"Observable {new_observable} specified for target {target} conflicts with"
             + f" existing observable {current_observable} on this target.")
     return add_observable
Beispiel #4
0
    def _add_to_qubit_observable_mapping(
        self, observable: Observable, observable_target: QubitSet
    ) -> None:
        targets = observable_target or list(self._qubit_observable_set)
        all_qubits_observable = self._qubit_observable_mapping.get(Circuit._ALL_QUBITS)
        tensor_product_dict = (
            Circuit._tensor_product_index_dict(observable, observable_target)
            if isinstance(observable, TensorProduct)
            else None
        )
        identity = Observable.I()
        for i in range(len(targets)):
            target = targets[i]
            new_observable = tensor_product_dict[i][0] if tensor_product_dict else observable
            current_observable = all_qubits_observable or self._qubit_observable_mapping.get(target)

            add_observable = not current_observable or (
                current_observable == identity and new_observable != identity
            )
            if (
                not add_observable
                and current_observable != identity
                and new_observable != identity
                and current_observable != new_observable
            ):
                return self._encounter_noncommuting_observable()

            if observable_target:
                new_targets = (
                    tensor_product_dict[i][1] if tensor_product_dict else tuple(observable_target)
                )

                if add_observable:
                    self._qubit_observable_target_mapping[target] = new_targets
                    self._qubit_observable_mapping[target] = new_observable
                elif new_observable.qubit_count > 1:
                    current_target = self._qubit_observable_target_mapping.get(target)
                    if current_target and current_target != new_targets:
                        return self._encounter_noncommuting_observable()

        if not observable_target:
            if all_qubits_observable and all_qubits_observable != observable:
                return self._encounter_noncommuting_observable()
            self._qubit_observable_mapping[Circuit._ALL_QUBITS] = observable
Beispiel #5
0
        """
        super().__init__(ascii_symbols=["H"])

    def to_ir(self) -> List[str]:
        return ["h"]

    def to_matrix(self) -> np.ndarray:
        return 1.0 / np.sqrt(2.0) * np.array([[1.0, 1.0], [1.0, -1.0]],
                                             dtype=complex)

    @property
    def basis_rotation_gates(self) -> Tuple[Gate, ...]:
        return tuple([Gate.Ry(-math.pi / 4)])


Observable.register_observable(H)


class I(Observable):  # noqa: E742, E261
    """Identity operation as an observable."""
    def __init__(self):
        """
        Examples:
            >>> Observable.I()
        """
        super().__init__(qubit_count=1, ascii_symbols=["I"])

    def to_ir(self) -> List[str]:
        return ["i"]

    def to_matrix(self) -> np.ndarray:
Beispiel #6
0
def _obs_from_qpo(operator: QubitPauliOperator, n_qubits: int) -> Observable:
    H = operator.to_sparse_matrix(n_qubits).toarray()
    return Observable.Hermitian(H)
Beispiel #7
0
def _obs_from_qps(pauli: QubitPauliString) -> Tuple[Observable, QubitSet]:
    obs, qbs = [], []
    for q, p in pauli.to_dict().items():
        obs.append(_observables[p])
        qbs.append(q.index[0])
    return Observable.TensorProduct(obs), qbs
Beispiel #8
0
    "cphaseshift10",
    "cswap",
    "cy",
    "cz",
    "iswap",
    "pswap",
    "swap",
    "unitary",
    "xx",
    "xy",
    "yy",
    "zz",
}

_observables = {
    Pauli.I: Observable.I(),
    Pauli.X: Observable.X(),
    Pauli.Y: Observable.Y(),
    Pauli.Z: Observable.Z(),
}


def _obs_from_qps(pauli: QubitPauliString) -> Tuple[Observable, QubitSet]:
    obs, qbs = [], []
    for q, p in pauli.to_dict().items():
        obs.append(_observables[p])
        qbs.append(q.index[0])
    return Observable.TensorProduct(obs), qbs


def _obs_from_qpo(operator: QubitPauliOperator, n_qubits: int) -> Observable: