-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
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:
-
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. -
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. -
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
. -
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).