def test_not_bipartite(self, tol): """Test exception raised if the graph is not bipartite""" A = np.array([[0, 1, 0, 0, 1, 1], [1, 0, 1, 0, 1, 1], [0, 1, 0, 1, 1, 0], [0, 0, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1], [1, 1, 0, 0, 1, 0]]) with pytest.raises(ValueError, match="does not represent a bipartite graph"): ops.BipartiteGraphEmbed(A) A = np.array([[0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1], [0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0]]) with pytest.raises(ValueError, match="does not represent a bipartite graph"): ops.BipartiteGraphEmbed(A) A = np.array([[0, 0, 1, 0, 1, 1], [0, 0, 0, 0, 1, 1], [0, 0, 0, 1, 1, 0], [0, 0, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 0, 0]]) with pytest.raises(ValueError, match="does not represent a bipartite graph"): ops.BipartiteGraphEmbed(A)
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_bipartite_graph_embed_edgeset(self, setup_eng, tol): """Test that embedding a bipartite edge set B results in the property Amat/A = c J, where c is a real constant, and J is the all ones matrix""" N = 6 eng, prog = setup_eng(6) B = Abp[:N//2, N//2:] print(B) with prog.context as q: ops.BipartiteGraphEmbed(B, edges=True) | q state = eng.run(prog).state Amat = eng.backend.circuit.Amat() # check that the matrix Amat is constructed to be of the form # Amat = [[B^\dagger, 0], [0, B]] assert np.allclose(Amat[:N, :N], Amat[N:, N:].conj().T, atol=tol) assert np.allclose(Amat[:N, N:], np.zeros([N, N]), atol=tol) assert np.allclose(Amat[N:, :N], np.zeros([N, N]), atol=tol) # final Amat Amat = Amat[:N, :N] n = N // 2 ratio = np.real_if_close(Amat[n:, :n] / B.T) ratio /= ratio[0, 0] assert np.allclose(ratio, np.ones([n, n]), atol=tol)
def test_decomposition(self, tol): """Test that a graph is correctly decomposed""" n = 3 prog = sf.Program(2*n) A = np.zeros([2*n, 2*n]) B = np.random.random([n, n]) A[:n, n:] = B A += A.T sq, U, V = dec.bipartite_graph_embed(B) G = ops.BipartiteGraphEmbed(A) cmds = G.decompose(prog.register) S = np.identity(4 * n) # calculating the resulting decomposed symplectic for cmd in cmds: # all operations should be BSgates, Rgates, or S2gates assert isinstance( cmd.op, (ops.Interferometer, ops.S2gate) ) # build up the symplectic transform modes = [i.ind for i in cmd.reg] if isinstance(cmd.op, ops.S2gate): # check that the registers are i, i+n assert len(modes) == 2 assert modes[1] == modes[0] + n r, phi = par_evaluate(cmd.op.p) assert -r in sq assert phi == 0 S = _two_mode_squeezing(r, phi, modes, 2*n) @ S if isinstance(cmd.op, ops.Interferometer): # check that each unitary only applies to half the modes assert len(modes) == n assert modes in ([0, 1, 2], [3, 4, 5]) # check matrix is unitary U1 = par_evaluate(cmd.op.p[0]) assert np.allclose(U1 @ U1.conj().T, np.identity(n), atol=tol, rtol=0) if modes[0] == 0: assert np.allclose(U1, U, atol=tol, rtol=0) else: assert modes[0] == 3 assert np.allclose(U1, V, atol=tol, rtol=0) S_U = np.vstack( [np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])] ) S = expand(S_U, modes, 2*n) @ S # the resulting covariance state cov = S @ S.T A_res = Amat(cov)[:2*n, :2*n] # The bottom right corner of A_res should be identical to A, # up to some constant scaling factor. Check if the ratio # of all elements is one ratio = np.real_if_close(A_res[n:, :n] / B.T) ratio /= ratio[0, 0] assert np.allclose(ratio, np.ones([n, n]), atol=tol, rtol=0)