This page describes some of the best practices when using the Cirq library. Following these guidelines will help you write code that is more performant and less likely to break from version to version. Many of these rules apply to other python libraries as well.
Use top-level constructs
The Cirq library is designed so that important user-facing classes and objects are exposed at the package level. Avoid referencing module names within Cirq.
For instance, use cirq.X
and not cirq.ops.X
. The second version will
break if we rename modules or move classes around from version to version.
Do not use private member variables of classes
Any member of a class that is prefixed with an underscore is, by convention, a
private variable and should not be used outside of this class. For instance,
cirq.XPowGate._dimension
should not be accessed or modified, since it is a
private member of that class. Using or modifying these values could result in
unexpected behavior or in broken code.
Do not mutate "immutable" classes
While python's flexibility allows developers to modify just about anything, it is bad practice to modify classes that are designed to be immutable. Doing so can violate assumptions made in other parts of the library.
In particular, attributes of cirq.Gate
, cirq.Operation
, cirq.Moment
, and
cirq.ParamResolver
should not be modified after creation. If these objects
need to be modified, a new object should be created instead.
Violating this principle could cause problems in other parts of the code. For
instance, changing the qubits of an cirq.Operation
could cause a cirq.Moment
that contains this Operation to have two Operations with the same qubits (which
is not allowed).
Note that Circuit
objects can be modified, but FrozenCircuit
objects cannot.
Be mindful of exponential scaling
Many algorithms and procedures in quantum computing scale in an exponential pattern. Cirq is designed for the noisy intermediate-scale quantum computing (NISQ) regime. Creating circuits with hundreds or thousands of qubits may surpass the capabilities of this library.
Even with smaller numbers of qubits, simulation and other tasks can very quickly consume resources and time. The difference between a one second and an hour's computation can be as few as ten qubits.
What you see is what you get
Cirq tries to be as true to the specified circuits as possible, especially with respect to hardware execution. Cirq highly discourages any hidden automatic decomposition, compilation, or other modification of a circuit that is unknown to the user. Any modification or transformation to the circuit should be initiated by the user of the library.
This philosophy is important for many use cases. For instance, certain benchmarking algorithms rely on the fact that gate sequences will not be optimized, even if the circuit is nominally inefficient.
Of course, Cirq provides routines and functions for compilation and transformation of circuits. Users can and should call these routines. However, Cirq and resulting hardware integrations should not modify the circuits without the user's "permission".
Other style and performance guidelines
- Use
cirq.CircuitOperation
to more compactly define large, repeated circuits. This can save space and time for analysis of larger circuits. - For hardware execution of multiple circuits, prefer using
run_sweep
to run variants of circuits. When not possible, try usingrun_batch
. Using these methods gives the hardware service the most opportunity to optimize the execution of circuits and can result in much faster execution. Read more details on the Parameter Sweeps page. - Consider defining and allocating qubits at the beginning of your code or function, then applying gates and circuits to those qubits. While not required, this style can produce cleaner code.