cirq-core 1.5.0.dev20250403060241__py3-none-any.whl → 1.5.0.dev20250403161251__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 (106) hide show
  1. cirq/_import.py +1 -1
  2. cirq/_version.py +1 -1
  3. cirq/_version_test.py +1 -1
  4. cirq/circuits/circuit.py +2 -2
  5. cirq/circuits/circuit_test.py +0 -13
  6. cirq/circuits/insert_strategy_test.py +1 -0
  7. cirq/circuits/optimization_pass.py +3 -3
  8. cirq/circuits/qasm_output.py +1 -1
  9. cirq/circuits/qasm_output_test.py +5 -0
  10. cirq/circuits/text_diagram_drawer.py +1 -1
  11. cirq/contrib/acquaintance/bipartite_test.py +11 -0
  12. cirq/contrib/acquaintance/devices_test.py +5 -0
  13. cirq/contrib/acquaintance/executor_test.py +1 -0
  14. cirq/contrib/acquaintance/inspection_utils_test.py +5 -0
  15. cirq/contrib/acquaintance/shift.py +1 -1
  16. cirq/contrib/custom_simulators/custom_state_simulator_test.py +6 -4
  17. cirq/contrib/graph_device/graph_device.py +3 -3
  18. cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
  19. cirq/contrib/paulistring/pauli_string_optimize_test.py +0 -1
  20. cirq/contrib/paulistring/recombine_test.py +1 -1
  21. cirq/contrib/qcircuit/qcircuit_pdf.py +11 -8
  22. cirq/contrib/qcircuit/qcircuit_pdf_test.py +21 -0
  23. cirq/contrib/qcircuit/qcircuit_test.py +1 -1
  24. cirq/contrib/quantum_volume/quantum_volume.py +1 -6
  25. cirq/contrib/quimb/mps_simulator.py +2 -2
  26. cirq/contrib/quimb/mps_simulator_test.py +5 -0
  27. cirq/contrib/routing/greedy_test.py +3 -1
  28. cirq/contrib/svg/svg.py +1 -1
  29. cirq/contrib/svg/svg_test.py +3 -2
  30. cirq/devices/unconstrained_device_test.py +6 -0
  31. cirq/experiments/qubit_characterizations.py +4 -2
  32. cirq/experiments/random_quantum_circuit_generation.py +2 -3
  33. cirq/experiments/readout_confusion_matrix.py +4 -4
  34. cirq/linalg/combinators_test.py +3 -0
  35. cirq/linalg/decompositions_test.py +0 -5
  36. cirq/linalg/predicates.py +1 -1
  37. cirq/ops/clifford_gate.py +5 -16
  38. cirq/ops/common_gates.py +8 -8
  39. cirq/ops/common_gates_test.py +5 -0
  40. cirq/ops/control_values.py +1 -1
  41. cirq/ops/controlled_gate.py +1 -1
  42. cirq/ops/controlled_operation.py +1 -1
  43. cirq/ops/controlled_operation_test.py +6 -2
  44. cirq/ops/dense_pauli_string.py +1 -1
  45. cirq/ops/eigen_gate.py +1 -1
  46. cirq/ops/fourier_transform.py +0 -2
  47. cirq/ops/gate_operation.py +1 -1
  48. cirq/ops/gate_operation_test.py +1 -0
  49. cirq/ops/gateset_test.py +7 -0
  50. cirq/ops/greedy_qubit_manager_test.py +5 -0
  51. cirq/ops/kraus_channel_test.py +1 -0
  52. cirq/ops/mixed_unitary_channel_test.py +1 -0
  53. cirq/ops/op_tree_test.py +4 -0
  54. cirq/ops/pauli_measurement_gate_test.py +1 -0
  55. cirq/ops/pauli_string.py +3 -80
  56. cirq/ops/pauli_string_test.py +46 -0
  57. cirq/ops/phased_x_gate.py +1 -1
  58. cirq/ops/random_gate_channel_test.py +0 -6
  59. cirq/ops/raw_types.py +1 -1
  60. cirq/ops/raw_types_test.py +26 -1
  61. cirq/protocols/decompose_protocol_test.py +1 -1
  62. cirq/protocols/has_unitary_protocol_test.py +8 -7
  63. cirq/protocols/json_serialization_test.py +7 -6
  64. cirq/protocols/kraus_protocol.py +2 -2
  65. cirq/protocols/measurement_key_protocol_test.py +7 -7
  66. cirq/protocols/unitary_protocol_test.py +1 -1
  67. cirq/qis/channels_test.py +0 -9
  68. cirq/qis/measures.py +2 -1
  69. cirq/qis/measures_test.py +7 -0
  70. cirq/qis/states.py +1 -1
  71. cirq/sim/clifford/clifford_simulator.py +2 -1
  72. cirq/sim/clifford/clifford_simulator_test.py +32 -9
  73. cirq/sim/density_matrix_simulator.py +2 -1
  74. cirq/sim/density_matrix_simulator_test.py +10 -2
  75. cirq/sim/simulation_state.py +1 -1
  76. cirq/sim/simulation_state_test.py +1 -1
  77. cirq/sim/simulator_test.py +1 -1
  78. cirq/sim/sparse_simulator.py +2 -1
  79. cirq/sim/sparse_simulator_test.py +10 -2
  80. cirq/sim/state_vector_simulation_state_test.py +1 -1
  81. cirq/study/resolver.py +0 -4
  82. cirq/study/resolver_test.py +10 -1
  83. cirq/study/sweeps_test.py +18 -0
  84. cirq/testing/circuit_compare_test.py +6 -6
  85. cirq/testing/consistent_pauli_expansion_test.py +1 -1
  86. cirq/testing/consistent_qasm.py +1 -1
  87. cirq/testing/equals_tester.py +1 -1
  88. cirq/testing/equals_tester_test.py +5 -5
  89. cirq/testing/gate_features_test.py +5 -0
  90. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +1 -1
  91. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +1 -1
  92. cirq/transformers/qubit_management_transformers.py +1 -1
  93. cirq/transformers/transformer_api_test.py +8 -0
  94. cirq/transformers/transformer_primitives_test.py +2 -2
  95. cirq/value/condition.py +1 -1
  96. cirq/value/duration.py +1 -1
  97. cirq/value/periodic_value_test.py +5 -0
  98. cirq/value/value_equality_attr_test.py +1 -1
  99. cirq/vis/heatmap_test.py +1 -1
  100. cirq/work/observable_settings.py +2 -1
  101. cirq/work/observable_settings_test.py +1 -0
  102. {cirq_core-1.5.0.dev20250403060241.dist-info → cirq_core-1.5.0.dev20250403161251.dist-info}/METADATA +1 -1
  103. {cirq_core-1.5.0.dev20250403060241.dist-info → cirq_core-1.5.0.dev20250403161251.dist-info}/RECORD +106 -105
  104. {cirq_core-1.5.0.dev20250403060241.dist-info → cirq_core-1.5.0.dev20250403161251.dist-info}/LICENSE +0 -0
  105. {cirq_core-1.5.0.dev20250403060241.dist-info → cirq_core-1.5.0.dev20250403161251.dist-info}/WHEEL +0 -0
  106. {cirq_core-1.5.0.dev20250403060241.dist-info → cirq_core-1.5.0.dev20250403161251.dist-info}/top_level.txt +0 -0
cirq/ops/common_gates.py CHANGED
@@ -177,7 +177,7 @@ class XPowGate(eigen_gate.EigenGate):
177
177
  return SingleQubitCliffordGate.X.on(*qubits)
178
178
  if self.exponent % 2 == 1.5:
179
179
  return SingleQubitCliffordGate.X_nsqrt.on(*qubits)
180
- return NotImplemented
180
+ return NotImplemented # pragma: no cover
181
181
 
182
182
  def _trace_distance_bound_(self) -> Optional[float]:
183
183
  if self._is_parameterized_() or self._dimension != 2:
@@ -259,7 +259,7 @@ class XPowGate(eigen_gate.EigenGate):
259
259
 
260
260
  def _pauli_expansion_(self) -> value.LinearDict[str]:
261
261
  if self._dimension != 2:
262
- return NotImplemented
262
+ return NotImplemented # pragma: no cover
263
263
  phase = 1j ** (2 * self._exponent * (self._global_shift + 0.5))
264
264
  lib = sympy if protocols.is_parameterized(self) else np
265
265
  angle = lib.pi * self._exponent / 2
@@ -451,7 +451,7 @@ class YPowGate(eigen_gate.EigenGate):
451
451
  return SingleQubitCliffordGate.Y.on(*qubits)
452
452
  if self.exponent % 2 == 1.5:
453
453
  return SingleQubitCliffordGate.Y_nsqrt.on(*qubits)
454
- return NotImplemented
454
+ return NotImplemented # pragma: no cover
455
455
 
456
456
  def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
457
457
  return [
@@ -656,7 +656,7 @@ class ZPowGate(eigen_gate.EigenGate):
656
656
  return SingleQubitCliffordGate.Z.on(*qubits)
657
657
  if self.exponent % 2 == 1.5:
658
658
  return SingleQubitCliffordGate.Z_nsqrt.on(*qubits)
659
- return NotImplemented
659
+ return NotImplemented # pragma: no cover
660
660
 
661
661
  def in_su2(self) -> 'Rz':
662
662
  """Returns an equal-up-global-phase gate from the group SU2."""
@@ -765,7 +765,7 @@ class ZPowGate(eigen_gate.EigenGate):
765
765
 
766
766
  def _pauli_expansion_(self) -> value.LinearDict[str]:
767
767
  if self._dimension != 2:
768
- return NotImplemented
768
+ return NotImplemented # pragma: no cover
769
769
  phase = 1j ** (2 * self._exponent * (self._global_shift + 0.5))
770
770
  lib = sympy if protocols.is_parameterized(self) else np
771
771
  angle = lib.pi * self._exponent / 2
@@ -982,7 +982,7 @@ class HPowGate(eigen_gate.EigenGate):
982
982
  return SingleQubitCliffordGate.H.on(*qubits)
983
983
  if self.exponent % 2 == 0:
984
984
  return []
985
- return NotImplemented
985
+ return NotImplemented # pragma: no cover
986
986
 
987
987
  def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
988
988
  if self._exponent != 1:
@@ -1080,7 +1080,7 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1080
1080
  return PauliInteractionGate.CZ.on(*qubits)
1081
1081
  if self.exponent % 2 == 0:
1082
1082
  return []
1083
- return NotImplemented
1083
+ return NotImplemented # pragma: no cover
1084
1084
 
1085
1085
  def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
1086
1086
  return [(0, np.diag([1, 1, 1, 0])), (1, np.diag([0, 0, 0, 1]))]
@@ -1275,7 +1275,7 @@ class CXPowGate(eigen_gate.EigenGate):
1275
1275
  return PauliInteractionGate.CNOT.on(*qubits)
1276
1276
  if self.exponent % 2 == 0:
1277
1277
  return []
1278
- return NotImplemented
1278
+ return NotImplemented # pragma: no cover
1279
1279
 
1280
1280
  def _decompose_(self, qubits):
1281
1281
  c, t = qubits
@@ -307,6 +307,11 @@ def test_h_str():
307
307
  assert str(cirq.H**0.5) == 'H**0.5'
308
308
 
309
309
 
310
+ def test_phase_exponent():
311
+ assert cirq.XPowGate(exponent=0.5).phase_exponent == 0.0
312
+ assert cirq.YPowGate(exponent=0.5).phase_exponent == 0.5
313
+
314
+
310
315
  def test_x_act_on_tableau():
311
316
  with pytest.raises(TypeError, match="Failed to act"):
312
317
  cirq.act_on(cirq.X, ExampleSimulationState(), qubits=())
@@ -275,7 +275,7 @@ class SumOfProducts(AbstractControlValues):
275
275
 
276
276
  if len(self._conjunctions) == 1:
277
277
  # Use a simpler diagram if there's only 1 term.
278
- return protocols.CircuitDiagramInfo(
278
+ return protocols.CircuitDiagramInfo( # pragma: no cover
279
279
  wire_symbols=["@" if x == 1 else f"({x})" for x in self._conjunctions[0]]
280
280
  )
281
281
 
@@ -314,7 +314,7 @@ class ControlledGate(raw_types.Gate):
314
314
  return None
315
315
  u = protocols.unitary(self.sub_gate, default=None)
316
316
  if u is None:
317
- return NotImplemented
317
+ return NotImplemented # pragma: no cover
318
318
  angle_list = np.append(np.angle(np.linalg.eigvals(u)), 0)
319
319
  return protocols.trace_distance_from_angle_list(angle_list)
320
320
 
@@ -297,7 +297,7 @@ class ControlledOperation(raw_types.Operation):
297
297
  return None
298
298
  u = protocols.unitary(self.sub_operation, default=None)
299
299
  if u is None:
300
- return NotImplemented
300
+ return NotImplemented # pragma: no cover
301
301
  angle_list = np.append(np.angle(np.linalg.eigvals(u)), 0)
302
302
  return protocols.trace_distance_from_angle_list(angle_list)
303
303
 
@@ -159,7 +159,7 @@ def test_str():
159
159
  return ()
160
160
 
161
161
  def with_qubits(self, *new_qubits: cirq.Qid):
162
- pass
162
+ return self
163
163
 
164
164
  def __str__(self):
165
165
  return "Op(q2)"
@@ -170,7 +170,11 @@ def test_str():
170
170
  assert str(cirq.ControlledOperation([c1, c2], SingleQubitOp())) == "CC(c1, c2, Op(q2))"
171
171
 
172
172
  assert (
173
- str(cirq.ControlledOperation([c1, c2.with_dimension(3)], SingleQubitOp()))
173
+ str(
174
+ cirq.ControlledOperation(
175
+ [c1, c2.with_dimension(3)], SingleQubitOp().with_qubits(cirq.q(1))
176
+ )
177
+ )
174
178
  == "CC(c1, c2 (d=3), Op(q2))"
175
179
  )
176
180
 
@@ -627,7 +627,7 @@ def _attempt_value_to_pauli_index(v: 'cirq.Operation') -> Optional[Tuple[int, in
627
627
  return None
628
628
 
629
629
  if not isinstance(v.gate, pauli_gates.Pauli):
630
- return None
630
+ return None # pragma: no cover
631
631
 
632
632
  q = v.qubits[0]
633
633
  from cirq import devices
cirq/ops/eigen_gate.py CHANGED
@@ -302,7 +302,7 @@ class EigenGate(raw_types.Gate):
302
302
  def __pow__(self, exponent: Union[float, sympy.Symbol]) -> 'EigenGate':
303
303
  new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
304
304
  if new_exponent is NotImplemented:
305
- return NotImplemented
305
+ return NotImplemented # pragma: no cover
306
306
  return self._with_exponent(exponent=new_exponent)
307
307
 
308
308
  @property
@@ -170,8 +170,6 @@ class PhaseGradientGate(raw_types.Gate):
170
170
  self, resolver: 'cirq.ParamResolver', recursive: bool
171
171
  ) -> 'PhaseGradientGate':
172
172
  new_exponent = cirq.resolve_parameters(self.exponent, resolver, recursive)
173
- if new_exponent is self.exponent:
174
- return self
175
173
  return PhaseGradientGate(num_qubits=self._num_qubits, exponent=new_exponent)
176
174
 
177
175
  def __str__(self) -> str:
@@ -302,7 +302,7 @@ class GateOperation(raw_types.Operation):
302
302
  def _decompose_into_clifford_(self):
303
303
  sub = getattr(self.gate, '_decompose_into_clifford_with_qubits_', None)
304
304
  if sub is None:
305
- return NotImplemented
305
+ return NotImplemented # pragma: no cover
306
306
  return sub(self.qubits)
307
307
 
308
308
  def _trace_distance_bound_(self) -> float:
@@ -454,6 +454,7 @@ def test_is_parameterized():
454
454
  return True
455
455
 
456
456
  q = cirq.LineQubit(0)
457
+ assert No1().num_qubits() == 1
457
458
  assert not cirq.is_parameterized(No1().on(q))
458
459
  assert not cirq.is_parameterized(No2().on(q))
459
460
  assert cirq.is_parameterized(Yes().on(q))
cirq/ops/gateset_test.py CHANGED
@@ -443,3 +443,10 @@ def test_gateset_contains_with_tags():
443
443
  # Both tags to accept and tags to ignore
444
444
  assert op in cirq.Gateset(gf_accept, gf_ignore)
445
445
  assert op_with_tag in cirq.Gateset(gf_accept, gf_ignore)
446
+
447
+
448
+ def test_gateset_contains_op_with_no_gate():
449
+ gf = cirq.GateFamily(cirq.ZPowGate)
450
+ op = cirq.X(cirq.q(1)).with_classical_controls('a')
451
+ assert op.gate is None
452
+ assert op not in gf
@@ -90,6 +90,11 @@ ancilla_1: ───X───X───
90
90
  )
91
91
 
92
92
 
93
+ def test_empty_qubits():
94
+ qm = cirq.GreedyQubitManager(prefix="anc")
95
+ assert qm.qalloc(0) == []
96
+
97
+
93
98
  def test_greedy_qubit_manager_preserves_order():
94
99
  qm = cirq.GreedyQubitManager(prefix="anc")
95
100
  ancillae = [cirq.q(f"anc_{i}") for i in range(100)]
@@ -54,6 +54,7 @@ def test_kraus_channel_remap_keys():
54
54
  kc_x = cirq.KrausChannel.from_channel(dp, key='x')
55
55
  assert cirq.with_measurement_key_mapping(kc_x, {'a': 'b'}) is kc_x
56
56
  assert cirq.measurement_key_name(cirq.with_key_path(kc_x, ('path',))) == 'path:x'
57
+ assert cirq.measurement_key_name(cirq.with_key_path_prefix(kc_x, ('path',))) == 'path:x'
57
58
 
58
59
  kc_a = cirq.KrausChannel.from_channel(dp, key='a')
59
60
  kc_b = cirq.KrausChannel.from_channel(dp, key='b')
@@ -55,6 +55,7 @@ def test_matrix_mixture_remap_keys():
55
55
  mm_x = cirq.MixedUnitaryChannel.from_mixture(dp, key='x')
56
56
  assert cirq.with_measurement_key_mapping(mm_x, {'a': 'b'}) is mm_x
57
57
  assert cirq.measurement_key_name(cirq.with_key_path(mm_x, ('path',))) == 'path:x'
58
+ assert cirq.measurement_key_name(cirq.with_key_path_prefix(mm_x, ('path',))) == 'path:x'
58
59
 
59
60
  mm_a = cirq.MixedUnitaryChannel.from_mixture(dp, key='a')
60
61
  mm_b = cirq.MixedUnitaryChannel.from_mixture(dp, key='b')
cirq/ops/op_tree_test.py CHANGED
@@ -135,6 +135,10 @@ def test_transform_leaves():
135
135
  # Just an item.
136
136
  assert move_tree_left_freeze(operations[0]) == expected[0]
137
137
 
138
+ # Just a moment
139
+ m = cirq.Moment(cirq.X(cirq.q(1)))
140
+ assert cirq.transform_op_tree(m, preserve_moments=True) is m
141
+
138
142
  # Flat list.
139
143
  assert move_tree_left_freeze(operations) == tuple(expected)
140
144
 
@@ -63,6 +63,7 @@ def test_measurement_eq():
63
63
  [
64
64
  (None, None, 'b'),
65
65
  (cirq.with_key_path, ('p', 'q'), 'p:q:a'),
66
+ (cirq.with_key_path_prefix, ('p', 'q'), 'p:q:a'),
66
67
  (cirq.with_measurement_key_mapping, {'a': 'b'}, 'b'),
67
68
  ],
68
69
  )
cirq/ops/pauli_string.py CHANGED
@@ -311,7 +311,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
311
311
  )
312
312
 
313
313
  if isinstance(other, raw_types.Operation) and isinstance(other.gate, identity.IdentityGate):
314
- return self
314
+ return self # pragma: no cover
315
315
 
316
316
  # Note: PauliString case handled by __mul__.
317
317
  return NotImplemented
@@ -462,7 +462,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
462
462
  fused = prefix + '*'.join(factors)
463
463
  if len(factors) > 1:
464
464
  return f'({fused})'
465
- return fused
465
+ return fused # pragma: no cover
466
466
 
467
467
  def __str__(self) -> str:
468
468
  ordered_qubits = sorted(self.qubits)
@@ -1646,88 +1646,11 @@ def _decompose_into_cliffords(op: 'cirq.Operation') -> List['cirq.Operation']:
1646
1646
  if decomposed is not None:
1647
1647
  return [out for sub_op in decomposed for out in _decompose_into_cliffords(sub_op)]
1648
1648
 
1649
- raise TypeError(
1649
+ raise TypeError( # pragma: no cover
1650
1650
  f'Operation is not a known Clifford and did not decompose into known Cliffords: {op!r}'
1651
1651
  )
1652
1652
 
1653
1653
 
1654
- def _pass_operation_over(
1655
- pauli_map: Dict[TKey, pauli_gates.Pauli], op: 'cirq.Operation', after_to_before: bool = False
1656
- ) -> bool:
1657
- if isinstance(op, gate_operation.GateOperation):
1658
- gate = op.gate
1659
- if isinstance(gate, clifford_gate.SingleQubitCliffordGate):
1660
- return _pass_single_clifford_gate_over(
1661
- pauli_map, gate, cast(TKey, op.qubits[0]), after_to_before=after_to_before
1662
- )
1663
- if isinstance(gate, pauli_interaction_gate.PauliInteractionGate):
1664
- return _pass_pauli_interaction_gate_over(
1665
- pauli_map,
1666
- gate,
1667
- cast(TKey, op.qubits[0]),
1668
- cast(TKey, op.qubits[1]),
1669
- after_to_before=after_to_before,
1670
- )
1671
- raise NotImplementedError(f'Unsupported operation: {op!r}')
1672
-
1673
-
1674
- def _pass_single_clifford_gate_over(
1675
- pauli_map: Dict[TKey, pauli_gates.Pauli],
1676
- gate: clifford_gate.SingleQubitCliffordGate,
1677
- qubit: TKey,
1678
- after_to_before: bool = False,
1679
- ) -> bool:
1680
- if qubit not in pauli_map:
1681
- return False # pragma: no cover
1682
- if not after_to_before:
1683
- gate **= -1
1684
- pauli, inv = gate.pauli_tuple(pauli_map[qubit])
1685
- pauli_map[qubit] = pauli
1686
- return inv
1687
-
1688
-
1689
- def _pass_pauli_interaction_gate_over(
1690
- pauli_map: Dict[TKey, pauli_gates.Pauli],
1691
- gate: pauli_interaction_gate.PauliInteractionGate,
1692
- qubit0: TKey,
1693
- qubit1: TKey,
1694
- after_to_before: bool = False,
1695
- ) -> bool:
1696
- def merge_and_kickback(
1697
- qubit: TKey,
1698
- pauli_left: Optional[pauli_gates.Pauli],
1699
- pauli_right: Optional[pauli_gates.Pauli],
1700
- inv: bool,
1701
- ) -> int:
1702
- assert pauli_left is not None or pauli_right is not None
1703
- if pauli_left is None or pauli_right is None:
1704
- pauli_map[qubit] = cast(pauli_gates.Pauli, pauli_left or pauli_right)
1705
- return 0
1706
- if pauli_left == pauli_right:
1707
- del pauli_map[qubit]
1708
- return 0
1709
-
1710
- pauli_map[qubit] = pauli_left.third(pauli_right)
1711
- if (pauli_left < pauli_right) ^ after_to_before:
1712
- return int(inv) * 2 + 1
1713
-
1714
- return int(inv) * 2 - 1
1715
-
1716
- quarter_kickback = 0
1717
- if qubit0 in pauli_map and not protocols.commutes(pauli_map[qubit0], gate.pauli0):
1718
- quarter_kickback += merge_and_kickback(
1719
- qubit1, gate.pauli1, pauli_map.get(qubit1), gate.invert1
1720
- )
1721
- if qubit1 in pauli_map and not protocols.commutes(pauli_map[qubit1], gate.pauli1):
1722
- quarter_kickback += merge_and_kickback(
1723
- qubit0, pauli_map.get(qubit0), gate.pauli0, gate.invert0
1724
- )
1725
- assert (
1726
- quarter_kickback % 2 == 0
1727
- ), 'Impossible condition. quarter_kickback is either incremented twice or never.'
1728
- return quarter_kickback % 4 == 2
1729
-
1730
-
1731
1654
  # Mypy has extreme difficulty with these constants for some reason.
1732
1655
  _i = cast(identity.IdentityGate, identity.I) # type: ignore
1733
1656
  _x = cast(pauli_gates.Pauli, pauli_gates.X) # type: ignore
@@ -1889,6 +1889,48 @@ def test_mutable_pauli_string_inplace_conjugate_by():
1889
1889
  p2 = p.inplace_after(cirq.S(a))
1890
1890
  assert p2 is p and p == cirq.X(a)
1891
1891
 
1892
+ # After sqrt-X and back.
1893
+ p2 = p.inplace_before(cirq.X(a) ** 0.5)
1894
+ assert p2 is p and p == cirq.X(a)
1895
+ p2 = p.inplace_after(cirq.X(a) ** 0.5)
1896
+ assert p2 is p and p == cirq.X(a)
1897
+
1898
+ # After sqrt-Y and back.
1899
+ p2 = p.inplace_before(cirq.Y(a) ** 0.5)
1900
+ assert p2 is p and p == cirq.Z(a)
1901
+ p2 = p.inplace_after(cirq.Y(a) ** 0.5)
1902
+ assert p2 is p and p == cirq.X(a)
1903
+
1904
+ # After inv-sqrt-Y and back.
1905
+ p2 = p.inplace_before(cirq.Y(a) ** 1.5)
1906
+ assert p2 is p and p == -cirq.Z(a)
1907
+ p2 = p.inplace_after(cirq.Y(a) ** 1.5)
1908
+ assert p2 is p and p == cirq.X(a)
1909
+
1910
+ # After X**0 and back.
1911
+ p2 = p.inplace_before(cirq.X(a) ** 0)
1912
+ assert p2 is p and p == cirq.X(a)
1913
+ p2 = p.inplace_after(cirq.X(a) ** 0)
1914
+ assert p2 is p and p == cirq.X(a)
1915
+
1916
+ # After Y**0 and back.
1917
+ p2 = p.inplace_before(cirq.Y(a) ** 0)
1918
+ assert p2 is p and p == cirq.X(a)
1919
+ p2 = p.inplace_after(cirq.Y(a) ** 0)
1920
+ assert p2 is p and p == cirq.X(a)
1921
+
1922
+ # After Z**0 and back.
1923
+ p2 = p.inplace_before(cirq.Z(a) ** 0)
1924
+ assert p2 is p and p == cirq.X(a)
1925
+ p2 = p.inplace_after(cirq.Z(a) ** 0)
1926
+ assert p2 is p and p == cirq.X(a)
1927
+
1928
+ # After H**0 and back.
1929
+ p2 = p.inplace_before(cirq.H(a) ** 0)
1930
+ assert p2 is p and p == cirq.X(a)
1931
+ p2 = p.inplace_after(cirq.H(a) ** 0)
1932
+ assert p2 is p and p == cirq.X(a)
1933
+
1892
1934
  # After inverse S and back.
1893
1935
  p2 = p.inplace_after(cirq.S(a) ** -1)
1894
1936
  assert p2 is p and p == -cirq.Y(a)
@@ -1900,6 +1942,10 @@ def test_mutable_pauli_string_inplace_conjugate_by():
1900
1942
  assert p2 is p and p == cirq.X(a)
1901
1943
 
1902
1944
  # Two qubit operation.
1945
+ p2 = p.inplace_after(cirq.CX(a, b) ** 0)
1946
+ assert p2 is p and p == cirq.X(a)
1947
+ p2 = p.inplace_after(cirq.CZ(a, b) ** 0)
1948
+ assert p2 is p and p == cirq.X(a)
1903
1949
  p2 = p.inplace_after(cirq.CZ(a, b))
1904
1950
  assert p2 is p and p == cirq.X(a) * cirq.Z(b)
1905
1951
  p2 = p.inplace_after(cirq.CZ(a, c))
cirq/ops/phased_x_gate.py CHANGED
@@ -116,7 +116,7 @@ class PhasedXPowGate(raw_types.Gate):
116
116
  def __pow__(self, exponent: Union[float, sympy.Expr]) -> 'PhasedXPowGate':
117
117
  new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
118
118
  if new_exponent is NotImplemented:
119
- return NotImplemented
119
+ return NotImplemented # pragma: no cover
120
120
  return PhasedXPowGate(
121
121
  phase_exponent=self._phase_exponent,
122
122
  exponent=new_exponent,
@@ -150,12 +150,6 @@ def test_mixture():
150
150
  assert {p for p, _ in m} == {7 / 8, 1 / 32, 3 / 32}
151
151
 
152
152
 
153
- def assert_channel_sums_to_identity(val):
154
- m = cirq.kraus(val)
155
- s = sum(np.conj(e.T) @ e for e in m)
156
- np.testing.assert_allclose(s, np.eye(np.prod(cirq.qid_shape(val), dtype=np.int64)), atol=1e-8)
157
-
158
-
159
153
  def test_channel():
160
154
  class NoDetailsGate(cirq.Gate):
161
155
  def num_qubits(self) -> int:
cirq/ops/raw_types.py CHANGED
@@ -902,7 +902,7 @@ class TaggedOperation(Operation):
902
902
  sub = getattr(self.sub_operation, "_is_measurement_", None)
903
903
  if sub is not None:
904
904
  return sub()
905
- return NotImplemented
905
+ return NotImplemented # pragma: no cover
906
906
 
907
907
  @cached_method
908
908
  def _is_parameterized_(self) -> bool:
@@ -77,6 +77,13 @@ def test_wrapped_qid():
77
77
  'dimension': 3,
78
78
  }
79
79
 
80
+ assert not ValidQubit('zz') == 4
81
+ assert ValidQubit('zz') != 4
82
+ assert ValidQubit('zz') > ValidQubit('aa')
83
+ assert ValidQubit('zz') <= ValidQubit('zz')
84
+ assert ValidQubit('zz') >= ValidQubit('zz')
85
+ assert ValidQubit('zz') >= ValidQubit('aa')
86
+
80
87
 
81
88
  def test_qid_dimension():
82
89
  assert ValidQubit('a').dimension == 2
@@ -210,6 +217,21 @@ def test_default_validation_and_inverse():
210
217
  cirq.testing.assert_implements_consistent_protocols(i, local_vals={'TestGate': TestGate})
211
218
 
212
219
 
220
+ def test_default_no_qubits():
221
+ class TestOp(cirq.Operation):
222
+ def with_qubits(self, *new_qubits):
223
+ raise NotImplementedError()
224
+
225
+ @property
226
+ def qubits(self):
227
+ pass
228
+
229
+ op = TestOp()
230
+ assert op.controlled_by(*[]) is op
231
+ op = TestOp().with_tags("abc")
232
+ assert op.classical_controls == frozenset()
233
+
234
+
213
235
  def test_default_inverse():
214
236
  class TestGate(cirq.Gate):
215
237
  def _num_qubits_(self):
@@ -357,7 +379,7 @@ def test_gate_shape_protocol():
357
379
  def test_operation_shape():
358
380
  class FixedQids(cirq.Operation):
359
381
  def with_qubits(self, *new_qids):
360
- raise NotImplementedError # pragma: no cover
382
+ raise NotImplementedError
361
383
 
362
384
  class QubitOp(FixedQids):
363
385
  @property
@@ -659,6 +681,9 @@ def test_tagged_operation_forwards_protocols():
659
681
  assert isinstance(controlled_y, cirq.Operation)
660
682
  assert not isinstance(controlled_y, cirq.TaggedOperation)
661
683
  classically_controlled_y = tagged_y.with_classical_controls("a")
684
+ assert classically_controlled_y.classical_controls == frozenset(
685
+ {cirq.KeyCondition(cirq.MeasurementKey(name='a'))}
686
+ )
662
687
  assert classically_controlled_y == y.with_classical_controls("a")
663
688
  assert isinstance(classically_controlled_y, cirq.Operation)
664
689
  assert not isinstance(classically_controlled_y, cirq.TaggedOperation)
@@ -358,7 +358,7 @@ class RecursiveDecompose(cirq.Gate):
358
358
 
359
359
  def _decompose_(self, qubits):
360
360
  if self.with_context:
361
- assert False
361
+ assert False # pragma: no cover
362
362
  else:
363
363
  return self._decompose_impl(qubits, self.mock_qm)
364
364
 
@@ -80,7 +80,8 @@ def test_via_apply_unitary():
80
80
 
81
81
  class No4: # A non-operation non-gate.
82
82
  def _apply_unitary_(self, args):
83
- assert False # Because has_unitary doesn't understand how to call.
83
+ # Because has_unitary doesn't understand how to call.
84
+ assert False # pragma: no cover
84
85
 
85
86
  class Yes1(EmptyOp):
86
87
  def _apply_unitary_(self, args):
@@ -155,13 +156,13 @@ def test_order():
155
156
  return True
156
157
 
157
158
  def _decompose_(self):
158
- assert False
159
+ assert False # pragma: no cover
159
160
 
160
161
  def _apply_unitary_(self, args):
161
- assert False
162
+ assert False # pragma: no cover
162
163
 
163
164
  def _unitary_(self):
164
- assert False
165
+ assert False # pragma: no cover
165
166
 
166
167
  class Yes2(EmptyOp):
167
168
  def _has_unitary_(self):
@@ -171,10 +172,10 @@ def test_order():
171
172
  return []
172
173
 
173
174
  def _apply_unitary_(self, args):
174
- assert False
175
+ assert False # pragma: no cover
175
176
 
176
177
  def _unitary_(self):
177
- assert False
178
+ assert False # pragma: no cover
178
179
 
179
180
  class Yes3(EmptyOp):
180
181
  def _has_unitary_(self):
@@ -187,7 +188,7 @@ def test_order():
187
188
  return args.target_tensor
188
189
 
189
190
  def _unitary_(self):
190
- assert False
191
+ assert False # pragma: no cover
191
192
 
192
193
  class Yes4(EmptyOp):
193
194
  def _has_unitary_(self):
@@ -84,20 +84,20 @@ def test_deprecated_cirq_type_in_json_dict():
84
84
  __module__ = 'test.noncirq.namespace'
85
85
 
86
86
  def __eq__(self, other):
87
- return isinstance(other, HasOldJsonDict)
87
+ return isinstance(other, HasOldJsonDict) # pragma: no cover
88
88
 
89
89
  def _json_dict_(self):
90
90
  return {'cirq_type': 'test.noncirq.namespace.HasOldJsonDict'}
91
91
 
92
92
  @classmethod
93
93
  def _from_json_dict_(cls, **kwargs):
94
- return cls()
94
+ return cls() # pragma: no cover
95
95
 
96
96
  with pytest.raises(ValueError, match='not a Cirq type'):
97
97
  _ = cirq.json_cirq_type(HasOldJsonDict)
98
98
 
99
99
  def custom_resolver(name):
100
- if name == 'test.noncirq.namespace.HasOldJsonDict':
100
+ if name == 'test.noncirq.namespace.HasOldJsonDict': # pragma: no cover
101
101
  return HasOldJsonDict
102
102
 
103
103
  test_resolvers = [custom_resolver] + cirq.DEFAULT_RESOLVERS
@@ -283,6 +283,7 @@ def test_builtins():
283
283
  def test_numpy():
284
284
  x = np.ones(1)[0]
285
285
 
286
+ assert_json_roundtrip_works(np.bool_(True))
286
287
  assert_json_roundtrip_works(x.astype(np.int8))
287
288
  assert_json_roundtrip_works(x.astype(np.int16))
288
289
  assert_json_roundtrip_works(x.astype(np.int32))
@@ -367,7 +368,7 @@ class SBKImpl(cirq.SerializableByKey):
367
368
 
368
369
  def __eq__(self, other):
369
370
  if not isinstance(other, SBKImpl):
370
- return False
371
+ return False # pragma: no cover
371
372
  return (
372
373
  self.name == other.name
373
374
  and self.data_list == other.data_list
@@ -542,7 +543,7 @@ def test_type_serialization(mod_spec: ModuleJsonTestSpec, cirq_obj_name: str, cl
542
543
  return pytest.xfail(reason="Not serializable (yet)")
543
544
 
544
545
  if cls is None:
545
- pytest.skip(f'No serialization for None-mapped type: {cirq_obj_name}')
546
+ pytest.skip(f'No serialization for None-mapped type: {cirq_obj_name}') # pragma: no cover
546
547
 
547
548
  try:
548
549
  typename = cirq.json_cirq_type(cls)
@@ -614,7 +615,7 @@ def _eval_repr_data_file(path: pathlib.Path, deprecation_deadline: Optional[str]
614
615
 
615
616
  for deprecation in TESTED_MODULES.values():
616
617
  if deprecation is not None and deprecation.old_name in content:
617
- ctx_managers.append(deprecation.deprecation_assertion)
618
+ ctx_managers.append(deprecation.deprecation_assertion) # pragma: no cover
618
619
 
619
620
  imports = {'cirq': cirq, 'pd': pd, 'sympy': sympy, 'np': np, 'datetime': datetime, 'nx': nx}
620
621
 
@@ -132,7 +132,7 @@ def kraus(
132
132
  """
133
133
  channel_getter = getattr(val, '_channel_', None)
134
134
  if channel_getter is not None:
135
- warnings.warn(
135
+ warnings.warn( # pragma: no cover
136
136
  '_channel_ is deprecated and will be removed in cirq 0.13, rename to _kraus_',
137
137
  DeprecationWarning,
138
138
  )
@@ -154,7 +154,7 @@ def kraus(
154
154
 
155
155
  channel_result = NotImplemented if channel_getter is None else channel_getter()
156
156
  if channel_result is not NotImplemented:
157
- return tuple(channel_result)
157
+ return tuple(channel_result) # pragma: no cover
158
158
 
159
159
  if default is not RaiseTypeErrorIfNotProvided:
160
160
  return default