def test_measured_parameter(self, setup_eng): """Test that a circuit with measured parameters executes successfully.""" eng, prog = setup_eng(2) with prog.context as q: ops.MeasureX | q[0] ops.Sgate(q[0].par) | q[1] # symbolic hermitian conjugate together with register reference ops.Dgate(q[0].par, 0).H | q[1] # algebraic transformation ops.Sgate(q[0].par**2) | q[1] # algebraic transformation and h.c. ops.Dgate(q[0].par, np.pi).H | q[1] eng.run(prog)
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_displaced_squeezed(self, setup_eng, hbar, cutoff, bsize, pure, tol): """Test displaced squeezed function matches Fock backends""" eng, prog = setup_eng(1) a = 0.32 + 0.1j r = 0.112 phi = 0.123 with prog.context as q: ops.Sgate(r, phi) | q[0] ops.Dgate(np.abs(a), np.angle(a)) | q[0] state = eng.run(prog).state ket = utils.displaced_squeezed_state(np.abs(a), np.angle(a), r, phi, basis="fock", fock_dim=cutoff, hbar=hbar) if not pure: expected = state.dm() ket = np.tile(np.outer(ket, ket.conj()), (bsize, 1, 1)) else: expected = state.ket() ket = np.tile(ket, (bsize, 1)) assert np.allclose(expected, ket, atol=tol, rtol=0)
def test_cropping_tdmprogram_with_several_spatial_modes(self): """Test that error is raised when cropping samples from a TDM program with more than one spatial mode""" prog = TDMProgram(N=[1, 2]) with prog.context([0, np.pi / 2], [0, np.pi / 2]) as (p, q): ops.Sgate(4) | q[0] ops.Sgate(4) | q[2] ops.MeasureHomodyne(p[0]) | q[0] ops.MeasureHomodyne(p[1]) | q[1] with pytest.raises( NotImplementedError, match="Cropping vacuum modes for programs with more than one spatial mode is not implemented.", ): prog.get_crop_value()
def test_S2gate_decomp_equal(self, setup_eng, r, tol): """Tests that the S2gate gives the same transformation as its decomposition.""" eng, prog = setup_eng(2) phi = 0.273 BS = ops.BSgate(np.pi / 4, 0) with prog.context as q: ops.S2gate(r, phi) | q # run decomposition with reversed arguments BS | q ops.Sgate(-r, phi) | q[0] ops.Sgate(r, phi) | q[1] BS.H | q eng.run(prog) assert np.all(eng.backend.is_vacuum(tol))
def test_apply_history(self, setup_eng, pure): """Tests the reapply history argument works correctly with a backend""" eng, q = setup_eng(2) a = 0.23 r = 0.1 def inspect(): res = [] print_fn = lambda x: res.append(x.__str__()) eng.print_applied(print_fn) return res with eng: ops.Dgate(a) | q[0] ops.Sgate(r) | q[1] state1 = eng.run() expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), ] assert inspect() == expected # reset backend, but reapply history eng.backend.reset(pure=pure) state2 = eng.run(apply_history=True) assert inspect() == expected assert state1 == state2 # append more commands to the same backend with eng: ops.Rgate(r) | q[0] state3 = eng.run() expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), "Run 1:", "Rgate({}) | (q[0])".format(r), ] assert inspect() == expected assert not state2 == state3 # reset backend, but reapply history eng.backend.reset(pure=pure) state4 = eng.run(apply_history=True) expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), "Rgate({}) | (q[0])".format(r), ] assert inspect() == expected assert state3 == state4
def test_displaced_squeezed(self, a, r, phi, setup_eng, hbar, tol): """Test displaced squeezed function matches Gaussian backends""" eng, prog = setup_eng(1) with prog.context as q: ops.Sgate(r, phi) | q[0] ops.Dgate(np.abs(a), np.angle(a)) | q[0] state = eng.run(prog).state mu, cov = utils.displaced_squeezed_state(np.abs(a), np.angle(a), r, phi, basis="gaussian", hbar=hbar) if eng.backend_name == "gassian": mu_exp, cov_exp = state.reduced_gaussian(0) assert np.allclose(mu, mu_exp, atol=tol, rtol=0) assert np.allclose(cov, cov_exp, atol=tol, rtol=0) elif eng.backend_name == "bosonic": _, mu_exp, cov_exp = state.reduced_bosonic(0) assert np.allclose(np.expand_dims(mu, axis=0), mu_exp, atol=tol, rtol=0) assert np.allclose(np.expand_dims(cov, axis=0), cov_exp, atol=tol, rtol=0)
def test_unroll_shots(self): """Test unrolling program several times using different number of shots.""" n = 2 shots = 2 prog = sf.TDMProgram(N=2) with prog.context([0] * n, [0] * n, [0] * n) as (p, q): ops.Sgate(0.5643, 0) | q[1] ops.BSgate(p[0]) | (q[1], q[0]) ops.Rgate(p[1]) | q[1] ops.MeasureHomodyne(p[2]) | q[0] prog_length = len(prog.circuit) assert prog_length == 4 prog.unroll(shots=shots) assert len(prog.circuit) == n * shots * prog_length # unroll once more with the same number of shots to cover caching prog.unroll(shots=shots) assert len(prog.circuit) == n * shots * prog_length # unroll once more with a different number of shots shots = 3 prog.unroll(shots=shots) assert len(prog.circuit) == n * shots * prog_length prog.roll() assert len(prog.circuit) == prog_length
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_free_parameters(setup_eng, tol): """Programs with free parameters.""" eng, prog = setup_eng(1) x = prog.params("x") # free parameter with prog.context as q: ops.Dgate(x) | q ops.Sgate(-1.2 * x * pf.sin(x**2 - 0.1)) | q with pytest.raises(ParameterError, match="Unknown free parameter"): eng.run(prog, args={"foo": 1.0}) with pytest.raises(ParameterError, match="unbound parameter with no default value"): eng.run(prog) # successful run eng.run(prog, args={x: 0.0}) assert np.all(eng.backend.is_vacuum(tol)) eng.reset() # now set a default value for the free parameter x.default = 0.0 eng.run(prog) assert np.all(eng.backend.is_vacuum(tol)) eng.reset() # override the default x.default = 1.0 eng.run(prog, args={x: 0.0}) assert np.all(eng.backend.is_vacuum(tol))
def setup_two_mode_circuit(self, setup_eng, cutoff): """Create the circuit for following tests""" eng_ref, q = setup_eng(2) S = ops.Sgate(2) B = ops.BSgate(2.234, -1.165) initial_state = np.complex64( np.random.rand(*[cutoff] * 4) + 1j * np.random.rand(*[cutoff] * 4)) with eng_ref: ops.DensityMatrix(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 rho = eng_ref.run().dm() return eng, rho, initial_state
def layer(params, q): """CV quantum neural network layer acting on ``N`` modes. Args: params (list[float]): list of length ``2*(max(1, N-1) + N**2 + n)`` containing the number of parameters for the layer q (list[RegRef]): list of Strawberry Fields quantum registers the layer is to be applied to """ N = len(q) M = int(N * (N - 1)) + max(1, N - 1) int1 = params[:M] s = params[M:M + N] int2 = params[M + N:2 * M + N] dr = params[2 * M + N:2 * M + 2 * N] dp = params[2 * M + 2 * N:2 * M + 3 * N] k = params[2 * M + 3 * N:2 * M + 4 * N] # begin layer interferometer(int1, q) for i in range(N): ops.Sgate(s[i]) | q[i] interferometer(int2, q) for i in range(N): ops.Dgate(dr[i], dp[i]) | q[i] ops.Kgate(k[i]) | q[i]
def test_modes_subset(depth): """Tests that the compiler recognizes which modes are not being modified and acts accordingly""" width = 10 eng = sf.LocalEngine(backend="gaussian") eng1 = sf.LocalEngine(backend="gaussian") circuit = sf.Program(width) indices = (1, 4, 2, 6, 7) active_modes = len(indices) with circuit.context as q: for _ in range(depth): U, s, V, _ = random_params(active_modes, 2.0 / depth, 1.0) ops.Interferometer(U) | tuple(q[i] for i in indices) for i, index in enumerate(indices): ops.Sgate(s[i]) | q[index] ops.Interferometer(V) | tuple(q[i] for i in indices) 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) assert len(compiled_circuit.circuit[0].reg) == 5 indices = [compiled_circuit.circuit[0].reg[i].ind for i in range(5)] assert indices == sorted(list(indices))
def test_delays_tdmprogram_with_several_spatial_modes(self): """Test that error is raised when calculating the delays of a TDM program with more than one spatial mode""" prog = TDMProgram(N=[1, 2]) with prog.context([0, np.pi / 2], [0, np.pi / 2]) as (p, q): ops.Sgate(4) | q[0] ops.Sgate(4) | q[2] ops.MeasureHomodyne(p[0]) | q[0] ops.MeasureHomodyne(p[1]) | q[1] with pytest.raises( NotImplementedError, match="Calculating delays for programs with more than one spatial mode is not implemented.", ): prog.get_delays()
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_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_GBS_compile_no_fock_meas(self): """Tests that GBS compilation fails when no fock measurements are made.""" prog = sf.Program(2) with prog.context as q: ops.Dgate(1.0) | q[0] ops.Sgate(-0.5) | q[1] with pytest.raises(program.CircuitError, match="GBS circuits must contain Fock measurements."): prog.compile('gbs')
def test_generate_code_no_engine(self): """Test generating code for a regular program with no engine""" prog = sf.Program(3) with prog.context as q: ops.Sgate(0.54, 0) | q[0] ops.BSgate(0.45, np.pi / 2) | (q[0], q[2]) ops.Sgate(3 * np.pi / 2, 0) | q[1] ops.BSgate(2 * np.pi, 0.62) | (q[0], q[1]) ops.MeasureFock() | q[0] code = io.generate_code(prog) code_list = code.split("\n") expected = prog_txt_no_engine.split("\n") for i, row in enumerate(code_list): assert row == expected[i]
def test_neq_operator(self): """Not-equal operator check.""" prog_1 = sf.Program(2) prog_2 = sf.Program(2) with prog_1.context as q: ops.Sgate(0.2) | q[0] ops.BSgate() | (q[0], q[1]) ops.MeasureFock() | q[1] with prog_2.context as q: ops.Sgate(4.2) | q[0] ops.BSgate() | (q[0], q[1]) ops.MeasureFock() | q[1] # should NOT be equal assert prog_1 != prog_2 assert prog_2 != prog_1
def test_one_dimensional_cluster_tokyo(): """ One-dimensional temporal-mode cluster state as demonstrated in https://aip.scitation.org/doi/pdf/10.1063/1.4962732 """ sq_r = 5 n = 10 # for an n-mode cluster state shots = 3 # first half of cluster state measured in X, second half in P theta1 = [0] * int(n / 2) + [np.pi / 2] * int(n / 2) # measurement angles for detector A theta2 = theta1 # measurement angles for detector B prog = TDMProgram(N=[1, 2]) with prog.context(theta1, theta2, shift="default") as (p, q): ops.Sgate(sq_r, 0) | q[0] ops.Sgate(sq_r, 0) | q[2] ops.Rgate(np.pi / 2) | q[0] ops.BSgate(np.pi / 4) | (q[0], q[2]) ops.BSgate(np.pi / 4) | (q[0], q[1]) ops.MeasureHomodyne(p[0]) | q[0] ops.MeasureHomodyne(p[1]) | q[1] eng = sf.Engine("gaussian") result = eng.run(prog, shots=shots) reshaped_samples = result.samples for sh in range(shots): X_A = reshaped_samples[sh][0][: n // 2] # X samples from detector A P_A = reshaped_samples[sh][0][n // 2 :] # P samples from detector A X_B = reshaped_samples[sh][1][: n // 2] # X samples from detector B P_B = reshaped_samples[sh][1][n // 2 :] # P samples from detector B # nullifiers defined in https://aip.scitation.org/doi/pdf/10.1063/1.4962732, Eqs. (1a) and (1b) ntot = len(X_A) - 1 nX = np.array([X_A[i] + X_B[i] + X_A[i + 1] - X_B[i + 1] for i in range(ntot)]) nP = np.array([P_A[i] + P_B[i] - P_A[i + 1] + P_B[i + 1] for i in range(ntot)]) nXvar = np.var(nX) nPvar = np.var(nP) assert np.allclose(nXvar, 2 * sf.hbar * np.exp(-2 * sq_r), rtol=5 / np.sqrt(n)) assert np.allclose(nPvar, 2 * sf.hbar * np.exp(-2 * sq_r), rtol=5 / np.sqrt(n))
def test_apply_history(self, eng): """Tests the reapply history argument""" a = 0.23 r = 0.1 def inspect(): res = [] print_fn = lambda x: res.append(x.__str__()) eng.print_applied(print_fn) return res p1 = sf.Program(2) with p1.context as q: ops.Dgate(a) | q[1] ops.Sgate(r) | q[1] eng.run(p1) expected = [ "Run 0:", "Dgate({}, 0) | (q[1])".format(a), "Sgate({}, 0) | (q[1])".format(r), ] assert inspect() == expected # run the program again eng.reset() eng.run(p1) assert inspect() == expected # apply more commands to the same backend p2 = sf.Program(2) with p2.context as q: ops.Rgate(r) | q[1] eng.run(p2) expected = [ "Run 0:", "Dgate({}, 0) | (q[1])".format(a), "Sgate({}, 0) | (q[1])".format(r), "Run 1:", "Rgate({}) | (q[1])".format(r), ] assert inspect() == expected # reapply history eng.reset() eng.run([p1, p2]) #expected = [ # "Run 0:", # "Dgate({}, 0) | (q[1])".format(a), # "Sgate({}, 0) | (q[1])".format(r), # "Rgate({}) | (q[1])".format(r), #] assert inspect() == expected
def test_CXgate_decomp_equal(self, setup_eng, s, tol): """Tests that the CXgate gives the same transformation as its decomposition.""" eng, prog = setup_eng(2) r = np.arcsinh(-s / 2) y = -1 / np.cosh(r) x = -np.tanh(r) theta = np.arctan2(y, x) / 2 with prog.context as q: ops.CXgate(s) | q # run decomposition with reversed arguments ops.BSgate(-(np.pi / 2 + theta), 0) | q ops.Sgate(r, np.pi) | q[0] ops.Sgate(r, 0) | q[1] ops.BSgate(-theta, 0) | q eng.run(prog) assert np.all(eng.backend.is_vacuum(tol))
def test_all_passive_gates(hbar, tol): """test that all gates run and do not cause anything to crash""" eng = sf.LocalEngine(backend="gaussian") circuit = sf.Program(4) with circuit.context as q: for i in range(4): ops.Sgate(1, 0.3) | q[i] ops.Rgate(np.pi) | q[0] ops.PassiveChannel(np.ones((2, 2))) | (q[1], q[2]) ops.LossChannel(0.9) | q[1] ops.MZgate(0.25 * np.pi, 0) | (q[2], q[3]) ops.PassiveChannel(np.array([[0.83]])) | q[0] ops.sMZgate(0.11, -2.1) | (q[0], q[3]) ops.Interferometer(np.array([[np.exp(1j * 2)]])) | q[1] ops.BSgate(0.8, 0.4) | (q[1], q[3]) ops.Interferometer(0.5**0.5 * np.fft.fft(np.eye(2))) | (q[0], q[2]) ops.PassiveChannel(0.1 * np.ones((3, 3))) | (q[3], q[1], q[0]) cov = eng.run(circuit).state.cov() circuit = sf.Program(4) with circuit.context as q: ops.Rgate(np.pi) | q[0] ops.PassiveChannel(np.ones((2, 2))) | (q[1], q[2]) ops.LossChannel(0.9) | q[1] ops.MZgate(0.25 * np.pi, 0) | (q[2], q[3]) ops.PassiveChannel(np.array([[0.83]])) | q[0] ops.sMZgate(0.11, -2.1) | (q[0], q[3]) ops.Interferometer(np.array([[np.exp(1j * 2)]])) | q[1] ops.BSgate(0.8, 0.4) | (q[1], q[3]) ops.Interferometer(0.5**0.5 * np.fft.fft(np.eye(2))) | (q[0], q[2]) ops.PassiveChannel(0.1 * np.ones((3, 3))) | (q[3], q[1], q[0]) compiled_circuit = circuit.compile(compiler="passive") T = compiled_circuit.circuit[0].op.p[0] S_sq = np.eye(8, dtype=np.complex128) r = 1 phi = 0.3 for i in range(4): S_sq[i, i] = np.cosh(r) - np.sinh(r) * np.cos(phi) S_sq[i, i + 4] = -np.sinh(r) * np.sin(phi) S_sq[i + 4, i] = -np.sinh(r) * np.sin(phi) S_sq[i + 4, i + 4] = np.cosh(r) + np.sinh(r) * np.cos(phi) cov_sq = (hbar / 2) * S_sq @ S_sq.T mu = np.zeros(8) P = interferometer(T) L = (hbar / 2) * (np.eye(P.shape[0]) - P @ P.T) cov2 = P @ cov_sq @ P.T + L assert np.allclose(cov, cov2, atol=tol, rtol=0)
def test_apply_history(self, backend): """Tests the reapply history argument""" eng, q = sf.Engine(2) a = 0.23 r = 0.1 def inspect(): res = [] print_fn = lambda x: res.append(x.__str__()) eng.print_applied(print_fn) return res with eng: ops.Dgate(a) | q[0] ops.Sgate(r) | q[1] eng.run(backend) expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), ] assert inspect() == expected # reapply history state2 = eng.run(apply_history=True) assert inspect() == expected # append more commands to the same backend with eng: ops.Rgate(r) | q[0] eng.run() expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), "Run 1:", "Rgate({}) | (q[0])".format(r), ] assert inspect() == expected # reapply history eng.run(apply_history=True) expected = [ "Run 0:", "Dgate({}, 0) | (q[0])".format(a), "Sgate({}, 0) | (q[1])".format(r), "Rgate({}) | (q[0])".format(r), ] assert inspect() == expected
def test_shots_default(self): """Test that default shots (1) is used""" prog = sf.TDMProgram(2) eng = sf.Engine("gaussian") with prog.context([1, 2], [3, 4]) as (p, q): ops.Sgate(p[0]) | q[0] ops.MeasureHomodyne(p[1]) | q[0] results = eng.run(prog) assert results.samples.shape[0] == 1
def test_shots_default(self): """Test that default shots (1) is used""" prog = sf.Program(1) eng = sf.Engine("gaussian") with prog.context as q: ops.Sgate(0.5) | q[0] ops.MeasureFock() | q results = eng.run(prog) assert results.samples.shape[0] == 1
def test_regref_no_func_str(self): """Test a regreftransform with no function string raises exception""" prog = Program(2) with prog.context as q: ops.Sgate(0.43) | q[0] ops.MeasureX | q[0] ops.Zgate(ops.RR(q[0], lambda x: 2 * x)) | q[1] with pytest.raises(ValueError, match="not supported by Blackbird"): io.to_blackbird(prog)
def test_measured_par_str(self): """Test a MeasuredParameter with some transformations converts properly""" prog = Program(2) with prog.context as q: ops.Sgate(0.43) | q[0] ops.MeasureX | q[0] ops.Zgate(2 * pf.sin(q[0].par)) | q[1] bb = io.to_blackbird(prog) expected = {"op": "Zgate", "modes": [1], "args": ["2*sin(q0)"], "kwargs": {}} assert bb.operations[-1] == expected
def test_free_par_str(self): """Test a FreeParameter with some transformations converts properly""" prog = Program(2) r, alpha = prog.params('r', 'alpha') with prog.context as q: ops.Sgate(r) | q[0] ops.Zgate(3 * pf.log(-alpha)) | q[1] bb = io.to_blackbird(prog) assert bb.operations[0] == {"op": "Sgate", "modes": [0], "args": ['{r}', 0.0], "kwargs": {}} assert bb.operations[1] == {"op": "Zgate", "modes": [1], "args": ['3*log(-{alpha})'], "kwargs": {}}
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)