コード例 #1
0
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),
        )
コード例 #2
0
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()
コード例 #3
0
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
コード例 #4
0
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
コード例 #5
0
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"})
コード例 #6
0
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"))
コード例 #7
0
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
コード例 #8
0
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)
コード例 #9
0
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])
コード例 #10
0
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})
コード例 #11
0
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))
コード例 #12
0
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)))
コード例 #13
0
ファイル: test_paramseq.py プロジェクト: sphkthnch/Pulser
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)
コード例 #14
0
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
コード例 #15
0
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
コード例 #16
0
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_)
コード例 #17
0
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")])
コード例 #18
0
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")
コード例 #19
0
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)
コード例 #20
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)

    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
コード例 #21
0
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
コード例 #22
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
コード例 #23
0
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]
コード例 #24
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"
コード例 #25
0
# 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)
コード例 #26
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")
コード例 #27
0
ファイル: test_paramseq.py プロジェクト: sphkthnch/Pulser
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")
コード例 #28
0
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()
コード例 #29
0
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")
コード例 #30
0
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_)