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_loss_channel(self, setup_eng, tol): """Test loss channel with no transmission produces vacuum""" eng, prog = setup_eng(1) with prog.context as q: ops.Dgate(A) | q[0] ops.LossChannel(0) | q[0] eng.run(prog) assert np.all(eng.backend.is_vacuum(tol))
def test_passive_program(tol, depth, width): """Tests that a circuit and its compiled version produce the same Gaussian state""" circuit = sf.Program(width) T_circuit = np.eye(width, dtype=np.complex128) with circuit.context as q: for _ in range(depth): U = unitary_group.rvs(width) T_circuit = U @ T_circuit ops.Interferometer(U) | q for i in range(width): ops.LossChannel(0.5) | q[i] T_circuit *= np.sqrt(0.5) compiled_circuit = circuit.compile(compiler="passive") T = compiled_circuit.circuit[0].op.p[0] assert np.allclose(T, T_circuit, atol=tol, rtol=0)
def setup_one_mode_circuit(self, setup_eng, cutoff): """Create the circuit for following tests""" eng_ref, p0 = setup_eng(1) S = ops.Sgate(1.1, -1.4) L = ops.LossChannel(0.45) initial_state = np.random.rand(cutoff, cutoff) with p0.context as q: ops.DensityMatrix(initial_state) | q prog = sf.Program(p0) with prog.context as q: S | q L | q rho = eng_ref.run([p0, prog]).state.dm() return prog, rho, initial_state
def setup_one_mode_circuit(self, setup_eng, cutoff): """Create the circuit for following tests""" eng_ref, q = setup_eng(1) S = ops.Sgate(1.1, -1.4) L = ops.LossChannel(0.45) initial_state = np.random.rand(cutoff, cutoff) with eng_ref: ops.DensityMatrix(initial_state) | q S | q L | q eng, q = sf.Engine(1) with eng: S | q L | q rho = eng_ref.run().dm() return eng, rho, initial_state
def test_passive_channel(self, M, setup_eng, tol): """check that passive channel is consistent with unitary methods""" U = unitary_group.rvs(M) loss_in = np.random.random(M) loss_out = np.random.random(M) T = (np.sqrt(loss_in) * U) * np.sqrt(loss_out[np.newaxis].T) eng, prog = setup_eng(M) with prog.context as q: for i in range(M): ops.Sgate(1) | q[i] ops.Dgate(A) | q[i] ops.PassiveChannel(T) | q state = eng.run(prog).state cov1 = state.cov() mu1 = state.means() eng, prog = setup_eng(M) with prog.context as q: for i in range(M): ops.Sgate(1) | q[i] ops.Dgate(A) | q[i] ops.LossChannel(loss_in[i]) | q[i] ops.Interferometer(U) | q for i in range(M): ops.LossChannel(loss_out[i]) | q[i] state = eng.run(prog).state cov2 = state.cov() mu2 = state.means() assert np.allclose(cov1, cov2, atol=tol, rtol=0) assert np.allclose(mu1, mu2, atol=tol, rtol=0) u, s, v = np.linalg.svd(T) eng, prog = setup_eng(M) with prog.context as q: for i in range(M): ops.Sgate(1) | q[i] ops.Dgate(A) | q[i] ops.Interferometer(v) | q for i in range(M): ops.LossChannel(s[i]**2) | q[i] ops.Interferometer(u) | q state = eng.run(prog).state cov3 = state.cov() mu3 = state.means() assert np.allclose(cov1, cov3, atol=tol, rtol=0) assert np.allclose(mu1, mu3, atol=tol, rtol=0) T1 = u * s eng, prog = setup_eng(M) with prog.context as q: for i in range(M): ops.Sgate(1) | q[i] ops.Dgate(A) | q[i] ops.PassiveChannel(v) | q ops.PassiveChannel(T1) | q state = eng.run(prog).state cov4 = state.cov() mu4 = state.means() assert np.allclose(cov1, cov4, atol=tol, rtol=0) assert np.allclose(mu1, mu4, atol=tol, rtol=0)
def test_thermalloss_merging_different_nbar(self, tol): """test the merging of Loss and ThermalLoss raises exception""" G = ops.ThermalLossChannel(a, 2 * c) with pytest.raises(MergeFailure): merged = G.merge(ops.LossChannel(b))
def test_loss_merging_identity(self, tol): """test the merging of two Loss channels such that the resulting loss channel is simply the identity""" G = ops.LossChannel(a) merged = G.merge(ops.LossChannel(1.0 / a)) assert merged is None
def test_loss_merging(self, tol): """test the merging of two Loss channels (with default values for optional parameters)""" G = ops.LossChannel(a) merged = G.merge(ops.LossChannel(b)) assert np.allclose(merged.p[0], a * b, atol=tol, rtol=0)
def circuit(cutoff, l1=0.85, l2=1): """Runs the heralded circuit with specified parameters, returning the output fidelity to the requested weak cubic phase state, the post-selection probability, and the Wigner log negativity. Args: cutoff (int): the Fock basis truncation l1 (float): squeeze cavity loss l2 (float): PNR loss Returns: tuple: a tuple containing the output fidelity to the target ON state, the probability of post-selection, the state norm before entering the beamsplitter, the state norm after exiting the beamsplitter, and the density matrix of the output state. """ # weak cubic phase state parameter a = 0.53 # the Fock state measurement of mode 0 to be post-selected m1 = 1 # the Fock state measurement of mode 1 to be post-selected m2 = 2 # define target state target_state = cubic_phase_state(a, cutoff) # gate parameters for the heralded quantum circuit. # squeezing magnitudes sq_r = [0.71, 0.67, -0.42] # squeezing phase sq_phi = [-2.07, 0.06, -3.79] # displacement magnitudes d_r = [-0.02, 0.34, 0.02] # beamsplitter theta bs_theta1, bs_theta2, bs_theta3 = [-1.57, 0.68, 2.5] # beamsplitter phi bs_phi1, bs_phi2, bs_phi3 = [0.53, -4.51, 0.72] # quantum circuit prior to entering the beamsplitter eng, q = sf.Engine(3) with eng: for k in range(3): ops.Sgate(sq_r[k], sq_phi[k]) | q[k] ops.Dgate(d_r[k]) | q[k] ops.LossChannel(l1) | q[k] ops.BSgate(bs_theta1, bs_phi1) | (q[0], q[1]) ops.BSgate(bs_theta2, bs_phi2) | (q[1], q[2]) ops.BSgate(bs_theta3, bs_phi3) | (q[0], q[1]) ops.LossChannel(l2) | q[0] ops.LossChannel(l2) | q[1] state = eng.run("gaussian", cutoff_dim=cutoff) mu = state.means() cov = state.cov() rho = density_matrix(mu, cov, post_select={ 0: m1, 1: m2 }, cutoff=cutoff, hbar=2) # probability of measuring m1 and m2 prob = np.abs(np.trace(rho)) # output state if prob != 0: rho = rho / prob # fidelity with the target state fidelity = np.abs(np.trace(np.einsum("ij,jk->ik", rho, target_state))) return fidelity, prob, rho