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))
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
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))