@@ -132,6 +132,8 @@ def __init__(
132
132
seed : Optional [Union [int , SeedSequence , BitGenerator , Generator ]] = None ,
133
133
two_qubit_gate : Optional [str ] = None ,
134
134
one_qubit_basis_gates : Optional [Sequence [str ]] = None ,
135
+ layer_barrier : Optional [bool ] = True ,
136
+ min_delay : Optional [Sequence [int ]] = None ,
135
137
):
136
138
"""Initialize a layer fidelity experiment.
137
139
@@ -153,6 +155,18 @@ def __init__(
153
155
one_qubit_basis_gates: Optional, 1q-gates to use for implementing 1q-Clifford operations.
154
156
If not specified (but ``backend`` is supplied),
155
157
all 1q-gates supported in the backend are automatically set.
158
+ layer_barrier (bool): Optional, enforce a barrier across the whole layer.
159
+ Default is True, which is the defined protocol for layer fidelity.
160
+ If this is set to false the code runs
161
+ simultaneous direct 1+2Q RB without a barrier across all qubits.
162
+ min_delay: Optional. Define a minimum delay in each 2Q layer in units of dt. This
163
+ delay operation will be applied in any 1Q edge of the layer during the 2Q gate layer
164
+ in order to enforce a minimum duration of the 2Q layer. This enables some crosstalk
165
+ testing by removing a gate from the layer without changing the layer duration. If not
166
+ None then is a list equal in length to the number of two_qubit_layers. Note that
167
+ this options requires at least one 1Q edge (a qubit in physical_qubits but
168
+ not in two_qubit_layers) to be applied. Also will not have an impact on the 2Q gates
169
+ if layer_barrier=False.
156
170
157
171
Raises:
158
172
QiskitError: If any invalid argument is supplied.
@@ -231,6 +245,8 @@ def __init__(
231
245
two_qubit_layers = two_qubit_layers ,
232
246
two_qubit_gate = two_qubit_gate ,
233
247
one_qubit_basis_gates = tuple (one_qubit_basis_gates ),
248
+ layer_barrier = layer_barrier ,
249
+ min_delay = min_delay ,
234
250
)
235
251
236
252
# Verify two_qubit_gate and one_qubit_basis_gates
@@ -254,6 +270,18 @@ def _default_experiment_options(cls) -> Options:
254
270
one_qubit_basis_gates (Tuple[str]): One-qubit gates to use for implementing 1q Cliffords.
255
271
clifford_synthesis_method (str): The name of the Clifford synthesis plugin to use
256
272
for building circuits of RB sequences.
273
+ layer_barrier (bool): Optional, enforce a barrier across the whole layer.
274
+ Default is True, which is the defined protocol for layer fidelity.
275
+ If this is set to false the code runs
276
+ simultaneous direct 1+2Q RB without a barrier across all qubits.
277
+ min_delay (List[int]): Optional. Define a minimum delay in each 2Q layer in units of dt. This
278
+ delay operation will be applied in any 1Q edge of the layer during the 2Q gate layer
279
+ in order to enforce a minimum duration of the 2Q layer. This enables some crosstalk
280
+ testing by removing a gate from the layer without changing the layer duration. If not
281
+ None then is a list equal in length to the number of two_qubit_layers. Note that
282
+ this options requires at least one 1Q edge (a qubit in physical_qubits but
283
+ not in two_qubit_layers) to be applied. Also will not have an impact on the 2Q gates
284
+ if layer_barrier=False.
257
285
"""
258
286
options = super ()._default_experiment_options ()
259
287
options .update_options (
@@ -264,6 +292,8 @@ def _default_experiment_options(cls) -> Options:
264
292
two_qubit_gate = None ,
265
293
one_qubit_basis_gates = None ,
266
294
clifford_synthesis_method = DEFAULT_SYNTHESIS_METHOD ,
295
+ layer_barrier = True ,
296
+ min_delay = None ,
267
297
)
268
298
return options
269
299
@@ -367,6 +397,11 @@ def circuits_generator(self) -> Iterable[QuantumCircuit]:
367
397
else :
368
398
gate2q = GATE_NAME_MAP [opts .two_qubit_gate ]
369
399
gate2q_cliff = num_from_2q_circuit (Clifford (gate2q ).to_circuit ())
400
+
401
+ # warn if min delay is not None and barrier is false
402
+ if opts .min_delay is not None and not opts .layer_barrier :
403
+ warnings .warn ("Min delay applied when layer_barrier is False." )
404
+
370
405
# Circuit generation
371
406
num_qubits = max (self .physical_qubits ) + 1
372
407
for i_sample in range (opts .num_samples ):
@@ -380,9 +415,32 @@ def circuits_generator(self) -> Iterable[QuantumCircuit]:
380
415
composite_clbits .extend (
381
416
[(c ,) for c in range (2 * num_2q_gates , 2 * num_2q_gates + num_1q_gates )]
382
417
)
418
+
419
+ if opts .min_delay is None :
420
+ min_delay = None
421
+ else :
422
+ min_delay = opts .min_delay [i_set ]
423
+
383
424
for length in opts .lengths :
384
425
circ = QuantumCircuit (num_qubits , num_qubits )
385
- barrier_inst = CircuitInstruction (Barrier (num_qubits ), circ .qubits )
426
+ # define the barrier instruction
427
+ full_barrier_inst = CircuitInstruction (Barrier (num_qubits ), circ .qubits )
428
+ if not opts .layer_barrier :
429
+ # we want separate barriers for each qubit so define them individually
430
+ barrier_inst_gate = []
431
+ for two_q_gate in two_qubit_layer :
432
+ barrier_inst_gate .append (
433
+ CircuitInstruction (
434
+ Barrier (2 ),
435
+ [circ .qubits [two_q_gate [0 ]], circ .qubits [two_q_gate [1 ]]],
436
+ )
437
+ )
438
+ for one_q in one_qubits :
439
+ barrier_inst_gate .append (
440
+ CircuitInstruction (Barrier (1 ), [circ .qubits [one_q ]])
441
+ )
442
+ else :
443
+ barrier_inst_gate = [full_barrier_inst ]
386
444
self .__circuit_body (
387
445
circ ,
388
446
length ,
@@ -393,10 +451,11 @@ def circuits_generator(self) -> Iterable[QuantumCircuit]:
393
451
_to_gate_2q ,
394
452
gate2q ,
395
453
gate2q_cliff ,
396
- barrier_inst ,
454
+ barrier_inst_gate ,
455
+ min_delay ,
397
456
)
398
457
# add the measurements
399
- circ ._append (barrier_inst )
458
+ circ ._append (full_barrier_inst )
400
459
for qubits , clbits in zip (composite_qubits , composite_clbits ):
401
460
circ .measure (qubits , clbits )
402
461
# store composite structure in metadata
@@ -443,8 +502,14 @@ def __circuit_body(
443
502
_to_gate_2q ,
444
503
gate2q ,
445
504
gate2q_cliff ,
446
- barrier_inst ,
505
+ barrier_inst_lst ,
506
+ min_delay = None ,
447
507
):
508
+
509
+ # warn if min_delay is not none and one_qubits is empty
510
+ if min_delay is not None and len (one_qubits ) == 0 :
511
+ warnings .warn ("Min delay will not be applied because there are no 1Q edges." )
512
+
448
513
# initialize cliffords and a ciruit (0: identity clifford)
449
514
cliffs_2q = [0 ] * len (two_qubit_layer )
450
515
cliffs_1q = [0 ] * len (one_qubits )
@@ -463,16 +528,21 @@ def __circuit_body(
463
528
sample = rng .integers (NUM_1Q_CLIFFORD )
464
529
cliffs_1q [k ] = compose_1q (cliffs_1q [k ], sample )
465
530
circ ._append (_to_gate_1q (sample ), (circ .qubits [q ],), ())
466
- circ ._append (barrier_inst )
531
+ for barrier_inst in barrier_inst_lst :
532
+ circ ._append (barrier_inst )
467
533
# add two qubit gates
468
534
for j , qpair in enumerate (two_qubit_layer ):
469
535
circ ._append (gate2q , tuple (circ .qubits [q ] for q in qpair ), ())
470
536
cliffs_2q [j ] = compose_2q (cliffs_2q [j ], gate2q_cliff )
471
537
# TODO: add dd if necessary
472
538
for k , q in enumerate (one_qubits ):
473
539
# TODO: add dd if necessary
474
- pass
475
- circ ._append (barrier_inst )
540
+ # if there is a min_delay, just need
541
+ # to add to one of the qubits
542
+ if min_delay is not None and k == 0 :
543
+ circ .delay (min_delay , q )
544
+ for barrier_inst in barrier_inst_lst :
545
+ circ ._append (barrier_inst )
476
546
# add the last inverse
477
547
for j , qpair in enumerate (two_qubit_layer ):
478
548
inv = inverse_2q (cliffs_2q [j ])
0 commit comments