def test_weyl_coordinates_simple(self): """Check Weyl coordinates against known cases. """ # Identity [0,0,0] U = np.identity(4) weyl = weyl_coordinates(U) assert_allclose(weyl, [0, 0, 0]) # CNOT [pi/4, 0, 0] U = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex) weyl = weyl_coordinates(U) assert_allclose(weyl, [np.pi / 4, 0, 0], atol=1e-07) # SWAP [pi/4, pi/4 ,pi/4] U = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=complex) weyl = weyl_coordinates(U) assert_allclose(weyl, [np.pi / 4, np.pi / 4, np.pi / 4]) # SQRT ISWAP [pi/8, pi/8, 0] U = np.array([[1, 0, 0, 0], [0, 1 / np.sqrt(2), 1j / np.sqrt(2), 0], [0, 1j / np.sqrt(2), 1 / np.sqrt(2), 0], [0, 0, 0, 1]], dtype=complex) weyl = weyl_coordinates(U) assert_allclose(weyl, [np.pi / 8, np.pi / 8, 0])
def _generate_xxyy_test_case(self): """ Generates a random pentuple of values (a_source, b_source), beta, (a_target, b_target) s.t. CAN(a_source, b_source) * exp(-i(s ZI + t IZ)) * CAN(beta) = exp(-i(u ZI + v IZ)) * CAN(a_target, b_target) * exp(-i(x ZI + y IZ)) admits a solution in (s, t, u, v, x, y). Returns (source_coordinate, interaction, target_coordinate). """ source_coordinate = [self.rng.random(), self.rng.random(), 0.0] source_coordinate = [ source_coordinate[0] * np.pi / 8, source_coordinate[1] * source_coordinate[0] * np.pi / 8, 0.0, ] interaction = [self.rng.random() * np.pi / 8] z_angles = [ self.rng.random() * np.pi / 8, self.rng.random() * np.pi / 8 ] prod = (canonical_matrix(*source_coordinate) @ np.kron( RZGate(2 * z_angles[0]).to_matrix(), RZGate(2 * z_angles[1]).to_matrix()) @ canonical_matrix( interaction[0], 0.0, 0.0)) target_coordinate = weyl_coordinates(prod) self.assertAlmostEqual(target_coordinate[-1], 0.0, delta=EPSILON) return source_coordinate, interaction, target_coordinate
def test_weyl_coordinates_random(self): """Randomly check Weyl coordinates with local invariants.""" for _ in range(10): U = random_unitary(4).data weyl = weyl_coordinates(U) local_equiv = local_equivalence(weyl) local = two_qubit_local_invariants(U) assert_allclose(local, local_equiv)
def num_basis_gates(self, unitary): """ Computes the number of basis gates needed in a decomposition of input unitary """ unitary = np.asarray(unitary, dtype=complex) a, b, c = weyl_coordinates(unitary)[:] traces = [ 4 * (math.cos(a) * math.cos(b) * math.cos(c) + 1j * math.sin(a) * math.sin(b) * math.sin(c)), 4 * (math.cos(np.pi / 4 - a) * math.cos(self.basis.b - b) * math.cos(c) + 1j * math.sin(np.pi / 4 - a) * math.sin(self.basis.b - b) * math.sin(c)), 4 * math.cos(c), 4 ] return np.argmax([ trace_to_fid(traces[i]) * self.basis_fidelity**i for i in range(4) ])
def num_basis_gates(self, unitary): """ Computes the number of basis gates needed in a decomposition of input unitary """ if hasattr(unitary, 'to_operator'): unitary = unitary.to_operator().data if hasattr(unitary, 'to_matrix'): unitary = unitary.to_matrix() unitary = np.asarray(unitary, dtype=complex) a, b, c = weyl_coordinates(unitary)[:] traces = [4*(np.cos(a)*np.cos(b)*np.cos(c)+1j*np.sin(a)*np.sin(b)*np.sin(c)), 4*(np.cos(np.pi/4-a)*np.cos(self.basis.b-b)*np.cos(c) + 1j*np.sin(np.pi/4-a)*np.sin(self.basis.b-b)*np.sin(c)), 4*np.cos(c), 4] return np.argmax([trace_to_fid(traces[i]) * self.basis_fidelity**i for i in range(4)])