def apply_channel(self, action: Any, axes: Sequence[int],
                      prng) -> Optional[int]:
        """Apply channel to state.

        Args:
            action: The value with a channel to apply.
            axes: The axes on which to apply the channel.
            prng: The pseudo random number generator to use.
        Returns:
            The kraus index if the operation succeeded, otherwise None.
        """
        kraus_operators = protocols.kraus(action, default=None)
        if kraus_operators is None:
            return None

        def prepare_into_buffer(k: int):
            linalg.targeted_left_multiply(
                left_matrix=kraus_tensors[k],
                right_target=self._state_vector,
                target_axes=axes,
                out=self._buffer,
            )

        shape = protocols.qid_shape(action)
        kraus_tensors = [
            e.reshape(shape * 2).astype(self._state_vector.dtype)
            for e in kraus_operators
        ]
        p = prng.random()
        weight = None
        fallback_weight = 0
        fallback_weight_index = 0
        index = None
        for index in range(len(kraus_tensors)):
            prepare_into_buffer(index)
            weight = np.linalg.norm(self._buffer)**2

            if weight > fallback_weight:
                fallback_weight_index = index
                fallback_weight = weight

            p -= weight
            if p < 0:
                break

        assert weight is not None, "No Kraus operators"
        if p >= 0 or weight == 0:
            # Floating point error resulted in a malformed sample.
            # Fall back to the most likely case.
            prepare_into_buffer(fallback_weight_index)
            weight = fallback_weight
            index = fallback_weight_index

        self._buffer /= np.sqrt(weight)
        self._swap_target_tensor_for(self._buffer)
        return index
예제 #2
0
    def _kraus_(self):
        if self._is_parameterized_():
            return NotImplemented

        channel = protocols.kraus(self.sub_gate, None)
        if channel is None:
            return NotImplemented

        do_nothing = np.eye(np.product(protocols.qid_shape(self.sub_gate)), dtype=np.float64)
        result = [e * np.sqrt(self.probability) for e in channel]
        result.append(np.sqrt(1 - float(self.probability)) * do_nothing)
        return result
예제 #3
0
def _strat_act_on_state_vector_from_channel(
        action: Any, args: 'cirq.ActOnStateVectorArgs',
        qubits: Sequence['cirq.Qid']) -> bool:
    kraus_operators = protocols.kraus(action, default=None)
    if kraus_operators is None:
        return NotImplemented

    def prepare_into_buffer(k: int):
        linalg.targeted_left_multiply(
            left_matrix=kraus_tensors[k],
            right_target=args.target_tensor,
            target_axes=args.get_axes(qubits),
            out=args.available_buffer,
        )

    shape = protocols.qid_shape(action)
    kraus_tensors = [
        e.reshape(shape * 2).astype(args.target_tensor.dtype)
        for e in kraus_operators
    ]
    p = args.prng.random()
    weight = None
    fallback_weight = 0
    fallback_weight_index = 0
    for index in range(len(kraus_tensors)):
        prepare_into_buffer(index)
        weight = np.linalg.norm(args.available_buffer)**2

        if weight > fallback_weight:
            fallback_weight_index = index
            fallback_weight = weight

        p -= weight
        if p < 0:
            break

    assert weight is not None, "No Kraus operators"
    if p >= 0 or weight == 0:
        # Floating point error resulted in a malformed sample.
        # Fall back to the most likely case.
        prepare_into_buffer(fallback_weight_index)
        weight = fallback_weight
        index = fallback_weight_index

    args.available_buffer /= np.sqrt(weight)
    args.swap_target_tensor_for(args.available_buffer)
    if protocols.is_measurement(action):
        key = protocols.measurement_key_name(action)
        args._classical_data.record_channel_measurement(key, index)
    return True
예제 #4
0
파일: channels.py 프로젝트: fmozafari/Cirq
def operation_to_channel_matrix(
        operation: 'protocols.SupportsChannel') -> np.ndarray:
    """Returns the matrix representation of a superoperator in standard basis.

    Let E: L(H1) -> L(H2) denote a linear map which takes linear operators on Hilbert space H1
    to linear operators on Hilbert space H2 and let d1 = dim H1 and d2 = dim H2. Also, let Fij
    denote an operator whose matrix has one in ith row and jth column and zeros everywhere else.
    Note that d1-by-d1 operators Fij form a basis of L(H1). Similarly, d2-by-d2 operators Fij
    form a basis of L(H2). This function returns the matrix of E in these bases.

    Args:
        operation: Quantum channel.
    Returns:
        Matrix representation of operation.
    """
    return kraus_to_channel_matrix(protocols.kraus(operation))
예제 #5
0
파일: channels.py 프로젝트: fmozafari/Cirq
def operation_to_choi(operation: 'protocols.SupportsChannel') -> np.ndarray:
    r"""Returns the unique Choi matrix associated with a superoperator.

    Choi matrix J(E) of a linear map E: L(H1) -> L(H2) which takes linear operators
    on Hilbert space H1 to linear operators on Hilbert space H2 is defined as

        $$
        J(E) = (E \otimes I)(|\phi\rangle\langle\phi|)
        $$

    where $|\phi\rangle = \sum_i|i\rangle|i\rangle$ is the unnormalized maximally
    entangled state and I: L(H1) -> L(H1) is the identity map. Note that J(E) is
    a square matrix with d1*d2 rows and columns where d1 = dim H1 and d2 = dim H2.

    Args:
        operation: Quantum channel.
    Returns:
        Choi matrix corresponding to operation.
    """
    return kraus_to_choi(protocols.kraus(operation))
예제 #6
0
def entanglement_fidelity(operation: 'cirq.SupportsKraus') -> float:
    r"""Returns entanglement fidelity of a given quantum channel.

    Entanglement fidelity $F_e$ of a quantum channel $E: L(H) \to L(H)$ is the overlap between
    the maximally entangled state $|\phi\rangle = \frac{1}{\sqrt{dim H}} \sum_i|i\rangle|i\rangle$
    and the state obtained by sending one half of $|\phi\rangle$ through the channel $E$, i.e.

        $$
        F_e = \langle\phi|(E \otimes I)(|\phi\rangle\langle\phi|)|\phi\rangle
        $$

    where $I: L(H) \to L(H)$ is the identity map.

    Args:
        operation: Quantum channel whose entanglement fidelity is to be computed.
    Returns:
        Entanglement fidelity of the channel represented by operation.
    """
    f = 0.0
    for k in protocols.kraus(operation):
        f += np.abs(np.trace(k)) ** 2
    n_qubits = protocols.num_qubits(operation)
    return float(f / 4**n_qubits)
예제 #7
0
 def _kraus_(self) -> Union[Tuple[np.ndarray], NotImplementedType]:
     return protocols.kraus(self.sub_operation, NotImplemented)
예제 #8
0
 def from_channel(channel: 'protocols.SupportsChannel',
                  key: Union[str, value.MeasurementKey, None] = None):
     """Creates a copy of a channel with the given measurement key."""
     return KrausChannel(kraus_ops=list(protocols.kraus(channel)), key=key)
예제 #9
0
 def kraus_tensors(op: 'cirq.Operation') -> Sequence[np.ndarray]:
     return tuple(
         np.reshape(k, (2, 2) * len(op.qubits))
         for k in protocols.kraus(op))
예제 #10
0
 def from_channel(channel: 'cirq.Gate',
                  key: Union[str, 'cirq.MeasurementKey', None] = None):
     """Creates a copy of a channel with the given measurement key."""
     return KrausChannel(kraus_ops=list(protocols.kraus(channel)), key=key)