Example #1
0
def _decompose_and_get_unitary(val: 'cirq.Operation') -> np.ndarray:
    """Try to decompose an `Operation` and return its unitary.

    Returns:
        If `val` can be decomposed into unitaries, calculate the resulting
        unitary and return it. If it doesn't exist, None is returned.
    """
    from cirq.protocols.apply_unitary import apply_unitary, ApplyUnitaryArgs
    from cirq.protocols.decompose import decompose_once

    decomposed_val = decompose_once(val, None)
    if decomposed_val is not None:
        # Calculate the resulting unitary (if it exists)
        n = len(val.qubits)
        state = np.eye(1 << n, dtype=np.complex128)
        state.shape = (2, ) * (2 * n)
        buffer = np.zeros(state.shape, dtype=np.complex128)
        qubit_map = {q: i for i, q in enumerate(val.qubits)}
        result = state
        for op in decomposed_val:
            indices = [qubit_map[q] for q in op.qubits]
            result = apply_unitary(unitary_value=op,
                                   args=ApplyUnitaryArgs(
                                       state, buffer, indices),
                                   default=None)
            if result is None:
                return None
            if result is buffer:
                buffer = state
            state = result
        if result is not None:
            return result.reshape((1 << n, 1 << n))
Example #2
0
def _apply_unitary(val: Any, args: 'ApplyChannelArgs') -> Optional[np.ndarray]:
    """Attempt to use `apply_unitary` and return the result.

    If `val` does not support `apply_unitary` returns None.
    """
    left_args = ApplyUnitaryArgs(target_tensor=args.target_tensor,
                                 available_buffer=args.auxiliary_buffer0,
                                 axes=args.left_axes)
    left_result = apply_unitary(val, left_args, None)
    if left_result is None:
        return None
    right_args = ApplyUnitaryArgs(target_tensor=np.conjugate(left_result),
                                  available_buffer=args.out_buffer,
                                  axes=args.right_axes)
    right_result = apply_unitary(val, right_args)
    np.conjugate(right_result, out=right_result)
    return right_result
Example #3
0
def _decompose_and_get_unitary(
        val: Union['cirq.Operation', 'cirq.Gate']) -> np.ndarray:
    """Try to decompose a cirq.Operation or cirq.Gate, and return its unitary
    if it exists.

    Returns:
        If `val` can be decomposed into unitaries, calculate the resulting
        unitary and return it. If it doesn't exist, None is returned.
    """
    from cirq.protocols.apply_unitary import apply_unitary, ApplyUnitaryArgs
    from cirq.protocols.decompose import (decompose_once,
                                          decompose_once_with_qubits)
    from cirq import Gate, LineQubit, Operation

    if isinstance(val, Operation):
        qubits = val.qubits
        decomposed_val = decompose_once(val, default=None)
    elif isinstance(val, Gate):
        # Since gates don't know about qubits, we need to create some
        qubits = tuple(LineQubit.range(val.num_qubits()))
        decomposed_val = decompose_once_with_qubits(val, qubits, default=None)

    if decomposed_val is not None:
        # Calculate the resulting unitary (if it exists)
        n = len(qubits)
        state = np.eye(1 << n, dtype=np.complex128)
        state.shape = (2, ) * (2 * n)
        buffer = np.zeros(state.shape, dtype=np.complex128)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        result = state
        for op in decomposed_val:
            indices = [qubit_map[q] for q in op.qubits]
            result = apply_unitary(unitary_value=op,
                                   args=ApplyUnitaryArgs(
                                       state, buffer, indices),
                                   default=None)
            if result is None:
                return None
            if result is buffer:
                buffer = state
            state = result
        if result is not None:
            return result.reshape((1 << n, 1 << n))