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
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
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
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
""" 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:
def _obs_from_qpo(operator: QubitPauliOperator, n_qubits: int) -> Observable: H = operator.to_sparse_matrix(n_qubits).toarray() return Observable.Hermitian(H)
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
"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: