![]() |
A helper class for implementing reversible classical arithmetic.
Inherits From: Operation
Used in the notebooks
Used in the tutorials |
---|
Child classes must override the registers
, with_registers
, and apply
methods.
This class handles the details of ensuring that the scaling of implementing
the operation is O(2^n) instead of O(4^n) where n is the number of qubits
being acted on, by implementing an _apply_unitary_
function in terms of
the registers and the apply function of the child class. It also handles the
boilerplate of implementing the qubits
and with_qubits
methods.
Examples:
<pre class="devsite-click-to-copy prettyprint lang-py">
<code class="devsite-terminal" data-terminal-prefix=">>>">class Add(cirq.ArithmeticOperation):</code>
<code class="devsite-terminal" data-terminal-prefix="..."> def __init__(self, target_register, input_register):</code>
<code class="devsite-terminal" data-terminal-prefix="..."> self.target_register = target_register</code>
<code class="devsite-terminal" data-terminal-prefix="..."> self.input_register = input_register</code>
<code class="devsite-terminal" data-terminal-prefix="..."></code>
<code class="devsite-terminal" data-terminal-prefix="..."> def registers(self):</code>
<code class="devsite-terminal" data-terminal-prefix="..."> return self.target_register, self.input_register</code>
<code class="devsite-terminal" data-terminal-prefix="..."></code>
<code class="devsite-terminal" data-terminal-prefix="..."> def with_registers(self, *new_registers):</code>
<code class="devsite-terminal" data-terminal-prefix="..."> return Add(*new_registers)</code>
<code class="devsite-terminal" data-terminal-prefix="..."></code>
<code class="devsite-terminal" data-terminal-prefix="..."> def apply(self, target_value, input_value):</code>
<code class="devsite-terminal" data-terminal-prefix="..."> return target_value + input_value</code>
<code class="devsite-terminal" data-terminal-prefix=">>>">cirq.unitary(</code>
<code class="devsite-terminal" data-terminal-prefix="..."> Add(target_register=cirq.LineQubit.range(2),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> input_register=1)</code>
<code class="devsite-terminal" data-terminal-prefix="...">).astype(np.int32)</code>
<code class="no-select nocode"> array([[0, 0, 0, 1],</code>
<code class="no-select nocode"> [1, 0, 0, 0],</code>
<code class="no-select nocode"> [0, 1, 0, 0],</code>
<code class="no-select nocode"> [0, 0, 1, 0]], dtype=int32)</code>
<code class="devsite-terminal" data-terminal-prefix=">>>">c = cirq.Circuit(</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.X(cirq.LineQubit(3)),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.X(cirq.LineQubit(2)),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.X(cirq.LineQubit(6)),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.measure(*cirq.LineQubit.range(4, 8), key='before:in'),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.measure(*cirq.LineQubit.range(4), key='before:out'),</code>
<code class="devsite-terminal" data-terminal-prefix="..."></code>
<code class="devsite-terminal" data-terminal-prefix="..."> Add(target_register=cirq.LineQubit.range(4),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> input_register=cirq.LineQubit.range(4, 8)),</code>
<code class="devsite-terminal" data-terminal-prefix="..."></code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.measure(*cirq.LineQubit.range(4, 8), key='after:in'),</code>
<code class="devsite-terminal" data-terminal-prefix="..."> cirq.measure(*cirq.LineQubit.range(4), key='after:out'),</code>
<code class="devsite-terminal" data-terminal-prefix="...">)</code>
<code class="devsite-terminal" data-terminal-prefix=">>>">cirq.sample(c).data</code>
<code class="no-select nocode"> before:in before:out after:in after:out</code>
<code class="no-select nocode"> 0 2 3 2 5</code>
<code class="no-select nocode"> </code>
</pre>
Attributes | |
---|---|
classical_controls
|
The classical controls gating this operation. |
gate
|
|
qubits
|
|
tags
|
Returns a tuple of the operation's tags. |
untagged
|
Returns the underlying operation without any tags. |
Methods
apply
@abc.abstractmethod
apply( *register_values ) -> Union[int, Iterable[int]]
Returns the result of the operation operating on classical values.
For example, an addition takes two values (the target and the source), adds the source into the target, then returns the target and source as the new register values.
The apply
method is permitted to be sloppy in three ways:
- The
apply
method is permitted to return values that have more bits than the registers they will be stored into. The extra bits are simply dropped. For example, if the value 5 is returned for a 2 qubit register then 5 % 22 = 1 will be used instead. Negative values are also permitted. For example, for a 3 qubit register the value -2 becomes -2 % 23 = 6. - When the value of the last
k
registers is not changed by the operation, theapply
method is permitted to omit these values from the result. That is to say, when the length of the output is less than the length of the input, it is padded up to the intended length by copying from the same position in the input. - When only the first register's value changes, the
apply
method is permitted to return anint
instead of a sequence of ints.
The apply
method must be reversible. Otherwise the operation will
not be unitary, and incorrect behavior will result.
Examples:
A fully detailed adder:
def apply(self, target, offset):
return (target + offset) % 2**len(self.target_register), offset
The same adder, with less boilerplate due to the details being
handled by the ArithmeticOperation
class:
def apply(self, target, offset):
return target + offset
controlled_by
controlled_by(
*control_qubits,
control_values: Optional[Sequence[Union[int, Collection[int]]]] = None
) -> 'cirq.Operation'
Returns a controlled version of this operation. If no control_qubits are specified, returns self.
Args | |
---|---|
control_qubits
|
Qubits to control the operation by. Required. |
control_values
|
For which control qubit values to apply the
operation. A sequence of the same length as control_qubits
where each entry is an integer (or set of integers)
corresponding to the qubit value (or set of possible values)
where that control is enabled. When all controls are enabled,
the operation is applied. If unspecified, control values
default to 1.
|
registers
@abc.abstractmethod
registers() -> Sequence[Union[int, Sequence['cirq.Qid']]]
The data acted upon by the arithmetic operation.
Each register in the list can either be a classical constant (an int
),
or else a list of qubits/qudits (a List[cirq.Qid]
). Registers that
are set to a classical constant must not be mutated by the arithmetic
operation (their value must remain fixed when passed to apply
).
Registers are big endian. The first qubit is the most significant, the last qubit is the 1s qubit, the before last qubit is the 2s qubit, etc.
Returns | |
---|---|
A list of constants and qubit groups that the operation will act upon. |
transform_qubits
transform_qubits(
qubit_map: Union[Dict['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']]
) -> TSelf
Returns the same operation, but with different qubits.
Args | |
---|---|
qubit_map
|
A function or a dict mapping each current qubit into a desired new qubit. |
Returns | |
---|---|
The receiving operation but with qubits transformed by the given function. |
Raises | |
---|---|
TypeError
|
qubit_map was not a function or dict mapping qubits to qubits. |
validate_args
validate_args(
qubits: Sequence['cirq.Qid']
)
Raises an exception if the qubits
don't match this operation's qid
shape.
Call this method from a subclass's with_qubits
method.
Args | |
---|---|
qubits
|
The new qids for the operation. |
Raises | |
---|---|
ValueError
|
The operation had qids that don't match it's qid shape. |
with_classical_controls
with_classical_controls(
*conditions
) -> 'cirq.ClassicallyControlledOperation'
Returns a classically controlled version of this operation.
An operation that is classically controlled is executed iff all conditions evaluate to True. Currently the only condition type is a measurement key. A measurement key evaluates to True iff any qubit in the corresponding measurement operation evaluated to a non-zero value.
The classical control will hide any tags on the existing operation, since tags are considered a local attribute.
Args | |
---|---|
conditions
|
A list of measurement keys, strings that can be parsed into measurement keys, or sympy expressions where the free symbols are measurement key strings. |
Returns | |
---|---|
A ClassicallyControlledOperation wrapping the operation.
|
with_probability
with_probability(
probability: 'cirq.TParamVal'
) -> 'cirq.Operation'
with_qubits
with_qubits(
*new_qubits
) -> TSelf
Returns the same operation, but applied to different qubits.
Args | |
---|---|
new_qubits
|
The new qubits to apply the operation to. The order must
exactly match the order of qubits returned from the operation's
qubits property.
|
with_registers
@abc.abstractmethod
with_registers( *new_registers ) -> TSelf
Returns the same operation targeting different registers.
Args | |
---|---|
new_registers
|
The new values that should be returned by the
registers method.
|
Returns | |
---|---|
An instance of the same kind of operation, but acting on different registers. |
with_tags
with_tags(
*new_tags
) -> 'cirq.Operation'
Creates a new TaggedOperation, with this op and the specified tags.
This method can be used to attach meta-data to specific operations without affecting their functionality. The intended usage is to attach classes intended for this purpose or strings to mark operations for specific usage that will be recognized by consumers. Specific examples include ignoring this operation in optimization passes, hardware-specific functionality, or circuit diagram customizability.
Tags can be a list of any type of object that is useful to identify this operation as long as the type is hashable. If you wish the resulting operation to be eventually serialized into JSON, you should also restrict the operation to be JSON serializable.
Args | |
---|---|
new_tags
|
The tags to wrap this operation in. |
without_classical_controls
without_classical_controls() -> 'cirq.Operation'
Removes all classical controls from the operation.
This function removes all classical controls gating the operation. It acts recursively, so that all classical control wrappers are always removed from the current operation.
If there are no classical controls on the operation, it will return
self
.
Since tags are considered local, this will also remove any tags from
the operation (unless there are no classical controls on it). If a
TaggedOperation
is under all the classical control layers, that
TaggedOperation
will be returned from this function.
Returns | |
---|---|
The operation with all classical controls removed. |