From cc3a33a000cdfb8c4698b4aa8e8a48b5f493bda8 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 28 Feb 2024 10:38:08 +0400 Subject: [PATCH] test --- src/qibo/noise.py | 20 +++--- tests/test_noise.py | 154 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 10 deletions(-) diff --git a/src/qibo/noise.py b/src/qibo/noise.py index 013006bc44..3864277ceb 100644 --- a/src/qibo/noise.py +++ b/src/qibo/noise.py @@ -373,7 +373,7 @@ def apply(self, circuit): return noisy_circuit -class _ConditionQubits: +class _Conditions: def __init__(self, qubits=None): self.qubits = qubits @@ -490,7 +490,7 @@ def from_dict(self, parameters: dict): if isinstance(depolarizing_one_qubit, (float, int)): self.add( DepolarizingError(depolarizing_one_qubit), - conditions=_ConditionQubits().condition_gate_single, + conditions=_Conditions().condition_gate_single, ) if isinstance(depolarizing_one_qubit, dict): @@ -498,13 +498,13 @@ def from_dict(self, parameters: dict): self.add( DepolarizingError(lamb), qubits=int(qubit_key), - conditions=_ConditionQubits().condition_gate_single, + conditions=_Conditions().condition_gate_single, ) if isinstance(depolarizing_two_qubit, (float, int)): self.add( DepolarizingError(depolarizing_two_qubit), - conditions=_ConditionQubits().condition_gate_two, + conditions=_Conditions().condition_gate_two, ) if isinstance(depolarizing_two_qubit, dict): @@ -515,19 +515,19 @@ def from_dict(self, parameters: dict): DepolarizingError(lamb), qubits=qubits, conditions=[ - _ConditionQubits().condition_gate_two, - _ConditionQubits(qubits).condition_qubits, + _Conditions().condition_gate_two, + _Conditions(qubits).condition_qubits, ], ) if isinstance(t_1, (float, int)) and isinstance(t_2, (float, int)): self.add( ThermalRelaxationError(t_1, t_2, gate_time_1, excited_population), - conditions=_ConditionQubits().condition_gate_single, + conditions=_Conditions().condition_gate_single, ) self.add( ThermalRelaxationError(t_1, t_2, gate_time_2, excited_population), - conditions=_ConditionQubits().condition_gate_two, + conditions=_Conditions().condition_gate_two, ) if isinstance(t_1, dict) and isinstance(t_2, dict): @@ -537,14 +537,14 @@ def from_dict(self, parameters: dict): t_1[qubit_key], t_2[qubit_key], gate_time_1, excited_population ), qubits=int(qubit_key), - conditions=_ConditionQubits().condition_gate_single, + conditions=_Conditions().condition_gate_single, ) self.add( ThermalRelaxationError( t_1[qubit_key], t_2[qubit_key], gate_time_2, excited_population ), qubits=int(qubit_key), - conditions=_ConditionQubits().condition_gate_two, + conditions=_Conditions().condition_gate_two, ) if isinstance(readout_one_qubit, (int, float)): diff --git a/tests/test_noise.py b/tests/test_noise.py index 19e21bd14b..25e0f933bb 100644 --- a/tests/test_noise.py +++ b/tests/test_noise.py @@ -17,6 +17,7 @@ UnitaryError, ) from qibo.quantum_info import ( + random_clifford, random_density_matrix, random_statevector, random_stochastic_matrix, @@ -611,3 +612,156 @@ def test_gate_independent_noise(backend, density_matrix): )._state backend.assert_allclose(final_state, target_final_state) + + +class _Conditions: + def __init__(self, qubits=None): + self.qubits = qubits + + def condition_single(self, gate): + return len(gate.qubits) == 1 + + def condition_two(self, gate): + return len(gate.qubits) == 2 + + def condition_qubits(self, gate): + return gate.qubits == self.qubits + + +@pytest.mark.parametrize( + "readout_one_qubit", [0.01, {"0": 0.01, "1": [0.001], "4": (0.02, 0.03)}] +) +@pytest.mark.parametrize("excited_population", [0.0, 0.1]) +@pytest.mark.parametrize("gate_times", [(0.1, 0.2)]) +@pytest.mark.parametrize( + "t1, t2", [(0.1, 0.01), ({"1": 0.1, "2": 0.05}, {"1": 0.01, "2": 0.001})] +) +@pytest.mark.parametrize( + "depolarizing_two_qubit", [0.01, {"0-1": 0.01, "1-3": 0.02, "4-5": 0.05}] +) +@pytest.mark.parametrize( + "depolarizing_one_qubit", [0.01, {"0": 0.01, "1": 0.02, "4": 0.05}] +) +@pytest.mark.parametrize("nqubits", [5]) +def test_ibmq_noise( + backend, + nqubits, + depolarizing_one_qubit, + depolarizing_two_qubit, + t1, + t2, + gate_times, + excited_population, + readout_one_qubit, +): + ## Since the IBMQNoiseModel inherits the NoiseModel class, + ## we will test only what is different + + circuit = random_clifford(nqubits, density_matrix=True, backend=backend) + circuit.add(gates.M(qubit) for qubit in range(nqubits)) + + parameters = { + "t1": t1, + "t2": t2, + "depolarizing_one_qubit": depolarizing_one_qubit, + "depolarizing_two_qubit": depolarizing_two_qubit, + "excited_population": excited_population, + "readout_one_qubit": readout_one_qubit, + "gate_times": gate_times, + } + + noise_model = IBMQNoiseModel() + noise_model.from_dict(parameters) + noisy_circuit = noise_model.apply(circuit) + + noise_model_target = NoiseModel() + if isinstance(depolarizing_one_qubit, float): + noise_model_target.add( + DepolarizingError(depolarizing_one_qubit), + conditions=_Conditions().condition_single, + ) + + if isinstance(depolarizing_one_qubit, dict): + for qubit_key, lamb in depolarizing_one_qubit.items(): + noise_model_target.add( + DepolarizingError(lamb), + qubits=int(qubit_key), + conditions=_Conditions().condition_single, + ) + + if isinstance(depolarizing_two_qubit, (float, int)): + noise_model_target.add( + DepolarizingError(depolarizing_two_qubit), + conditions=_Conditions().condition_two, + ) + + if isinstance(depolarizing_two_qubit, dict): + for key, lamb in depolarizing_two_qubit.items(): + qubits = key.replace(" ", "").split("-") + qubits = tuple(map(int, qubits)) + noise_model_target.add( + DepolarizingError(lamb), + qubits=qubits, + conditions=[ + _Conditions().condition_two, + _Conditions(qubits).condition_qubits, + ], + ) + + if isinstance(t1, float): + noise_model_target.add( + ThermalRelaxationError(t1, t2, gate_times[0], excited_population), + conditions=_Conditions().condition_single, + ) + noise_model_target.add( + ThermalRelaxationError(t1, t2, gate_times[1], excited_population), + conditions=_Conditions().condition_two, + ) + else: + for qubit in t1.keys(): + noise_model_target.add( + ThermalRelaxationError( + t1[qubit], t2[qubit], gate_times[0], excited_population + ), + qubits=int(qubit), + conditions=_Conditions().condition_single, + ) + noise_model_target.add( + ThermalRelaxationError( + t1[qubit], t2[qubit], gate_times[1], excited_population + ), + qubits=int(qubit), + conditions=_Conditions().condition_two, + ) + + if isinstance(readout_one_qubit, float): + probabilities = [ + [1 - readout_one_qubit, readout_one_qubit], + [readout_one_qubit, 1 - readout_one_qubit], + ] + noise_model_target.add(ReadoutError(probabilities), gate=gates.M) + else: + for qubit, probs in readout_one_qubit.items(): + if isinstance(probs, (int, float)): + probs = (probs, probs) + elif isinstance(probs, (tuple, list)) and len(probs) == 1: + probs *= 2 + + probabilities = [[1 - probs[0], probs[0]], [probs[1], 1 - probs[1]]] + noise_model_target.add( + ReadoutError(probabilities), + gate=gates.M, + qubits=int(qubit), + ) + + noisy_circuit_target = noise_model_target.apply(circuit) + + assert noisy_circuit.draw() == noisy_circuit_target.draw() + + backend.set_seed(2024) + state = backend.execute_circuit(noisy_circuit, nshots=10) + + backend.set_seed(2024) + state_target = backend.execute_circuit(noisy_circuit_target, nshots=10) + + backend.assert_allclose(state, state_target)