Skip to content

Commit 2438935

Browse files
Update backend_converter.py
Based on the latest version on Qiskit/qiskit-ibm-runtime#102 Co-Authored-By: Rathish Cholarajan <rathishc24@gmail.com>
1 parent 806cdd3 commit 2438935

File tree

1 file changed

+91
-96
lines changed

1 file changed

+91
-96
lines changed
+91-96
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
1-
import pprint
2-
import sys
3-
import json
4-
import warnings
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2022.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""Converters for migration from IBM Quantum BackendV1 to BackendV2."""
14+
15+
from typing import Any, Dict
516

617
from qiskit.transpiler.target import Target, InstructionProperties
718
from qiskit.providers.backend import QubitProperties
@@ -11,11 +22,21 @@
1122
from qiskit.circuit.gate import Gate
1223
from qiskit.circuit.measure import Measure
1324
from qiskit.circuit.reset import Reset
14-
from qiskit.providers.models.pulsedefaults import PulseDefaults
15-
from qiskit.test.mock.utils.json_decoder import decode_pulse_defaults
25+
from qiskit.providers.models import (
26+
BackendConfiguration,
27+
BackendProperties,
28+
PulseDefaults,
29+
)
1630

1731

18-
def convert_to_target(configuration, properties=None, defaults=None):
32+
def convert_to_target(
33+
configuration: BackendConfiguration,
34+
properties: BackendProperties = None,
35+
defaults: PulseDefaults = None,
36+
) -> Target:
37+
"""Uses configuration, properties and pulse defaults
38+
to construct and return Target class.
39+
"""
1940
name_mapping = {
2041
"id": IGate(),
2142
"sx": SXGate(),
@@ -25,123 +46,97 @@ def convert_to_target(configuration, properties=None, defaults=None):
2546
"reset": Reset(),
2647
}
2748
custom_gates = {}
28-
target = Target()
49+
target = Target(num_qubits=configuration.n_qubits)
2950
# Parse from properties if it exsits
3051
if properties is not None:
3152
# Parse instructions
32-
gates = {}
33-
for gate in properties["gates"]:
34-
name = gate["gate"]
53+
gates: Dict[str, Any] = {}
54+
for gate in properties.gates:
55+
name = gate.gate
3556
if name in name_mapping:
3657
if name not in gates:
3758
gates[name] = {}
3859
elif name not in custom_gates:
39-
custom_gate = Gate(name, len(gate["qubits"]), [])
60+
custom_gate = Gate(name, len(gate.qubits), [])
4061
custom_gates[name] = custom_gate
4162
gates[name] = {}
4263

43-
qubits = tuple(gate["qubits"])
64+
qubits = tuple(gate.qubits)
4465
gate_props = {}
45-
for param in gate["parameters"]:
46-
if param["name"] == "gate_error":
47-
gate_props["error"] = param["value"]
48-
if param["name"] == "gate_length":
49-
gate_props["duration"] = apply_prefix(param["value"], param["unit"])
66+
for param in gate.parameters:
67+
if param.name == "gate_error":
68+
gate_props["error"] = param.value
69+
if param.name == "gate_length":
70+
gate_props["duration"] = apply_prefix(param.value, param.unit)
5071
gates[name][qubits] = InstructionProperties(**gate_props)
5172
for gate, props in gates.items():
5273
if gate in name_mapping:
53-
inst = name_mapping[gate]
74+
inst = name_mapping.get(gate)
5475
else:
5576
inst = custom_gates[gate]
5677
target.add_instruction(inst, props)
5778
# Create measurement instructions:
5879
measure_props = {}
59-
count = 0
60-
for qubit in properties["qubits"]:
61-
qubit_prop = {}
62-
for prop in qubit:
63-
if prop["name"] == "readout_length":
64-
qubit_prop["duration"] = apply_prefix(prop["value"], prop["unit"])
65-
if prop["name"] == "readout_error":
66-
qubit_prop["error"] = prop["value"]
67-
measure_props[(count,)] = InstructionProperties(**qubit_prop)
68-
count += 1
80+
for qubit, _ in enumerate(properties.qubits):
81+
measure_props[(qubit,)] = InstructionProperties(
82+
duration=properties.readout_length(qubit),
83+
error=properties.readout_error(qubit),
84+
)
6985
target.add_instruction(Measure(), measure_props)
7086
# Parse from configuration because properties doesn't exist
7187
else:
72-
for gate in configuration["gates"]:
73-
name = gate["name"]
74-
gate_props = {tuple(x): None for x in gate["coupling_map"]}
88+
for gate in configuration.gates:
89+
name = gate.name
90+
gate_props = (
91+
{tuple(x): None for x in gate.coupling_map} # type: ignore[misc]
92+
if hasattr(gate, "coupling_map")
93+
else {None: None}
94+
)
95+
gate_len = len(gate.coupling_map[0]) if hasattr(gate, "coupling_map") else 0
7596
if name in name_mapping:
7697
target.add_instruction(name_mapping[name], gate_props)
7798
else:
78-
custom_gate = Gate(name, len(gate["coupling_map"][0]))
99+
custom_gate = Gate(name, gate_len, [])
79100
target.add_instruction(custom_gate, gate_props)
80-
measure_props = {(n,): None for n in range(configuration["n_qubits"])}
81-
target.add_instruction(Measure(), measure_props)
101+
target.add_instruction(Measure())
82102
# parse global configuration properties
83-
dt = configuration.get("dt")
84-
if dt:
85-
target.dt = dt ** 1e-6
86-
if "timing_constraints" in configuration:
87-
target.granularity = configuration["timing_constraints"].get("granularity")
88-
target.min_length = configuration["timing_constraints"].get("min_length")
89-
target.pulse_alignment = configuration["timing_constraints"].get("pulse_alignment")
90-
target.aquire_alignment = configuration["timing_constraints"].get("aquire_alignment")
91-
# If a pulse defaults exists use that as the source of truth
92-
# TODO: uncomment when measurement qargs fix is applied
93-
# if defaults is not None:
94-
# decode_pulse_defaults(defaults)
95-
# pulse_defs = PulseDefaults.from_dict(defaults)
96-
# target.update_from_instruction_schedule_map(pulse_defs.instruction_schedule_map)
103+
if hasattr(configuration, "dt"):
104+
target.dt = configuration.dt
105+
if hasattr(configuration, "timing_constraints"):
106+
target.granularity = configuration.timing_constraints.get("granularity")
107+
target.min_length = configuration.timing_constraints.get("min_length")
108+
target.pulse_alignment = configuration.timing_constraints.get("pulse_alignment")
109+
target.aquire_alignment = configuration.timing_constraints.get(
110+
"acquire_alignment"
111+
)
112+
# If pulse defaults exists use that as the source of truth
113+
if defaults is not None:
114+
inst_map = defaults.instruction_schedule_map
115+
for inst in inst_map.instructions:
116+
for qarg in inst_map.qubits_with_instruction(inst):
117+
sched = inst_map.get(inst, qarg)
118+
if inst in target:
119+
try:
120+
qarg = tuple(qarg)
121+
except TypeError:
122+
qarg = (qarg,)
123+
if inst == "measure":
124+
for qubit in qarg:
125+
target[inst][(qubit,)].calibration = sched
126+
else:
127+
target[inst][qarg].calibration = sched
97128
return target
98129

99130

100-
def qubit_properties_dict_from_properties(properties: dict):
101-
count = 0
131+
def qubit_props_dict_from_props(properties: BackendProperties) -> QubitProperties:
132+
"""Uses BackendProperties to construct
133+
and return QubitProperties class.
134+
"""
102135
qubit_props = {}
103-
for qubit in properties["qubits"]:
104-
qubit_properties = {}
105-
for prop_dict in qubit:
106-
if prop_dict["name"] == "T1":
107-
qubit_properties["t1"] = apply_prefix(prop_dict["value"], prop_dict["unit"])
108-
elif prop_dict["name"] == "T2":
109-
qubit_properties["t2"] = apply_prefix(prop_dict["value"], prop_dict["unit"])
110-
elif prop_dict["name"] == "frequency":
111-
qubit_properties["frequency"] = apply_prefix(
112-
prop_dict["value"], prop_dict["unit"]
113-
)
114-
qubit_props[count] = QubitProperties(**qubit_properties)
115-
count += 1
116-
return qubit_props
117-
118-
119-
def main():
120-
conf_path = sys.argv[1]
121-
properties_path = None
122-
if len(sys.argv) > 2:
123-
properties_path = sys.argv[2]
124-
defaults_path = None
125-
if len(sys.argv) > 3:
126-
defaults_path = sys.argv[3]
127-
with open(conf_path, "r") as fd:
128-
conf_dict = json.load(fd)
129-
defaults_dict = None
130-
if defaults_path:
131-
with open(defaults_path, "r") as fd:
132-
defaults_dict = json.load(fd)
133-
properties_dict = None
134-
if properties_path:
135-
with open(properties_path, "r") as fd:
136-
properties_dict = json.load(fd)
137-
target = convert_to_target(conf_dict, properties_dict, defaults_dict)
138-
if properties_dict is not None:
139-
qubit_properties = qubit_properties_dict_from_properties(properties_dict)
140-
else:
141-
qubit_properties = {}
142-
print(target)
143-
pprint.pprint(qubit_properties)
144-
145-
146-
if __name__ == "__main__":
147-
main()
136+
for qubit, _ in enumerate(properties.qubits):
137+
qubit_props[qubit] = QubitProperties(
138+
t1=properties.t1(qubit),
139+
t2=properties.t2(qubit),
140+
frequency=properties.frequency(qubit),
141+
)
142+
return qubit_props

0 commit comments

Comments
 (0)