Status | Implemented |
---|---|
RFC # | 0009 |
Authors | Jake Lishman (jake.lishman@ibm.com) |
Deprecates | None |
Submitted | 2022-05-31 |
Updated | 2023-05-10 |
Currently, only subclasses of Instruction
can be put on QuantumCircuit
, but
this interface has become unwieldy and includes too many methods and attributes
for general-purpose objects. We propose to put a new interface in place that is
far more stripped down, and to remove transpilation-specific methods from the
objects themselves, and move them to make them transpiler behaviour. We propose
that this new interface will be called Operation
.
-
Instruction
as a complete type has too many unrelated attributes and methods from the base interface, which not all "quantum operations" can reasonably fulfil. For example,definition
(which is already circumvented in several cases),duration
andunit
(which only have meaning after transpilation), andassemble
(which supposes that the object is immediately executable).Some of these are fine after transpilation, but are too restrictive for
Instruction
to be the only input type for the transpiler. -
Instruction
is defined as part ofqiskit.circuit
, which poses cyclic dependency issues for some lower-level objects (e.g. those based inquantum_info
types). -
Having a simpler, abstract interface (
Operation
) allows us to break the cyclical dependencies (it can be the lowest part of Terra), make more objects suitable for being "transpiler input", and reduce the memory/implementation complexity for those objects that can be. -
Instruction
need not be replaced by this; we still want something to represent "a transpiled operation". This is a greater restriction than "an operation that can be transpiled", soInstruction
can (and will) also implementOperation
. -
Defining an immutable interface lets us re-use the same objects more during transpilation, which will save a lot of memory. For example, we will not need to repeatedly copy
definition
circuits just in case the parameters are mutated by some later pass, and we will not need to copy in case thecondition
of the instruction is modified.
-
Users will have more freedom to work with a variety of objects (such as
quantum_info.Clifford
) and store them directly onto circuits, letting them interact again with the rich objects. -
Developers gain a backwards-compatible way to reduce the dependence on some of the memory-hungriest components of
Instruction
. -
Transpiler pass writers can use the rich methods of the objects without the additional memory usage (and type-unsafety) of wrapping each thing it its own
Instruction
subclass. -
Transpiler pass writes will be able to more easily write synthesis methods that use more information from the transpiler.
-
Researchers will be able to more easily "plug in" their own synthesis methods for higher-order objects at transpilation run time, without needing to modify the objects themselves, or mess with pass managers.
We propose an abstract interface that defines a circuit operation that can be
input to the transpiler. We call this Operation
.
The propsed attributes on Operation
are:
-
name
: the name identifier, to provide a link between objects andTarget
, the API that backends use to describe what operations they support. -
num_qubits
: the logical number of qubits this instruction operates on. Synthesis methods may use more qubits than this to implement the operation, but this is the number of "data" qubits. This is to enable quantum resource tracking and type safety. -
parameter_spec
: number and types of the parameters that need to be supplied to this object at run-time (notably not the parameters themselves). This is to enable classical resource tracking and type safety. -
state
: an opaque object that contains the full state of the object, which can be passed to some as-yet-undefined method to reconstruct the object. This is for serialisation.
Some things Operation
should not do:
- force objects to make decisions about their synthesis
- force all objects to be stateful (i.e. there should be a valid implementation
of
HGate
that is a singleton) - require objects to construct / be able to construct a
QuantumCircuit
through any of the abstract methods
These things mean that the following properties or methods should not be part
of Operation
:
-
condition
: this should be part of separate classical control flow, and its stateful nature is one of the current reasons for a lot of copying ofInstruction
instances. -
duration
andunit
: these are properties of the output of the transpiler, and should also depend on the particular qubits in use. This likely wants to become part ofCircuitInstruction
(see Qiskit/qiskit#8093). -
assemble
: this is particular to the conversion to theQobj
type, which may not exist in the long-term, but even in the short-term, this is conversion behaviour and the interfaces should be well-enough defined such that this does not need to be specialised. -
definition
or_define
: this ties synthesis to the object, causing us to carry around extra circuits (and frequently copy them).
It is in theory possible to maintain the status quo, and have Instruction
be
the definition of the transpiler-input interface. Some things (such as
pluggable, controllable synthesis passes) are still possible to do in this
structure. The memory problems are (at best) exacerbated by Instruction
,
though, and it is difficult to fix this will maintaining backwards
compatibility. This also would do nothing to address the general design
problems with operations currently needing to define their own synthesis.
The memory usage is already showing problematic strain for scalability. See:
Having all operations have to define their own definition
causes cyclic
dependency and hierarchy issues: quantum_info
classes generally should not
need to care about the circuit model, since they are using a different
formalism. This also means that objects with more than one synthesis method
have to define a "preferred" synthesis method. This is an issue for things like
the multi-controlled X.
-
At this point, the exact requirements for
Operation
are not fully finalized. This RFC will not be ready for a complete implementation until they are. -
Will classical operations also be
Operation
, or will we do something different with them? -
What information about necessary qubits should we expose, bearing in mind that the "number of qubits needed" may be dependent on the synthesis method?
This has generally come up as part of two additional strands of work:
- richer, more controllable synthesis on complex objects
- separation of concerns between "operations" and "operands" in
QuantumCircuit
Defining Operation
completely ties a lot into both of these.
For the richer synthesis to be a powerful, (relatively) easy-to-use tool, we
need to make sure that the transpiler has all the information it needs within
the Operation
class to do its job while treating the objects as otherwise
entirely opaque. The more the transpiler needs to know about an object, the
more onerous and memory-hungry it is for general-purpose objects to implement
the interface, which is a problem for scaling.
The separation of concerns between the operations, operands, and circuit-level
properties of given instructions is inherently tied in, because some components
of Instruction
can be made "operands", rather than needing to be tied to the
instance. This is immediately params
as part of Instruction
.