cirq-core 1.6.0.dev20250423233500__py3-none-any.whl → 1.6.0.dev20250425004112__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

Files changed (57) hide show
  1. cirq/_version.py +1 -1
  2. cirq/_version_test.py +1 -1
  3. cirq/ops/dense_pauli_string.py +28 -28
  4. cirq/ops/diagonal_gate.py +12 -14
  5. cirq/ops/eigen_gate.py +8 -5
  6. cirq/ops/fourier_transform.py +8 -12
  7. cirq/ops/fsim_gate.py +38 -37
  8. cirq/ops/gate_operation.py +25 -27
  9. cirq/ops/gateset.py +7 -5
  10. cirq/ops/global_phase_op.py +11 -11
  11. cirq/ops/greedy_qubit_manager.py +9 -7
  12. cirq/ops/identity.py +8 -6
  13. cirq/ops/kraus_channel.py +7 -4
  14. cirq/ops/linear_combinations.py +36 -34
  15. cirq/ops/matrix_gates.py +10 -10
  16. cirq/ops/measure_util.py +6 -4
  17. cirq/ops/measurement_gate.py +12 -12
  18. cirq/ops/mixed_unitary_channel.py +7 -4
  19. cirq/ops/named_qubit.py +8 -5
  20. cirq/ops/op_tree.py +4 -2
  21. cirq/ops/parallel_gate.py +11 -13
  22. cirq/ops/parity_gates.py +15 -17
  23. cirq/ops/pauli_gates.py +20 -17
  24. cirq/ops/pauli_interaction_gate.py +10 -14
  25. cirq/ops/pauli_measurement_gate.py +20 -20
  26. cirq/ops/pauli_string.py +76 -79
  27. cirq/ops/pauli_string_phasor.py +30 -30
  28. cirq/ops/pauli_string_raw_types.py +6 -4
  29. cirq/ops/pauli_sum_exponential.py +11 -11
  30. cirq/ops/permutation_gate.py +5 -3
  31. cirq/ops/phased_iswap_gate.py +8 -8
  32. cirq/ops/phased_x_gate.py +8 -9
  33. cirq/ops/phased_x_z_gate.py +15 -13
  34. cirq/ops/qid_util.py +6 -4
  35. cirq/ops/qubit_manager.py +9 -7
  36. cirq/ops/random_gate_channel.py +9 -7
  37. cirq/ops/raw_types.py +70 -72
  38. cirq/ops/raw_types_test.py +10 -6
  39. cirq/ops/state_preparation_channel.py +4 -4
  40. cirq/ops/swap_gates.py +7 -9
  41. cirq/ops/three_qubit_gates.py +22 -28
  42. cirq/ops/two_qubit_diagonal_gate.py +8 -8
  43. cirq/ops/uniform_superposition_gate.py +3 -1
  44. cirq/ops/wait_gate.py +12 -9
  45. cirq/protocols/act_on_protocol.py +6 -4
  46. cirq/protocols/act_on_protocol_test.py +8 -5
  47. cirq/protocols/apply_unitary_protocol.py +10 -8
  48. cirq/protocols/circuit_diagram_info_protocol.py +10 -8
  49. cirq/protocols/control_key_protocol.py +5 -3
  50. cirq/protocols/decompose_protocol.py +25 -22
  51. cirq/protocols/decompose_protocol_test.py +5 -2
  52. cirq/protocols/inverse_protocol.py +10 -8
  53. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/METADATA +1 -1
  54. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/RECORD +57 -57
  55. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/WHEEL +0 -0
  56. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/licenses/LICENSE +0 -0
  57. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/top_level.txt +0 -0
cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 10, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.1.*")'
29
29
  )
30
30
 
31
- __version__ = "1.6.0.dev20250423233500"
31
+ __version__ = "1.6.0.dev20250425004112"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version():
6
- assert cirq.__version__ == "1.6.0.dev20250423233500"
6
+ assert cirq.__version__ == "1.6.0.dev20250425004112"
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import abc
16
18
  import numbers
17
19
  from types import NotImplementedType
@@ -45,7 +47,7 @@ if TYPE_CHECKING:
45
47
 
46
48
  # Order is important! Index equals numeric value.
47
49
  PAULI_CHARS = 'IXYZ'
48
- PAULI_GATES: List[Union['cirq.Pauli', 'cirq.IdentityGate']] = [
50
+ PAULI_GATES: List[Union[cirq.Pauli, cirq.IdentityGate]] = [
49
51
  identity.I,
50
52
  pauli_gates.X,
51
53
  pauli_gates.Y,
@@ -84,9 +86,9 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
84
86
 
85
87
  def __init__(
86
88
  self,
87
- pauli_mask: Union[Iterable['cirq.PAULI_GATE_LIKE'], np.ndarray],
89
+ pauli_mask: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray],
88
90
  *,
89
- coefficient: 'cirq.TParamValComplex' = 1,
91
+ coefficient: cirq.TParamValComplex = 1,
90
92
  ):
91
93
  """Initializes a new dense pauli string.
92
94
 
@@ -116,7 +118,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
116
118
  return self._pauli_mask
117
119
 
118
120
  @property
119
- def coefficient(self) -> 'cirq.TParamValComplex':
121
+ def coefficient(self) -> cirq.TParamValComplex:
120
122
  """A complex coefficient or symbol."""
121
123
  return self._coefficient
122
124
 
@@ -129,7 +131,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
129
131
  return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
130
132
 
131
133
  @classmethod
132
- def one_hot(cls, *, index: int, length: int, pauli: 'cirq.PAULI_GATE_LIKE') -> Self:
134
+ def one_hot(cls, *, index: int, length: int, pauli: cirq.PAULI_GATE_LIKE) -> Self:
133
135
  """Creates a dense pauli string with only one non-identity Pauli.
134
136
 
135
137
  Args:
@@ -179,9 +181,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
179
181
  decomposed_ops = cast(Iterable['cirq.OP_TREE'], self._decompose_(qubits))
180
182
  return protocols.apply_unitaries(decomposed_ops, qubits, args)
181
183
 
182
- def _decompose_(
183
- self, qubits: Sequence['cirq.Qid']
184
- ) -> Union[NotImplementedType, 'cirq.OP_TREE']:
184
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Union[NotImplementedType, cirq.OP_TREE]:
185
185
  if not self._has_unitary_():
186
186
  return NotImplemented
187
187
  result = [PAULI_GATES[p].on(q) for p, q in zip(self.pauli_mask, qubits) if p]
@@ -195,7 +195,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
195
195
  def _parameter_names_(self) -> AbstractSet[str]:
196
196
  return protocols.parameter_names(self.coefficient)
197
197
 
198
- def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> Self:
198
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
199
199
  return self.copy(
200
200
  coefficient=protocols.resolve_parameters(self.coefficient, resolver, recursive)
201
201
  )
@@ -218,7 +218,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
218
218
  return NotImplemented
219
219
 
220
220
  @overload
221
- def __getitem__(self, item: int) -> Union['cirq.Pauli', 'cirq.IdentityGate']:
221
+ def __getitem__(self, item: int) -> Union[cirq.Pauli, cirq.IdentityGate]:
222
222
  pass
223
223
 
224
224
  @overload
@@ -234,7 +234,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
234
234
 
235
235
  raise TypeError(f'indices must be integers or slices, not {type(item)}')
236
236
 
237
- def __iter__(self) -> Iterator[Union['cirq.Pauli', 'cirq.IdentityGate']]:
237
+ def __iter__(self) -> Iterator[Union[cirq.Pauli, cirq.IdentityGate]]:
238
238
  for i in range(len(self)):
239
239
  yield self[i]
240
240
 
@@ -301,7 +301,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
301
301
 
302
302
  return NotImplemented
303
303
 
304
- def tensor_product(self, other: 'BaseDensePauliString') -> Self:
304
+ def tensor_product(self, other: BaseDensePauliString) -> Self:
305
305
  """Concatenates dense pauli strings and multiplies their coefficients.
306
306
 
307
307
  Args:
@@ -323,10 +323,10 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
323
323
  pauli_mask=self.pauli_mask,
324
324
  )
325
325
 
326
- def on(self, *qubits: 'cirq.Qid') -> 'cirq.PauliString':
326
+ def on(self, *qubits: cirq.Qid) -> cirq.PauliString:
327
327
  return self.sparse(qubits)
328
328
 
329
- def sparse(self, qubits: Optional[Sequence['cirq.Qid']] = None) -> 'cirq.PauliString':
329
+ def sparse(self, qubits: Optional[Sequence[cirq.Qid]] = None) -> cirq.PauliString:
330
330
  """A `cirq.PauliString` version of this dense pauli string.
331
331
 
332
332
  Args:
@@ -390,11 +390,11 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
390
390
 
391
391
  return NotImplemented
392
392
 
393
- def frozen(self) -> 'DensePauliString':
393
+ def frozen(self) -> DensePauliString:
394
394
  """A `cirq.DensePauliString` with the same contents."""
395
395
  return DensePauliString(coefficient=self.coefficient, pauli_mask=self.pauli_mask)
396
396
 
397
- def mutable_copy(self) -> 'MutableDensePauliString':
397
+ def mutable_copy(self) -> MutableDensePauliString:
398
398
  """A `cirq.MutableDensePauliString` with the same contents."""
399
399
  return MutableDensePauliString(
400
400
  coefficient=self.coefficient, pauli_mask=np.copy(self.pauli_mask)
@@ -403,7 +403,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
403
403
  @abc.abstractmethod
404
404
  def copy(
405
405
  self,
406
- coefficient: Optional['cirq.TParamValComplex'] = None,
406
+ coefficient: Optional[cirq.TParamValComplex] = None,
407
407
  pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
408
408
  ) -> Self:
409
409
  """Returns a copy with possibly modified contents.
@@ -454,14 +454,14 @@ class DensePauliString(BaseDensePauliString):
454
454
  dense pauli strings, see `cirq.MutableDensePauliString`.
455
455
  """
456
456
 
457
- def frozen(self) -> 'DensePauliString':
457
+ def frozen(self) -> DensePauliString:
458
458
  return self
459
459
 
460
460
  def copy(
461
461
  self,
462
- coefficient: Optional['cirq.TParamValComplex'] = None,
462
+ coefficient: Optional[cirq.TParamValComplex] = None,
463
463
  pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
464
- ) -> 'DensePauliString':
464
+ ) -> DensePauliString:
465
465
  if pauli_mask is None and (coefficient is None or coefficient == self.coefficient):
466
466
  return self
467
467
  return DensePauliString(
@@ -489,14 +489,14 @@ class MutableDensePauliString(BaseDensePauliString):
489
489
  """
490
490
 
491
491
  @overload
492
- def __setitem__(self, key: int, value: 'cirq.PAULI_GATE_LIKE') -> Self:
492
+ def __setitem__(self, key: int, value: cirq.PAULI_GATE_LIKE) -> Self:
493
493
  pass
494
494
 
495
495
  @overload
496
496
  def __setitem__(
497
497
  self,
498
498
  key: slice,
499
- value: Union[Iterable['cirq.PAULI_GATE_LIKE'], np.ndarray, BaseDensePauliString],
499
+ value: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray, BaseDensePauliString],
500
500
  ) -> Self:
501
501
  pass
502
502
 
@@ -559,9 +559,9 @@ class MutableDensePauliString(BaseDensePauliString):
559
559
 
560
560
  def copy(
561
561
  self,
562
- coefficient: Optional['cirq.TParamValComplex'] = None,
562
+ coefficient: Optional[cirq.TParamValComplex] = None,
563
563
  pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
564
- ) -> 'MutableDensePauliString':
564
+ ) -> MutableDensePauliString:
565
565
  return MutableDensePauliString(
566
566
  coefficient=self.coefficient if coefficient is None else coefficient,
567
567
  pauli_mask=np.copy(self.pauli_mask) if pauli_mask is None else pauli_mask,
@@ -574,7 +574,7 @@ class MutableDensePauliString(BaseDensePauliString):
574
574
  return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
575
575
 
576
576
  @classmethod
577
- def inline_gaussian_elimination(cls, rows: 'List[MutableDensePauliString]') -> None:
577
+ def inline_gaussian_elimination(cls, rows: List[MutableDensePauliString]) -> None:
578
578
  if not rows:
579
579
  return
580
580
 
@@ -605,7 +605,7 @@ class MutableDensePauliString(BaseDensePauliString):
605
605
  next_row += 1
606
606
 
607
607
 
608
- def _pauli_index(val: 'cirq.PAULI_GATE_LIKE') -> int:
608
+ def _pauli_index(val: cirq.PAULI_GATE_LIKE) -> int:
609
609
  m = pauli_string.PAULI_GATE_LIKE_TO_INDEX_MAP
610
610
  if val not in m:
611
611
  raise TypeError(
@@ -616,13 +616,13 @@ def _pauli_index(val: 'cirq.PAULI_GATE_LIKE') -> int:
616
616
  return m[val]
617
617
 
618
618
 
619
- def _as_pauli_mask(val: Union[Iterable['cirq.PAULI_GATE_LIKE'], np.ndarray]) -> np.ndarray:
619
+ def _as_pauli_mask(val: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray]) -> np.ndarray:
620
620
  if isinstance(val, np.ndarray):
621
621
  return np.asarray(val, dtype=np.uint8)
622
622
  return np.array([_pauli_index(v) for v in val], dtype=np.uint8)
623
623
 
624
624
 
625
- def _attempt_value_to_pauli_index(v: 'cirq.Operation') -> Optional[Tuple[int, int]]:
625
+ def _attempt_value_to_pauli_index(v: cirq.Operation) -> Optional[Tuple[int, int]]:
626
626
  if not isinstance(v, raw_types.Operation):
627
627
  return None
628
628
 
cirq/ops/diagonal_gate.py CHANGED
@@ -18,6 +18,8 @@ The gate is used to create a (2^n)x(2^n) matrix with the diagonal elements
18
18
  passed as a list.
19
19
  """
20
20
 
21
+ from __future__ import annotations
22
+
21
23
  from typing import (
22
24
  AbstractSet,
23
25
  Any,
@@ -81,7 +83,7 @@ class DiagonalGate(raw_types.Gate):
81
83
  all phases.
82
84
  """
83
85
 
84
- def __init__(self, diag_angles_radians: Sequence['cirq.TParamVal']) -> None:
86
+ def __init__(self, diag_angles_radians: Sequence[cirq.TParamVal]) -> None:
85
87
  r"""A n-qubit gate with only diagonal elements.
86
88
 
87
89
  This gate's off-diagonal elements are zero and its on-diagonal
@@ -92,10 +94,10 @@ class DiagonalGate(raw_types.Gate):
92
94
  If these values are $(x_0, x_1, \ldots , x_N)$ then the unitary
93
95
  has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_N})$.
94
96
  """
95
- self._diag_angles_radians: Tuple['cirq.TParamVal', ...] = tuple(diag_angles_radians)
97
+ self._diag_angles_radians: Tuple[cirq.TParamVal, ...] = tuple(diag_angles_radians)
96
98
 
97
99
  @property
98
- def diag_angles_radians(self) -> Tuple['cirq.TParamVal', ...]:
100
+ def diag_angles_radians(self) -> Tuple[cirq.TParamVal, ...]:
99
101
  return self._diag_angles_radians
100
102
 
101
103
  def _num_qubits_(self):
@@ -109,9 +111,7 @@ class DiagonalGate(raw_types.Gate):
109
111
  name for angle in self._diag_angles_radians for name in protocols.parameter_names(angle)
110
112
  }
111
113
 
112
- def _resolve_parameters_(
113
- self, resolver: 'cirq.ParamResolver', recursive: bool
114
- ) -> 'DiagonalGate':
114
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> DiagonalGate:
115
115
  return DiagonalGate(
116
116
  protocols.resolve_parameters(self._diag_angles_radians, resolver, recursive)
117
117
  )
@@ -124,7 +124,7 @@ class DiagonalGate(raw_types.Gate):
124
124
  return None
125
125
  return np.diag([np.exp(1j * angle) for angle in self._diag_angles_radians])
126
126
 
127
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> np.ndarray:
127
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray:
128
128
  if self._is_parameterized_():
129
129
  return NotImplemented
130
130
  for index, angle in enumerate(self._diag_angles_radians):
@@ -132,9 +132,7 @@ class DiagonalGate(raw_types.Gate):
132
132
  args.target_tensor[subspace_index] *= np.exp(1j * angle)
133
133
  return args.target_tensor
134
134
 
135
- def _circuit_diagram_info_(
136
- self, args: 'cirq.CircuitDiagramInfoArgs'
137
- ) -> 'cirq.CircuitDiagramInfo':
135
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
138
136
  rounded_angles = np.array(self._diag_angles_radians)
139
137
  if args.precision is not None:
140
138
  rounded_angles = rounded_angles.round(args.precision)
@@ -150,7 +148,7 @@ class DiagonalGate(raw_types.Gate):
150
148
  [diag_str] + [f"#{i}" for i in range(2, self._num_qubits_() + 1)]
151
149
  )
152
150
 
153
- def __pow__(self, exponent: Any) -> 'DiagonalGate':
151
+ def __pow__(self, exponent: Any) -> DiagonalGate:
154
152
  if not isinstance(exponent, (int, float, sympy.Basic)):
155
153
  return NotImplemented
156
154
  angles = []
@@ -163,8 +161,8 @@ class DiagonalGate(raw_types.Gate):
163
161
  return tuple(self._diag_angles_radians)
164
162
 
165
163
  def _decompose_for_basis(
166
- self, index: int, bit_flip: int, theta: 'cirq.TParamVal', qubits: Sequence['cirq.Qid']
167
- ) -> Iterator[Union['cirq.ZPowGate', 'cirq.CXPowGate']]:
164
+ self, index: int, bit_flip: int, theta: cirq.TParamVal, qubits: Sequence[cirq.Qid]
165
+ ) -> Iterator[Union[cirq.ZPowGate, cirq.CXPowGate]]:
168
166
  if index == 0:
169
167
  return
170
168
  largest_digit = self._num_qubits_() - (len(bin(index)) - 2)
@@ -175,7 +173,7 @@ class DiagonalGate(raw_types.Gate):
175
173
  elif _flip_bit > largest_digit:
176
174
  yield common_gates.CNOT(qubits[_flip_bit], qubits[largest_digit])
177
175
 
178
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
176
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
179
177
  """Decompose the n-qubit diagonal gates into CNOT and Rz gates.
180
178
 
181
179
  A 3 qubits decomposition looks like
cirq/ops/eigen_gate.py CHANGED
@@ -11,6 +11,9 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
14
17
  import abc
15
18
  import fractions
16
19
  import math
@@ -131,7 +134,7 @@ class EigenGate(raw_types.Gate):
131
134
  return self._global_shift
132
135
 
133
136
  # virtual method
134
- def _with_exponent(self, exponent: value.TParamVal) -> 'EigenGate':
137
+ def _with_exponent(self, exponent: value.TParamVal) -> EigenGate:
135
138
  """Return the same kind of gate, but with a different exponent.
136
139
 
137
140
  Child classes should override this method if they have an __init__
@@ -144,7 +147,7 @@ class EigenGate(raw_types.Gate):
144
147
  # pylint: enable=unexpected-keyword-arg
145
148
 
146
149
  def _diagram_exponent(
147
- self, args: 'protocols.CircuitDiagramInfoArgs', *, ignore_global_phase: bool = True
150
+ self, args: protocols.CircuitDiagramInfoArgs, *, ignore_global_phase: bool = True
148
151
  ):
149
152
  """The exponent to use in circuit diagrams.
150
153
 
@@ -199,7 +202,7 @@ class EigenGate(raw_types.Gate):
199
202
  return result
200
203
 
201
204
  def _format_exponent_as_angle(
202
- self, args: 'protocols.CircuitDiagramInfoArgs', order: int = 2
205
+ self, args: protocols.CircuitDiagramInfoArgs, order: int = 2
203
206
  ) -> str:
204
207
  """Returns string with exponent expressed as angle in radians.
205
208
 
@@ -297,7 +300,7 @@ class EigenGate(raw_types.Gate):
297
300
  real_periods = [abs(2 / e) for e in exponents if e != 0]
298
301
  return _approximate_common_period(real_periods)
299
302
 
300
- def __pow__(self, exponent: Union[float, sympy.Symbol]) -> 'EigenGate':
303
+ def __pow__(self, exponent: Union[float, sympy.Symbol]) -> EigenGate:
301
304
  new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
302
305
  if new_exponent is NotImplemented:
303
306
  return NotImplemented # pragma: no cover
@@ -344,7 +347,7 @@ class EigenGate(raw_types.Gate):
344
347
  def _parameter_names_(self) -> AbstractSet[str]:
345
348
  return protocols.parameter_names(self._exponent)
346
349
 
347
- def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> 'EigenGate':
350
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> EigenGate:
348
351
  exponent = resolver.value_of(self._exponent, recursive)
349
352
  if isinstance(exponent, numbers.Complex):
350
353
  if isinstance(exponent, numbers.Real):
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from typing import AbstractSet, Any, Dict, Union
16
18
 
17
19
  import numpy as np
@@ -87,9 +89,7 @@ class QuantumFourierTransformGate(raw_types.Gate):
87
89
  f'without_reverse={self._without_reverse!r})'
88
90
  )
89
91
 
90
- def _circuit_diagram_info_(
91
- self, args: 'cirq.CircuitDiagramInfoArgs'
92
- ) -> 'cirq.CircuitDiagramInfo':
92
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
93
93
  return cirq.CircuitDiagramInfo(
94
94
  wire_symbols=(str(self),) + tuple(f'#{k+1}' for k in range(1, self._num_qubits)),
95
95
  exponent_qubit_index=0,
@@ -133,7 +133,7 @@ class PhaseGradientGate(raw_types.Gate):
133
133
  for i, q in enumerate(qubits):
134
134
  yield cirq.Z(q) ** (self.exponent / 2**i)
135
135
 
136
- def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs'):
136
+ def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs):
137
137
  if isinstance(self.exponent, sympy.Basic):
138
138
  return NotImplemented
139
139
 
@@ -167,8 +167,8 @@ class PhaseGradientGate(raw_types.Gate):
167
167
  return cirq.parameter_names(self.exponent)
168
168
 
169
169
  def _resolve_parameters_(
170
- self, resolver: 'cirq.ParamResolver', recursive: bool
171
- ) -> 'PhaseGradientGate':
170
+ self, resolver: cirq.ParamResolver, recursive: bool
171
+ ) -> PhaseGradientGate:
172
172
  new_exponent = cirq.resolve_parameters(self.exponent, resolver, recursive)
173
173
  return PhaseGradientGate(num_qubits=self._num_qubits, exponent=new_exponent)
174
174
 
@@ -182,9 +182,7 @@ class PhaseGradientGate(raw_types.Gate):
182
182
  f'exponent={_compat.proper_repr(self.exponent)})'
183
183
  )
184
184
 
185
- def _circuit_diagram_info_(
186
- self, args: 'cirq.CircuitDiagramInfoArgs'
187
- ) -> 'cirq.CircuitDiagramInfo':
185
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
188
186
  return cirq.CircuitDiagramInfo(
189
187
  wire_symbols=('Grad',) + tuple(f'#{k+1}' for k in range(1, self._num_qubits)),
190
188
  exponent=self.exponent,
@@ -192,9 +190,7 @@ class PhaseGradientGate(raw_types.Gate):
192
190
  )
193
191
 
194
192
 
195
- def qft(
196
- *qubits: 'cirq.Qid', without_reverse: bool = False, inverse: bool = False
197
- ) -> 'cirq.Operation':
193
+ def qft(*qubits: cirq.Qid, without_reverse: bool = False, inverse: bool = False) -> cirq.Operation:
198
194
  """The quantum Fourier transform.
199
195
 
200
196
  Transforms a qubit register from the computational basis to the frequency
cirq/ops/fsim_gate.py CHANGED
@@ -11,6 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  """Defines the fermionic simulation gate.
15
16
 
16
17
  This is the family of two-qubit gates that preserve excitations (number of ON
@@ -21,6 +22,8 @@ context of chemistry the electron count is conserved over time. This property
21
22
  applies more generally to fermions, thus the name of the gate.
22
23
  """
23
24
 
25
+ from __future__ import annotations
26
+
24
27
  import cmath
25
28
  import math
26
29
  from typing import AbstractSet, Any, Dict, Iterator, Optional, Tuple
@@ -34,7 +37,7 @@ from cirq._compat import proper_repr
34
37
  from cirq.ops import gate_features, raw_types
35
38
 
36
39
 
37
- def _canonicalize(value: 'cirq.TParamVal') -> 'cirq.TParamVal':
40
+ def _canonicalize(value: cirq.TParamVal) -> cirq.TParamVal:
38
41
  """Assumes value is 2π-periodic and shifts it into [-π, π)."""
39
42
  if protocols.is_parameterized(value):
40
43
  return value
@@ -42,12 +45,12 @@ def _canonicalize(value: 'cirq.TParamVal') -> 'cirq.TParamVal':
42
45
  return value - period * np.floor((value + np.pi) / period)
43
46
 
44
47
 
45
- def _zero_mod_pi(param: 'cirq.TParamVal') -> bool:
48
+ def _zero_mod_pi(param: cirq.TParamVal) -> bool:
46
49
  """Returns True iff param, assumed to be in [-pi, pi), is 0 (mod pi)."""
47
50
  return param in (0.0, -np.pi, -sympy.pi)
48
51
 
49
52
 
50
- def _half_pi_mod_pi(param: 'cirq.TParamVal') -> bool:
53
+ def _half_pi_mod_pi(param: cirq.TParamVal) -> bool:
51
54
  """Returns True iff param, assumed to be in [-pi, pi), is pi/2 (mod pi)."""
52
55
  return param in (-np.pi / 2, np.pi / 2, -sympy.pi / 2, sympy.pi / 2)
53
56
 
@@ -90,7 +93,7 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
90
93
  FSimGate(θ, φ) = ISWAP**(-2θ/π) CZPowGate(exponent=-φ/π)
91
94
  """
92
95
 
93
- def __init__(self, theta: 'cirq.TParamVal', phi: 'cirq.TParamVal') -> None:
96
+ def __init__(self, theta: cirq.TParamVal, phi: cirq.TParamVal) -> None:
94
97
  """Inits FSimGate.
95
98
 
96
99
  Args:
@@ -106,11 +109,11 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
106
109
  self._phi = _canonicalize(phi)
107
110
 
108
111
  @property
109
- def theta(self) -> 'cirq.TParamVal':
112
+ def theta(self) -> cirq.TParamVal:
110
113
  return self._theta
111
114
 
112
115
  @property
113
- def phi(self) -> 'cirq.TParamVal':
116
+ def phi(self) -> cirq.TParamVal:
114
117
  return self._phi
115
118
 
116
119
  def _num_qubits_(self) -> int:
@@ -162,15 +165,13 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
162
165
  }
163
166
  )
164
167
 
165
- def _resolve_parameters_(
166
- self, resolver: 'cirq.ParamResolver', recursive: bool
167
- ) -> 'cirq.FSimGate':
168
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.FSimGate:
168
169
  return FSimGate(
169
170
  protocols.resolve_parameters(self.theta, resolver, recursive),
170
171
  protocols.resolve_parameters(self.phi, resolver, recursive),
171
172
  )
172
173
 
173
- def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs') -> Optional[np.ndarray]:
174
+ def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> Optional[np.ndarray]:
174
175
  if cirq.is_parameterized(self):
175
176
  return None
176
177
  if self.theta != 0:
@@ -187,7 +188,7 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
187
188
  out[ii] *= cmath.exp(-1j * self.phi)
188
189
  return out
189
190
 
190
- def _decompose_(self, qubits) -> Iterator['cirq.OP_TREE']:
191
+ def _decompose_(self, qubits) -> Iterator[cirq.OP_TREE]:
191
192
  a, b = qubits
192
193
  xx = cirq.XXPowGate(exponent=self.theta / np.pi, global_shift=-0.5)
193
194
  yy = cirq.YYPowGate(exponent=self.theta / np.pi, global_shift=-0.5)
@@ -195,12 +196,12 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
195
196
  yield yy(a, b)
196
197
  yield cirq.CZ(a, b) ** (-self.phi / np.pi)
197
198
 
198
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
199
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
199
200
  t = args.format_radians(self.theta)
200
201
  p = args.format_radians(self.phi)
201
202
  return f'FSim({t}, {p})', f'FSim({t}, {p})'
202
203
 
203
- def __pow__(self, power) -> 'FSimGate':
204
+ def __pow__(self, power) -> FSimGate:
204
205
  return FSimGate(cirq.mul(self.theta, power), cirq.mul(self.phi, power))
205
206
 
206
207
  def __repr__(self) -> str:
@@ -275,11 +276,11 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
275
276
 
276
277
  def __init__(
277
278
  self,
278
- theta: 'cirq.TParamVal',
279
- zeta: 'cirq.TParamVal' = 0.0,
280
- chi: 'cirq.TParamVal' = 0.0,
281
- gamma: 'cirq.TParamVal' = 0.0,
282
- phi: 'cirq.TParamVal' = 0.0,
279
+ theta: cirq.TParamVal,
280
+ zeta: cirq.TParamVal = 0.0,
281
+ chi: cirq.TParamVal = 0.0,
282
+ gamma: cirq.TParamVal = 0.0,
283
+ phi: cirq.TParamVal = 0.0,
283
284
  ) -> None:
284
285
  """Inits PhasedFSimGate.
285
286
 
@@ -302,32 +303,32 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
302
303
  self._phi = _canonicalize(phi)
303
304
 
304
305
  @property
305
- def theta(self) -> 'cirq.TParamVal':
306
+ def theta(self) -> cirq.TParamVal:
306
307
  return self._theta
307
308
 
308
309
  @property
309
- def zeta(self) -> 'cirq.TParamVal':
310
+ def zeta(self) -> cirq.TParamVal:
310
311
  return self._zeta
311
312
 
312
313
  @property
313
- def chi(self) -> 'cirq.TParamVal':
314
+ def chi(self) -> cirq.TParamVal:
314
315
  return self._chi
315
316
 
316
317
  @property
317
- def gamma(self) -> 'cirq.TParamVal':
318
+ def gamma(self) -> cirq.TParamVal:
318
319
  return self._gamma
319
320
 
320
321
  @property
321
- def phi(self) -> 'cirq.TParamVal':
322
+ def phi(self) -> cirq.TParamVal:
322
323
  return self._phi
323
324
 
324
325
  @staticmethod
325
326
  def from_fsim_rz(
326
- theta: 'cirq.TParamVal',
327
- phi: 'cirq.TParamVal',
328
- rz_angles_before: Tuple['cirq.TParamVal', 'cirq.TParamVal'],
329
- rz_angles_after: Tuple['cirq.TParamVal', 'cirq.TParamVal'],
330
- ) -> 'PhasedFSimGate':
327
+ theta: cirq.TParamVal,
328
+ phi: cirq.TParamVal,
329
+ rz_angles_before: Tuple[cirq.TParamVal, cirq.TParamVal],
330
+ rz_angles_after: Tuple[cirq.TParamVal, cirq.TParamVal],
331
+ ) -> PhasedFSimGate:
331
332
  """Creates PhasedFSimGate using an alternate parametrization.
332
333
 
333
334
  Args:
@@ -348,7 +349,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
348
349
  return PhasedFSimGate(theta, zeta, chi, gamma, phi)
349
350
 
350
351
  @staticmethod
351
- def from_matrix(u: np.ndarray) -> Optional['PhasedFSimGate']:
352
+ def from_matrix(u: np.ndarray) -> Optional[PhasedFSimGate]:
352
353
  """Contruct a PhasedFSimGate from unitary.
353
354
 
354
355
  Args:
@@ -387,14 +388,14 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
387
388
  return None
388
389
 
389
390
  @property
390
- def rz_angles_before(self) -> Tuple['cirq.TParamVal', 'cirq.TParamVal']:
391
+ def rz_angles_before(self) -> Tuple[cirq.TParamVal, cirq.TParamVal]:
391
392
  """Returns 2-tuple of phase angles applied to qubits before FSimGate."""
392
393
  b0 = (-self.gamma + self.zeta + self.chi) / 2.0
393
394
  b1 = (-self.gamma - self.zeta - self.chi) / 2.0
394
395
  return b0, b1
395
396
 
396
397
  @property
397
- def rz_angles_after(self) -> Tuple['cirq.TParamVal', 'cirq.TParamVal']:
398
+ def rz_angles_after(self) -> Tuple[cirq.TParamVal, cirq.TParamVal]:
398
399
  """Returns 2-tuple of phase angles applied to qubits after FSimGate."""
399
400
  a0 = (-self.gamma + self.zeta - self.chi) / 2.0
400
401
  a1 = (-self.gamma - self.zeta + self.chi) / 2.0
@@ -456,8 +457,8 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
456
457
  # fmt: on
457
458
 
458
459
  def _resolve_parameters_(
459
- self, resolver: 'cirq.ParamResolver', recursive: bool
460
- ) -> 'cirq.PhasedFSimGate':
460
+ self, resolver: cirq.ParamResolver, recursive: bool
461
+ ) -> cirq.PhasedFSimGate:
461
462
  return PhasedFSimGate(
462
463
  protocols.resolve_parameters(self.theta, resolver, recursive),
463
464
  protocols.resolve_parameters(self.zeta, resolver, recursive),
@@ -466,7 +467,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
466
467
  protocols.resolve_parameters(self.phi, resolver, recursive),
467
468
  )
468
469
 
469
- def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs') -> Optional[np.ndarray]:
470
+ def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> Optional[np.ndarray]:
470
471
  if cirq.is_parameterized(self):
471
472
  return None
472
473
  oi = args.subspace_index(0b01)
@@ -491,7 +492,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
491
492
  out[ii] *= f * f
492
493
  return out
493
494
 
494
- def _decompose_(self, qubits) -> Iterator['cirq.OP_TREE']:
495
+ def _decompose_(self, qubits) -> Iterator[cirq.OP_TREE]:
495
496
  """Decomposes self into Z rotations and FSimGate.
496
497
 
497
498
  Note that Z rotations returned by this method have unusual global phase
@@ -500,7 +501,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
500
501
  makes the top left element of the matrix equal to 1.
501
502
  """
502
503
 
503
- def to_exponent(angle_rads: 'cirq.TParamVal') -> 'cirq.TParamVal':
504
+ def to_exponent(angle_rads: cirq.TParamVal) -> cirq.TParamVal:
504
505
  """Divides angle_rads by symbolic or numerical pi."""
505
506
  pi = sympy.pi if protocols.is_parameterized(angle_rads) else np.pi
506
507
  return angle_rads / pi
@@ -514,7 +515,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
514
515
  yield cirq.Z(q0) ** to_exponent(after[0])
515
516
  yield cirq.Z(q1) ** to_exponent(after[1])
516
517
 
517
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
518
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
518
519
  theta = args.format_radians(self.theta)
519
520
  zeta = args.format_radians(self.zeta)
520
521
  chi = args.format_radians(self.chi)