def test_extract_arbitrary_unitary_one_mode(self, setup_eng, cutoff, tol): """Test that arbitrary unitary extraction works for 1 mode""" S = ops.Sgate(0.4, -1.2) D = ops.Dgate(2, 0.9) K = ops.Kgate(-1.5) # not a state but it doesn't matter initial_state = np.random.rand(cutoff) + 1j * np.random.rand(cutoff) eng_ref, p0 = setup_eng(1) with p0.context as q: ops.Ket(initial_state) | q prog = sf.Program(p0) with prog.context as q: S | q D | q K | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=eng_ref.backend_name) if isinstance(U, tf.Tensor): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) in_state = tf.constant(initial_state.reshape([-1]), dtype=tf.complex64) final_state = sess.run(tf.einsum("ab,b", U, in_state)) else: final_state = U @ initial_state expected_state = eng_ref.run([p0, prog]).ket() assert np.allclose(final_state, expected_state, atol=tol, rtol=0)
def test_extract_arbitrary_unitary_one_mode(self, setup_eng, cutoff, tol): """Test that arbitrary unitary extraction works for 1 mode""" S = ops.Sgate(0.4, -1.2) D = ops.Dgate(2, 0.9) K = ops.Kgate(-1.5) # not a state but it doesn't matter initial_state = np.random.rand(cutoff) + 1j * np.random.rand(cutoff) eng_ref, p0 = setup_eng(1) with p0.context as q: ops.Ket(initial_state) | q prog = sf.Program(p0) with prog.context as q: S | q D | q K | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=eng_ref.backend_name) if isinstance(U, tf.Tensor): U = U.numpy() final_state = U @ initial_state expected_state = eng_ref.run([p0, prog]).state.ket() assert np.allclose(final_state, expected_state, atol=tol, rtol=0)
def test_extract_arbitrary_unitary_two_modes_vectorized( self, setup_eng, cutoff, batch_size, tol): """Test that arbitrary unitary extraction works for 2 mode when vectorized""" bsize = 1 if batch_size is not None: bsize = batch_size S = ops.Sgate(0.4, -1.2) B = ops.BSgate(2.234, -1.165) # not a state but it doesn't matter initial_state = np.complex64( np.random.rand(cutoff, cutoff) + 1j * np.random.rand(cutoff, cutoff)) eng_ref, p0 = setup_eng(2) with p0.context as q: ops.Ket(initial_state) | q prog = sf.Program(p0) with prog.context as q: S | q[0] B | q S | q[1] B | q U = utils.extract_unitary( prog, cutoff_dim=cutoff, vectorize_modes=True, backend=eng_ref.backend_name, ) if isinstance(U, tf.Tensor): U = U.numpy() final_state = U @ initial_state.reshape([-1]) expected_state = eng_ref.run([p0, prog]).state.ket() if isinstance(expected_state, tf.Tensor): expected_state = expected_state.numpy() if expected_state.shape[ 0] == bsize: # the Fock backend does not support batching! for exp_state in expected_state: assert np.allclose(final_state, exp_state.reshape([-1]), atol=tol, rtol=0) else: assert np.allclose(final_state, expected_state.reshape([-1]), atol=tol, rtol=0)
def test_extract_arbitrary_unitary_two_modes_vectorized( self, setup_eng, cutoff, batch_size, tol): """Test that arbitrary unitary extraction works for 2 mode when vectorized""" bsize = 1 if batch_size is not None: bsize = batch_size S = ops.Sgate(0.4, -1.2) B = ops.BSgate(2.234, -1.165) # not a state but it doesn't matter initial_state = np.complex64( np.random.rand(cutoff, cutoff) + 1j * np.random.rand(cutoff, cutoff)) eng_ref, q = setup_eng(2) with eng_ref: ops.Ket(initial_state) | q S | q[0] B | q S | q[1] B | q eng, q = sf.Engine(2) with eng: S | q[0] B | q S | q[1] B | q U = utils.extract_unitary( eng, cutoff_dim=cutoff, vectorize_modes=True, backend=eng_ref.backend._short_name, ) if isinstance(U, tf.Tensor): final_state = tf.Session().run( tf.einsum("ab,b", U, tf.constant(initial_state.reshape([-1])))) final_state = np.tile(final_state, bsize) else: final_state = U @ initial_state.reshape([-1]) expected_state = eng_ref.run().ket().reshape([-1]) assert np.allclose(final_state, expected_state, atol=tol, rtol=0)
def test_extract_displacement(self, backend_name, cutoff, tol): """test that the displacement gate is correctly extracted""" prog = sf.Program(1) alpha = 0.432 - 0.8543j with prog.context as q: ops.Dgate(alpha) | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=backend_name) expected = disp_U(alpha, cutoff) if isinstance(U, tf.Tensor): U = tf.Session().run(U) assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_beamsplitter(self, backend_name, cutoff, tol): """test that the beamsplitter gate is correctly extracted""" prog = sf.Program(2) theta = 0.432 phi = 0.765 with prog.context as q: ops.BSgate(theta, phi) | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=backend_name) expected = bs_U(theta, phi, cutoff) if isinstance(U, tf.Tensor): U = U.numpy() assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_displacement(self, backend_name, cutoff, tol): """test that the displacement gate is correctly extracted""" prog = sf.Program(1) r = 0.95732 phi = -1.10262 with prog.context as q: ops.Dgate(r, phi) | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=backend_name) expected = disp_U(r, phi, cutoff) if isinstance(U, tf.Tensor): U = U.numpy() assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_kerr(self, backend_name, cutoff, tol): """test that the Kerr gate is correctly extracted""" prog = sf.Program(1) kappa = 0.432 with prog.context as q: ops.Kgate(kappa) | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=backend_name) expected = np.diag(np.exp(1j * kappa * np.arange(cutoff)**2)) if isinstance(U, tf.Tensor): U = U.numpy() assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_squeezing(self, backend_name, cutoff, tol): """test that the squeezing gate is correctly extracted""" prog = sf.Program(1) r = 0.432 phi = -0.96543 with prog.context as q: ops.Sgate(r, phi) | q U = utils.extract_unitary(prog, cutoff_dim=cutoff, backend=backend_name) expected = sq_U(r, phi, cutoff) if isinstance(U, tf.Tensor): U = U.numpy() assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_displacement(self, setup_backend, cutoff, tol): """test that the displacement gate is correctly extracted""" backend = setup_backend(1) eng, q = sf.Engine(1) alpha = 0.432 - 0.8543j with eng: ops.Dgate(alpha) | q U = utils.extract_unitary(eng, cutoff_dim=cutoff, backend=backend._short_name) expected = disp_U(alpha, cutoff) if isinstance(U, tf.Tensor): U = tf.Session().run(U) assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_kerr(self, setup_backend, cutoff, tol): """test that the Kerr gate is correctly extracted""" backend = setup_backend(1) eng, q = sf.Engine(1) kappa = 0.432 with eng: ops.Kgate(kappa) | q U = utils.extract_unitary(eng, cutoff_dim=cutoff, backend=backend._short_name) expected = np.diag(np.exp(1j * kappa * np.arange(cutoff)**2)) if isinstance(U, tf.Tensor): U = tf.Session().run(U) assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_beamsplitter(self, setup_backend, cutoff, tol): """test that the beamsplitter gate is correctly extracted""" backend = setup_backend(2) eng, q = sf.Engine(2) theta = 0.432 phi = 0.765 with eng: ops.BSgate(theta, phi) | q U = utils.extract_unitary(eng, cutoff_dim=cutoff, backend=backend._short_name) expected = bs_U(np.cos(theta), np.sin(theta), phi, cutoff) if isinstance(U, tf.Tensor): U = tf.Session().run(U) assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_squeezing(self, setup_backend, cutoff, tol): """test that the squeezing gate is correctly extracted""" backend = setup_backend(1) eng, q = sf.Engine(1) r = 0.432 phi = -0.96543 with eng: ops.Sgate(r, phi) | q U = utils.extract_unitary(eng, cutoff_dim=cutoff, backend=backend._short_name) expected = sq_U(r, phi, cutoff) if isinstance(U, tf.Tensor): U = tf.Session().run(U) assert np.allclose(U, expected, atol=tol, rtol=0)
def test_extract_arbitrary_unitary_two_modes_not_vectorized( self, setup_eng, cutoff, tol): """Test that arbitrary unitary extraction works for 2 mode""" S = ops.Sgate(0.4, -1.2) B = ops.BSgate(2.234, -1.165) # not a state but it doesn't matter initial_state = np.complex64( np.random.rand(cutoff, cutoff) + 1j * np.random.rand(cutoff, cutoff)) eng_ref, q = setup_eng(2) if eng_ref.backend._short_name == "tf": pytest.skip( "Un vectorized mode only supports Fock backend for now") with eng_ref: ops.Ket(initial_state) | q S | q[0] B | q S | q[1] B | q eng, q = sf.Engine(2) with eng: S | q[0] B | q S | q[1] B | q U = utils.extract_unitary( eng, cutoff_dim=cutoff, vectorize_modes=False, backend=eng_ref.backend._short_name, ) final_state = np.einsum("abcd,bd->ac", U, initial_state) expected_state = eng_ref.run().ket() assert np.allclose(final_state, expected_state, atol=tol, rtol=0)