This developer document explains what is expected of a gate or operation exposed by Cirq. In particular, we have a stricter standard than what is required of users of the library.
For a user of Cirq, specifying either a
_unitary_ method or a
method is sufficient to get a gate working.
Most other protocols will infer what they need from these two methods.
A gate specified in this way will not be particularly performant, but it will
For internal gates, we also want high performance, and so we require several
other protocol methods to be implemented.
In general, the source of truth for what has to be implemented is enforced
This method verifies the following properties:
The class has a
__repr__method that produces a python expression that evaluates to an object equal to the original value. The expression assumes that
numpy as np, and
pandas as pdhave been imported.
If the class is unitary, it specifies a
The classes various protocols agree with each other. For example, the decomposition that
_decompose_produces should have the same effect as the unitary produced by
_unitary_or the transformation applied by
If the gate is exposed by
cirq/__init__.py or another public module, other
tests will notice it and verify that it is serializable.
See the serialization guidelines.
There are several other informal constraints:
Large gates should have a
_decompose_method that returns a composition of smaller gates. This allows optimizers and other tools that cannot understand the gate to break it into pieces that they do understand.
Gates should specify a good
_circuit_diagram_info_method. In some cases the default behavior of using
Gates should have a good
__repr__is cumbersome, gates should specify a
_repr_pretty_method. This method will be used preferentially by Jupyter notebooks, ipython, etc.
Gates should specify an
_apply_unitary_method. This is not necessary for single or two qubit gates, but it is a huge performance difference for larger gates.
Gates that take parameters (e.g. a rotation angle) should generally allow for those parameters to be sympy objects instead of floats, and implement corresponding
Prefer creating a
Gateover creating an
Operation. In some cases it makes sense to only have an
Operation, but these cases are generally surprising to users. If you have to use an operation, try to have the
.gateproperty of the operation can return something useful instead of
Consider adding interop methods like
_qasm_. These methods will fallback to using things like
_decompose_, but the output is usually much better when specialized.