def decompose_4x4_optimal(U): """Builds optimal decomposition of general 4x4 unitary matrix. This decomposition consists of at most 3 CNOT gates, 15 Rx/Ry gates and one R1 gate. Returns list of `Gate`s. """ assert is_unitary(U) magic_decomp = decompose_to_magic_diagonal(U) result = [] result += apply_on_qubit(su_to_gates(magic_decomp['VA']), 1) result += apply_on_qubit(su_to_gates(magic_decomp['VB']), 0) result += decompose_magic_N(magic_decomp['alpha']) result += apply_on_qubit(su_to_gates(magic_decomp['UA']), 1) result += apply_on_qubit(su_to_gates(magic_decomp['UB']), 0) # Adding global phase using Rz and R1. gl_phase = magic_decomp['global_phase'] + 0.25 * np.pi if np.abs(gl_phase) > 1e-9: result.append(GateSingle(Gate2('Rz', 2 * gl_phase), 0)) result.append(GateSingle(Gate2('R1', 2 * gl_phase), 0)) result = skip_identities(result) assert _allclose(U, gates_to_matrix(result, 2)) return result
def decompose_magic_N(a): """Decomposes "Magic N" matrix into 3 CNOTs, 4 Rz and 1 Ry gate. Result is missing global phase pi/4. Implements cirquit on fig. 7 from [1]. """ t1 = 2 * a[2] - 0.5 * np.pi t2 = 0.5 * np.pi - 2 * a[0] t3 = 2 * a[1] - 0.5 * np.pi result = [] result.append(GateSingle(Gate2('Rz', 0.5 * np.pi), 1)) result.append(GateFC(Gate2('X'), 0)) result.append(GateSingle(Gate2('Rz', t1), 0)) result.append(GateSingle(Gate2('Ry', t2), 1)) result.append(GateFC(Gate2('X'), 1)) result.append(GateSingle(Gate2('Ry', t3), 1)) result.append(GateFC(Gate2('X'), 0)) result.append(GateSingle(Gate2('Rz', -0.5 * np.pi), 0)) N = magic_N(a) assert np.allclose(N, gates_to_matrix(result, 2) * np.exp(0.25j * np.pi)) return result
def check_decomp(matrix, gates, tol=1e-9): """Checks that `gates` is decomposition of `matrix`.""" qubits_count = int(np.log2(matrix.shape[0])) assert_all_close(matrix, gates_to_matrix(gates, qubits_count), tol=tol)
def check_decomp(matrix, gates, tol=1e-9): """Checks that `gates` is decomposition of `matrix`.""" assert_all_close(matrix, gates_to_matrix(gates), tol=tol)
def test_matrix_to_gates_SWAP(self): gates = qd.matrix_to_gates(SWAP) assert np.allclose(SWAP, gates_to_matrix(gates))
def test_TwoLevelUnitary_to_fc_gates(self): matrix = TwoLevelUnitary(unitary_group.rvs(2), 8, 1, 5) gates = matrix.to_fc_gates() assert np.allclose(gates_to_matrix(gates), matrix.get_full_matrix())