def test_oper_equiv(self): self.assertFalse( util.oper_equiv(qutip.rand_ket(2), qutip.rand_dm(2))[0]) for d in rng.integers(2, 10, (5, )): psi = qutip.rand_ket(d) U = qutip.rand_dm(d) phase = rng.standard_normal() result = util.oper_equiv(psi, psi * np.exp(1j * phase)) self.assertTrue(result[0]) self.assertAlmostEqual(np.mod(result[1], 2 * np.pi), np.mod(phase, 2 * np.pi), places=5) result = util.oper_equiv(psi * np.exp(1j * phase), psi) self.assertTrue(result[0]) self.assertAlmostEqual(np.mod(result[1], 2 * np.pi), np.mod(-phase, 2 * np.pi), places=5) result = util.oper_equiv(U, U * np.exp(1j * phase)) self.assertTrue(result[0]) self.assertAlmostEqual(np.mod(result[1], 2 * np.pi), np.mod(phase, 2 * np.pi), places=5) result = util.oper_equiv(U * np.exp(1j * phase), U) self.assertTrue(result[0]) self.assertAlmostEqual(np.mod(result[1], 2 * np.pi), np.mod(-phase, 2 * np.pi), places=5)
def test_oper_equiv(self): with self.assertRaises(ValueError): util.oper_equiv(rng.standard_normal((2, 2)), rng.standard_normal((3, 3))) for d in rng.randint(2, 10, (5, )): psi = rng.standard_normal((d, 1)) + 1j * rng.standard_normal( (d, 1)) # Also test broadcasting U = testutil.rand_herm(d, rng.randint(1, 11)).squeeze() phase = rng.standard_normal() result = util.oper_equiv(psi, psi * np.exp(1j * phase)) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], phase, places=5) result = util.oper_equiv(psi * np.exp(1j * phase), psi) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], -phase, places=5) psi /= np.linalg.norm(psi, ord=2) result = util.oper_equiv(psi, psi * np.exp(1j * phase), normalized=True, eps=1e-13) self.assertTrue(result[0]) self.assertArrayAlmostEqual(result[1], phase, atol=1e-5) result = util.oper_equiv(psi, psi + 1) self.assertFalse(result[0]) result = util.oper_equiv(U, U * np.exp(1j * phase)) self.assertTrue(np.all(result[0])) self.assertArrayAlmostEqual(result[1], phase, atol=1e-5) result = util.oper_equiv(U * np.exp(1j * phase), U) self.assertTrue(np.all(result[0])) self.assertArrayAlmostEqual(result[1], -phase, atol=1e-5) norm = np.sqrt(util.dot_HS(U, U)) norm = norm[:, None, None] if U.ndim == 3 else norm U /= norm # TIP: In numpy 1.18 we could just do: # U /= np.expand_dims(np.sqrt(util.dot_HS(U, U)), axis=(-1, -2)) result = util.oper_equiv(U, U * np.exp(1j * phase), normalized=True, eps=1e-10) self.assertTrue(np.all(result[0])) self.assertArrayAlmostEqual(result[1], phase) result = util.oper_equiv(U, U + 1) self.assertFalse(np.all(result[0]))
def test_oper_equiv(self): with self.assertRaises(ValueError): util.oper_equiv(*[np.ones((1, 2, 3))] * 2) for d in rng.randint(2, 10, (5, )): psi = rng.standard_normal((d, 1)) + 1j * rng.standard_normal( (d, 1)) U = testutil.rand_herm(d).squeeze() phase = rng.standard_normal() result = util.oper_equiv(psi, psi * np.exp(1j * phase)) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], phase, places=5) result = util.oper_equiv(psi * np.exp(1j * phase), psi) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], -phase, places=5) psi /= np.linalg.norm(psi, ord=2) result = util.oper_equiv(psi, psi * np.exp(1j * phase), normalized=True, eps=1e-13) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], phase, places=5) result = util.oper_equiv(psi, psi + 1) self.assertFalse(result[0]) result = util.oper_equiv(U, U * np.exp(1j * phase)) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], phase, places=5) result = util.oper_equiv(U * np.exp(1j * phase), U) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], -phase, places=5) U /= np.sqrt(util.dot_HS(U, U)) result = util.oper_equiv(U, U * np.exp(1j * phase), normalized=True, eps=1e-10) self.assertTrue(result[0]) self.assertAlmostEqual(result[1], phase) result = util.oper_equiv(U, U + 1) self.assertFalse(result[0])
def find_inverse(U: ndarray) -> ndarray: """ Function to find the inverting gate to take the input state back to itself. """ eye = np.identity(U.shape[0]) if util.oper_equiv(U, eye, eps=1e-8)[0]: return Id for i, gate in enumerate(permutation(cliffords)): if util.oper_equiv(gate.total_propagator @ U, eye, eps=1e-8)[0]: return gate # Shouldn't reach this point because the major axis pi and pi/2 rotations # are in the Clifford group, the state is always an eigenstate of a Pauli # operator during the pulse sequence. raise Exception