The process of developing quantum software often begins with testing against a QVM. Eventually, you'll come to a point where you're ready to run your programs against a real QPU.
This guide will focus specifically on the differences between QPUs and QVMs when targeting them via the Forest SDK.
Your pyQuil code will more than likely include a call to
get_qc(). For instance, if you're targeting a 2-qubit QVM, the call might look something like:
qc = get_qc("2q-qvm")
From a pyQuil perspective, changing from a QVM to a QPU (and vice versa) is usually as simple as changing the string within the
get_qc() function call. For example, to target the
Aspen-9 QPU, you can change the line above to:
qc = get_qc("Aspen-9")
In both cases above, the
qc object will be an instance of a pyQuil
QuantumComputer is comprised of:
A quantum abstract machine, accessed via
An abstract compiler, accessed via
If your code accesses either
qc.compiler, it's important to understand that the
AbstractCompiler implementations differ between QPU and QVM use cases.
For instance, if your code targets a QVM,
qc.qam will be a
QVM instance, and
qc.compiler will be a
QVMCompiler instance. However, if your code targets a QPU,
qc.qam will be a
QPU instance, and
qc.compiler will be a
While these subcomponents follow common interfaces, namely
AbstractCompiler, there may be some methods or properties that are accessible on the QPU-based instances but not on the QVM-based instances, and vice versa.
You can make your code robust by performing type checks on
qc.compiler. For example:
from pyquil import get_qcfrom pyquil.api import QPUCompilerqc = get_qc("Aspen-9") # or "2q-qvm"if isinstance(qc.compiler, QPUCompiler):# Working with a QPU - refresh calibrationsqc.compiler.get_calibration_program(force_refresh=True)
Without the type check on line 6, your code might run well when targeting a QPU but raise an error when changing to a QVM (because
get_calibration_program() is not available on
QVMCompiler). With the type check in place, your code will run seamlessly between both cases.
While QVMs typically run in your current environment and therefore don't have special access requirements, QPUs are remote resources hosted by QCS. As such, a QPU will only be accessible to you during a reservation window. You must also have network access to the QPU, which is most easily obtained by using your provisioned JupyterLab IDE.
When moving from a QVM to a QPU, it's important to consider qubit topology. Qubit topology describes which qubits can be used together in quantum operations. For a QVM, this is a fully-connected graph — meaning any qubit can be used with any other qubit. This is not necessarily the case for a QPU, in which only certain qubits can be used together.
You can inspect a QPU's topology when making a QPU reservation on the QCS website, as shown below.
On a QPU, qubits and qubit pairs also have differing fidelities for certain operations. You can view this information by clicking
Device Calibration under a QPU when making a reservation, as shown above.
Assume your quantum program includes an operation on qubits 0 and 1. On a QVM, your program may run well, but what about on a particular QPU? What if these qubits are not connected in the desired QPU's topology? Or perhaps they are connected but have poor fidelity for the operation in question. To run your program on the desired QPU, you can take advantage of compiler rewiring.
Rewiring is a step that the Quil compiler will perform to select optimal qubits for you. The qubits selected will be based on a QPU's topology and calibration information. Rewiring will happen by default, if needed, but rewiring behavior can also be explicitly overridden using a compiler directive.
To learn more about rewiring, including how to override default behavior, see the pyQuil documentation on rewiring.
Active reset — enacted by using the Quil
RESET instruction at the beginning of a program — forces all qubits to their ground states. This is useful when running sequential programs against a QPU, as it reduces the time needed for qubits to return to their ground states between programs.
Active reset has no effect when running programs against a QVM, as a QVM will start with its qubits in their ground states regardless of active reset.
It may seem theoretically trivial to use active reset when targeting a QPU. However, its use can have side effects in practice, as active reset has its own associated fidelity (as seen in the figure under QPU Topology & Fidelities) — it's important to be aware of this when moving from a QVM to a QPU.