def test_drawing(): with pytest.raises(ValueError, match="Blockade radius"): reg = Register.from_coordinates([(1, 0), (0, 1)]) reg.draw(blockade_radius=0.0, draw_half_radius=True) reg = Register.from_coordinates([(1, 0), (0, 1)]) with patch("matplotlib.pyplot.show"): reg.draw(blockade_radius=0.1, draw_graph=True) reg = Register.triangular_lattice(3, 8) with patch("matplotlib.pyplot.show"): reg.draw() with patch("matplotlib.pyplot.show"): with patch("matplotlib.pyplot.savefig"): reg.draw(fig_name="my_register.pdf") reg = Register.rectangle(1, 8) with patch("matplotlib.pyplot.show"): reg.draw(blockade_radius=5, draw_half_radius=True, draw_graph=True) with pytest.raises(ValueError, match="'blockade_radius' to draw."): reg.draw(draw_half_radius=True) reg = Register.square(1) with pytest.raises(NotImplementedError, match="Needs more than one atom"): reg.draw(blockade_radius=5, draw_half_radius=True)
def test_dephasing(): np.random.seed(123) reg = Register.from_coordinates([(0, 0)], prefix="q") seq = Sequence(reg, Chadoq2) seq.declare_channel("ch0", "rydberg_global") duration = 2500 pulse = Pulse.ConstantPulse(duration, np.pi, 0.0 * 2 * np.pi, 0) seq.add(pulse, "ch0") sim = Simulation(seq, sampling_rate=0.01, config=SimConfig(noise="dephasing")) assert sim.run().sample_final_state() == Counter({"0": 595, "1": 405}) assert len(sim._collapse_ops) != 0 with pytest.warns(UserWarning, match="first-order"): reg = Register.from_coordinates([(0, 0), (0, 10)], prefix="q") seq2 = Sequence(reg, Chadoq2) seq2.declare_channel("ch0", "rydberg_global") duration = 2500 pulse = Pulse.ConstantPulse(duration, np.pi, 0.0 * 2 * np.pi, 0) seq2.add(pulse, "ch0") sim = Simulation( seq2, sampling_rate=0.01, config=SimConfig(noise="dephasing", dephasing_prob=0.5), )
def test_creation(): empty_dict = {} with pytest.raises(ValueError, match="Cannot create a Register with"): Register(empty_dict) coords = [(0, 0), (1, 0)] ids = ("q0", "q1") qubits = dict(zip(ids, coords)) with pytest.raises(TypeError): Register(coords) Register(ids) with pytest.raises(ValueError, match="vectors of size 2"): Register.from_coordinates([(0, 1, 0, 1)]) with pytest.raises(NotImplementedError, match="a prefix and a set of labels"): Register.from_coordinates(coords, prefix="a", labels=["a", "b"]) with pytest.raises(ValueError, match="vectors of size 3"): Register3D.from_coordinates([((1, 0), ), ((-1, 0), )]) reg1 = Register(qubits) reg2 = Register.from_coordinates(coords, center=False, prefix="q") assert np.all(np.array(reg1._coords) == np.array(reg2._coords)) assert reg1._ids == reg2._ids reg2b = Register.from_coordinates(coords, center=False, labels=["a", "b"]) assert reg2b._ids == ("a", "b") with pytest.raises(ValueError, match="Label length"): Register.from_coordinates(coords, center=False, labels=["a", "b", "c"]) reg3 = Register.from_coordinates(np.array(coords), prefix="foo") coords_ = np.array([(-0.5, 0), (0.5, 0)]) assert reg3._ids == ("foo0", "foo1") assert np.all(reg3._coords == coords_) assert not np.all(coords_ == coords) reg4 = Register.rectangle(1, 2, spacing=1) assert np.all(reg4._coords == coords_) reg5 = Register.square(2, spacing=2) coords_ = np.array([(-1, -1), (1, -1), (-1, 1), (1, 1)], dtype=float) assert np.all(np.array(reg5._coords) == coords_) reg6 = Register.triangular_lattice(2, 2, spacing=4) coords_ = np.array([ (-3, -np.sqrt(3)), (1, -np.sqrt(3)), (-1, np.sqrt(3)), (3, np.sqrt(3)), ]) assert np.all(np.array(reg6._coords) == coords_) with pytest.raises(ValueError, match="must only be 'layout' and 'trap_ids'"): Register(qubits, spacing=10, layout="square", trap_ids=(0, 1, 3))
def test_get_xy_hamiltonian(): simple_reg = Register.from_coordinates([[0, 10], [10, 0], [0, 0]], prefix="atom") detun = 1.0 amp = 3.0 rise = Pulse.ConstantPulse(1500, amp, detun, 0.0) simple_seq = Sequence(simple_reg, MockDevice) simple_seq.declare_channel("ch0", "mw_global") simple_seq.set_magnetic_field(0, 1.0, 0.0) simple_seq.add(rise, "ch0") assert np.isclose(np.linalg.norm(simple_seq.magnetic_field[0:2]), 1) simple_sim = Simulation(simple_seq, sampling_rate=0.03) with pytest.raises(ValueError, match="less than or equal to the sequence duration"): simple_sim.get_hamiltonian(1650) with pytest.raises(ValueError, match="greater than or equal to 0"): simple_sim.get_hamiltonian(-10) # Constant detuning, so |ud><du| term is C_3/r^3 - 2*detuning for any time simple_ham = simple_sim.get_hamiltonian(143) assert simple_ham[1, 2] == 0.5 * MockDevice.interaction_coeff_xy / 10**3 assert (np.abs(simple_ham[1, 4] - (-2 * 0.5 * MockDevice.interaction_coeff_xy / 10**3)) < 1e-10) assert simple_ham[0, 1] == 0.5 * amp assert simple_ham[3, 3] == -2 * detun
def test_config(): np.random.seed(123) reg = Register.from_coordinates([(0, 0), (0, 5)], prefix="q") seq = Sequence(reg, Chadoq2) seq.declare_channel("ch0", "rydberg_global") duration = 2500 pulse = Pulse.ConstantPulse(duration, np.pi, 0.0 * 2 * np.pi, 0) seq.add(pulse, "ch0") sim = Simulation(seq, config=SimConfig(noise="SPAM")) sim.reset_config() assert sim.config == SimConfig() sim.show_config() with pytest.raises(ValueError, match="not a valid"): sim.set_config("bad_config") clean_ham = sim.get_hamiltonian(123) new_cfg = SimConfig(noise="doppler", temperature=10000) sim.set_config(new_cfg) assert sim.config == new_cfg noisy_ham = sim.get_hamiltonian(123) assert (noisy_ham[0, 0] != clean_ham[0, 0] and noisy_ham[3, 3] == clean_ham[3, 3]) sim.set_config(SimConfig(noise="amplitude")) noisy_amp_ham = sim.get_hamiltonian(123) assert (noisy_amp_ham[0, 0] == clean_ham[0, 0] and noisy_amp_ham[0, 1] != clean_ham[0, 1])
def test_rotation(): with pytest.raises(NotImplementedError): reg_ = Register.from_coordinates([(1, 0, 0), (0, 1, 4)]) reg_.rotate(20) reg = Register.square(2, spacing=np.sqrt(2)) reg.rotate(45) coords_ = np.array([(0, -1), (1, 0), (-1, 0), (0, 1)], dtype=float) assert np.all(np.isclose(reg._coords, coords_))
def test_single_atom_simulation(): one_reg = Register.from_coordinates([(0, 0)], 'atom') one_seq = Sequence(one_reg, Chadoq2) one_seq.declare_channel('ch0', 'rydberg_global') one_seq.add(Pulse.ConstantDetuning(ConstantWaveform(16, 1.), 1., 0), 'ch0') one_sim = Simulation(seq) one_res = one_sim.run() assert (one_res._size == one_sim._size)
def test_single_atom_simulation(): one_reg = Register.from_coordinates([(0, 0)], "atom") one_seq = Sequence(one_reg, Chadoq2) one_seq.declare_channel("ch0", "rydberg_global") one_seq.add(Pulse.ConstantDetuning(ConstantWaveform(16, 1.0), 1.0, 0), "ch0") one_sim = Simulation(one_seq) one_res = one_sim.run() assert one_res._size == one_sim._size one_sim = Simulation(one_seq, evaluation_times="Minimal") one_resb = one_sim.run() assert one_resb._size == one_sim._size
def test_expect(): with pytest.raises(TypeError, match="must be a list"): results.expect("bad_observable") with pytest.raises(TypeError, match="Incompatible type"): results.expect(["bad_observable"]) with pytest.raises(ValueError, match="Incompatible shape"): results.expect([np.array(3)]) reg_single = Register.from_coordinates([(0, 0)], prefix="q") seq_single = Sequence(reg_single, Chadoq2) seq_single.declare_channel("ryd", "rydberg_global") seq_single.add(pi, "ryd") sim_single = Simulation(seq_single) results_single = sim_single.run() op = [qutip.basis(2, 0).proj()] exp = results_single.expect(op)[0] assert np.isclose(exp[-1], 1) assert len(exp) == duration + 1 # +1 for the final instant np.testing.assert_almost_equal( results_single._calc_pseudo_density(-1).full(), np.array([[1, 0], [0, 0]]), ) config = SimConfig(noise="SPAM", eta=0) sim_single.set_config(config) sim_single.evaluation_times = "Minimal" results_single = sim_single.run() exp = results_single.expect(op)[0] assert len(exp) == 2 assert isinstance(results_single, CoherentResults) assert results_single._meas_errors == { "epsilon": config.epsilon, "epsilon_prime": config.epsilon_prime, } # Probability of measuring 1 = probability of false positive assert np.isclose(exp[0], config.epsilon) # Probability of measuring 1 = 1 - probability of false negative assert np.isclose(exp[-1], 1 - config.epsilon_prime) np.testing.assert_almost_equal( results_single._calc_pseudo_density(-1).full(), np.array([[1 - config.epsilon_prime, 0], [0, config.epsilon_prime]]), ) seq3dim = Sequence(reg, Chadoq2) seq3dim.declare_channel("ryd", "rydberg_global") seq3dim.declare_channel("ram", "raman_local", initial_target="A") seq3dim.add(pi, "ram") seq3dim.add(pi, "ryd") sim3dim = Simulation(seq3dim) exp3dim = sim3dim.run().expect( [qutip.tensor(qutip.basis(3, 0).proj(), qutip.qeye(3))]) assert np.isclose(exp3dim[0][-1], 1.89690200e-14)
def test_get_hamiltonian(): simple_reg = Register.from_coordinates([[10, 0], [0, 0]], prefix='atom') detun = 1. rise = Pulse.ConstantDetuning(RampWaveform(1500, 0., 2.), detun, 0.) simple_seq = Sequence(simple_reg, Chadoq2) simple_seq.declare_channel('ising', 'rydberg_global') simple_seq.add(rise, 'ising') simple_sim = Simulation(simple_seq, sampling_rate=0.01) with pytest.raises(ValueError, match='larger than'): simple_sim.get_hamiltonian(1650) with pytest.raises(ValueError, match='negative'): simple_sim.get_hamiltonian(-10) # Constant detuning, so |rr><rr| term is C_6/r^6 - 2*detuning for any time simple_ham = simple_sim.get_hamiltonian(143) assert (simple_ham[0, 0] == Chadoq2.interaction_coeff / 10**6 - 2 * detun)
def test_get_hamiltonian(): simple_reg = Register.from_coordinates([[10, 0], [0, 0]], prefix="atom") detun = 1.0 rise = Pulse.ConstantDetuning(RampWaveform(1500, 0.0, 2.0), detun, 0.0) simple_seq = Sequence(simple_reg, Chadoq2) simple_seq.declare_channel("ising", "rydberg_global") simple_seq.add(rise, "ising") simple_sim = Simulation(simple_seq, sampling_rate=0.01) with pytest.raises(ValueError, match="less than or equal to"): simple_sim.get_hamiltonian(1650) with pytest.raises(ValueError, match="greater than or equal to"): simple_sim.get_hamiltonian(-10) # Constant detuning, so |rr><rr| term is C_6/r^6 - 2*detuning for any time simple_ham = simple_sim.get_hamiltonian(143) assert np.isclose(simple_ham[0, 0], Chadoq2.interaction_coeff / 10**6 - 2 * detun) np.random.seed(123) simple_sim_noise = Simulation(simple_seq, config=SimConfig(noise="doppler", temperature=20000)) simple_ham_noise = simple_sim_noise.get_hamiltonian(144) assert np.isclose( simple_ham_noise.full(), np.array([ [ 4.47984523 + 0.0j, 0.09606404 + 0.0j, 0.09606404 + 0.0j, 0.0 + 0.0j, ], [ 0.09606404 + 0.0j, 12.03082372 + 0.0j, 0.0 + 0.0j, 0.09606404 + 0.0j, ], [ 0.09606404 + 0.0j, 0.0 + 0.0j, -12.97113702 + 0.0j, 0.09606404 + 0.0j, ], [0.0 + 0.0j, 0.09606404 + 0.0j, 0.09606404 + 0.0j, 0.0 + 0.0j], ]), ).all()
def test_add_max_step_and_delays(): reg = Register.from_coordinates([(0, 0)]) seq = Sequence(reg, Chadoq2) seq.declare_channel("ch", "rydberg_global") seq.delay(1500, "ch") seq.add(Pulse.ConstantDetuning(BlackmanWaveform(600, np.pi), 0, 0), "ch") seq.delay(2000, "ch") seq.add(Pulse.ConstantDetuning(BlackmanWaveform(600, np.pi / 2), 0, 0), "ch") sim = Simulation(seq) res_large_max_step = sim.run(max_step=1) res_auto_max_step = sim.run() r = qutip.basis(2, 0) occ_large = res_large_max_step.expect([r.proj()])[0] occ_auto = res_auto_max_step.expect([r.proj()])[0] assert np.isclose(occ_large[-1], 0, 1e-4) assert np.isclose(occ_auto[-1], 0.5, 1e-4)
def test_drawing(): with pytest.raises(NotImplementedError, match="register layouts in 2D."): reg_ = Register.from_coordinates([(1, 0, 0), (0, 1, 4)]) reg_.draw() reg = Register.triangular_lattice(3, 8) with patch('matplotlib.pyplot.show'): reg.draw() reg = Register.rectangle(1, 8) with patch('matplotlib.pyplot.show'): reg.draw(blockade_radius=5, draw_half_radius=True, draw_graph=True) with pytest.raises(ValueError, match="'blockade_radius' to draw."): reg.draw(draw_half_radius=True) reg = Register.square(1) with pytest.raises(NotImplementedError, match="Needs more than one atom"): reg.draw(blockade_radius=5, draw_half_radius=True)
def test_add_config(): reg = Register.from_coordinates([(0, 0)], prefix="q") seq = Sequence(reg, Chadoq2) seq.declare_channel("ch0", "rydberg_global") duration = 2500 pulse = Pulse.ConstantPulse(duration, np.pi, 0.0 * 2 * np.pi, 0) seq.add(pulse, "ch0") sim = Simulation(seq, sampling_rate=0.01, config=SimConfig(noise="SPAM", eta=0.5)) with pytest.raises(ValueError, match="is not a valid"): sim.add_config("bad_cfg") sim.add_config( SimConfig(noise=("dephasing", "SPAM", "doppler"), temperature=20000)) assert "dephasing" in sim.config.noise and "SPAM" in sim.config.noise assert sim.config.eta == 0.5 assert sim.config.temperature == 20000.0e-6 sim.set_config(SimConfig(noise="dephasing", laser_waist=175.0)) sim.add_config(SimConfig(noise=("SPAM", "amplitude"), laser_waist=172.0)) assert "amplitude" in sim.config.noise and "SPAM" in sim.config.noise assert sim.config.laser_waist == 172.0
def test_run_xy(): simple_reg = Register.from_coordinates([[10, 0], [0, 0]], prefix="atom") detun = 1.0 amp = 3.0 rise = Pulse.ConstantPulse(1500, amp, detun, 0.0) simple_seq = Sequence(simple_reg, MockDevice) simple_seq.declare_channel("ch0", "mw_global") simple_seq.add(rise, "ch0") sim = Simulation(simple_seq, sampling_rate=0.01) good_initial_array = np.r_[1, np.zeros(sim.dim**sim._size - 1)] good_initial_qobj = qutip.tensor( [qutip.basis(sim.dim, 0) for _ in range(sim._size)]) sim.initial_state = good_initial_array sim.run() sim.initial_state = good_initial_qobj sim.run() assert not hasattr(sim._seq, "_measurement") simple_seq.measure(basis="XY") sim.run() assert sim._seq._measurement == "XY"
def test_creation(): coords = [(0, 0), (1, 0)] ids = ['q0', 'q1'] qubits = dict(zip(ids, coords)) with pytest.raises(TypeError): Register(coords) Register(ids) with pytest.raises(ValueError, match="vectors of size 2 or 3"): Register.from_coordinates([(0, 1, 0, 1)]) with pytest.raises(ValueError, match="vectors of size 2 or 3"): Register.from_coordinates([((1, 0),), ((-1, 0),)]) reg1 = Register(qubits) reg2 = Register.from_coordinates(coords, center=False, prefix='q') assert np.all(np.array(reg1._coords) == np.array(reg2._coords)) assert reg1._ids == reg2._ids reg3 = Register.from_coordinates(np.array(coords), prefix='foo') coords_ = np.array([(-0.5, 0), (0.5, 0)]) assert reg3._ids == ['foo0', 'foo1'] assert np.all(reg3._coords == coords_) assert not np.all(coords_ == coords) reg4 = Register.rectangle(1, 2, spacing=1) assert np.all(reg4._coords == coords_) reg5 = Register.square(2, spacing=2) coords_ = np.array([(-1, -1), (1, -1), (-1, 1), (1, 1)], dtype=float) assert np.all(np.array(reg5._coords) == coords_) reg6 = Register.triangular_lattice(2, 2, spacing=4) coords_ = np.array([(-3, -np.sqrt(3)), (1, -np.sqrt(3)), (-1, np.sqrt(3)), (3, np.sqrt(3))]) assert np.all(np.array(reg6._coords) == coords_)
def test_max_connectivity(): device = Chadoq2 max_atom_num = device.max_atom_num spacing = device.min_atom_distance crest_y = np.sqrt(3) / 2.0 # Check device type with pytest.raises(TypeError): reg = Register.max_connectivity(2, None) # Check min number of atoms with pytest.raises(ValueError, match=r"The number of qubits(.+)greater than"): reg = Register.max_connectivity(0, device) # Check max number of atoms with pytest.raises(ValueError, match=r"The number of qubits(.+)less than"): reg = Register.max_connectivity(max_atom_num + 1, device) # Check spacing reg = Register.max_connectivity(max_atom_num, device, spacing=spacing) with pytest.raises(ValueError, match="Spacing "): reg = Register.max_connectivity(max_atom_num, device, spacing=spacing - 1.0) # Check 1 atom reg = Register.max_connectivity(1, device) assert len(reg.qubits) == 1 atoms = list(reg.qubits.values()) assert np.all(np.isclose(atoms[0], [0.0, 0.0])) # Check for less than 7 atoms: for i in range(1, 7): hex_coords = np.array([ (0.0, 0.0), (-0.5, crest_y), (0.5, crest_y), (1.0, 0.0), (0.5, -crest_y), (-0.5, -crest_y), ]) reg = Register.max_connectivity(i, device) device.validate_register(reg) reg2 = Register.from_coordinates(spacing * hex_coords[:i], center=False) assert len(reg.qubits) == i atoms = list(reg.qubits.values()) atoms2 = list(reg2.qubits.values()) for k in range(i): assert np.all(np.isclose(atoms[k], atoms2[k])) # Check full layers on a small hexagon (1 layer) reg = Register.max_connectivity(7, device) device.validate_register(reg) assert len(reg.qubits) == 7 atoms = list(reg.qubits.values()) assert np.all(np.isclose(atoms[0], [0.0, 0.0])) assert np.all(np.isclose(atoms[1], [-0.5 * spacing, crest_y * spacing])) assert np.all(np.isclose(atoms[2], [0.5 * spacing, crest_y * spacing])) assert np.all(np.isclose(atoms[3], [1.0 * spacing, 0.0])) assert np.all(np.isclose(atoms[4], [0.5 * spacing, -crest_y * spacing])) assert np.all(np.isclose(atoms[5], [-0.5 * spacing, -crest_y * spacing])) assert np.all(np.isclose(atoms[6], [-1.0 * spacing, 0.0])) # Check full layers for a bigger hexagon (2 layers) reg = Register.max_connectivity(19, device) device.validate_register(reg) assert len(reg.qubits) == 19 atoms = list(reg.qubits.values()) assert np.all(np.isclose(atoms[7], [-1.5 * spacing, crest_y * spacing])) assert np.all( np.isclose(atoms[8], [-1.0 * spacing, 2.0 * crest_y * spacing])) assert np.all(np.isclose(atoms[13], [1.5 * spacing, -crest_y * spacing])) assert np.all( np.isclose(atoms[14], [1.0 * spacing, -2.0 * crest_y * spacing])) # Check extra atoms (2 full layers + 7 extra atoms) # for C3 symmetry, C6 symmetry and offset for next atoms reg = Register.max_connectivity(26, device) device.validate_register(reg) assert len(reg.qubits) == 26 atoms = list(reg.qubits.values()) assert np.all(np.isclose(atoms[19], [-2.5 * spacing, crest_y * spacing])) assert np.all( np.isclose(atoms[20], [-2.0 * spacing, 2.0 * crest_y * spacing])) assert np.all( np.isclose(atoms[21], [-0.5 * spacing, 3.0 * crest_y * spacing])) assert np.all( np.isclose(atoms[22], [2.0 * spacing, 2.0 * crest_y * spacing])) assert np.all(np.isclose(atoms[23], [2.5 * spacing, -crest_y * spacing])) assert np.all( np.isclose(atoms[24], [0.5 * spacing, -3.0 * crest_y * spacing])) assert np.all( np.isclose(atoms[25], [-2.0 * spacing, -2.0 * crest_y * spacing]))