@@ -4014,12 +4014,18 @@ def from_qiskit(cls, circuit,
4014
4014
4015
4015
Returns
4016
4016
-------
4017
- pygsti_circuit
4018
- A pyGSTi Circuit instance equivalent to the specified Qiskit one.
4017
+ Tuple:
4018
+ pygsti_circuit
4019
+ A pyGSTi Circuit instance equivalent to the specified Qiskit one.
4020
+
4021
+ Dict {qiskit_qubit_idx, pyGSTi_qubit}
4019
4022
"""
4020
4023
4021
4024
try :
4022
4025
import qiskit
4026
+ if qiskit .__version__ != '1.1.1' :
4027
+ print ("warning: Circuit class method 'from_qiskit()' is designed for qiskit version 1.1.1 and may not \
4028
+ function properly for your qiskit version, which is " + qiskit .__version__ )
4023
4029
except ImportError :
4024
4030
raise ImportError ("Qiskit is required for this operation, and it does not appear to be installed." )
4025
4031
@@ -4044,15 +4050,18 @@ def from_qiskit(cls, circuit,
4044
4050
4045
4051
#ensure all of these have a conversion available.
4046
4052
if qubit_conversion is not None :
4047
- if isinstance (qubit_conversion , dict ):
4048
- unmapped_qubits = set (qubits ).difference (set (qubit_conversion .keys ()))
4049
- assert len (unmapped_qubits ) == 0 , f'Missing Qiskit to pygsti conversions for some qubits: { unmapped_qubits } '
4053
+ unmapped_qubits = set (qubits ).difference (set (qubit_conversion .keys ()))
4054
+ assert len (unmapped_qubits ) == 0 , f'Missing Qiskit to pygsti conversions for some qubits: { unmapped_qubits } '
4055
+
4056
+ qubit_idx_conversion = {i : qubit_conversion [circuit .qbit_argument_conversion (i )[0 ]] for i in range (circuit .num_qubits )}
4050
4057
4051
4058
#if it is None, build a default mapping.
4052
4059
else :
4053
4060
#default mapping is the identify mapping: qubit i in the Qiskit circuit maps to qubit i in the pyGSTi circuit
4054
4061
qubit_conversion = {circuit .qbit_argument_conversion (i )[0 ]: f'Q{ i } ' for i in range (circuit .num_qubits )} # in Qiskit 1.1.1, the method is called qbit_argument_conversion. In Qiskit >=1.2 (as far as Noah can tell), the method is called _qbit_argument_conversion.
4055
4062
4063
+ qubit_idx_conversion = {i : f'Q{ i } ' for i in range (circuit .num_qubits )}
4064
+
4056
4065
# for i in range(circuit.num_qubits):
4057
4066
4058
4067
# qubit_conversion = {i: f'Q{i}' for i in qiskit_qubits}
@@ -4091,9 +4100,11 @@ def from_qiskit(cls, circuit,
4091
4100
num_qubits = instruction .operation .num_qubits
4092
4101
# instruction_qubit_indices = [qubit._index for qubit in instruction.qubits]
4093
4102
params = instruction .operation .params
4094
- # print(name)
4095
- # print(num_qubits)
4096
- # print(params)
4103
+
4104
+ if verbose :
4105
+ print (name )
4106
+ print (num_qubits )
4107
+ print (params )
4097
4108
4098
4109
pygsti_gate_qubits = [qubit_conversion [qubit ] for qubit in instruction .qubits ]
4099
4110
@@ -4102,7 +4113,11 @@ def from_qiskit(cls, circuit,
4102
4113
continue
4103
4114
4104
4115
if name == 'barrier' :
4105
- _warnings .warn ('skipping barrier' )
4116
+ next_index = max (layer_indices [qubit ] for qubit in pygsti_gate_qubits )
4117
+ for qubit in pygsti_gate_qubits :
4118
+ layer_indices [qubit ] = next_index
4119
+
4120
+ # _warnings.warn('skipping barrier')
4106
4121
continue
4107
4122
4108
4123
pygsti_gate_name = qiskit_to_gate_name_mapping [name ][0 ]
@@ -4146,7 +4161,7 @@ def from_qiskit(cls, circuit,
4146
4161
4147
4162
circuit = cls (pygsti_circ_layers , line_labels = line_labels )
4148
4163
4149
- return circuit
4164
+ return ( circuit , qubit_idx_conversion )
4150
4165
4151
4166
4152
4167
@@ -4317,6 +4332,81 @@ def convert_to_quil(self,
4317
4332
4318
4333
return quil
4319
4334
4335
+
4336
+ def convert_to_qiskit (self , num_qubits = None ,
4337
+ qubit_conversion = None ,
4338
+ gatename_conversion = None ,
4339
+ block_between_layers = True ,
4340
+ qubits_to_measure = None ,
4341
+ ):
4342
+
4343
+ try :
4344
+ import qiskit
4345
+ except ImportError :
4346
+ raise ImportError ("Qiskit is required for this operation, and it does not appear to be installed." )
4347
+
4348
+ depth = self .depth
4349
+
4350
+ if num_qubits is None :
4351
+ num_qubits = self .width
4352
+
4353
+ if qubit_conversion is None :
4354
+ qubit_conversion = {label : label for label in self .line_labels }
4355
+ elif qubit_conversion == 'remove-Q' :
4356
+ qubit_conversion = {label : int (label [1 :]) for label in self .line_labels }
4357
+
4358
+
4359
+ qiskit_qc = qiskit .QuantumCircuit (num_qubits )
4360
+
4361
+ qiskit_gate_conversion = _itgs .standard_gatenames_qiskit_conversions ()
4362
+
4363
+ for i in range (depth ):
4364
+ layer = self .layer_label (i ).components
4365
+ for gate in layer :
4366
+ qiskit_gate , is_standard_gate = qiskit_gate_conversion [gate .name ]
4367
+ # pseudo-code
4368
+ qiskit_qubits = [qubit_conversion [qubit ] for qubit in gate .qubits ]
4369
+
4370
+ # if qiskit_version >= 2.0:
4371
+ # if is_standard_gate:
4372
+ # qiskit_qc._append_standard_gate(qiskit_gate, qiskit_qubits, gate.args)
4373
+ # else:
4374
+ # qiskit_qc.append(qiskit_gate(gate.args), gate.qubits, copy=False)
4375
+
4376
+ qiskit_qc .append (qiskit_gate (* (gate .args )), qiskit_qubits , copy = False )
4377
+
4378
+ if block_between_layers :
4379
+ qiskit_qc .barrier ()
4380
+
4381
+
4382
+ if qubits_to_measure is not None :
4383
+ if isinstance (qubits_to_measure , str ):
4384
+ if qubits_to_measure == 'all' :
4385
+ qiskit_qc .measure_all ()
4386
+
4387
+ elif qubits_to_measure == 'active' :
4388
+ qiskit_qubits_to_measure = [v for v in qubit_conversion .values ()]
4389
+ new_creg = qiskit_qc ._create_creg (len (qiskit_qubits_to_measure ), "meas" )
4390
+ qiskit_qc .add_register (new_creg )
4391
+ qiskit_qc .barrier ()
4392
+ qiskit_qc .measure (qiskit_qubits_to_measure , new_creg )
4393
+
4394
+ else :
4395
+ raise ValueError (f"unknown string option for 'qubits_to_measure': { qubits_to_measure } " )
4396
+
4397
+ elif isinstance (qubits_to_measure , list ):
4398
+ qiskit_qubits_to_measure = [qubit_conversion [qubit ] for qubit in qubits_to_measure ]
4399
+ new_creg = qiskit_qc ._create_creg (len (qiskit_qubits_to_measure ), "meas" )
4400
+ qiskit_qc .add_register (new_creg )
4401
+ qiskit_qc .barrier ()
4402
+ qiskit_qc .measure (qiskit_qubits_to_measure , new_creg )
4403
+
4404
+ else :
4405
+ raise ValueError (f"could not parse argument for 'qubits_to_measure': { qubits_to_measure } " )
4406
+
4407
+ return qiskit_qc
4408
+
4409
+
4320
4410
def convert_to_openqasm (self , num_qubits = None ,
4321
4411
standard_gates_version = 'u3' ,
4322
4412
gatename_conversion = None , qubit_conversion = None ,
@@ -4453,7 +4543,7 @@ def convert_to_openqasm(self, num_qubits=None,
4453
4543
if openqasmlist_for_gate is None :
4454
4544
# Try to look up the operation in mapping dict instead
4455
4545
openqasmfn_for_gate = gateargs_map .get (gate .name , None )
4456
- assert openqasmfn_for_gate is not None , "Could not look up {} as qasm list or func" % gate . name
4546
+ assert openqasmfn_for_gate is not None , f "Could not look up { gate . name } as qasm list or func"
4457
4547
openqasmlist_for_gate = openqasmfn_for_gate (gate .args )
4458
4548
4459
4549
openqasm_for_gate = ''
0 commit comments