def test_truncations(states, truncations=[10, 15, 20]): batch_size = states.shape[0] x = tf.placeholder(tf.complex64, shape=[batch_size, 3]) eng, q = sf.Engine(1) with eng: Sgate(x[:, 0]) | q[0] Dgate(x[:, 1]) | q[0] Vgate(x[:, 2]) | q[0] sess = tf.Session() sess.run(tf.global_variables_initializer()) traces = np.zeros([batch_size, len(truncations)]) for n in range(len(truncations)): state = eng.run('tf', eval=False, batch_size=batch_size, cutoff_dim=truncations[n]) trace = tf.real(state.trace()) traces[:, n] = sess.run(trace, feed_dict={x: states}) print("Evaluated T={}".format(truncations[n])) import matplotlib.pyplot as plt for n in range(len(truncations)): plt.subplot(len(truncations), 1, n + 1) plt.hist(traces[:, n], bins=25) plt.xlabel("Trace") plt.ylabel("Frequency") plt.ylim([0, batch_size]) plt.show()
def ClosestClassicalState(r, K, eta, U, t): M = len(U) ap = eta * np.exp(2 * r) + 1 - eta an = eta * np.exp(-2 * r) + 1 - eta ss = 0.25 * np.log(ap / an) ns = 0.5 * (np.sqrt(ap * an) - 1) sc = 0.5 * np.log(2 * ns + 1) nt = 0.5 - 0.5 * np.sqrt(1 + 2 * t * np.sinh(2 * sc) * np.exp(2 * ss)) s0 = 0.5 * np.log((2 * nt + 1) / t) if ss < s0: st = ss nt = ns else: s0 = 0.5 * np.log((2 * nt + 1) / t) st = s0 # build the state prog = sf.Program(M) with prog.context as q: for i in range(K): Thermal(nt) | q[i] Sgate(st) | q[i] Interferometer(U) | q eng = sf.Engine('gaussian') result = eng.run(prog) cov = result.state.cov() return cov
def test_rotation(self, hbar): """Test rotation gives correct means and cov""" prog = sf.Program(1) eng = sf.Engine("gaussian") x = 0.2 p = 0.3 phi = 0.123 H, t = rotation(phi, hbar=hbar) with prog.context as q: Xgate(x) | q[0] Zgate(p) | q[0] Sgate(2) | q[0] GaussianPropagation(H, t) | q[0] state = eng.run(prog).state # test the covariance matrix res = state.cov() V = np.diag([np.exp(-4), np.exp(4)]) * hbar / 2 expected = rot(phi) @ V @ rot(phi).T assert np.allclose(res, expected) # test the vector of means res = state.means() exp = rot(phi) @ np.diag(np.exp([-2, 2])) @ np.array([x, p]) assert np.allclose(res, exp)
def test_is_unitary_with_channel(self, prog): """test that the is_unitary function returns False if channels are present""" with prog.context as q: Sgate(0.4) | q[0] LossChannel(0.4) | q[0] BSgate(0.4) | q assert not utils.is_unitary(prog)
def test_displaced_squeezed_mean_photon_gradient(self, setup_eng, cutoff, tol, batch_size): """Test whether the gradient of the mean photon number of a displaced squeezed state is correct. """ if batch_size is not None: pytest.skip( "Cannot calculate gradient in batch mode, as tape.gradient " "cannot differentiate non-scalar output.") eng, prog = setup_eng(1) with prog.context as q: Sgate(prog.params("r"), prog.params("phi")) | q Dgate(prog.params("a")) | q a = tf.Variable(ALPHA) r = tf.Variable(0.105) phi = tf.Variable(0.123) with tf.GradientTape() as tape: state = eng.run(prog, args={"a": a, "r": r, "phi": phi}).state mean, _ = state.mean_photon(0) # test the mean and variance of the photon number is correct mean_ex = a**2 + tf.sinh(r)**2 assert np.allclose(mean, mean_ex, atol=tol, rtol=0) # test the gradient of the mean is correct grad = tape.gradient(mean, [a, r, phi]) grad_ex = [2 * a, 2 * tf.sinh(r) * tf.cosh(r), 0] assert np.allclose(grad, grad_ex, atol=tol, rtol=0)
def test_rotation(self): """Test rotation gives correct means and cov""" self.eng.reset() q = self.eng.register x = 0.2 p = 0.3 phi = 0.123 H, t = rotation(phi, hbar=self.hbar) with self.eng: Xgate(x) | q[0] Zgate(p) | q[0] Sgate(2) | q[0] GaussianPropagation(H, t) | q[0] state = self.eng.run('gaussian') # test the covariance matrix res = state.cov() V = np.diag([np.exp(-4), np.exp(4)]) * self.hbar / 2 expected = rot(phi) @ V @ rot(phi).T self.assertTrue(np.allclose(res, expected)) # test the vector of means res = state.means() exp = rot(phi) @ np.diag(np.exp([-2, 2])) @ np.array([x, p]) self.assertTrue(np.allclose(res, exp))
def qnn_layer(layer_number): with tf.name_scope('layer_{}'.format(layer_number)): BSgate(bs_variables[layer_number, 0, 0, 0], bs_variables[layer_number, 0, 0, 1]) \ | (q[0], q[1]) for i in range(mode_number): Rgate(phase_variables[layer_number, i, 0]) | q[i] for i in range(mode_number): Sgate( tf.clip_by_value(sq_magnitude_variables[layer_number, i], -sq_clip, sq_clip), sq_phase_variables[layer_number, i]) | q[i] BSgate(bs_variables[layer_number, 0, 1, 0], bs_variables[layer_number, 0, 1, 1]) \ | (q[0], q[1]) for i in range(mode_number): Rgate(phase_variables[layer_number, i, 1]) | q[i] for i in range(mode_number): Dgate( tf.clip_by_value(disp_magnitude_variables[layer_number, i], -disp_clip, disp_clip), disp_phase_variables[layer_number, i]) | q[i] for i in range(mode_number): Kgate( tf.clip_by_value(kerr_variables[layer_number, i], -kerr_clip, kerr_clip)) | q[i]
def test_is_unitary_no_channel(self, prog): """test that the is_unitary function returns True if no channels are present""" assert utils.is_unitary(prog) with prog.context as q: Sgate(0.4) | q[0] BSgate(0.4) | q assert utils.is_unitary(prog)
def test_is_channel_preparation(self, prog): """is_channel() returns False if preparations are present""" with prog.context as q: Sgate(0.4) | q[0] BSgate() | q Squeezed(0.4) | q[1] assert not utils.is_channel(prog)
def test_cov_is_pure(): """Tests space unrolling when going into the Gaussian backend""" delays = [1, 6, 36] modes = 216 angles = np.concatenate([ generate_valid_bs_sequence(delays, modes), generate_valid_r_sequence(delays, modes) ]) net = modes + sum(delays) d = len(delays) n, N = get_mode_indices(delays) prog = sf.TDMProgram([N]) vac_modes = sum(delays) with prog.context(*angles) as (p, q): Sgate(0.8) | q[n[0]] for i in range(d): Rgate(p[i + d]) | q[n[i]] BSgate(p[i], np.pi / 2) | (q[n[i + 1]], q[n[i]]) prog.space_unroll() eng = sf.Engine(backend="gaussian") results = eng.run(prog) cov = results.state.cov() mu = np.zeros(len(cov)) mu_vac, cov_vac = reduced_state(mu, cov, list(range(vac_modes))) mu_comp, cov_comp = reduced_state(mu, cov, list(range(vac_modes, net))) assert np.allclose(cov_vac, 0.5 * (sf.hbar) * np.identity(2 * vac_modes)) assert is_pure_cov(cov_comp, hbar=sf.hbar)
def layer(i, size): Rgate(rtheta_1[i, 0]) | (q[0]) BSgate(phi_1[i, 0], 0) | (q[0], q[1]) Rgate(rtheta_1[i, 2]) | (q[1]) for j in range(size): Sgate(r[i, j]) | q[j] Rgate(rtheta_2[i, 0]) | (q[0]) BSgate(phi_2[i, 0], 0) | (q[0], q[1]) Rgate(rtheta_2[i, 2]) | (q[2]) BSgate(phi_2[i, 2], theta_2[i, 3]) | (q[2], q[3]) Rgate(rtheta_2[i, 1]) | (q[1]) BSgate(phi_2[i, 1], 0) | (q[1], q[2]) Rgate(rtheta_2[i, 0]) | (q[0]) BSgate(phi_2[i, 0], 0) | (q[0], q[1]) Rgate(rtheta_2[i, 0]) | (q[0]) Rgate(rtheta_2[i, 1]) | (q[1]) Rgate(rtheta_2[i, 2]) | (q[2]) Rgate(rtheta_2[i, 3]) | (q[3]) BSgate(phi_2[i, 2], 0) | (q[2], q[3]) Rgate(rtheta_2[i, 2]) | (q[2]) BSgate(phi_2[i, 1], 0) | (q[1], q[2]) Rgate(rtheta_2[i, 1]) | (q[1]) for j in range(size): Kgate(kappa[i, j]) | q[j]
def test_is_channel_no_measurement(self, prog): """test that the is_channel function returns True if no measurements are present""" assert utils.is_channel(prog) with prog.context as q: Sgate(0.4) | q[0] LossChannel(0.4) | q[0] BSgate(0.4) | q assert utils.is_channel(prog)
def input_qnn_layer(): with tf.name_scope('inputlayer'): Sgate(tf.clip_by_value(output_layer[:, 0], -sq_clip, sq_clip), output_layer[:, 1]) | q[0] Sgate(tf.clip_by_value(output_layer[:, 2], -sq_clip, sq_clip), output_layer[:, 3]) | q[1] BSgate(output_layer[:, 4], output_layer[:, 5]) | (q[0], q[1]) Rgate(output_layer[:, 6]) | q[0] Rgate(output_layer[:, 7]) | q[1] Dgate(tf.clip_by_value(output_layer[:, 8], -disp_clip, disp_clip), output_layer[:, 9]) \ | q[0] Dgate(tf.clip_by_value(output_layer[:, 10], -disp_clip, disp_clip), output_layer[:, 11]) \ | q[0] Kgate(tf.clip_by_value(output_layer[:, 12], -kerr_clip, kerr_clip)) | q[0] Kgate(tf.clip_by_value(output_layer[:, 13], -kerr_clip, kerr_clip)) | q[0]
def test_is_channel_no_measurement(self): """test that the is_channel function returns True if no measurements are present""" eng, q = sf.Engine(2) assert utils.is_channel(eng) with eng: Sgate(0.4) | q[0] BSgate(0.4) | q assert utils.is_channel(eng) with eng: Sgate(0.4) | q[0] LossChannel(0.4) | q[0] BSgate(0.4) | q assert utils.is_channel(eng)
def test_is_unitary_with_channel(self): """test that the is_unitary function returns False if channels are present""" eng, q = sf.Engine(2) with eng: Sgate(0.4) | q[0] LossChannel(0.4) | q[0] BSgate(0.4) | q assert not utils.is_unitary(eng)
def circuit(A, n_qmodes, params): I = np.eye(2 * n_qmodes) X_top = np.hstack((np.zeros((n_qmodes, n_qmodes)), np.eye(n_qmodes))) X_bot = np.hstack((np.eye(n_qmodes), np.zeros((n_qmodes, n_qmodes)))) X = np.vstack((X_top, X_bot)) # c = 0 # A = np.array([[c,-2,-10,1], # [-2,c,1,5], # [-10,1,c,-2], # [1,5,-2,c]]) zeros_4 = np.zeros((n_qmodes, n_qmodes)) c_prim = 1 A_prim = np.vstack((np.hstack((zeros_4, A)), np.hstack( (A, zeros_4)))) + np.eye(2 * n_qmodes) * c_prim d = 0.05 # Cov = np.linalg.inv(I - X@(d*A)) - I/2 Cov = np.linalg.inv(I - X @ (d * A_prim)) - I / 2 eng, q = sf.Engine(n_qmodes) with eng: # beamsplitter array Gaussian(Cov) | q Sgate(params[0]) | q[0] Sgate(params[1]) | q[1] Sgate(params[2]) | q[2] Sgate(params[3]) | q[3] Dgate(params[4]) | q[0] Dgate(params[5]) | q[1] Dgate(params[6]) | q[2] Dgate(params[7]) | q[3] BSgate(params[8], params[9]) | (q[0], q[1]) BSgate(params[10], params[11]) | (q[2], q[3]) BSgate(params[12], params[13]) | (q[1], q[2]) return eng, q
def test_is_unitary_no_channel(self): """test that the is_unitary function returns True if no channels are present""" eng, q = sf.Engine(2) assert utils.is_unitary(eng) with eng: Sgate(0.4) | q[0] BSgate(0.4) | q assert utils.is_unitary(eng)
def test_is_channel_measurement(self): """test that the is_channel function returns False if measurements or preparations are present""" eng, q = sf.Engine(2) with eng: Sgate(0.4) | q[0] BSgate() | q MeasureX | q[0] Sgate(0.4) | q[1] assert not utils.is_channel(eng) eng.reset() with eng: Sgate(0.4) | q[0] BSgate() | q Squeezed(0.4) | q[1] assert not utils.is_channel(eng)
def H_circuit(self, H, t): """Test circuit for Gaussian Hamiltonian""" self.eng.reset() q = self.eng.register with self.eng: # pylint: disable=pointless-statement q = init_layer(q) Xgate(0.1) | q[2] Sgate(0.1) | q[2] GaussianPropagation(H, t, mode='global') | q state = self.eng.run('gaussian') return state.means(), state.cov()
def ref_circuit(self, gate, qm): """Reference circuit for Gaussian gate""" self.eng.reset() q = self.eng.register with self.eng: # pylint: disable=pointless-statement q = init_layer(q) Xgate(0.1) | q[2] Sgate(0.1) | q[2] gate | qm state = self.eng.run('gaussian') return state.means(), state.cov()
def H_circuit(self, H, t): """Test circuit for Gaussian Hamiltonian""" prog = sf.Program(3) eng = sf.Engine("gaussian") with prog.context as q: # pylint: disable=pointless-statement q = init_layer(q) Xgate(0.1) | q[2] Sgate(0.1) | q[2] GaussianPropagation(H, t, mode='global') | q state = eng.run(prog).state return state.means(), state.cov()
def ref_circuit(self, gate, qm): """Reference circuit for Gaussian gate""" prog = sf.Program(3) eng = sf.Engine("gaussian") with prog.context as q: # pylint: disable=pointless-statement q = init_layer(q) Xgate(0.1) | q[2] Sgate(0.1) | q[2] gate | qm state = eng.run(prog).state return state.means(), state.cov()
def test_raises_gaussian_no_cutoff(self, monkeypatch): """Test that an error is raised if not cutoff value is specified for a Gaussian state.""" prog = sf.Program(1) eng = sf.Engine("gaussian") with prog.context as q: Sgate(2) | q[0] state = eng.run(prog).state modes = [0] with monkeypatch.context() as m: # Avoid plotting even if the test failed m.setattr(pio, "show", lambda x: None) with pytest.raises(ValueError, match="No cutoff specified for"): sf.plot_fock(state, modes, renderer="browser")
def test_global(self, eng, tol): """Test a 1x2 lattice Bose-Hubbard model in global mode""" prog = sf.Program(3) with prog.context as q: Sgate(0.1) | q[2] Fock(2) | q[0] BoseHubbardPropagation(self.H, self.t, self.k, mode='global') | q state = eng.run(prog, run_options={"modes": [0, 1]}).state Hm = -self.J*np.sqrt(2)*np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) \ + self.U*np.diag([1, 0, 1]) init_state = np.array([1, 0, 0]) exp = np.abs(np.dot(expm(-1j * self.t * Hm), init_state))**2 assert np.allclose(state.fock_prob([2, 0]), exp[0], rtol=tol) assert np.allclose(state.fock_prob([1, 1]), exp[1], rtol=tol) assert np.allclose(state.fock_prob([0, 2]), exp[2], rtol=tol)
def test_displaced_squeezed_mean_photon_gradient(self, setup_eng, cutoff, tol, batch_size): """Test whether the gradient of the mean photon number of a displaced squeezed state is correct. .. note:: As this test contains multiple gates being applied to the program, this test will fail in TensorFlow 2.1 due to the bug discussed in https://github.com/tensorflow/tensorflow/issues/37307, if `tf.einsum` is being used in ``tfbackend/ops.py`` rather than _einsum_v1. """ if batch_size is not None: pytest.skip( "Cannot calculate gradient in batch mode, as tape.gradient " "cannot differentiate non-scalar output." ) eng, prog = setup_eng(1) with prog.context as q: Sgate(prog.params("r"), prog.params("phi")) | q Dgate(prog.params("a")) | q a = tf.Variable(ALPHA) r = tf.Variable(0.105) phi = tf.Variable(0.123) with tf.GradientTape() as tape: state = eng.run(prog, args={"a": a, "r": r, "phi": phi}).state mean, _ = state.mean_photon(0) # test the mean and variance of the photon number is correct mean_ex = a ** 2 + tf.sinh(r) ** 2 assert np.allclose(mean, mean_ex, atol=tol, rtol=0) # test the gradient of the mean is correct grad = tape.gradient(mean, [a, r, phi]) grad_ex = [2 * a, 2 * tf.sinh(r) * tf.cosh(r), 0] assert np.allclose(grad, grad_ex, atol=tol, rtol=0)
def test_space_unrolling(): """Tests that space-unrolling works and that it can be done twice""" delays = [1, 6, 36] modes = 216 angles = np.concatenate([ generate_valid_bs_sequence(delays, modes), generate_valid_r_sequence(delays, modes) ]) d = len(delays) n, N = get_mode_indices(delays) prog = sf.TDMProgram([N]) with prog.context(*angles) as (p, q): Sgate(0.8) | q[n[0]] for i in range(d): Rgate(p[i + d]) | q[n[i]] BSgate(p[i], np.pi / 2) | (q[n[i + 1]], q[n[i]]) assert prog.is_unrolled == False prog.space_unroll() assert prog.timebins == 259 vac_modes = prog.concurr_modes - 1 assert prog.num_subsystems == prog.timebins + vac_modes # check that the number of gates are correct. assert [isinstance(cmd.op, Sgate) for cmd in prog.circuit].count(True) == prog.timebins assert [isinstance(cmd.op, Rgate) for cmd in prog.circuit].count(True) == 259 * len(delays) assert [isinstance(cmd.op, BSgate) for cmd in prog.circuit].count(True) == 259 * len(delays) prog.space_unroll() # space-unroll the program twice to check that it works assert prog.is_unrolled == True
def test_rolling_space_unrolled(): """Tests that rolling a space-unrolled circuit works""" delays = [1, 6, 36] modes = 216 angles = np.concatenate([ generate_valid_bs_sequence(delays, modes), generate_valid_r_sequence(delays, modes) ]) d = len(delays) n, N = get_mode_indices(delays) prog = sf.TDMProgram([N]) with prog.context(*angles) as (p, q): Sgate(0.8) | q[n[0]] for i in range(d): Rgate(p[i + d]) | q[n[i]] BSgate(p[i], np.pi / 2) | (q[n[i + 1]], q[n[i]]) rolled_circuit = prog.circuit.copy() num_subsystems_pre_roll = prog.num_subsystems init_num_subsystems_pre_roll = prog.init_num_subsystems assert prog.is_unrolled == False # space-unroll the program prog.space_unroll() assert prog.is_unrolled == True # roll the program back up prog.roll() assert prog.is_unrolled == False assert prog.num_subsystems == num_subsystems_pre_roll assert prog.init_num_subsystems == init_num_subsystems_pre_roll assert len(prog.circuit) == len(rolled_circuit) assert prog.circuit == rolled_circuit
def test_local(self): """Test a 1x2 lattice Bose-Hubbard model in local mode""" self.eng.reset() q = self.eng.register with self.eng: Sgate(0.1) | q[1] Fock(2) | q[0] BoseHubbardPropagation(self.H, self.t, self.k) | (q[0], q[2]) state = self.eng.run('fock', cutoff_dim=7, modes=[0, 2]) Hm = -self.J*np.sqrt(2)*np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) \ + self.U*np.diag([1, 0, 1]) init_state = np.array([1, 0, 0]) exp = np.abs(np.dot(expm(-1j * self.t * Hm), init_state))**2 self.assertTrue( np.allclose(state.fock_prob([2, 0]), exp[0], rtol=self.tol)) self.assertTrue( np.allclose(state.fock_prob([1, 1]), exp[1], rtol=self.tol)) self.assertTrue( np.allclose(state.fock_prob([0, 2]), exp[2], rtol=self.tol))
def dummy_func(r, theta, phi, q): Sgate(r) | q[0] BSgate(theta, phi) | (q[0], q[1])
def dummy_func(q): Sgate(rval) | q[0]