qiskit
qiskit copied to clipboard
Supporting native instructions
Currently the transpiler consults backend.configuration().coupling_map
and backend.configuration().basis_gates
in order to map a circuit to a backend. The assumption is that all the 1-qubit gates in the basis_gates are present on all qubits, and all the 2-qubit gates in the basis_gates are present on all edges of the coupling_map.
This has some limitations, namely that we cannot support a heterogeneous gateset (different gates on different qubits). We should move towards a model where the backend is free to tune up any gate on any qubit(s) and report it, and the transpiler can optimize over those instructions.
To do this, we need:
- Provider v2 support:
-
[x] Provider to parse the datastructure that the backend reports and present them as a list of
Instruction
s [*] to qiskit. That is, each entry has the Gate plus qubits it acts on. Same for Measure/Reset, etc. This is basically a list of everything that is calibrated on the device. -
[x] Note a: The keys to
InstructionScheduleMap
should work with the elements of this list, that isInstructionScheduleMap
says what the pulse sequence is for each of those calibrated gates. If one of these is not reported for some reason, a meaningful error should be raised saying that this gate is in fact calibrated, but the pulse def is not available. -
[x] Note b: We could have a scenario where we calibrate the same gate in two different ways, say a slow CNOT and a fast CNOT. Those should show up as two different entries in the list of Instructions, and have two separate entries in
InstructionScheduleMap
. -
[x] Note c: There are places, e.g. in the current backend properties, where defining this
Instruction
really helps. For example gate_length is currently keyed on (name, qubits), and this precludes backends from making gate_length depend on the parameter (e.g. one duration for rx(pi/2) and another for rx(pi/4)). Again here we need this datastructure to be keyed onInstruction
, as every calibrated instruction on the backend has its own length.
- The stages of the compiler that work with physical circuits should be modified to work with these physical
Instruction
s.
-
[ ] The first and most important are the basis translators. These currently assume universal gates on all qubits, but should be modified to know which Gate works on which qubit.
-
[ ] There are a lot of places where the compiler works with gate names, and these should be changed to work with Instruction or Gate objects. The reason is the backend may tune up any unitary, and we can't assume these exist in the library. So while we can give them a name, it should not be germane to the compilation process as the unitary + qubits is all you need to know about the gate.
-
[ ] A future step could be modifying layout & routing passes so they take into account the native gates on each of the physical qubits and try to steer the virtual gates onto the ones that will later be basis-translated with the least cost.
[*] Some suggestions on terminology and classes:
- Instruction: this should be equivalent to a line of QASM or one entry in
circuit.data
(i.e. the gate plus its params plus its operands). (note: Currently it is used as such ininstruction_schedule_map
, but not in theInstruction
class --- instead we use a tuple for this) - Operation: A quantum channel that acts on qubit(s) (reset, measure, gate, or a combination thereof)
- Directive: Something that is a hint to compiler but does not actually execute on the processor
- CircuitElement: everything that can go in the circuit (combination of Operation and Directive and possibly future classical code?)
- Gate: a unitary (
X
is a gate.RZ(theta)
is a (parameterized) gate.RZ(0.1) q0
is an instruction).
https://github.com/Qiskit/qiskit-terra/pull/5885 is where I'm collecting work on the new version of the backend interface. As part of that it changes how we represent gates, we should make sure that the requirements here are reflected in that.
@ajavadia is there anything more on this issue now that we have the Target
class? There is still work on updating all the passes to work with the target (see #7113) and then follow up issues on expanding the transpiler to support more types of instructions (see #7797 and #7812) but I'm not sure how you were thinking of scoping this issue.
I checked "Note a", "Note b" and "Note c" above. That is correct since Backend V2 was merged right?
Can we also check off the next box about basis translators now?
I think @jakelishman mentioned adding a CircuitInstruction
to replace the tuple of (operation, qubits, clbits)
. I think a bunch of bullet points in this issue are about that. Do we have a separate issue tracking this?
And the box about not using gate names in the transpiler would be good to track somewhere as well. i.e. can we have an example where a FakeBackend tunes a gate that it calls "foo". In Qiskit we don't know what "foo" is but the backend also provides the gate matrix definition. So Qiskit is still able to translate to "foo" using translation_method='synthesis'
. This would be quite useful to not explode the standard gate library in Qiskit with all the gate names in the world.
I'm good with deferring the last bullet point to later as that is a bit complicated.
I'm going to close this as the bulk of this is done. I'll open up a follow up issue to track the last piece which is supporting instruction specialization with tuned fixed angle variants through the basis translator which is the only thing preventing the transpiler from selecting a fixed angle variant if it's a valid output. Or alternatively if both a free parameter and fixed parameter are both available in the target selecting the more specialized version when appropriate.