Skip to content

Commit

Permalink
Revert NoiseModel.from_dict (Qiskit#2222)
Browse files Browse the repository at this point in the history
  • Loading branch information
doichanj committed Sep 12, 2024
1 parent ff0ee2b commit e384a36
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 2 deletions.
102 changes: 101 additions & 1 deletion qiskit_aer/noise/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

import numpy as np

from qiskit.circuit import Instruction, Delay
from qiskit.circuit import QuantumCircuit, Instruction, Delay, Reset
from qiskit.circuit.library.generalized_gates import PauliGate, UnitaryGate
from qiskit.providers import QubitProperties
from qiskit.providers.exceptions import BackendPropertyError
from qiskit.providers.models.backendproperties import BackendProperties
Expand Down Expand Up @@ -959,6 +960,105 @@ def to_dict(self, serializable=False):

return ret

@staticmethod
def from_dict(noise_dict):
"""
Load NoiseModel from a dictionary.
Args:
noise_dict (dict): A serialized noise model.
Returns:
NoiseModel: the noise model.
Raises:
NoiseError: if dict cannot be converted to NoiseModel.
"""
warn(
"from_dict has been deprecated as of qiskit-aer 0.15.0"
" and will be removed no earlier than 3 months from that release date.",
DeprecationWarning,
stacklevel=2,
)

def inst_dic_list_to_circuit(dic_list):
num_qubits = max(max(dic["qubits"]) for dic in dic_list) + 1
circ = QuantumCircuit(num_qubits)
for dic in dic_list:
if dic["name"] == "reset":
circ.append(Reset(), qargs=dic["qubits"])
elif dic["name"] == "kraus":
circ.append(
Instruction(
name="kraus",
num_qubits=len(dic["qubits"]),
num_clbits=0,
params=dic["params"],
),
qargs=dic["qubits"],
)
elif dic["name"] == "unitary":
circ.append(UnitaryGate(data=dic["params"][0]), qargs=dic["qubits"])
elif dic["name"] == "pauli":
circ.append(PauliGate(dic["params"][0]), qargs=dic["qubits"])
else:
with catch_warnings():
filterwarnings(
"ignore",
category=DeprecationWarning,
module="qiskit_aer.noise.errors.errorutils",
)
circ.append(
UnitaryGate(
label=dic["name"], data=_standard_gate_unitary(dic["name"])
),
qargs=dic["qubits"],
)
return circ

# Return noise model
noise_model = NoiseModel()

# Get error terms
errors = noise_dict.get("errors", [])

for error in errors:
error_type = error["type"]

# Add QuantumError
if error_type == "qerror":
circuits = [inst_dic_list_to_circuit(dics) for dics in error["instructions"]]
noise_ops = tuple(zip(circuits, error["probabilities"]))
qerror = QuantumError(noise_ops)
qerror._id = error.get("id", None) or qerror.id
instruction_names = error["operations"]
all_gate_qubits = error.get("gate_qubits", None)
if all_gate_qubits is not None:
for gate_qubits in all_gate_qubits:
# Add local quantum error
noise_model.add_quantum_error(
qerror, instruction_names, gate_qubits, warnings=False
)
else:
# Add all-qubit quantum error
noise_model.add_all_qubit_quantum_error(
qerror, instruction_names, warnings=False
)

# Add ReadoutError
elif error_type == "roerror":
probabilities = error["probabilities"]
all_gate_qubits = error.get("gate_qubits", None)
roerror = ReadoutError(probabilities)
# Add local readout error
if all_gate_qubits is not None:
for gate_qubits in all_gate_qubits:
noise_model.add_readout_error(roerror, gate_qubits, warnings=False)
# Add all-qubit readout error
else:
noise_model.add_all_qubit_readout_error(roerror, warnings=False)
# Invalid error type
else:
raise NoiseError("Invalid error type: {}".format(error_type))
return noise_model

def _instruction_names_labels(self, instructions):
"""Return two lists of instruction name strings and label strings."""
if not isinstance(instructions, (list, tuple)):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
deprecations:
- |
Reverting NoiseModel.from_dict temporary to extend deprecation period
for qiskit-ibm-runtime, but we will remove again in the future release
23 changes: 22 additions & 1 deletion test/terra/noise/test_noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from qiskit_aer.backends import AerSimulator
from qiskit_aer.noise import NoiseModel
from qiskit_aer.noise.device.models import _excited_population
from qiskit_aer.noise.errors import PauliError, PauliLindbladError
from qiskit_aer.noise.errors import QuantumError, PauliError, PauliLindbladError
from qiskit_aer.noise.errors.standard_errors import amplitude_damping_error
from qiskit_aer.noise.errors.standard_errors import kraus_error
from qiskit_aer.noise.errors.standard_errors import pauli_error
Expand All @@ -31,6 +31,8 @@

import qiskit
from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.circuit.library.standard_gates import IGate, XGate
from qiskit.circuit.library.generalized_gates import PauliGate
from qiskit.compiler import transpile
from qiskit.transpiler import CouplingMap, Target
from qiskit.providers import QubitProperties, BackendV2, Options
Expand Down Expand Up @@ -416,6 +418,25 @@ def test_pauli_lindblad_error_sampling_equiv(self):
probs2 = [counts2.get(i, 0) / shots for i in ["00", "01", "10", "11"]]
np.testing.assert_allclose(probs1, probs2, atol=5e-2)

def test_from_dict(self):
noise_ops_1q = [((IGate(), [0]), 0.9), ((XGate(), [0]), 0.1)]

noise_ops_2q = [
((PauliGate("II"), [0, 1]), 0.9),
((PauliGate("IX"), [0, 1]), 0.045),
((PauliGate("XI"), [0, 1]), 0.045),
((PauliGate("XX"), [0, 1]), 0.01),
]

noise_model = NoiseModel()
with self.assertWarns(DeprecationWarning):
noise_model.add_quantum_error(QuantumError(noise_ops_1q), "h", [0])
noise_model.add_quantum_error(QuantumError(noise_ops_1q), "h", [1])
noise_model.add_quantum_error(QuantumError(noise_ops_2q), "cx", [0, 1])
noise_model.add_quantum_error(QuantumError(noise_ops_2q), "cx", [1, 0])
deserialized = NoiseModel.from_dict(noise_model.to_dict())
self.assertEqual(noise_model, deserialized)


if __name__ == "__main__":
unittest.main()

0 comments on commit e384a36

Please sign in to comment.