@@ -70,17 +70,28 @@ def _get_cirq_quregs(signature: Signature, qm: InteropQubitManager):
7070 return ret
7171
7272
73- class CirqGateAsBloqBase (GateWithRegisters , metaclass = abc .ABCMeta ):
74- """A Bloq wrapper around a `cirq.Gate`"""
73+ class CirqGateAsBloqBase (Bloq , metaclass = abc .ABCMeta ):
74+ """A base class to bootstrap a bloq from a `cirq.Gate`.
75+
76+ Bloq authors can inherit from this abstract class and override the `cirq_gate` property
77+ to get a bloq adapted from the cirq gate. Authors can continue to customize the bloq
78+ by overriding methods (like costs, string representations, ...).
79+
80+ Otherwise, this class fulfils the Bloq API by delegating to `cirq.Gate` methods.
81+
82+ This is the base class that provides the functionality for the `CirqGateAsBloq` adapter.
83+ The adapter lets you use any `cirq.Gate` as a bloq immediately (without defining a new class
84+ that inherits from `CirqGateAsBloqBase`), and is used as a fallback in the interoperability
85+ functionality.
86+ """
7587
7688 @property
7789 @abc .abstractmethod
78- def cirq_gate (self ) -> cirq .Gate : ...
90+ def cirq_gate (self ) -> cirq .Gate :
91+ """The `cirq.Gate` to use as the source of truth."""
7992
8093 @cached_property
8194 def signature (self ) -> 'Signature' :
82- if isinstance (self .cirq_gate , Bloq ):
83- return self .cirq_gate .signature
8495 nqubits = cirq .num_qubits (self .cirq_gate )
8596 if nqubits == 1 :
8697 return Signature ([Register ('q' , QBit ())])
@@ -89,14 +100,13 @@ def signature(self) -> 'Signature':
89100 # else
90101 return Signature ([Register ('q' , QBit (), shape = nqubits )])
91102
103+ def decompose_bloq (self ) -> 'CompositeBloq' :
104+ return decompose_from_cirq_style_method (self )
105+
92106 def decompose_from_registers (
93107 self , * , context : cirq .DecompositionContext , ** quregs : CirqQuregT
94108 ) -> cirq .OP_TREE :
95- op = (
96- self .cirq_gate .on_registers (** quregs )
97- if isinstance (self .cirq_gate , GateWithRegisters )
98- else self .cirq_gate .on (* quregs .get ('q' , np .array (())).flatten ())
99- )
109+ op = self .cirq_gate .on (* quregs .get ('q' , np .array (())).flatten ())
100110 try :
101111 return cirq .decompose_once (op )
102112 except TypeError as e :
@@ -112,37 +122,35 @@ def my_tensors(
112122 def as_cirq_op (
113123 self , qubit_manager : 'cirq.QubitManager' , ** in_quregs : 'CirqQuregT'
114124 ) -> Tuple [Union ['cirq.Operation' , None ], Dict [str , 'CirqQuregT' ]]:
115- if isinstance (self .cirq_gate , GateWithRegisters ):
116- return self .cirq_gate .as_cirq_op (qubit_manager , ** in_quregs )
117125 qubits = in_quregs .get ('q' , np .array ([])).flatten ()
118126 return self .cirq_gate .on (* qubits ), in_quregs
119127
120- # Delegate all cirq-style protocols to underlying gate
121- def _unitary_ (self ):
122- return cirq .unitary (self .cirq_gate , default = None )
123-
124- def _circuit_diagram_info_ (
125- self , args : cirq .CircuitDiagramInfoArgs
126- ) -> Optional [cirq .CircuitDiagramInfo ]:
127- return cirq .circuit_diagram_info (self .cirq_gate , default = None )
128-
129- def __str__ (self ):
130- return str (self .cirq_gate )
131-
132128 def __pow__ (self , power ):
133129 return CirqGateAsBloq (gate = cirq .pow (self .cirq_gate , power ))
134130
135131 def adjoint (self ) -> 'Bloq' :
136132 return CirqGateAsBloq (gate = cirq .inverse (self .cirq_gate ))
137133
134+ def __str__ (self ):
135+ return f'cirq.{ self .cirq_gate } '
136+
138137
139138@frozen
140139class CirqGateAsBloq (CirqGateAsBloqBase ):
141- gate : cirq .Gate
140+ """An adapter that fulfils the Bloq API by delegating to `cirq.Gate` methods.
141+
142+ - The bloq's signature is one register named "q" of type QBit() with shape (n_qubits,) as
143+ determined by `cirq.num_qubits`.
144+ - Decomposition will go via `cirq.decompose_once`.
145+ - Tensor data is derived from `cirq.unitary`.
146+ - `as_cirq_op` will use the adapted cirq gate directly
147+ - Adjoint and exponentiation go via `cirq.inverse` and `cirq.pow`, respectively.
148+ - The string representation is "cirq.{gate}".
142149
143- def __str__ (self ) -> str :
144- g = min (self .cirq_gate .__class__ .__name__ , str (self .cirq_gate ), key = len )
145- return f'cirq.{ g } '
150+ If you'd rather bootstrap your own bloq based on an existing `cirq.Gate`, you can inherit
151+ from `CirqGateAsBloqBase`."""
152+
153+ gate : cirq .Gate
146154
147155 @property
148156 def cirq_gate (self ) -> cirq .Gate :
0 commit comments