From 7982c537dc232ba759c26180554f485ae5e0e5bd Mon Sep 17 00:00:00 2001 From: a_corni Date: Wed, 28 Feb 2024 10:36:33 +0100 Subject: [PATCH] Enable digital simulation --- .../pulser_simulation/hamiltonian.py | 7 +- tests/test_simulation.py | 103 ++++++++++++++---- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/pulser-simulation/pulser_simulation/hamiltonian.py b/pulser-simulation/pulser_simulation/hamiltonian.py index 73d964c42..ca9ecc549 100644 --- a/pulser-simulation/pulser_simulation/hamiltonian.py +++ b/pulser-simulation/pulser_simulation/hamiltonian.py @@ -107,11 +107,10 @@ def config(self) -> NoiseModel: def _build_collapse_operators(self, config: NoiseModel) -> None: def basis_check(noise_type: str) -> None: """Checks if the basis allows for the use of noise.""" - if self.basis_name == "digital" or self.basis_name == "all": + if self.basis_name == "all": # Go back to previous config raise NotImplementedError( - f"Cannot include {noise_type} " - + "noise in digital- or all-basis." + f"Cannot include {noise_type} noise in all-basis." ) local_collapse_ops = [] @@ -121,7 +120,7 @@ def basis_check(noise_type: str) -> None: local_collapse_ops.append(coeff * qutip.sigmaz()) if "depolarizing" in config.noise_types: - basis_check("dephasing") + basis_check("depolarizing") coeff = np.sqrt(config.depolarizing_rate / 4) local_collapse_ops.append(coeff * qutip.sigmax()) local_collapse_ops.append(coeff * qutip.sigmay()) diff --git a/tests/test_simulation.py b/tests/test_simulation.py index 133372769..5cb21e055 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -37,38 +37,48 @@ def reg(): return Register(q_dict) +duration = 1000 +pi_pulse = Pulse.ConstantDetuning(BlackmanWaveform(duration, np.pi), 0.0, 0) +twopi_pulse = Pulse.ConstantDetuning( + BlackmanWaveform(duration, 2 * np.pi), 0.0, 0 +) +pi_Y_pulse = Pulse.ConstantDetuning( + BlackmanWaveform(duration, np.pi), 0.0, -np.pi / 2 +) + + @pytest.fixture -def seq(reg): - duration = 1000 - pi = Pulse.ConstantDetuning(BlackmanWaveform(duration, np.pi), 0.0, 0) - twopi = Pulse.ConstantDetuning( - BlackmanWaveform(duration, 2 * np.pi), 0.0, 0 - ) - pi_Y = Pulse.ConstantDetuning( - BlackmanWaveform(duration, np.pi), 0.0, -np.pi / 2 - ) +def seq_digital(reg): seq = Sequence(reg, DigitalAnalogDevice) # Declare Channels - seq.declare_channel("ryd", "rydberg_local", "control1") seq.declare_channel("raman", "raman_local", "control1") # Prepare state 'hhh': - seq.add(pi_Y, "raman") + seq.add(pi_Y_pulse, "raman") seq.target("target", "raman") - seq.add(pi_Y, "raman") + seq.add(pi_Y_pulse, "raman") seq.target("control2", "raman") - seq.add(pi_Y, "raman") + seq.add(pi_Y_pulse, "raman") + return seq + +@pytest.fixture +def seq(seq_digital): # Write CCZ sequence: - seq.add(pi, "ryd", protocol="wait-for-all") + with pytest.warns( + UserWarning, match="Building a non-parametrized sequence" + ): + seq = seq_digital.build() + seq.declare_channel("ryd", "rydberg_local", "control1") + seq.add(pi_pulse, "ryd", protocol="wait-for-all") seq.target("control2", "ryd") - seq.add(pi, "ryd") + seq.add(pi_pulse, "ryd") seq.target("target", "ryd") - seq.add(twopi, "ryd") + seq.add(twopi_pulse, "ryd") seq.target("control2", "ryd") - seq.add(pi, "ryd") + seq.add(pi_pulse, "ryd") seq.target("control1", "ryd") - seq.add(pi, "ryd") + seq.add(pi_pulse, "ryd") # Add a ConstantWaveform part to testout the drawing procedure seq.add(Pulse.ConstantPulse(duration, 1, 0, 0), "ryd") @@ -744,9 +754,10 @@ def test_noise_with_zero_epsilons(seq, matrices): (("eff_noise", "dephasing"), {"0": 595, "1": 405}, 2), ], ) -def test_noises(matrices, noise, result, n_collapse_ops): +def test_noises_rydberg(matrices, noise, result, n_collapse_ops): np.random.seed(123) reg = Register.from_coordinates([(0, 0)], prefix="q") + # Test with Rydberg Sequence seq = Sequence(reg, DigitalAnalogDevice) seq.declare_channel("ch0", "rydberg_global") duration = 2500 @@ -769,6 +780,60 @@ def test_noises(matrices, noise, result, n_collapse_ops): assert np.trace(trace_2) < 1 and not np.isclose(np.trace(trace_2), 1) +depo_res = { + "111": 821, + "110": 61, + "011": 59, + "101": 48, + "100": 5, + "001": 3, + "010": 3, +} +deph_depo_res = { + "111": 806, + "110": 65, + "011": 63, + "101": 52, + "100": 6, + "001": 4, + "010": 3, + "000": 1, +} +eff_deph_res = {"111": 958, "110": 19, "011": 12, "101": 11} + + +@pytest.mark.parametrize( + "noise, result, n_collapse_ops", + [ + ("dephasing", {"111": 978, "110": 11, "011": 6, "101": 5}, 1), + ("eff_noise", {"111": 978, "110": 11, "011": 6, "101": 5}, 1), + ("depolarizing", depo_res, 3), + (("dephasing", "depolarizing"), deph_depo_res, 4), + (("eff_noise", "dephasing"), eff_deph_res, 2), + ], +) +def test_noises_digital(matrices, noise, result, n_collapse_ops, seq_digital): + np.random.seed(123) + # Test with Digital Sequence + sim = QutipEmulator.from_sequence( + seq_digital, # resulting state should be hhh + sampling_rate=0.01, + config=SimConfig( + noise=noise, + eff_noise_opers=[matrices["Z"]], + eff_noise_rates=[0.025], + ), + ) + res = sim.run() + res_samples = res.sample_final_state() + assert res_samples == Counter(result) + assert len(sim._hamiltonian._collapse_ops) == n_collapse_ops * len( + seq_digital.register.qubits + ) + trace_2 = res.states[-1] ** 2 + assert np.trace(trace_2) < 1 and not np.isclose(np.trace(trace_2), 1) + + def test_add_config(matrices): reg = Register.from_coordinates([(0, 0)], prefix="q") seq = Sequence(reg, DigitalAnalogDevice)