Today, most quantum software is written at the gate level, performed by specifying the interconnection between qubits and quantum gates.
But as quantum computers become more powerful and complex – reaching 100’s or 1000’s of qubits very soon – it will become nearly impossible to write valuable and sophisticated quantum code this way.
Here are seven examples of why this is the case:
- Reusing auxiliary qubits. Auxiliary qubits (sometimes called ancillary qubits or ancilla) often need to be allocated and de-allocated. But once an auxiliary qubit has been used, the designer can reuse it down the circuit. This reuse is either to make specific calculations more efficient or to ensure that quantum circuits are reversible. Keeping track of which qubits are auxiliary and can be reused becomes increasingly difficult as the number of qubits increases.
- Un-computation strategy. Un-Computation is useful in quantum software when trying to free auxiliary qubits for future use or to disentangle some of the qubits to reduce noise. We can also uncompute intermediate results when the result is no longer needed in the algorithm. In many cases, the question of when and if a function should be uncomputed is complex. For example, in quantum arithmetic, we can uncompute the intermediate results in many different ways, trading off the qubits needed and the circuit depth.
- Multiple function implementations. The user may wish to perform some function, e.g. a quantum adder, an mcmt gate, a state preparation, etc. These functions have different implementations, trading off complexity, accuracy, the number of qubits, and the resources needed. As a simple example, mcmt gates can be implemented in many ways by choosing the number of available auxiliary qubits. Choosing which function instance to use at each stage is a complex problem that cannot be done manually for large circuits.
- Organizing the Hamiltonian terms in the right order. In some cases, we encode Hamiltonians of a certain system into the quantum circuit. This is common for example in the QAOA framework. A common approach is Trotterization, where the Hamiltonian is broken into local terms which are placed individually. Placing these different terms has many different options. Naively, a Hamiltonian with n local terms has n! possible placement options. Placing these local terms manually will give a much longer (larger circuit depth) than necessary.
- Trading off depth, number of qubits, and accuracy at the circuit level. We have many design choices, some of which were discussed above. We are faced with global constraints on the circuit – number of available qubits, total coherence time, gate fidelities, hardware connectivity, native gates, etc. We also wish to optimize the circuits under the constraints, for example, achieve maximal accuracy, minimize the number of T gates, etc. Optimizing under the given constraints at the circuit level requires knowledge of all the different design possibilities, as well as large computational power to go over the countless design choices.
- Optimizing functions for specific hardware. There are many different hardware implementations of quantum computers. They differ in the number of qubits, their noise characteristics, the type of native gates, the connectivity between qubits, and much more. As a result, code that is optimized for one hardware may be far from optimal for another. The ability to understand the hardware characteristics and define them as constraints that need to be satisfied is particularly important during this market period when the pace of innovation is fast and the number of different architectures is large.
- Analyzing the circuit at the functional level. When one wishes to debug a circuit or modify a circuit created by someone else, it is often good to start at a high level. But how can you start at a high level when working at the gate level? Using a classical analogy, it is much easier to dive from Python code to assembly language than try to deduce the Python intent by looking at the assembly language code.
This evolution mirrors what we have seen in other industries. Very few people write assembly-language code for high-end CPUs, and even fewer build manual ‘netlist’ files for electronic circuits. The process of climbing up the abstraction stack is common and probably unavoidable in many cases, including quantum computing.
So the choice is yours: continue to work at the gate level, or start adopting the platforms and skills that allow you to code that for larger computers as well.