def test_CZgate(self, setup_eng, pure, hbar, tol): """Test the action of the CZ gate in phase space""" if not pure: pytest.skip("Test only runs on pure states") N = 2 eng, prog = setup_eng(N) r = 3 x1 = 2 x2 = 1 p1 = 1.37 p2 = 2.71 s = 0.5 with prog.context as q: ops.Sgate(r) | q[0] ops.Xgate(x1) | q[0] ops.Zgate(p1) | q[0] ops.Sgate(r) | q[1] ops.Xgate(x2) | q[1] ops.Zgate(p2) | q[1] ops.CZgate(s) | q state = eng.run(prog).state CZmat = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, s, 1, 0], [s, 0, 0, 1]]) Vexpected = 0.5 * hbar * CZmat @ np.diag( np.exp([-2 * r, -2 * r, 2 * r, 2 * r])) @ CZmat.T # Checks the covariance matrix is transformed correctly assert np.allclose(state.cov(), Vexpected, atol=tol, rtol=0) rexpected = CZmat @ np.array([x1, x2, p1, p2]) # Checks the means are transformed correctly assert np.allclose(state.means(), rexpected, atol=tol, rtol=0)
def test_Pgate(self, setup_eng, pure, hbar, tol): """Test the action of the P gate in phase space""" if not pure: pytest.skip("Test only runs on pure states") N = 1 eng, prog = setup_eng(N) r = 3 x1 = 2 p1 = 1.3 s = 0.5 with prog.context as q: ops.Sgate(r) | q ops.Xgate(x1) | q ops.Zgate(p1) | q ops.Pgate(s) | q state = eng.run(prog).state Pmat = np.array([[1, 0], [s, 1]]) Vexpected = 0.5 * hbar * Pmat @ np.diag(np.exp([-2 * r, 2 * r])) @ Pmat.T rexpected = Pmat @ np.array([x1, p1]) # Check the covariance and mean transformed correctly if eng.backend_name == "gaussian": assert np.allclose(state.cov(), Vexpected, atol=tol, rtol=0) assert np.allclose(state.means(), rexpected, atol=tol, rtol=0) elif eng.backend_name == "bosonic": assert np.allclose(state.covs(), np.expand_dims(Vexpected,axis=0), atol=tol, rtol=0) assert np.allclose(state.means(), np.expand_dims(rexpected,axis=0), atol=tol, rtol=0)
def test_non_primitive_gates(): """Tests that the compiler is able to compile a number of non-primitive Gaussian gates""" width = 6 eng = sf.LocalEngine(backend="gaussian") eng1 = sf.LocalEngine(backend="gaussian") circuit = sf.Program(width) A = np.random.rand(width, width) + 1j * np.random.rand(width, width) A = A + A.T valsA = np.linalg.svd(A, compute_uv=False) A = A / 2 * np.max(valsA) B = np.random.rand( width // 2, width // 2) + 1j * np.random.rand(width // 2, width // 2) valsB = np.linalg.svd(B, compute_uv=False) B = B / 2 * valsB B = np.block([[0 * B, B], [B.T, 0 * B]]) with circuit.context as q: ops.GraphEmbed(A) | q ops.BipartiteGraphEmbed(B) | q ops.Pgate(0.1) | q[1] ops.CXgate(0.2) | (q[0], q[1]) ops.MZgate(0.4, 0.5) | (q[2], q[3]) ops.Fourier | q[0] ops.Xgate(0.4) | q[1] ops.Zgate(0.5) | q[3] compiled_circuit = circuit.compile(compiler="gaussian_unitary") cv = eng.run(circuit).state.cov() mean = eng.run(circuit).state.means() cv1 = eng1.run(compiled_circuit).state.cov() mean1 = eng1.run(compiled_circuit).state.means() assert np.allclose(cv, cv1) assert np.allclose(mean, mean1)
def test_CXgate(self, setup_eng, pure, hbar, tol): """Test the action of the CX gate in phase space""" if not pure: pytest.skip("Test only runs on pure states") N = 2 eng, prog = setup_eng(N) r = 3 x1 = 2 x2 = 1 p1 = 1.37 p2 = 2.71 s = 0.5 with prog.context as q: ops.Sgate(r) | q[0] ops.Xgate(x1) | q[0] ops.Zgate(p1) | q[0] ops.Sgate(r) | q[1] ops.Xgate(x2) | q[1] ops.Zgate(p2) | q[1] ops.CXgate(s) | q state = eng.run(prog).state CXmat = np.array([[1, 0, 0, 0], [s, 1, 0, 0], [0, 0, 1, -s], [0, 0, 0, 1]]) Vexpected = 0.5 * hbar * CXmat @ np.diag( np.exp([-2 * r, -2 * r, 2 * r, 2 * r])) @ CXmat.T rexpected = CXmat @ np.array([x1, x2, p1, p2]) # Check the covariance and mean transformed correctly if eng.backend_name == "gaussian": assert np.allclose(state.cov(), Vexpected, atol=tol, rtol=0) assert np.allclose(state.means(), rexpected, atol=tol, rtol=0) elif eng.backend_name == "bosonic": indices = from_xp(2) Vexpected = Vexpected[:, indices][indices, :] rexpected = rexpected[indices] assert np.allclose(state.covs(), np.expand_dims(Vexpected, axis=0), atol=tol, rtol=0) assert np.allclose(state.means(), np.expand_dims(rexpected, axis=0), atol=tol, rtol=0)
def test_merge_incompatible(): """Test merging of incompatible gates does nothing""" eng, _ = sf.Engine(3) with eng: ops.Xgate(0.6) | 0 ops.Zgate(0.2) | 0 eng.optimize() assert len(eng.cmd_queue) == 2
def test_merge_incompatible(self): """Test merging of incompatible gates does nothing""" prog = sf.Program(3) with prog.context: ops.Xgate(0.6) | 0 ops.Zgate(0.2) | 0 prog = prog.optimize() assert len(prog) == 2
def test_xx_1(self, tmpdir): prog = sf.Program(3) with prog.context as q: ops.Xgate(1) | (q[1]) ops.Xgate(1) | (q[1]) xx_test_1_output = dedent(r""" \documentclass{article} \usepackage{qcircuit} \begin{document} \Qcircuit { & \qw & \qw & \qw \\ & \gate{X} & \gate{X} & \qw \\ & \qw & \qw & \qw \\ } \end{document}""") result = prog.draw_circuit(tex_dir=tmpdir)[1] assert result == xx_test_1_output, failure_message( result, xx_test_1_output)
def test_xx_1(self, tmpdir): eng, q = sf.Engine(3) with eng: ops.Xgate(1) | (q[1]) ops.Xgate(1) | (q[1]) xx_test_1_output = dedent(r""" \documentclass{article} \usepackage{qcircuit} \begin{document} \Qcircuit { & \qw & \qw & \qw \\ & \gate{X} & \gate{X} & \qw \\ & \qw & \qw & \qw \\ } \end{document}""") result = eng.draw_circuit(print_queued_ops=True, tex_dir=tmpdir)[1] assert result == xx_test_1_output, failure_message( result, xx_test_1_output)
def test_Xgate_decomposition(self, hbar, tol): """Test that the X gate is correctly decomposed into a displacement gate""" n = 1 prog = sf.Program(n) x = 0.7 alpha = x / np.sqrt(2 * hbar) X = ops.Xgate(x) cmds = X.decompose(prog.register) assert isinstance(cmds[0].op, ops.Dgate) assert np.allclose(cmds[0].op.p[0], alpha, atol=tol, rtol=0) assert np.allclose(cmds[0].op.p[1], 0, atol=tol, rtol=0)
def test_x_displacement(self, setup_eng, hbar, tol): """test x displacement on the Gaussian backend gives correct displacement""" eng, prog = setup_eng(1) with prog.context as q: ops.Xgate(X) | q state = eng.run(prog) mu_x = state.means()[0] assert state.hbar == hbar assert np.allclose(mu_x, X, atol=tol, rtol=0)
def test_x_displacement(self, setup_eng, hbar, tol): """test x displacement on the Gaussian and Bosonic backends gives correct displacement""" eng, prog = setup_eng(1) with prog.context as q: ops.Xgate(X) | q state = eng.run(prog).state if eng.backend_name == "gaussian": mu_x = state.means()[0] elif eng.backend_name == "bosonic": mu_x = state.means()[0, 0] assert state.hbar == hbar assert np.allclose(mu_x, X, atol=tol, rtol=0)
def test_shots_with_timebins_non_multiple_of_concurrent_modes(self): """Test that multiple shots work when having the number of timebins be a non-multiple of the number of concurrent modes""" theta = [0] * 3 shots = 2 prog = sf.TDMProgram(N=2) with prog.context(theta) as (p, q): ops.Xgate(50) | q[1] ops.MeasureHomodyne(p[0]) | q[0] eng = sf.Engine("gaussian") res = eng.run(prog, shots=shots) samples = res.samples expected = np.array([[[0, 50, 50]], [[50, 50, 50]]]) assert np.allclose(samples, expected, atol=4)
def test_one_mode_gates_from_operators(self, drawer): prog = sf.Program(3) with prog.context as q: ops.Xgate(1) | (q[0]) ops.Zgate(1) | (q[0]) ops.Kgate(1) | (q[0]) ops.Vgate(1) | (q[0]) ops.Pgate(1) | (q[0]) ops.Rgate(1) | (q[0]) ops.Sgate(1) | (q[0]) ops.Dgate(1) | (q[0]) for op in prog.circuit: method, mode = drawer._gate_from_operator(op) assert callable(method) and hasattr(drawer, method.__name__) assert mode == 1
def test_one_mode_gates_from_operators(self, drawer): eng, q = sf.Engine(3) with eng: ops.Xgate(1) | (q[0]) ops.Zgate(1) | (q[0]) ops.Kgate(1) | (q[0]) ops.Vgate(1) | (q[0]) ops.Pgate(1) | (q[0]) ops.Rgate(1) | (q[0]) ops.Sgate(1) | (q[0]) ops.Dgate(1) | (q[0]) for op in eng.cmd_queue: method, mode = drawer._gate_from_operator(op) assert callable(method) and hasattr(drawer, method.__name__) assert mode == 1
def test_parse_op(self, drawer): prog = sf.Program(3) with prog.context as q: ops.Xgate(1) | (q[0]) ops.Zgate(1) | (q[0]) ops.CXgate(1) | (q[0], q[1]) ops.CZgate(1) | (q[0], q[1]) ops.BSgate(0, 1) | (q[0], q[1]) ops.S2gate(0, 1) | (q[0], q[1]) ops.CKgate(1) | (q[0], q[1]) ops.Kgate(1) | (q[0]) ops.Vgate(1) | (q[0]) ops.Pgate(1) | (q[0]) ops.Rgate(1) | (q[0]) ops.Sgate(1) | (q[0]) ops.Dgate(1) | (q[0]) for op in prog.circuit: drawer.parse_op(op) expected_circuit_matrix = [ [ "\\gate{X}", "\\gate{Z}", "\\ctrl{1}", "\\ctrl{1}", "\\multigate{1}{BS}", "\\multigate{1}{S}", "\\ctrl{1}", "\\gate{K}", "\\gate{V}", "\\gate{P}", "\\gate{R}", "\\gate{S}", "\\gate{D}", ], ["\\qw"] * 2 + ["\\targ", "\\gate{Z}", "\\ghost{BS}", "\\ghost{S}", "\\gate{K}"] + ["\\qw"] * 6, ["\\qw"] * 13, ] assert drawer._circuit_matrix == expected_circuit_matrix
def test_parse_op(self, drawer): eng, q = sf.Engine(3) with eng: ops.Xgate(1) | (q[0]) ops.Zgate(1) | (q[0]) ops.CXgate(1) | (q[0], q[1]) ops.CZgate(1) | (q[0], q[1]) ops.BSgate(0, 1) | (q[0], q[1]) ops.S2gate(0, 1) | (q[0], q[1]) ops.CKgate(1) | (q[0], q[1]) ops.Kgate(1) | (q[0]) ops.Vgate(1) | (q[0]) ops.Pgate(1) | (q[0]) ops.Rgate(1) | (q[0]) ops.Sgate(1) | (q[0]) ops.Dgate(1) | (q[0]) for op in eng.cmd_queue: drawer.parse_op(op) expected_circuit_matrix = [ [ "\\gate{X}", "\\gate{Z}", "\\ctrl{1}", "\\ctrl{1}", "\\multigate{1}{BS}", "\\multigate{1}{S}", "\\ctrl{1}", "\\gate{K}", "\\gate{V}", "\\gate{P}", "\\gate{R}", "\\gate{S}", "\\gate{D}", ], ["\\qw"] * 2 + ["\\targ", "\\gate{Z}", "\\ghost{BS}", "\\ghost{S}", "\\gate{K}"] + ["\\qw"] * 6, ["\\qw"] * 13, ] assert drawer._circuit_matrix == expected_circuit_matrix
def test_Pgate(self, setup_eng, pure, hbar, tol): """Test the action of the P gate in phase space""" if not pure: pytest.skip("Test only runs on pure states") N = 1 eng, prog = setup_eng(N) r = 3 x1 = 2 p1 = 1.3 s = 0.5 with prog.context as q: ops.Sgate(r) | q ops.Xgate(x1) | q ops.Zgate(p1) | q ops.Pgate(s) | q state = eng.run(prog).state Pmat = np.array([[1, 0], [s, 1]]) Vexpected = 0.5 * hbar * Pmat @ np.diag(np.exp([-2 * r, 2 * r ])) @ Pmat.T assert np.allclose(Vexpected, state.cov(), atol=tol, rtol=0) rexpected = Pmat @ np.array([x1, p1]) assert np.allclose(rexpected, state.means(), atol=tol, rtol=0)
def Q(self): """The common test gate""" return ops.Xgate(0.5)
def test_create_delete_reset(self, backend): """Test various use cases creating and deleting modes, together with engine resets.""" eng, reg = sf.Engine(2) # define some gates X = ops.Xgate(0.5) alice, bob = reg # states of the subsystems: active, not_measured state = np.full((len(reg), 2), True) def prog1(q): """program 1""" X | q ops.MeasureX | q def prog2(q): """program 2""" X | q ops.MeasureX | q ops.Del | q state[q.ind, 0] = False # no longer active def reset(): """reset the engine""" eng.reset() state[:] = True def check(): """Check the activity and measurement state of subsystems. Activity state is changed right away when a Del command is applied to Engine, but a measurement result only becomes available during Engine.run(). """ for r, (a, nm) in zip(reg, state): assert r.active == a assert (r.val is None) == nm def input(p, reg): """input a program to the engine""" with eng: p(reg) check() def input_and_run(p, reg): """input a program to the engine and run it""" with eng: p(reg) check() eng.run(backend) # now measured (assumes p will always measure reg!) state[reg.ind, 1] = False check() reset() ## (1) run several independent programs, resetting everything in between input_and_run(prog1, alice) reset() input_and_run(prog2, bob) reset() ## (2) interactive state evolution in multiple runs input_and_run(prog2, alice) input_and_run(prog1, bob) reset() ## (3) repeat a (possibly extended) program fragment (the fragment must not create/delete subsystems!) input_and_run(prog1, alice) eng.cmd_queue.extend(eng.cmd_applied[-1]) check() input_and_run(prog1, bob) reset() ## (4) interactive use, "changed my mind" input_and_run(prog1, alice) input(prog2, bob) eng.reset_queue() # scratch that, back to last checkpoint state[bob.ind, 0] = True # bob should be active again check() input_and_run(prog1, bob) reset() ## (5) reset the state, run the same program again to get new measurement samples input_and_run(prog1, alice) input(prog2, bob) eng.reset(keep_history=True) state[ alice.ind, 1] = True # measurement result was erased, activity did not change state[bob.ind, 1] = True check() eng.run(backend) state[alice.ind, 1] = False state[bob.ind, 1] = False check()