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
5
16
6
17
from qiskit .transpiler .target import Target , InstructionProperties
7
18
from qiskit .providers .backend import QubitProperties
11
22
from qiskit .circuit .gate import Gate
12
23
from qiskit .circuit .measure import Measure
13
24
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
+ )
16
30
17
31
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
+ """
19
40
name_mapping = {
20
41
"id" : IGate (),
21
42
"sx" : SXGate (),
@@ -25,123 +46,97 @@ def convert_to_target(configuration, properties=None, defaults=None):
25
46
"reset" : Reset (),
26
47
}
27
48
custom_gates = {}
28
- target = Target ()
49
+ target = Target (num_qubits = configuration . n_qubits )
29
50
# Parse from properties if it exsits
30
51
if properties is not None :
31
52
# 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
35
56
if name in name_mapping :
36
57
if name not in gates :
37
58
gates [name ] = {}
38
59
elif name not in custom_gates :
39
- custom_gate = Gate (name , len (gate [ " qubits" ] ), [])
60
+ custom_gate = Gate (name , len (gate . qubits ), [])
40
61
custom_gates [name ] = custom_gate
41
62
gates [name ] = {}
42
63
43
- qubits = tuple (gate [ " qubits" ] )
64
+ qubits = tuple (gate . qubits )
44
65
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 )
50
71
gates [name ][qubits ] = InstructionProperties (** gate_props )
51
72
for gate , props in gates .items ():
52
73
if gate in name_mapping :
53
- inst = name_mapping [ gate ]
74
+ inst = name_mapping . get ( gate )
54
75
else :
55
76
inst = custom_gates [gate ]
56
77
target .add_instruction (inst , props )
57
78
# Create measurement instructions:
58
79
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
+ )
69
85
target .add_instruction (Measure (), measure_props )
70
86
# Parse from configuration because properties doesn't exist
71
87
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
75
96
if name in name_mapping :
76
97
target .add_instruction (name_mapping [name ], gate_props )
77
98
else :
78
- custom_gate = Gate (name , len ( gate [ "coupling_map" ][ 0 ]) )
99
+ custom_gate = Gate (name , gate_len , [] )
79
100
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 ())
82
102
# 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
97
128
return target
98
129
99
130
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
+ """
102
135
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