def yzy_to_zyz(xi, theta1, theta2, eps=1e-9): """Express a Y.Z.Y single qubit gate as a Z.Y.Z gate. Solve the equation .. math:: Ry(theta1).Rz(xi).Ry(theta2) = Rz(phi).Ry(theta).Rz(lambda) for theta, phi, and lambda. Return a solution theta, phi, and lambda. """ Q = quaternion_from_euler([theta1, xi, theta2], 'yzy') euler = Q.to_zyz() P = quaternion_from_euler(euler, 'zyz') # output order different than rotation order out_angles = (euler[1], euler[0], euler[2]) abs_inner = abs(P.data.dot(Q.data)) if not np.allclose(abs_inner, 1, eps): logger.debug("xi=%s", xi) logger.debug("theta1=%s", theta1) logger.debug("theta2=%s", theta2) logger.debug("solutions=%s", out_angles) logger.debug("abs_inner=%s", abs_inner) raise MapperError('YZY and ZYZ angles do not give same rotation matrix.') return out_angles
def test_equiv_quaternions(self): """Different Euler rotations give same quaternion, up to sign.""" # Check if euler angles from to_zyz return same quaternion # up to a sign (2pi rotation) rot = { 0: 'xyz', 1: 'xyx', 2: 'xzy', 3: 'xzx', 4: 'yzx', 5: 'yzy', 6: 'yxz', 7: 'yxy', 8: 'zxy', 9: 'zxz', 10: 'zyx', 11: 'zyz' } for _ in range(1000): rnd = 4 * np.pi * (np.random.random(3) - 0.5) idx = np.random.randint(12) quat1 = quaternion_from_euler(rnd, rot[idx]) euler = quat1.to_zyz() quat2 = quaternion_from_euler(euler, 'zyz') self.assertTrue(np.allclose(abs(quat1.data.dot(quat2.data)), 1))
def test_det(self): """Quaternion det = 1""" # Check det for rotation and not reflection axes = {0: 'x', 1: 'y', 2: 'z'} for _ in range(1000): rnd = 4*np.pi*(np.random.random(3)-0.5) idx = np.random.randint(3, size=3) axes_str = ''.join(axes[i] for i in idx) quat = quaternion_from_euler(rnd, axes_str) mat = quat.to_matrix() self.assertTrue(np.allclose(la.det(mat), 1))
def test_orthogonality(self): """Quaternion rotation matrix orthogonality""" # Check orthogonality of generated roation matrix axes = {0: 'x', 1: 'y', 2: 'z'} for _ in range(1000): rnd = 4*np.pi*(np.random.random(3)-0.5) idx = np.random.randint(3, size=3) axes_str = ''.join(axes[i] for i in idx) quat = quaternion_from_euler(rnd, axes_str) mat = quat.to_matrix() self.assertTrue(np.allclose(mat.dot(mat.T), np.identity(3, dtype=float)))
def test_random_euler(self): """Quaternion from random Euler rotations.""" # Random angles and axes axes = {0: 'x', 1: 'y', 2: 'z'} for _ in range(1000): rnd = 4*np.pi*(np.random.random(3)-0.5) idx = np.random.randint(3, size=3) mat1 = _rotm(rnd[0], axes[idx[0]]).dot( _rotm(rnd[1], axes[idx[1]]).dot(_rotm(rnd[2], axes[idx[2]]))) axes_str = ''.join(axes[i] for i in idx) quat = quaternion_from_euler(rnd, axes_str) mat2 = quat.to_matrix() self.assertTrue(np.allclose(mat1, mat2))