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_slm_mask(): reg = Register({"q0": (0, 0), "q1": (10, 10), "q2": (-10, -10)}) targets = ["q0", "q2"] pulse1 = Pulse.ConstantPulse(100, 10, 0, 0) pulse2 = Pulse.ConstantPulse(200, 10, 0, 0) # Set mask when an XY pulse is already in the schedule seq_xy1 = Sequence(reg, MockDevice) seq_xy1.declare_channel("ch_xy", "mw_global") seq_xy1.add(pulse1, "ch_xy") seq_xy1.config_slm_mask(targets) assert seq_xy1._slm_mask_time == [0, 100] # Set mask and then add an XY pulse to the schedule seq_xy2 = Sequence(reg, MockDevice) seq_xy2.config_slm_mask(targets) seq_xy2.declare_channel("ch_xy", "mw_global") seq_xy2.add(pulse1, "ch_xy") assert seq_xy2._slm_mask_time == [0, 100] # Check that adding extra pulses does not change SLM mask time seq_xy2.add(pulse2, "ch_xy") assert seq_xy2._slm_mask_time == [0, 100] # Check that SLM mask time is updated accordingly if a new pulse with # earlier start is added seq_xy3 = Sequence(reg, MockDevice) seq_xy3.declare_channel("ch_xy1", "mw_global") seq_xy3.config_slm_mask(targets) seq_xy3.delay(duration=100, channel="ch_xy1") seq_xy3.add(pulse1, "ch_xy1") assert seq_xy3._slm_mask_time == [100, 200] seq_xy3.declare_channel("ch_xy2", "mw_global") seq_xy3.add(pulse1, "ch_xy2", "no-delay") assert seq_xy3._slm_mask_time == [0, 100] # Same as previous check, but mask is added afterwards seq_xy4 = Sequence(reg, MockDevice) seq_xy4.declare_channel("ch_xy1", "mw_global") seq_xy4.delay(duration=100, channel="ch_xy1") seq_xy4.add(pulse1, "ch_xy1") seq_xy4.declare_channel("ch_xy2", "mw_global") seq_xy4.add(pulse1, "ch_xy2", "no-delay") seq_xy4.config_slm_mask(targets) assert seq_xy4._slm_mask_time == [0, 100] # Check that paramatrize works with SLM mask seq_xy5 = Sequence(reg, MockDevice) seq_xy5.declare_channel("ch", "mw_global") var = seq_xy5.declare_variable("var") seq_xy5.add(Pulse.ConstantPulse(200, var, 0, 0), "ch") assert seq_xy5.is_parametrized() seq_xy5.config_slm_mask(targets) seq_xy5_str = seq_xy5.serialize() seq_xy5_ = Sequence.deserialize(seq_xy5_str) assert str(seq_xy5) == str(seq_xy5_) # Check drawing method with patch("matplotlib.pyplot.show"): seq_xy2.draw()
def test_min_pulse_duration(): seq = Sequence(reg, device) seq.declare_channel("ch0", "rydberg_global") seq.declare_channel("ch1", "rydberg_local") seq.target("q0", "ch1") pulse0 = Pulse.ConstantPulse(60, 1, 1, 0) pulse1 = Pulse.ConstantPulse(80, 1, 1, 0) seq.add(pulse1, "ch1") assert seq._min_pulse_duration() == 80 seq.add(pulse0, "ch0") seq.delay(52, "ch0") seq.target("q1", "ch1") seq.add(pulse1, "ch1") assert seq._min_pulse_duration() == 60
def test_mask_two_pulses(): """Similar to test_mask_equals_remove, but with more pulses afterwards. Three global pulses act on a three qubit register, with one qubit masked during the first pulse. """ reg_three = Register({"q0": (0, 0), "q1": (10, 10), "q2": (-10, -10)}) reg_two = Register({"q0": (0, 0), "q1": (10, 10)}) pulse = Pulse.ConstantPulse(100, 10, 0, 0) no_pulse = Pulse.ConstantPulse(100, 0, 0, 0) for channel_type in ["mw_global", "rydberg_global", "raman_global"]: # Masked simulation seq_masked = Sequence(reg_three, MockDevice) seq_masked.declare_channel("ch_masked", channel_type) masked_qubits = ["q2"] seq_masked.config_slm_mask(masked_qubits) seq_masked.add(pulse, "ch_masked") # First pulse: masked seq_masked.add(pulse, "ch_masked") # Second pulse: unmasked seq_masked.add(pulse, "ch_masked") # Third pulse: unmasked sim_masked = Simulation(seq_masked) # Unmasked simulation on full register seq_three = Sequence(reg_three, MockDevice) seq_three.declare_channel("ch_three", channel_type) seq_three.add(no_pulse, "ch_three") seq_three.add(pulse, "ch_three") seq_three.add(pulse, "ch_three") sim_three = Simulation(seq_three) # Unmasked simulation on reduced register seq_two = Sequence(reg_two, MockDevice) seq_two.declare_channel("ch_two", channel_type) seq_two.add(pulse, "ch_two") seq_two.add(no_pulse, "ch_two") seq_two.add(no_pulse, "ch_two") sim_two = Simulation(seq_two) ti = seq_masked._slm_mask_time[0] tf = seq_masked._slm_mask_time[1] for t in sim_masked.sampling_times: ham_masked = sim_masked.get_hamiltonian(t) ham_three = sim_three.get_hamiltonian(t) ham_two = sim_two.get_hamiltonian(t) if ti <= t <= tf: assert ham_masked == qutip.tensor(ham_two, qutip.qeye(2)) else: assert ham_masked == ham_three
def test_delay_min_duration(): # Check that a delay shorter than a channel's minimal duration # is automatically extended to that minimal duration seq = Sequence(reg, device) seq.declare_channel("ch0", "rydberg_global") seq.declare_channel("ch1", "rydberg_local") seq.target("q0", "ch1") pulse0 = Pulse.ConstantPulse(52, 1, 1, 0) pulse1 = Pulse.ConstantPulse(180, 1, 1, 0) seq.add(pulse1, "ch1") seq.add(pulse0, "ch0") seq.target("q1", "ch1") seq.add(pulse1, "ch1") min_duration = seq._channels["ch1"].min_duration assert seq._schedule["ch1"][3] == _TimeSlot("delay", 220, 220 + min_duration, {"q1"})
def test_noisy_xy(): np.random.seed(15092021) simple_reg = Register.square(2, 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) with pytest.raises(NotImplementedError, match="mode 'XY' does not support simulation of"): sim.set_config(SimConfig(("SPAM", "doppler"))) sim.set_config(SimConfig("SPAM", eta=0.4)) assert sim._bad_atoms == { "atom0": True, "atom1": False, "atom2": True, "atom3": False, } with pytest.raises(NotImplementedError, match="simulation of noise types: amplitude"): sim.add_config(SimConfig("amplitude"))
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_build(): reg_ = Register.rectangle(2, 1, prefix="q") sb = Sequence(reg_, device) var = sb.declare_variable("var") targ_var = sb.declare_variable("targ_var", size=2, dtype=int) sb.declare_channel("ch1", "rydberg_local") sb.declare_channel("ch2", "raman_local") sb.target_index(targ_var[0], "ch2") sb.target_index(targ_var[1], "ch1") wf = BlackmanWaveform(var * 100, np.pi) pls = Pulse.ConstantDetuning(wf, var, var) sb.add(pls, "ch1") sb.delay(var * 50, "ch1") sb.align("ch2", "ch1") sb.phase_shift_index(var, targ_var[0]) pls2 = Pulse.ConstantPulse(var * 100, var, var, 0) sb.add(pls2, "ch2") sb.measure() with pytest.warns(UserWarning, match="No declared variables"): sb.build(t=100, var=2, targ_var=reg_.find_indices(["q1", "q0"])) with pytest.raises(TypeError, match="Did not receive values for"): sb.build(var=2) seq = sb.build(var=2, targ_var=reg_.find_indices(["q1", "q0"])) assert seq._schedule["ch2"][-1].tf == 500 assert seq.current_phase_ref("q1") == 2.0 assert seq.current_phase_ref("q0") == 0.0 assert seq._measurement == "ground-rydberg" s = sb.serialize() sb_ = Sequence.deserialize(s) assert str(sb) == str(sb_) s2 = sb_.serialize() sb_2 = Sequence.deserialize(s2) assert str(sb) == str(sb_2)
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_mappable_register(): layout = TriangularLatticeLayout(100, 5) mapp_reg = layout.make_mappable_register(10) seq = Sequence(mapp_reg, Chadoq2) assert seq.is_register_mappable() reserved_qids = tuple([f"q{i}" for i in range(10)]) assert seq._qids == set(reserved_qids) with pytest.raises(RuntimeError, match="Can't access the qubit info"): seq.qubit_info with pytest.raises(RuntimeError, match="Can't access the sequence's register"): seq.register seq.declare_channel("ryd", "rydberg_global") seq.declare_channel("ram", "raman_local", initial_target="q2") seq.add(Pulse.ConstantPulse(100, 1, 0, 0), "ryd") seq.add(Pulse.ConstantPulse(200, 1, 0, 0), "ram") assert seq._last("ryd").targets == set(reserved_qids) assert seq._last("ram").targets == {"q2"} with pytest.raises(ValueError, match="Can't draw the register"): seq.draw(draw_register=True) # Can draw if 'draw_register=False' with patch("matplotlib.pyplot.show"): seq.draw() with pytest.raises(ValueError, match="'qubits' must be specified"): seq.build() with pytest.raises(ValueError, match="targeted but have not been assigned"): seq.build(qubits={"q0": 1, "q1": 10}) with pytest.warns(UserWarning, match="No declared variables named: a"): seq.build(qubits={"q2": 20, "q0": 10}, a=5) seq_ = seq.build(qubits={"q2": 20, "q0": 10}) assert seq_._last("ryd").targets == {"q2", "q0"} assert not seq_.is_register_mappable() assert seq_.register == Register({ "q0": layout.traps_dict[10], "q2": layout.traps_dict[20] }) with pytest.raises(ValueError, match="already has a concrete register"): seq_.build(qubits={"q2": 20, "q0": 10})
def test_mask_equals_remove(): """Check that masking is equivalent to removing the masked qubits. A global pulse acting on three qubits of which one is masked, should be equivalent to acting on a register with only the two unmasked qubits. """ reg_three = Register({"q0": (0, 0), "q1": (10, 10), "q2": (-10, -10)}) reg_two = Register({"q0": (0, 0), "q1": (10, 10)}) pulse = Pulse.ConstantPulse(100, 10, 0, 0) local_pulse = Pulse.ConstantPulse(200, 10, 0, 0) for channel_type in ["mw_global", "rydberg_global", "raman_global"]: # Masked simulation seq_masked = Sequence(reg_three, MockDevice) if channel_type == "mw_global": seq_masked.set_magnetic_field(0, 1.0, 0.0) else: # Add a local channel acting on a masked qubit (has no effect) seq_masked.declare_channel( "local", channel_type[:-len("global")] + "local", initial_target="q2", ) seq_masked.add(local_pulse, "local") seq_masked.declare_channel("ch_masked", channel_type) masked_qubits = ["q2"] seq_masked.config_slm_mask(masked_qubits) seq_masked.add(pulse, "ch_masked") sim_masked = Simulation(seq_masked) # Simulation on reduced register seq_two = Sequence(reg_two, MockDevice) if channel_type == "mw_global": seq_two.set_magnetic_field(0, 1.0, 0.0) seq_two.declare_channel("ch_two", channel_type) if channel_type != "mw_global": seq_two.delay(local_pulse.duration, "ch_two") seq_two.add(pulse, "ch_two") sim_two = Simulation(seq_two) # Check equality for t in sim_two.sampling_times: ham_masked = sim_masked.get_hamiltonian(t) ham_two = sim_two.get_hamiltonian(t) assert ham_masked == qutip.tensor(ham_two, qutip.qeye(2))
def test_magnetic_field(): seq = Sequence(reg, MockDevice) with pytest.raises( AttributeError, match="only defined when the sequence " "is in 'XY Mode'.", ): seq.magnetic_field seq.declare_channel("ch0", "mw_global") # seq in XY mode # mag field is the default assert np.all(seq.magnetic_field == np.array((0.0, 0.0, 30.0))) seq.set_magnetic_field(bx=1.0, by=-1.0, bz=0.5) assert np.all(seq.magnetic_field == np.array((1.0, -1.0, 0.5))) with pytest.raises(ValueError, match="magnitude greater than 0"): seq.set_magnetic_field(bz=0.0) assert seq._empty_sequence seq.add(Pulse.ConstantPulse(100, 1, 1, 0), "ch0") assert not seq._empty_sequence with pytest.raises(ValueError, match="can only be set on an empty seq"): seq.set_magnetic_field(1.0, 0.0, 0.0) seq2 = Sequence(reg, MockDevice) seq2.declare_channel("ch0", "rydberg_global") # not in XY mode with pytest.raises(ValueError, match="can only be set in 'XY Mode'."): seq2.set_magnetic_field(1.0, 0.0, 0.0) seq3 = Sequence(reg, MockDevice) seq3.set_magnetic_field(1.0, 0.0, 0.0) # sets seq to XY mode assert set(seq3.available_channels) == {"mw_global"} seq3.declare_channel("ch0", "mw_global") # Does not change to default assert np.all(seq3.magnetic_field == np.array((1.0, 0.0, 0.0))) var = seq3.declare_variable("var") # Sequence is marked as non-empty when parametrized too seq3.add(Pulse.ConstantPulse(100, var, 1, 0), "ch0") assert seq3.is_parametrized() with pytest.raises(ValueError, match="can only be set on an empty seq"): seq3.set_magnetic_field() seq3_str = seq3.serialize() seq3_ = Sequence.deserialize(seq3_str) assert seq3_._in_xy assert str(seq3) == str(seq3_) assert np.all(seq3_.magnetic_field == np.array((1.0, 0.0, 0.0)))
def test_str(): reg_ = Register.rectangle(2, 1, prefix="q") sb = Sequence(reg_, device) sb.declare_channel("ch1", "rydberg_global") with pytest.warns(UserWarning, match="Building a non-parametrized"): seq = sb.build() var = sb.declare_variable("var") pls = Pulse.ConstantPulse(var * 100, var, -1, var) sb.add(pls, "ch1") s = (f"Prelude\n-------\n{str(seq)}Stored calls\n------------\n\n" + "1. add(Pulse.ConstantPulse(mul(var, 100), var, -1, var), ch1)") assert s == str(sb)
def test_str(): seq = Sequence(reg, device) seq.declare_channel("ch0", "raman_local", initial_target="q0") pulse = Pulse.ConstantPulse(500, 2, -10, 0, post_phase_shift=np.pi) seq.add(pulse, "ch0") seq.delay(200, "ch0") seq.target("q7", "ch0") seq.measure("digital") msg = ("Channel: ch0\nt: 0 | Initial targets: q0 | Phase Reference: 0.0 " + "\nt: 0->500 | Pulse(Amp=2 rad/µs, Detuning=-10 rad/µs, Phase=0) " + "| Targets: q0\nt: 500->700 | Delay \nt: 700->700 | Target: q7 | " + "Phase Reference: 0.0\n\nMeasured in basis: digital") assert seq.__str__() == msg
def test_str(): seq = Sequence(reg, device) seq.declare_channel('ch0', 'raman_local', initial_target='q0') pulse = Pulse.ConstantPulse(500, 2, -10, 0, post_phase_shift=np.pi) seq.add(pulse, 'ch0') seq.delay(200, 'ch0') seq.target('q7', 'ch0') seq.measure('digital') msg = ('Channel: ch0\nt: 0 | Initial targets: q0 | Phase Reference: 0.0 ' + '\nt: 0->500 | Pulse(Amp=2 rad/µs, Detuning=-10 rad/µs, Phase=0) ' + '| Targets: q0\nt: 500->700 | Delay \nt: 700->700 | Target: q7 | ' + 'Phase Reference: 0.0\n\nMeasured in basis: digital') assert seq.__str__() == msg
def test_initialization_and_construction_of_hamiltonian(): fake_sequence = {"pulse1": "fake", "pulse2": "fake"} with pytest.raises(TypeError, match="sequence has to be a valid"): Simulation(fake_sequence) sim = Simulation(seq, sampling_rate=0.011) assert sim._seq == seq assert sim._qdict == seq.qubit_info assert sim._size == len(seq.qubit_info) assert sim._tot_duration == duration * d assert sim._qid_index == {"control1": 0, "target": 1, "control2": 2} with pytest.raises(ValueError, match="too small, less than"): Simulation(seq, sampling_rate=0.0001) with pytest.raises(ValueError, match="`sampling_rate`"): Simulation(seq, sampling_rate=5) with pytest.raises(ValueError, match="`sampling_rate`"): Simulation(seq, sampling_rate=-1) assert sim._sampling_rate == 0.011 assert len(sim.sampling_times) == int(sim._sampling_rate * sim._tot_duration) assert isinstance(sim._hamiltonian, qutip.QobjEvo) # Checks adapt() method: assert bool(set(sim._hamiltonian.tlist).intersection(sim.sampling_times)) for qobjevo in sim._hamiltonian.ops: for sh in qobjevo.qobj.shape: assert sh == sim.dim**sim._size assert not seq.is_parametrized() seq_copy = seq.build() # Take a copy of the sequence x = seq_copy.declare_variable("x") seq_copy.add(Pulse.ConstantPulse(x, 1, 0, 0), "ryd") assert seq_copy.is_parametrized() with pytest.raises(ValueError, match="needs to be built"): Simulation(seq_copy) layout = RegisterLayout([[0, 0], [10, 10]]) mapp_reg = layout.make_mappable_register(1) seq_ = Sequence(mapp_reg, Chadoq2) assert seq_.is_register_mappable() and not seq_.is_parametrized() with pytest.raises(ValueError, match="needs to be built"): Simulation(seq_)
def test_effective_size_disjoint(): simple_reg = Register.square(2, prefix="atom") rise = Pulse.ConstantPulse(1500, 0, 0, 0) for channel_type in ["mw_global", "rydberg_global", "raman_global"]: np.random.seed(15092021) seq = Sequence(simple_reg, MockDevice) seq.declare_channel("ch0", channel_type) seq.add(rise, "ch0") seq.config_slm_mask(["atom1"]) sim = Simulation(seq, sampling_rate=0.01) sim.set_config(SimConfig("SPAM", eta=0.4)) assert sim._bad_atoms == { "atom0": True, "atom1": False, "atom2": True, "atom3": False, } assert sim.get_hamiltonian(0) == 0 * sim.build_operator( [("I", "global")])
def test_measure(): pulse = Pulse.ConstantPulse(500, 2, -10, 0, post_phase_shift=np.pi) seq = Sequence(reg, MockDevice) seq.declare_channel("ch0", "rydberg_global") assert "XY" in MockDevice.supported_bases with pytest.raises(ValueError, match="not supported"): seq.measure(basis="XY") seq.measure() with pytest.raises(RuntimeError, match="already been measured"): seq.measure(basis="digital") with pytest.raises(RuntimeError, match="Nothing more can be added."): seq.add(pulse, "ch0") seq = Sequence(reg, MockDevice) seq.declare_channel("ch0", "mw_global") assert "digital" in MockDevice.supported_bases with pytest.raises(ValueError, match="not supported"): seq.measure(basis="digital") seq.measure(basis="XY")
def test_draw_register(): # Draw 2d register from sequence reg = Register({"q0": (0, 0), "q1": (10, 10), "q2": (-10, -10)}) targets = ["q0", "q2"] pulse = Pulse.ConstantPulse(100, 10, 0, 0) seq = Sequence(reg, MockDevice) seq.declare_channel("ch_xy", "mw_global") seq.add(pulse, "ch_xy") seq.config_slm_mask(targets) with patch("matplotlib.pyplot.show"): seq.draw(draw_register=True) # Draw 3d register from sequence reg3d = Register3D.cubic(3, 8) seq3d = Sequence(reg3d, MockDevice) seq3d.declare_channel("ch_xy", "mw_global") seq3d.add(pulse, "ch_xy") seq3d.config_slm_mask([6, 15]) with patch("matplotlib.pyplot.show"): seq3d.draw(draw_register=True)
def test_creation(): with pytest.raises(TypeError): Pulse(10, 0, 0, post_phase_shift=2) Pulse(cwf, 1, 0) Pulse(0, bwf, 1) Pulse(bwf, cwf, bwf) Pulse(bwf, cwf, 0, post_phase_shift=cwf) with pytest.raises(ValueError, match="The duration of"): Pulse(bwf, cwf, 0) with pytest.raises(ValueError, match="All samples of an amplitude"): Pulse(cwf, cwf, 0) Pulse.ConstantAmplitude(-1, cwf, 0) Pulse.ConstantPulse(100, -1, 0, 0) assert pls.phase == 0 assert pls2 == pls3 assert pls != pls4 assert pls4.detuning != cwf assert pls4.amplitude == pls.amplitude
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_creation(): with pytest.raises(TypeError): Pulse(10, 0, 0, post_phase_shift=2) Pulse(cwf, 1, 0) Pulse(0, bwf, 1) Pulse(bwf, cwf, bwf) Pulse(bwf, cwf, 0, post_phase_shift=cwf) with pytest.raises(ValueError, match="durations don't match"): Pulse(bwf, cwf, 0) with pytest.raises(ValueError, match="has always to be non-negative."): Pulse(cwf, cwf, 0) Pulse.ConstantAmplitude(-1, cwf, 0) Pulse.ConstantPulse(100, -1, 0, 0) assert pls.phase == 0 assert pls2.amplitude == pls3.amplitude assert pls2.detuning == pls3.detuning assert pls2.phase == np.pi assert pls3.phase == 1 assert pls4.detuning != cwf assert pls4.amplitude == pls.amplitude
def test_cuncurrent_pulses(): reg = Register({"q0": (0, 0)}) seq = Sequence(reg, Chadoq2) seq.declare_channel("ch_local", "rydberg_local", initial_target="q0") seq.declare_channel("ch_global", "rydberg_global") pulse = Pulse.ConstantPulse(20, 10, 0, 0) seq.add(pulse, "ch_local") seq.add(pulse, "ch_global", protocol="no-delay") # Clean simulation sim_no_noise = Simulation(seq) # Noisy simulation sim_with_noise = Simulation(seq) config_doppler = SimConfig(noise=("doppler")) sim_with_noise.set_config(config_doppler) for t in sim_no_noise.evaluation_times: ham_no_noise = sim_no_noise.get_hamiltonian(t) ham_with_noise = sim_with_noise.get_hamiltonian(t) assert ham_no_noise[0, 1] == ham_with_noise[0, 1]
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"
# limitations under the License. from unittest.mock import patch import numpy as np import pytest from pulser import Pulse from pulser.waveforms import BlackmanWaveform, ConstantWaveform, RampWaveform cwf = ConstantWaveform(100, -10) bwf = BlackmanWaveform(200, 3) rwf = RampWaveform(200, 0, 1) pls = Pulse(bwf, bwf, 2 * np.pi) pls2 = Pulse.ConstantPulse(100, 1, -10, -np.pi) pls3 = Pulse.ConstantAmplitude(1, cwf, -np.pi) pls4 = Pulse.ConstantDetuning(bwf, -10, 0) def test_creation(): with pytest.raises(TypeError): Pulse(10, 0, 0, post_phase_shift=2) Pulse(cwf, 1, 0) Pulse(0, bwf, 1) Pulse(bwf, cwf, bwf) Pulse(bwf, cwf, 0, post_phase_shift=cwf) with pytest.raises(ValueError, match="The duration of"): Pulse(bwf, cwf, 0)
def test_stored_calls(): sb = Sequence(reg, device) assert sb._calls[-1].name == "__init__" var = sb.declare_variable("var") assert sb._to_build_calls == [] with pytest.raises( TypeError, match="initial_target cannot be parametrized" ): sb.declare_channel("ch1", "rydberg_local", initial_target=var) sb.declare_channel("ch1", "rydberg_local") sb.target_index(var, "ch1") assert sb._calls[-1].name == "declare_channel" assert sb._to_build_calls[-1].name == "_target_index" assert sb._to_build_calls[-1].args == (var, "ch1") with pytest.raises(ValueError, match="name of a declared channel"): sb.delay(1000, "rydberg_local") x = Variable("x", int) var_ = copy.deepcopy(var) with pytest.raises(ValueError, match="Unknown variable 'x'"): sb.target_index(x, "ch1") with pytest.raises(ValueError, match="come from this Sequence"): sb.target(var_, "ch1") with pytest.raises(ValueError, match="ids have to be qubit ids"): sb.target("q20", "ch1") with pytest.raises( NotImplementedError, match="Using parametrized objects or variables to refer to channels", ): sb.target("q0", var) sb.delay(var, "ch1") call = sb._to_build_calls[1] assert call.name == "delay" assert call.args == (var, "ch1") assert call.kwargs == {} pls = Pulse.ConstantPulse(1000, var, var, var) with pytest.raises(ValueError, match="Invalid protocol 'last'"): sb.add(pls, "ch1", protocol="last") with pytest.raises(ValueError, match="amplitude goes over the maximum"): sb.add( Pulse.ConstantPulse(20, 2 * np.pi * 100, -2 * np.pi * 100, 0), "ch1", ) with pytest.raises( ValueError, match="detuning values go out of the range" ): sb.add(Pulse.ConstantPulse(500, 2 * np.pi, -2 * np.pi * 100, 0), "ch1") assert sb._to_build_calls[-1] == call sb.add(pls, "ch1", protocol="wait-for-all") call = sb._to_build_calls[2] assert call.name == "add" assert call.args == (pls, "ch1") assert call.kwargs == {"protocol": "wait-for-all"} q_var = sb.declare_variable("q_var", size=5, dtype=int) sb.declare_channel("ch2", "rydberg_global") assert len(sb._calls) == 3 assert sb._calls[-1].name == "declare_channel" with pytest.raises(ValueError, match="'Local' channels"): sb.target(0, "ch2") with pytest.raises(ValueError, match="target at most 1 qubits"): sb.target_index(q_var, "ch1") sb2 = Sequence(reg, MockDevice) sb2.declare_channel("ch1", "rydberg_local", initial_target={3, 4, 5}) q_var2 = sb2.declare_variable("q_var2", size=5, dtype=int) var2 = sb2.declare_variable("var2") assert sb2._building with pytest.raises(ValueError, match="ids have to be qubit ids"): sb2.target({var2, 7, 9, 10}, "ch1") sb2.target_index(q_var2, "ch1") assert not sb2._building with pytest.raises(ValueError, match="targets the given 'basis'"): sb.phase_shift_index(var, *q_var) with pytest.raises( ValueError, match="ids have to be qubit ids", ): sb.phase_shift(var, "wacky_id", basis="ground-rydberg") with pytest.raises(ValueError, match="ids have to be qubit ids"): sb2.phase_shift(np.pi, var2, basis="ground-rydberg") with pytest.raises( ValueError, match="All non-variable targets must be indices valid for the" " register, between 0 and 11. Wrong index: 'q1'.", ): sb.phase_shift_index(var, *q_var, "q1", basis="ground-rydberg") with pytest.raises( ValueError, match="All non-variable targets must be indices valid for the" " register, between 0 and 11. Wrong index: 'q1'.", ): sb.target_index("q1", channel="ch1") with pytest.raises(ValueError, match="correspond to declared channels"): sb.align("ch1", var) with pytest.raises(ValueError, match="more than once"): sb.align("ch1", "ch2", "ch2") with pytest.raises(ValueError, match="at least two channels"): sb.align("ch1") with pytest.raises(ValueError, match="not supported"): sb.measure(basis=var) sb.measure() with pytest.raises(RuntimeError): sb.delay(var * 50, "ch1")
def test_stored_calls(): sb = Sequence(reg, device) assert sb._calls[-1].name == "__init__" var = sb.declare_variable("var") assert sb._to_build_calls == [] sb.declare_channel("ch1", "rydberg_local", initial_target=var) assert sb._calls[-1].name == "declare_channel" assert sb._to_build_calls[-1].name == "target" assert sb._to_build_calls[-1].args == (var, "ch1") with pytest.raises(ValueError, match="name of a declared channel"): sb.delay(1000, "rydberg_local") x = Variable("x", str) var_ = copy.deepcopy(var) with pytest.raises(ValueError, match="Unknown variable 'x'"): sb.target(x, "ch1") with pytest.raises(ValueError, match="come from this Sequence"): sb.target(var_, "ch1") with pytest.raises(ValueError, match="non-variable qubits must belong"): sb.target('q20', "ch1") sb.delay(var, "ch1") call = sb._to_build_calls[1] assert call.name == "delay" assert call.args == (var, "ch1") assert call.kwargs == {} pls = Pulse.ConstantPulse(1000, var, var, var) with pytest.raises(ValueError, match="Invalid protocol 'last'"): sb.add(pls, "ch1", protocol="last") with pytest.raises(ValueError, match='amplitude goes over the maximum'): sb.add(Pulse.ConstantPulse(20, 2 * np.pi * 100, -2 * np.pi * 100, 0), 'ch1') with pytest.raises(ValueError, match='detuning values go out of the range'): sb.add(Pulse.ConstantPulse(500, 2 * np.pi, -2 * np.pi * 100, 0), 'ch1') assert sb._to_build_calls[-1] == call sb.add(pls, "ch1", protocol="wait-for-all") call = sb._to_build_calls[2] assert call.name == "add" assert call.args == (pls, "ch1") assert call.kwargs == {"protocol": "wait-for-all"} q_var = sb.declare_variable("q_var", size=5, dtype=str) sb.declare_channel("ch2", "rydberg_global") assert len(sb._calls) == 3 assert sb._calls[-1].name == "declare_channel" with pytest.raises(ValueError, match="'Local' channels"): sb.target(0, "ch2") with pytest.raises(ValueError, match="target at most 1 qubits"): sb.target(q_var, "ch1") sb2 = Sequence(reg, MockDevice) sb2.declare_channel("ch1", "rydberg_local", initial_target={3, 4, 5}) q_var2 = sb2.declare_variable("q_var2", size=5, dtype=str) var2 = sb2.declare_variable("var2") assert sb2._building sb2.target({var2, 7, 9, 10}, "ch1") assert not sb2._building sb2.target(q_var2, "ch1") with pytest.raises(ValueError, match="targets the given 'basis'"): sb.phase_shift(var, *q_var) with pytest.raises(ValueError, match="non-variable targets must belong"): sb.phase_shift(var, *q_var, "q1", basis="ground-rydberg") with pytest.raises(ValueError, match="correspond to declared channels"): sb.align("ch1", var) with pytest.raises(ValueError, match="more than once"): sb.align("ch1", "ch2", "ch2") with pytest.raises(ValueError, match="at least two channels"): sb.align("ch1") with pytest.raises(ValueError, match="not supported"): sb.measure(basis="z") sb.measure() with pytest.raises(SystemError): sb.delay(var * 50, "ch1")
def test_sequence(): seq = Sequence(reg, device) with pytest.raises(SystemError, match='empty sequence'): seq.draw() seq.declare_channel('ch0', 'raman_local', initial_target='q0') seq.declare_channel('ch1', 'rydberg_local', initial_target='q0') seq.declare_channel('ch2', 'rydberg_global') seq.phase_shift(np.pi, 'q0', basis='ground-rydberg') pulse1 = Pulse.ConstantPulse(500, 2, -10, 0, post_phase_shift=np.pi) pulse2 = Pulse.ConstantDetuning(BlackmanWaveform(1e3, np.pi / 4), 25, np.pi, post_phase_shift=1) with pytest.raises(TypeError): seq.add([1, 5, 3], 'ch0') with pytest.raises(ValueError, match='amplitude goes over the maximum'): seq.add(Pulse.ConstantPulse(20, 2 * np.pi * 10, -2 * np.pi * 100, 0), 'ch2') with pytest.raises(ValueError, match='detuning values go out of the range'): seq.add(Pulse.ConstantPulse(500, 2 * np.pi, -2 * np.pi * 100, 0), 'ch0') with pytest.raises(ValueError, match='qubits with different phase ref'): seq.add(pulse2, 'ch2') with pytest.raises(ValueError, match='Invalid protocol'): seq.add(pulse1, 'ch0', protocol='now') seq.add(pulse1, 'ch0') seq.add(pulse1, 'ch1') seq.add(pulse2, 'ch2') assert seq._last('ch0').ti == 0 assert seq._last('ch0').tf == seq._last('ch1').ti assert seq._last('ch2').tf == seq._last('ch2').ti + 1000 assert seq.current_phase_ref('q0', 'digital') == np.pi seq.add(pulse1, 'ch2') assert seq._last('ch2').tf == 2500 seq.add(pulse2, 'ch1', protocol='no-delay') assert seq._last('ch1').tf == 3500 seq.add(pulse1, 'ch0', protocol='no-delay') assert seq._last('ch0').ti == 500 assert seq._last('ch0').tf == 1000 assert seq.current_phase_ref('q0', 'digital') == 0 seq.phase_shift(np.pi / 2, 'q1') seq.target('q1', 'ch0') assert seq._last_used['digital']['q1'] == 0 assert seq._last_target['ch0'] == 1000 assert seq._last('ch0').ti == 1000 assert seq._last('ch0').tf == 1000 seq.add(pulse1, 'ch0') assert seq._last('ch0').ti == 2500 assert seq._last('ch0').tf == 3000 seq.add(pulse1, 'ch0', protocol='wait-for-all') assert seq._last('ch0').ti == 3500 assert seq._last('ch2').tf != seq._last('ch0').tf seq.align('ch0', 'ch2') assert seq._last('ch2').tf == seq._last('ch0').tf with patch('matplotlib.pyplot.show'): seq.draw() assert seq._total_duration == 4000 with pytest.raises(ValueError, match='not supported'): seq.measure(basis='computational') seq.measure(basis='digital') with pytest.raises(SystemError, match='already been measured'): seq.measure(basis='digital') with pytest.raises(SystemError, match='Nothing more can be added.'): seq.add(pulse1, 'ch0') with patch('matplotlib.pyplot.show'): seq.draw()
def test_hardware_constraints(): rydberg_global = Rydberg.Global( 2 * np.pi * 20, 2 * np.pi * 2.5, phase_jump_time=120, # ns mod_bandwidth=4, # MHz ) raman_local = Raman.Local( 2 * np.pi * 20, 2 * np.pi * 10, phase_jump_time=120, # ns fixed_retarget_t=200, # ns mod_bandwidth=7, # MHz ) ConstrainedChadoq2 = Device( name="ConstrainedChadoq2", dimensions=2, rydberg_level=70, max_atom_num=100, max_radial_distance=50, min_atom_distance=4, _channels=( ("rydberg_global", rydberg_global), ("raman_local", raman_local), ), ) with pytest.warns(UserWarning, match="should be imported from 'pulser.devices'"): seq = Sequence(reg, ConstrainedChadoq2) seq.declare_channel("ch0", "rydberg_global") seq.declare_channel("ch1", "raman_local", initial_target="q1") const_pls = Pulse.ConstantPulse(100, 1, 0, np.pi) seq.add(const_pls, "ch0") black_wf = BlackmanWaveform(500, np.pi) black_pls = Pulse.ConstantDetuning(black_wf, 0, 0) seq.add(black_pls, "ch1") blackman_slot = seq._last("ch1") # The pulse accounts for the modulation buffer assert (blackman_slot.ti == const_pls.duration + rydberg_global.rise_time * 2) seq.target("q0", "ch1") target_slot = seq._last("ch1") fall_time = black_pls.fall_time(raman_local) assert (fall_time == raman_local.rise_time + black_wf.modulation_buffers(raman_local)[1]) fall_time += (raman_local.clock_period - fall_time % raman_local.clock_period) assert target_slot.ti == blackman_slot.tf + fall_time assert target_slot.tf == target_slot.ti + raman_local.fixed_retarget_t assert raman_local.min_retarget_interval > raman_local.fixed_retarget_t seq.target("q2", "ch1") assert (seq.get_duration("ch1") == target_slot.tf + raman_local.min_retarget_interval) # Check for phase jump buffer seq.add(black_pls, "ch0") # Phase = 0 tf_ = seq.get_duration("ch0") mid_delay = 40 seq.delay(mid_delay, "ch0") seq.add(const_pls, "ch0") # Phase = π assert seq._last("ch0").ti - tf_ == rydberg_global.phase_jump_time added_delay_slot = seq._schedule["ch0"][-2] assert added_delay_slot.type == "delay" assert (added_delay_slot.tf - added_delay_slot.ti == rydberg_global.phase_jump_time - mid_delay) tf_ = seq.get_duration("ch0") seq.align("ch0", "ch1") fall_time = const_pls.fall_time(rydberg_global) assert seq.get_duration() == tf_ + fall_time with pytest.raises(ValueError, match="'mode' must be one of"): seq.draw(mode="all") with patch("matplotlib.pyplot.show"): with pytest.warns( UserWarning, match="'draw_phase_area' doesn't work in 'output' mode", ): seq.draw(mode="output", draw_interp_pts=False, draw_phase_area=True) with pytest.warns( UserWarning, match="'draw_interp_pts' doesn't work in 'output' mode", ): seq.draw(mode="output") seq.draw(mode="input+output")
def test_sequence(): seq = Sequence(reg, device) assert seq.get_duration() == 0 with pytest.raises(RuntimeError, match="empty sequence"): seq.draw() seq.declare_channel("ch0", "raman_local", initial_target="q0") seq.declare_channel("ch1", "rydberg_local", initial_target="q0") seq.declare_channel("ch2", "rydberg_global") assert seq.get_duration("ch0") == 0 assert seq.get_duration("ch2") == 0 seq.phase_shift(np.pi, "q0", basis="ground-rydberg") with patch("matplotlib.pyplot.show"): with patch("matplotlib.figure.Figure.savefig"): seq.draw(fig_name="my_sequence.pdf") seq.draw(draw_register=True, fig_name="both.pdf") pulse1 = Pulse( InterpolatedWaveform(500, [0, 1, 0]), InterpolatedWaveform(500, [-1, 1, 0]), phase=0, post_phase_shift=np.pi, ) pulse2 = Pulse.ConstantDetuning(BlackmanWaveform(1e3, np.pi / 4), 25, np.pi, post_phase_shift=1) with pytest.raises(TypeError): seq.add([1, 5, 3], "ch0") with pytest.raises(ValueError, match="amplitude goes over the maximum"): seq.add(Pulse.ConstantPulse(20, 2 * np.pi * 10, -2 * np.pi * 100, 0), "ch2") with pytest.raises(ValueError, match="detuning values go out of the range"): seq.add(Pulse.ConstantPulse(500, 2 * np.pi, -2 * np.pi * 100, 0), "ch0") with pytest.raises(ValueError, match="qubits with different phase ref"): seq.add(pulse2, "ch2") with pytest.raises(ValueError, match="Invalid protocol"): seq.add(pulse1, "ch0", protocol="now") wf_ = CompositeWaveform(BlackmanWaveform(30, 1), RampWaveform(15, 0, 2)) with pytest.raises(TypeError, match="Failed to automatically adjust"): with pytest.warns(UserWarning, match="rounded up to 48 ns"): seq.add(Pulse.ConstantAmplitude(1, wf_, 0), "ch0") pulse1_ = Pulse.ConstantPulse(499, 2, -10, 0, post_phase_shift=np.pi) with pytest.warns(UserWarning, match="rounded up to 500 ns"): seq.add(pulse1_, "ch0") seq.add(pulse1, "ch1") seq.add(pulse2, "ch2") assert seq._last("ch0").ti == 0 assert seq._last("ch0").tf == seq._last("ch1").ti assert seq._last("ch2").tf == seq._last("ch2").ti + 1000 assert seq.current_phase_ref("q0", "digital") == np.pi seq.add(pulse1, "ch2") assert seq.get_duration("ch2") == 2500 seq.add(pulse2, "ch1", protocol="no-delay") assert seq.get_duration("ch1") == 3500 seq.add(pulse1, "ch0", protocol="no-delay") assert seq._last("ch0").ti == 500 assert seq.get_duration("ch0") == 1000 assert seq.current_phase_ref("q0", "digital") == 0 seq.phase_shift(np.pi / 2, "q1") seq.target("q1", "ch0") assert seq._last_used["digital"]["q1"] == 0 assert seq._last_target["ch0"] == 1000 assert seq._last("ch0").ti == 1000 assert seq.get_duration("ch0") == 1000 seq.add(pulse1, "ch0") assert seq._last("ch0").ti == 2500 assert seq.get_duration("ch0") == 3000 seq.add(pulse1, "ch0", protocol="wait-for-all") assert seq._last("ch0").ti == 3500 assert seq.get_duration("ch2") != seq.get_duration("ch0") seq.align("ch0", "ch2") assert seq.get_duration("ch2") == seq.get_duration("ch0") with patch("matplotlib.pyplot.show"): seq.draw(draw_phase_shifts=True) assert seq.get_duration() == 4000 seq.measure(basis="digital") with patch("matplotlib.pyplot.show"): seq.draw(draw_phase_area=True) s = seq.serialize() assert json.loads(s)["__version__"] == pulser.__version__ seq_ = Sequence.deserialize(s) assert str(seq) == str(seq_)