qiskit-community / qiskit-ignis

Ignis (deprecated) provides tools for quantum hardware verification, noise characterization, and error correction.
Apache License 2.0
168 stars 162 forks source link

`randomized_benchmarking_seq` doesn't work when interleaved element has a pulse gate #564

Closed singular-value closed 3 years ago

singular-value commented 3 years ago

Informations

What is the current behavior?

randomized_benchmarking_seq doesn't work when called with an interleaved_elem that has a pulse gate. In the example below, the interleaved_elem is a circuit comprising of a single gate, custom_swap, which is a pulse gate. Running this code is necessary to run pulse-gates for the Open Science Challenge.

In [19]: rb_circs, xdata, circuits_interleaved = rb.randomized_benchmarking_seq(length_vector=length_vector,
    ...:                                              nseeds=nseeds,
    ...:                                              rb_pattern=rb_pattern,
    ...:                                              interleaved_elem=interleaved_elem)
    ...: 
---------------------------------------------------------------------------
QiskitError                               Traceback (most recent call last)
<ipython-input-19-3ce568c12718> in <module>
      2                                              nseeds=nseeds,
      3                                              rb_pattern=rb_pattern,
----> 4                                              interleaved_elem=interleaved_elem)

~/miniconda3/envs/my-env/lib/python3.7/site-packages/qiskit/ignis/verification/randomized_benchmarking/circuits.py in randomized_benchmarking_seq(nseeds, length_vector, rb_pattern, length_multiplier, seed_offset, align_cliffs, interleaved_gates, interleaved_elem, is_purity, group_gates, rand_seed)
    402 
    403     # Handle various types of the interleaved element
--> 404     interleaved_elem = handle_interleaved_elem(interleaved_elem, rb_group)
    405 
    406     # initialization: rb sequences

~/miniconda3/envs/my-env/lib/python3.7/site-packages/qiskit/ignis/verification/randomized_benchmarking/circuits.py in handle_interleaved_elem(interleaved_elem, rb_group)
    154                 qc = elem
    155                 elem = rb_group.iden(num_qubits)
--> 156                 elem = elem.from_circuit(qc)
    157             if (isinstance(elem, qiskit.quantum_info.operators.symplectic.clifford.Clifford)
    158                     and group_gates_type == 0) or (isinstance(elem, CNOTDihedral)

~/miniconda3/envs/my-env/lib/python3.7/site-packages/qiskit/quantum_info/operators/symplectic/clifford.py in from_circuit(circuit)
    386         # Initialize an identity Clifford
    387         clifford = Clifford(np.eye(2 * circuit.num_qubits), validate=False)
--> 388         _append_circuit(clifford, circuit)
    389         return clifford
    390 

~/miniconda3/envs/my-env/lib/python3.7/site-packages/qiskit/quantum_info/operators/symplectic/clifford_circuits.py in _append_circuit(clifford, circuit, qargs)
     97         # Get the integer position of the flat register
     98         new_qubits = [qargs[tup.index] for tup in qregs]
---> 99         _append_circuit(clifford, instr, new_qubits)
    100     return clifford
    101 

~/miniconda3/envs/my-env/lib/python3.7/site-packages/qiskit/quantum_info/operators/symplectic/clifford_circuits.py in _append_circuit(clifford, circuit, qargs)
     86     # are a single qubit Clifford gate rather than raise an exception.
     87     if gate.definition is None:
---> 88         raise QiskitError('Cannot apply Instruction: {}'.format(gate.name))
     89     if not isinstance(gate.definition, QuantumCircuit):
     90         raise QiskitError('{} instruction definition is {}; expected QuantumCircuit'.format(
QiskitError: 'Cannot apply Instruction: custom_swap'

Steps to reproduce the problem

import numpy as np
import qiskit
from qiskit import pulse
from qiskit.ignis.verification import randomized_benchmarking as rb
custom_swap = qiskit.circuit.Gate("custom_swap", 2, [])
with pulse.build(name='custom') as my_schedule:
    pulse.play(pulse.library.Gaussian(duration=64, amp=0.2, sigma=8), pulse.DriveChannel(0))
qc_swap = qiskit.QuantumCircuit(2)
qc_swap.append(custom_swap, [0, 1])
qc_swap.add_calibration(custom_swap, [0, 1], my_schedule)
rb_circs, xdata, circuits_interleaved = rb.randomized_benchmarking_seq(length_vector=np.arange(1, 200, 20), nseeds=5, rb_pattern=[[0, 1]], interleaved_elem=[qc_swap])

What is the expected behavior?

It doesn't fail.

Suggested solutions

Not sure. Ideally there would be a way to both denote that the custom gate is clifford, while also preserving our own pulse-level calibration for it.

In a previous version of qiskit-ignis, we could pass in something like interleaved_gates = [['swap 0 1']] instead of interleaved_elem. Then we could hack around the resultant circuits to manually insert the pulse gates. But hopefully there is a more elegant fix.

ShellyGarion commented 3 years ago

@singular-value - thank you very much for reporting this. I think that this bug has just been fixed when PR #548 has been merged. Could you please check this again with the new ignis master?

singular-value commented 3 years ago

Cool—will do.

ShellyGarion commented 3 years ago

Seems that PR #548 fixed this.