Source code for cirq.ops.gate_features

# Copyright 2018 The Cirq Developers## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## https://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License."""Marker classes for indicating which additional features gates support.For example: some gates are reversible, some have known matrices, etc."""fromtypingimportAny,Dict,Optional,Sequence,Tuple,Iterable,TypeVarimportstringimportnumpyasnpfromcirqimportabcfromcirq.opsimportop_treefromcirq.opsimportraw_typesfromcirq.studyimportParamResolver

[docs]classInterchangeableQubitsGate(metaclass=abc.ABCMeta):"""Indicates operations should be equal under some qubit permutations."""

[docs]defqubit_index_to_equivalence_group_key(self,index:int)->int:"""Returns a key that differs between non-interchangeable qubits."""return0

[docs]classReversibleEffect(metaclass=abc.ABCMeta):"""A gate whose effect can be undone in a known way."""

[docs]@abc.abstractmethoddefinverse(self)->'ReversibleEffect':"""Returns a gate with an exactly opposite effect."""

[docs]@abc.abstractmethoddefextrapolate_effect(self:TSelf_ExtrapolatableEffect,factor:float)->TSelf_ExtrapolatableEffect:"""Augments, diminishes, or reverses the effect of the receiving gate. Args: factor: The amount to scale the gate's effect by. Returns: A gate equivalent to applying the receiving gate 'factor' times. """

def__pow__(self:TSelf_ExtrapolatableEffect,power:float)->TSelf_ExtrapolatableEffect:"""Extrapolates the effect of the gate. Note that there are cases where (G**a)**b != G**(a*b). For example, start with a 90 degree rotation then cube it then raise it to a non-integer power such as 3/2. Assuming that rotations are always normalized into the range (-180, 180], note that: ((rot 90)**3)**1.5 = (rot 270)**1.5 = (rot -90)**1.5 = rot -135 but (rot 90)**(3*1.5) = (rot 90)**4.5 = rot 405 = rot 35 Because normalization discards the winding number. Args: power: The extrapolation factor. Returns: A gate with the extrapolated effect. """returnself.extrapolate_effect(power)

[docs]classCompositeGate(metaclass=abc.ABCMeta):"""A gate with a known decomposition into simpler gates."""

[docs]@abc.abstractmethoddefdefault_decompose(self,qubits:Sequence[raw_types.QubitId])->op_tree.OP_TREE:"""Yields operations for performing this gate on the given qubits. Args: qubits: The qubits the gate should be applied to. """

[docs]classKnownMatrix(metaclass=abc.ABCMeta):"""An effect that can be described by a matrix."""

[docs]@abc.abstractmethoddefmatrix(self)->np.ndarray:"""The unitary matrix of the gate/operation. The matrix order is implicit for both gates and operations. For a gate, the matrix must be in order with respect to the list of qubits that the gate is applied to. For an operation, the order must be with respect to its qubits attribute. The qubit-to-amplitude order mapping matches the ordering of numpy.kron(A, B), where A is a qubit earlier in the list than the qubit B. For example, when applying a CNOT gate the control qubit goes first and so the CNOT gate's matrix is: 1 _ _ _ _ 1 _ _ _ _ _ 1 _ _ 1 _ """

classTextDiagramInfoArgs:""" Attributes: known_qubits: The qubits the gate is being applied to. None means this information is not known by the caller. known_qubit_count: The number of qubits the gate is being applied to None means this information is not known by the caller. use_unicode_characters: If true, the wire symbols are permitted to include unicode characters (as long as they work well in fixed width fonts). If false, use only ascii characters. ASCII is preferred in cases where UTF8 support is done poorly, or where the fixed-width font being used to show the diagrams does not properly handle unicode characters. precision: The number of digits after the decimal to show for numbers in the text diagram. None means use full precision. """UNINFORMED_DEFAULT=None# type: TextDiagramInfoArgsdef__init__(self,known_qubits:Optional[Tuple[raw_types.QubitId,...]],known_qubit_count:Optional[int],use_unicode_characters:bool,precision:Optional[int])->None:self.known_qubits=known_qubitsself.known_qubit_count=known_qubit_countself.use_unicode_characters=use_unicode_charactersself.precision=precisionTextDiagramInfoArgs.UNINFORMED_DEFAULT=TextDiagramInfoArgs(known_qubits=None,known_qubit_count=None,use_unicode_characters=True,precision=3)classTextDiagramInfo:def__init__(self,wire_symbols:Tuple[str,...],exponent:Any=1)->None:""" Args: wire_symbols: The symbols that should be shown on the qubits affected by this operation. Must match the number of qubits that the operation is applied to. exponent: An optional convenience value that will be appended onto an operation's final gate symbol with a caret in front (unless it's equal to 1). For example, the square root of X gate has a text diagram exponent of 0.5 and symbol of 'X' so it is drawn as 'X^0.5'. """self.wire_symbols=wire_symbolsself.exponent=exponentdef_eq_tuple(self):returnTextDiagramInfo,self.wire_symbols,self.exponentdef__eq__(self,other):ifnotisinstance(other,type(self)):returnNotImplementedreturnself._eq_tuple()==other._eq_tuple()def__ne__(self,other):returnnotself==otherdef__hash__(self):returnhash(self._eq_tuple())def__repr__(self):return'TextDiagramInfo(wire_symbols={!r}, exponent={!r})'.format(self.wire_symbols,self.exponent)

[docs]classTextDiagrammable(metaclass=abc.ABCMeta):"""A thing which can be printed in a text diagram."""

[docs]@abc.abstractmethoddeftext_diagram_info(self,args:TextDiagramInfoArgs)->TextDiagramInfo:"""Describes how to draw something in a text diagram. Args: args: A TextDiagramInfoArgs instance encapsulating various pieces of information (e.g. how many qubits are we being applied to) as well as user options (e.g. whether to avoid unicode characters). Returns: A TextDiagramInfo instance describing what to print. """

[docs]classPhaseableEffect(metaclass=abc.ABCMeta):"""An effect that can be phased around the Z axis of target qubits."""

[docs]@abc.abstractmethoddefphase_by(self:TSelf_PhaseableEffect,phase_turns:float,qubit_index:int)->TSelf_PhaseableEffect:"""Returns a phased version of the effect. For example, an X gate phased by 90 degrees would be a Y gate. Args: phase_turns: The amount to phase the gate, in fractions of a whole turn. qubit_index: The index of the target qubit the phasing applies to. Returns: The phased gate or operation. """

[docs]classBoundedEffect(metaclass=abc.ABCMeta):"""An effect with known bounds on how easy it is to detect. Used when deciding whether or not an operation is negligible. For example, the trace distance between the states before and after a Z**0.00000001 operation is very close to 0, so it would typically be considered negligible. """

[docs]@abc.abstractmethoddeftrace_distance_bound(self)->float:"""A maximum on the trace distance between this effect's input/output. Generally this method is used when deciding whether to keep gates, so only the behavior near 0 is important. Approximations that overestimate the maximum trace distance are permitted. Even ones that exceed 1. Underestimates are not permitted. """

[docs]classSingleQubitGate(raw_types.Gate,metaclass=abc.ABCMeta):"""A gate that must be applied to exactly one qubit."""

[docs]defon_each(self,targets:Iterable[raw_types.QubitId])->op_tree.OP_TREE:"""Returns a list of operations apply this gate to each of the targets. Args: targets: The qubits to apply this gate to. Returns: Operations applying this gate to the target qubits. """return[self.on(target)fortargetintargets]

[docs]classTwoQubitGate(raw_types.Gate,metaclass=abc.ABCMeta):"""A gate that must be applied to exactly two qubits."""

[docs]defvalidate_args(self,qubits):iflen(qubits)!=2:raiseValueError('Two-qubit gate not applied to two qubits: {}({})'.format(self,qubits))

classThreeQubitGate(raw_types.Gate,metaclass=abc.ABCMeta):"""A gate that must be applied to exactly three qubits."""defvalidate_args(self,qubits):iflen(qubits)!=3:raiseValueError('Three-qubit gate not applied to three qubits: {}({})'.format(self,qubits))TSelf_ParameterizableEffect=TypeVar('TSelf_ParameterizableEffect',bound='ParameterizableEffect')

[docs]classParameterizableEffect(metaclass=abc.ABCMeta):"""An effect that can be parameterized by Symbols."""

[docs]@abc.abstractmethoddefis_parameterized(self)->bool:"""Whether the effect is parameterized. Returns True if the gate has any unresolved Symbols and False otherwise. """

[docs]@abc.abstractmethoddefwith_parameters_resolved_by(self:TSelf_ParameterizableEffect,param_resolver:ParamResolver)->TSelf_ParameterizableEffect:"""Resolve the parameters in the effect. Returns a gate or operation of the same type, but with all Symbols replaced with floats according to the given ParamResolver. """

classQasmOutputArgs(string.Formatter):""" Attributes: precision: The number of digits after the decimal to show for numbers in the text diagram. version: The QASM version to output. QasmConvertableGate/Operation may return different text depending on version. qubit_id_map: A dictionary mapping qubits to qreg QASM identifiers. meas_key_id_map: A dictionary mapping measurement keys to creg QASM identifiers. """def__init__(self,precision:int=10,version:str='2.0',qubit_id_map:Dict[raw_types.QubitId,str]=None,meas_key_id_map:Dict[str,str]=None,)->None:self.precision=precisionself.version=versionself.qubit_id_map={}ifqubit_id_mapisNoneelsequbit_id_mapself.meas_key_id_map=({}ifmeas_key_id_mapisNoneelsemeas_key_id_map)defformat_field(self,value:Any,spec:str)->str:"""Method of string.Formatter that specifies the output of format()."""ifisinstance(value,float):value=round(value,self.precision)ifspec=='half_turns':value='pi*{}'.format(value)ifvalue!=0else'0'spec=''elifisinstance(value,raw_types.QubitId):value=self.qubit_id_map[value]elifisinstance(value,str)andspec=='meas':value=self.meas_key_id_map[value]spec=''returnsuper().format_field(value,spec)defvalidate_version(self,*supported_versions:str)->None:ifself.versionnotinsupported_versions:raiseValueError('QASM version {} output is not supported.'.format(self.version))

[docs]classQasmConvertableGate(metaclass=abc.ABCMeta):"""A gate that knows its representation in QASM."""

[docs]@abc.abstractmethoddefknown_qasm_output(self,qubits:Tuple[raw_types.QubitId,...],args:QasmOutputArgs)->Optional[str]:"""Returns lines of QASM output representing the gate on the given qubits or None if a simple conversion is not possible. """

[docs]classQasmConvertableOperation(metaclass=abc.ABCMeta):"""An operation that knows its representation in QASM."""

[docs]@abc.abstractmethoddefknown_qasm_output(self,args:QasmOutputArgs)->Optional[str]:"""Returns lines of QASM output representing the operation or None if a simple conversion is not possible."""