cirq-core 1.2.0.dev20230717225858__py3-none-any.whl → 1.3.0__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.
Files changed (158) hide show
  1. cirq/__init__.py +5 -0
  2. cirq/_compat.py +26 -11
  3. cirq/_compat_test.py +37 -3
  4. cirq/_version.py +31 -1
  5. cirq/_version_test.py +1 -1
  6. cirq/circuits/circuit.py +106 -32
  7. cirq/circuits/circuit_operation.py +2 -2
  8. cirq/circuits/circuit_operation_test.py +1 -1
  9. cirq/circuits/circuit_test.py +109 -3
  10. cirq/circuits/frozen_circuit.py +80 -5
  11. cirq/circuits/frozen_circuit_test.py +47 -2
  12. cirq/circuits/qasm_output_test.py +9 -9
  13. cirq/conftest.py +1 -2
  14. cirq/contrib/acquaintance/devices.py +1 -1
  15. cirq/contrib/hacks/disable_validation_test.py +1 -1
  16. cirq/contrib/noise_models/noise_models.py +1 -2
  17. cirq/contrib/paulistring/clifford_optimize.py +1 -1
  18. cirq/contrib/paulistring/clifford_target_gateset_test.py +4 -4
  19. cirq/contrib/qcircuit/qcircuit_pdf.py +1 -1
  20. cirq/contrib/quimb/density_matrix.py +2 -3
  21. cirq/contrib/quimb/grid_circuits.py +3 -3
  22. cirq/contrib/quimb/state_vector.py +3 -5
  23. cirq/contrib/routing/utils.py +1 -2
  24. cirq/contrib/svg/svg.py +4 -6
  25. cirq/devices/grid_qubit.py +49 -38
  26. cirq/devices/grid_qubit_test.py +1 -3
  27. cirq/devices/insertion_noise_model.py +21 -1
  28. cirq/devices/insertion_noise_model_test.py +6 -0
  29. cirq/devices/line_qubit.py +67 -40
  30. cirq/devices/named_topologies.py +8 -14
  31. cirq/devices/noise_properties.py +1 -1
  32. cirq/devices/noise_utils.py +7 -5
  33. cirq/devices/noise_utils_test.py +7 -0
  34. cirq/experiments/fidelity_estimation_test.py +1 -1
  35. cirq/experiments/qubit_characterizations.py +6 -5
  36. cirq/experiments/random_quantum_circuit_generation.py +1 -1
  37. cirq/experiments/random_quantum_circuit_generation_test.py +28 -1
  38. cirq/experiments/readout_confusion_matrix.py +6 -6
  39. cirq/experiments/xeb_fitting.py +3 -5
  40. cirq/experiments/xeb_fitting_test.py +2 -2
  41. cirq/experiments/xeb_sampling.py +1 -1
  42. cirq/interop/quirk/url_to_circuit.py +40 -38
  43. cirq/json_resolver_cache.py +2 -0
  44. cirq/linalg/decompositions.py +6 -5
  45. cirq/ops/__init__.py +2 -0
  46. cirq/ops/classically_controlled_operation.py +1 -1
  47. cirq/ops/clifford_gate.py +9 -9
  48. cirq/ops/clifford_gate_test.py +3 -4
  49. cirq/ops/common_channels.py +2 -5
  50. cirq/ops/common_channels_test.py +3 -5
  51. cirq/ops/common_gates_test.py +7 -7
  52. cirq/ops/controlled_operation_test.py +2 -2
  53. cirq/ops/dense_pauli_string.py +3 -0
  54. cirq/ops/eigen_gate_test.py +1 -3
  55. cirq/ops/fourier_transform.py +1 -2
  56. cirq/ops/fsim_gate.py +1 -1
  57. cirq/ops/gate_features_test.py +2 -2
  58. cirq/ops/gate_operation_test.py +1 -2
  59. cirq/ops/greedy_qubit_manager.py +86 -0
  60. cirq/ops/greedy_qubit_manager_test.py +98 -0
  61. cirq/ops/linear_combinations.py +1 -1
  62. cirq/ops/named_qubit.py +55 -18
  63. cirq/ops/parity_gates.py +65 -18
  64. cirq/ops/parity_gates_test.py +41 -2
  65. cirq/ops/pauli_gates.py +2 -2
  66. cirq/ops/pauli_string.py +3 -4
  67. cirq/ops/pauli_string_raw_types_test.py +3 -3
  68. cirq/ops/pauli_string_test.py +3 -4
  69. cirq/ops/random_gate_channel_test.py +3 -3
  70. cirq/ops/raw_types.py +1 -1
  71. cirq/ops/raw_types_test.py +5 -5
  72. cirq/ops/three_qubit_gates.py +12 -8
  73. cirq/protocols/act_on_protocol_test.py +9 -9
  74. cirq/protocols/apply_channel_protocol.py +9 -6
  75. cirq/protocols/apply_unitary_protocol_test.py +1 -1
  76. cirq/protocols/equal_up_to_global_phase_protocol_test.py +2 -2
  77. cirq/protocols/has_stabilizer_effect_protocol.py +52 -6
  78. cirq/protocols/has_stabilizer_effect_protocol_test.py +21 -8
  79. cirq/protocols/has_unitary_protocol_test.py +1 -3
  80. cirq/protocols/json_serialization.py +6 -6
  81. cirq/protocols/json_serialization_test.py +7 -14
  82. cirq/protocols/json_test_data/InsertionNoiseModel.json +91 -0
  83. cirq/protocols/json_test_data/InsertionNoiseModel.repr +4 -0
  84. cirq/protocols/json_test_data/OpIdentifier.json +45 -10
  85. cirq/protocols/json_test_data/OpIdentifier.repr +7 -1
  86. cirq/protocols/json_test_data/spec.py +4 -0
  87. cirq/protocols/measurement_key_protocol_test.py +1 -1
  88. cirq/protocols/unitary_protocol_test.py +13 -16
  89. cirq/qis/clifford_tableau.py +7 -8
  90. cirq/qis/measures.py +1 -1
  91. cirq/qis/states.py +2 -3
  92. cirq/sim/__init__.py +2 -0
  93. cirq/sim/classical_simulator.py +107 -0
  94. cirq/sim/classical_simulator_test.py +207 -0
  95. cirq/sim/clifford/clifford_simulator_test.py +7 -7
  96. cirq/sim/clifford/stabilizer_simulation_state.py +2 -2
  97. cirq/sim/clifford/stabilizer_state_ch_form.py +7 -7
  98. cirq/sim/density_matrix_simulation_state.py +19 -4
  99. cirq/sim/density_matrix_simulator_test.py +5 -13
  100. cirq/sim/simulation_state_test.py +13 -14
  101. cirq/sim/simulator_test.py +6 -9
  102. cirq/sim/state_vector_simulation_state.py +1 -1
  103. cirq/study/resolver.py +41 -41
  104. cirq/study/resolver_test.py +13 -12
  105. cirq/testing/__init__.py +4 -1
  106. cirq/testing/circuit_compare.py +1 -1
  107. cirq/testing/circuit_compare_test.py +11 -11
  108. cirq/testing/consistent_controlled_gate_op.py +15 -1
  109. cirq/testing/consistent_controlled_gate_op_test.py +12 -3
  110. cirq/testing/consistent_decomposition.py +0 -1
  111. cirq/testing/consistent_protocols.py +6 -1
  112. cirq/testing/consistent_protocols_test.py +5 -10
  113. cirq/testing/consistent_qasm.py +2 -4
  114. cirq/testing/consistent_qasm_test.py +2 -3
  115. cirq/testing/consistent_specified_has_unitary_test.py +1 -3
  116. cirq/testing/equals_tester.py +1 -1
  117. cirq/testing/equals_tester_test.py +5 -5
  118. cirq/testing/equivalent_repr_eval_test.py +1 -3
  119. cirq/testing/gate_features_test.py +6 -6
  120. cirq/testing/order_tester_test.py +1 -3
  121. cirq/testing/random_circuit_test.py +1 -3
  122. cirq/transformers/__init__.py +3 -0
  123. cirq/transformers/analytical_decompositions/__init__.py +1 -0
  124. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +1 -2
  125. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +2 -5
  126. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +38 -0
  127. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +18 -0
  128. cirq/transformers/expand_composite_test.py +4 -4
  129. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +1 -1
  130. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +1 -2
  131. cirq/transformers/merge_k_qubit_gates_test.py +2 -2
  132. cirq/transformers/qubit_management_transformers.py +177 -0
  133. cirq/transformers/qubit_management_transformers_test.py +250 -0
  134. cirq/transformers/routing/route_circuit_cqc.py +23 -4
  135. cirq/transformers/routing/route_circuit_cqc_test.py +42 -0
  136. cirq/transformers/stratify.py +10 -11
  137. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +10 -10
  138. cirq/transformers/target_gatesets/cz_gateset_test.py +8 -10
  139. cirq/transformers/transformer_primitives.py +138 -28
  140. cirq/value/abc_alt_test.py +4 -4
  141. cirq/value/duration.py +68 -37
  142. cirq/value/duration_test.py +2 -0
  143. cirq/value/measurement_key_test.py +1 -1
  144. cirq/value/product_state.py +4 -8
  145. cirq/value/value_equality_attr.py +12 -5
  146. cirq/vis/heatmap.py +7 -4
  147. cirq/vis/heatmap_test.py +14 -4
  148. cirq/vis/histogram.py +4 -4
  149. cirq/vis/state_histogram.py +10 -6
  150. cirq/vis/state_histogram_test.py +2 -0
  151. cirq/work/observable_measurement_data_test.py +1 -1
  152. cirq/work/observable_measurement_test.py +2 -2
  153. cirq/work/zeros_sampler.py +1 -1
  154. {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/METADATA +11 -19
  155. {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/RECORD +158 -150
  156. {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/WHEEL +1 -1
  157. {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/LICENSE +0 -0
  158. {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/top_level.txt +0 -0
@@ -108,12 +108,11 @@ def benchmark_2q_xeb_fidelities(
108
108
  def _try_keep(k):
109
109
  """If all the values for a key `k` are the same in this group, we can keep it."""
110
110
  if k not in df.columns:
111
- return # coverage: ignore
111
+ return # pragma: no cover
112
112
  vals = df[k].unique()
113
113
  if len(vals) == 1:
114
114
  ret[k] = vals[0]
115
- else:
116
- # coverage: ignore
115
+ else: # pragma: no cover
117
116
  raise AssertionError(
118
117
  f"When computing per-cycle-depth fidelity, multiple "
119
118
  f"values for {k} were grouped together: {vals}"
@@ -574,8 +573,7 @@ def _fit_exponential_decay(
574
573
  p0=(a_0, layer_fid_0),
575
574
  bounds=((0, 0), (1, 1)),
576
575
  )
577
- except ValueError: # coverage: ignore
578
- # coverage: ignore
576
+ except ValueError: # pragma: no cover
579
577
  return 0, 0, np.inf, np.inf
580
578
 
581
579
  a_std, layer_fid_std = np.sqrt(np.diag(pcov))
@@ -129,8 +129,8 @@ def test_benchmark_2q_xeb_fidelities_parallel():
129
129
 
130
130
  def test_benchmark_2q_xeb_fidelities_vectorized():
131
131
  rs = np.random.RandomState(52)
132
- dummy_records = [{'pure_probs': rs.rand(4), 'sampled_probs': rs.rand(4)} for _ in range(100)]
133
- df = pd.DataFrame(dummy_records)
132
+ mock_records = [{'pure_probs': rs.rand(4), 'sampled_probs': rs.rand(4)} for _ in range(100)]
133
+ df = pd.DataFrame(mock_records)
134
134
 
135
135
  # Using `df.apply` is wayyyy slower than the new implementation!
136
136
  # but they should give the same results
@@ -130,7 +130,7 @@ def _verify_two_line_qubits_from_circuits(circuits: Sequence['cirq.Circuit']):
130
130
 
131
131
 
132
132
  class _NoProgress:
133
- """Dummy (lack of) tqdm-style progress bar."""
133
+ """Lack of tqdm-style progress bar."""
134
134
 
135
135
  def __init__(self, total: int):
136
136
  pass
@@ -77,39 +77,40 @@ def quirk_url_to_circuit(
77
77
  a billion laughs attack in the form of nested custom gates.
78
78
 
79
79
  Examples:
80
- >>> print(cirq.quirk_url_to_circuit(
81
- ... 'http://algassert.com/quirk#circuit={"cols":[["H"],["•","X"]]}'
82
- ... ))
83
- 0: ───H───@───
84
-
85
- 1: ───────X───
86
-
87
- >>> print(cirq.quirk_url_to_circuit(
88
- ... 'http://algassert.com/quirk#circuit={"cols":[["H"],["•","X"]]}',
89
- ... qubits=[cirq.NamedQubit('Alice'), cirq.NamedQubit('Bob')]
90
- ... ))
91
- Alice: ───H───@───
92
-
93
- Bob: ─────────X───
94
-
95
- >>> print(cirq.quirk_url_to_circuit(
96
- ... 'http://algassert.com/quirk#circuit={"cols":[["iswap"]]}',
97
- ... extra_cell_makers={'iswap': cirq.ISWAP}))
98
- 0: ───iSwap───
99
-
100
- 1: ───iSwap───
101
-
102
- >>> print(cirq.quirk_url_to_circuit(
103
- ... 'http://algassert.com/quirk#circuit={"cols":[["iswap"]]}',
104
- ... extra_cell_makers=[
105
- ... cirq.interop.quirk.cells.CellMaker(
106
- ... identifier='iswap',
107
- ... size=2,
108
- ... maker=lambda args: cirq.ISWAP(*args.qubits))
109
- ... ]))
110
- 0: ───iSwap───
80
+
81
+ >>> print(cirq.quirk_url_to_circuit(
82
+ ... 'http://algassert.com/quirk#circuit={"cols":[["H"],["•","X"]]}'
83
+ ... ))
84
+ 0: ───H───@───
111
85
 
112
- 1: ───iSwap───
86
+ 1: ───────X───
87
+
88
+ >>> print(cirq.quirk_url_to_circuit(
89
+ ... 'http://algassert.com/quirk#circuit={"cols":[["H"],["•","X"]]}',
90
+ ... qubits=[cirq.NamedQubit('Alice'), cirq.NamedQubit('Bob')]
91
+ ... ))
92
+ Alice: ───H───@───
93
+
94
+ Bob: ─────────X───
95
+
96
+ >>> print(cirq.quirk_url_to_circuit(
97
+ ... 'http://algassert.com/quirk#circuit={"cols":[["iswap"]]}',
98
+ ... extra_cell_makers={'iswap': cirq.ISWAP}))
99
+ 0: ───iSwap───
100
+
101
+ 1: ───iSwap───
102
+
103
+ >>> print(cirq.quirk_url_to_circuit(
104
+ ... 'http://algassert.com/quirk#circuit={"cols":[["iswap"]]}',
105
+ ... extra_cell_makers=[
106
+ ... cirq.interop.quirk.cells.CellMaker(
107
+ ... identifier='iswap',
108
+ ... size=2,
109
+ ... maker=lambda args: cirq.ISWAP(*args.qubits))
110
+ ... ]))
111
+ 0: ───iSwap───
112
+
113
+ 1: ───iSwap───
113
114
 
114
115
  Returns:
115
116
  The parsed circuit.
@@ -172,12 +173,13 @@ def quirk_json_to_circuit(
172
173
  a billion laughs attack in the form of nested custom gates.
173
174
 
174
175
  Examples:
175
- >>> print(cirq.quirk_json_to_circuit(
176
- ... {"cols":[["H"], ["•", "X"]]}
177
- ... ))
178
- 0: ───H───@───
179
-
180
- 1: ───────X───
176
+
177
+ >>> print(cirq.quirk_json_to_circuit(
178
+ ... {"cols":[["H"], ["•", "X"]]}
179
+ ... ))
180
+ 0: ───H───@───
181
+
182
+ 1: ───────X───
181
183
 
182
184
  Returns:
183
185
  The parsed circuit.
@@ -47,6 +47,7 @@ def _class_resolver_dictionary() -> Dict[str, ObjectFactory]:
47
47
  import pandas as pd
48
48
  import numpy as np
49
49
  from cirq.devices.noise_model import _NoNoiseModel
50
+ from cirq.devices import InsertionNoiseModel
50
51
  from cirq.experiments import GridInteractionLayer
51
52
  from cirq.experiments.grid_parallel_two_qubit_xeb import GridParallelXEBMetadata
52
53
 
@@ -147,6 +148,7 @@ def _class_resolver_dictionary() -> Dict[str, ObjectFactory]:
147
148
  'ISwapPowGate': cirq.ISwapPowGate,
148
149
  'IdentityGate': cirq.IdentityGate,
149
150
  'InitObsSetting': cirq.work.InitObsSetting,
151
+ 'InsertionNoiseModel': InsertionNoiseModel,
150
152
  'KeyCondition': cirq.KeyCondition,
151
153
  'KrausChannel': cirq.KrausChannel,
152
154
  'LinearDict': cirq.LinearDict,
@@ -20,6 +20,7 @@ import math
20
20
  from typing import (
21
21
  Any,
22
22
  Callable,
23
+ cast,
23
24
  Iterable,
24
25
  List,
25
26
  Optional,
@@ -33,7 +34,7 @@ from typing import (
33
34
  import matplotlib.pyplot as plt
34
35
 
35
36
  # this is for older systems with matplotlib <3.2 otherwise 3d projections fail
36
- from mpl_toolkits import mplot3d # pylint: disable=unused-import
37
+ from mpl_toolkits import mplot3d
37
38
  import numpy as np
38
39
 
39
40
  from cirq import value, protocols
@@ -554,7 +555,7 @@ def scatter_plot_normalized_kak_interaction_coefficients(
554
555
  interactions: Iterable[Union[np.ndarray, 'cirq.SupportsUnitary', 'KakDecomposition']],
555
556
  *,
556
557
  include_frame: bool = True,
557
- ax: Optional[plt.Axes] = None,
558
+ ax: Optional[mplot3d.axes3d.Axes3D] = None,
558
559
  **kwargs,
559
560
  ):
560
561
  r"""Plots the interaction coefficients of many two-qubit operations.
@@ -633,13 +634,13 @@ def scatter_plot_normalized_kak_interaction_coefficients(
633
634
  show_plot = not ax
634
635
  if not ax:
635
636
  fig = plt.figure()
636
- ax = fig.add_subplot(1, 1, 1, projection='3d')
637
+ ax = cast(mplot3d.axes3d.Axes3D, fig.add_subplot(1, 1, 1, projection='3d'))
637
638
 
638
639
  def coord_transform(
639
640
  pts: Union[List[Tuple[int, int, int]], np.ndarray]
640
- ) -> Tuple[Iterable[float], Iterable[float], Iterable[float]]:
641
+ ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
641
642
  if len(pts) == 0:
642
- return [], [], []
643
+ return np.array([]), np.array([]), np.array([])
643
644
  xs, ys, zs = np.transpose(pts)
644
645
  return xs, zs, ys
645
646
 
cirq/ops/__init__.py CHANGED
@@ -122,6 +122,8 @@ from cirq.ops.controlled_operation import ControlledOperation
122
122
 
123
123
  from cirq.ops.qubit_manager import BorrowableQubit, CleanQubit, QubitManager, SimpleQubitManager
124
124
 
125
+ from cirq.ops.greedy_qubit_manager import GreedyQubitManager
126
+
125
127
  from cirq.ops.qubit_order import QubitOrder
126
128
 
127
129
  from cirq.ops.qubit_order_or_list import QubitOrderOrList
@@ -155,7 +155,7 @@ class ClassicallyControlledOperation(raw_types.Operation):
155
155
  )
156
156
  sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)
157
157
  if sub_info is None:
158
- return NotImplemented # coverage: ignore
158
+ return NotImplemented # pragma: no cover
159
159
  control_label_count = 0
160
160
  if args.label_map is not None:
161
161
  control_label_count = len({k for c in self._conditions for k in c.keys})
cirq/ops/clifford_gate.py CHANGED
@@ -448,7 +448,7 @@ class CliffordGate(raw_types.Gate, CommonCliffordGates):
448
448
  sim_state._state = sim_state.tableau.then(padded_tableau)
449
449
  return True
450
450
 
451
- if isinstance(sim_state, sim.clifford.StabilizerChFormSimulationState): # coverage: ignore
451
+ if isinstance(sim_state, sim.clifford.StabilizerChFormSimulationState): # pragma: no cover
452
452
  # Do we know how to apply CliffordTableau on StabilizerChFormSimulationState?
453
453
  # It should be unlike because CliffordTableau ignores the global phase but CHForm
454
454
  # is aimed to fix that.
@@ -683,25 +683,26 @@ class SingleQubitCliffordGate(CliffordGate):
683
683
  flip_index = int(z_to_flip) * 2 + x_to_flip
684
684
  a, x, z = 0.0, 0.0, 0.0
685
685
 
686
- if np.array_equal(self.clifford_tableau.matrix(), [[1, 0], [0, 1]]):
686
+ matrix = self.clifford_tableau.matrix()
687
+ if np.array_equal(matrix, [[1, 0], [0, 1]]):
687
688
  # I, Z, X, Y cases
688
689
  to_phased_xz = [(0.0, 0.0, 0.0), (0.0, 0.0, 1.0), (0.0, 1.0, 0.0), (0.5, 1.0, 0.0)]
689
690
  a, x, z = to_phased_xz[flip_index]
690
- elif np.array_equal(self.clifford_tableau.matrix(), [[1, 0], [1, 1]]):
691
+ elif np.array_equal(matrix, [[1, 0], [1, 1]]):
691
692
  # +/- X_sqrt, 2 Hadamard-like gates acting on the YZ plane
692
693
  a = 0.0
693
694
  x = 0.5 if x_to_flip ^ z_to_flip else -0.5
694
695
  z = 1.0 if x_to_flip else 0.0
695
- elif np.array_equal(self.clifford_tableau.matrix(), [[0, 1], [1, 0]]):
696
+ elif np.array_equal(matrix, [[0, 1], [1, 0]]):
696
697
  # +/- Y_sqrt, 2 Hadamard-like gates acting on the XZ plane
697
698
  a = 0.5
698
699
  x = 0.5 if x_to_flip else -0.5
699
700
  z = 0.0 if x_to_flip ^ z_to_flip else 1.0
700
- elif np.array_equal(self.clifford_tableau.matrix(), [[1, 1], [0, 1]]):
701
+ elif np.array_equal(matrix, [[1, 1], [0, 1]]):
701
702
  # +/- Z_sqrt, 2 Hadamard-like gates acting on the XY plane
702
703
  to_phased_xz = [(0.0, 0.0, 0.5), (0.0, 0.0, -0.5), (0.25, 1.0, 0.0), (-0.25, 1.0, 0.0)]
703
704
  a, x, z = to_phased_xz[flip_index]
704
- elif np.array_equal(self.clifford_tableau.matrix(), [[0, 1], [1, 1]]):
705
+ elif np.array_equal(matrix, [[0, 1], [1, 1]]):
705
706
  # axis swapping rotation -- (312) permutation
706
707
  a = 0.5
707
708
  x = 0.5 if x_to_flip else -0.5
@@ -709,7 +710,7 @@ class SingleQubitCliffordGate(CliffordGate):
709
710
  else:
710
711
  # axis swapping rotation -- (231) permutation.
711
712
  # This should be the only cases left.
712
- assert np.array_equal(self.clifford_tableau.matrix(), [[1, 1], [1, 0]])
713
+ assert np.array_equal(matrix, [[1, 1], [1, 0]])
713
714
  a = 0.0
714
715
  x = -0.5 if x_to_flip ^ z_to_flip else 0.5
715
716
  z = -0.5 if x_to_flip else 0.5
@@ -846,8 +847,7 @@ class SingleQubitCliffordGate(CliffordGate):
846
847
  ]
847
848
 
848
849
  return [(pauli_gates.Z, 1 if y_rot[1] else -1), (pauli_gates.X, 1 if z_rot[1] else -1)]
849
- # coverage: ignore
850
- assert (
850
+ assert ( # pragma: no cover
851
851
  False
852
852
  ), 'Impossible condition where this gate only rotates one Pauli to a different Pauli.'
853
853
 
@@ -20,7 +20,7 @@ import numpy as np
20
20
  import pytest
21
21
 
22
22
  import cirq
23
- from cirq.protocols.act_on_protocol_test import DummySimulationState
23
+ from cirq.protocols.act_on_protocol_test import ExampleSimulationState
24
24
  from cirq.testing import EqualsTester, assert_allclose_up_to_global_phase
25
25
 
26
26
  _bools = (False, True)
@@ -47,7 +47,7 @@ def _assert_no_collision(gate) -> None:
47
47
 
48
48
 
49
49
  def _all_rotations():
50
- for (pauli, flip) in itertools.product(_paulis, _bools):
50
+ for pauli, flip in itertools.product(_paulis, _bools):
51
51
  yield (pauli, flip)
52
52
 
53
53
 
@@ -490,7 +490,6 @@ def test_commutes_pauli(gate, pauli, half_turns):
490
490
 
491
491
 
492
492
  def test_to_clifford_tableau_util_function():
493
-
494
493
  tableau = cirq.ops.clifford_gate._to_clifford_tableau(
495
494
  x_to=(cirq.X, False), z_to=(cirq.Z, False)
496
495
  )
@@ -879,7 +878,7 @@ def test_clifford_gate_act_on_ch_form():
879
878
 
880
879
  def test_clifford_gate_act_on_fail():
881
880
  with pytest.raises(TypeError, match="Failed to act"):
882
- cirq.act_on(cirq.CliffordGate.X, DummySimulationState(), qubits=())
881
+ cirq.act_on(cirq.CliffordGate.X, ExampleSimulationState(), qubits=())
883
882
 
884
883
 
885
884
  def test_all_single_qubit_clifford_unitaries():
@@ -400,13 +400,10 @@ class GeneralizedAmplitudeDampingChannel(raw_types.Gate):
400
400
  This channel evolves a density matrix via
401
401
 
402
402
  $$
403
- \rho \rightarrow M_0 \rho M_0^\dagger
404
- + M_1 \rho M_1^\dagger
405
- + M_2 \rho M_2^\dagger
406
- + M_3 \rho M_3^\dagger
403
+ \rho \rightarrow \sum_{i=0}^3 M_i \rho M_i^\dagger
407
404
  $$
408
405
 
409
- With
406
+ with
410
407
 
411
408
  $$
412
409
  \begin{aligned}
@@ -18,7 +18,7 @@ import numpy as np
18
18
  import pytest
19
19
 
20
20
  import cirq
21
- from cirq.protocols.act_on_protocol_test import DummySimulationState
21
+ from cirq.protocols.act_on_protocol_test import ExampleSimulationState
22
22
 
23
23
  X = np.array([[0, 1], [1, 0]])
24
24
  Y = np.array([[0, -1j], [1j, 0]])
@@ -87,7 +87,6 @@ def test_asymmetric_depolarizing_channel_str():
87
87
 
88
88
 
89
89
  def test_asymmetric_depolarizing_channel_eq():
90
-
91
90
  a = cirq.asymmetric_depolarize(0.0099999, 0.01)
92
91
  b = cirq.asymmetric_depolarize(0.01, 0.0099999)
93
92
  c = cirq.asymmetric_depolarize(0.0, 0.0, 0.0)
@@ -492,7 +491,7 @@ def test_reset_channel_text_diagram():
492
491
 
493
492
  def test_reset_act_on():
494
493
  with pytest.raises(TypeError, match="Failed to act"):
495
- cirq.act_on(cirq.ResetChannel(), DummySimulationState(), qubits=())
494
+ cirq.act_on(cirq.ResetChannel(), ExampleSimulationState(), qubits=())
496
495
 
497
496
  args = cirq.StateVectorSimulationState(
498
497
  available_buffer=np.empty(shape=(2, 2, 2, 2, 2), dtype=np.complex64),
@@ -697,7 +696,6 @@ def test_bit_flip_channel_str():
697
696
 
698
697
 
699
698
  def test_bit_flip_channel_eq():
700
-
701
699
  a = cirq.bit_flip(0.0099999)
702
700
  b = cirq.bit_flip(0.01)
703
701
  c = cirq.bit_flip(0.0)
@@ -735,7 +733,7 @@ def test_bit_flip_channel_text_diagram():
735
733
  def test_stabilizer_supports_depolarize():
736
734
  with pytest.raises(TypeError, match="act_on"):
737
735
  for _ in range(100):
738
- cirq.act_on(cirq.depolarize(3 / 4), DummySimulationState(), qubits=())
736
+ cirq.act_on(cirq.depolarize(3 / 4), ExampleSimulationState(), qubits=())
739
737
 
740
738
  q = cirq.LineQubit(0)
741
739
  c = cirq.Circuit(cirq.depolarize(3 / 4).on(q), cirq.measure(q, key='m'))
@@ -17,7 +17,7 @@ import pytest
17
17
  import sympy
18
18
 
19
19
  import cirq
20
- from cirq.protocols.act_on_protocol_test import DummySimulationState
20
+ from cirq.protocols.act_on_protocol_test import ExampleSimulationState
21
21
 
22
22
  H = np.array([[1, 1], [1, -1]]) * np.sqrt(0.5)
23
23
  HH = cirq.kron(H, H)
@@ -310,7 +310,7 @@ def test_h_str():
310
310
 
311
311
  def test_x_act_on_tableau():
312
312
  with pytest.raises(TypeError, match="Failed to act"):
313
- cirq.act_on(cirq.X, DummySimulationState(), qubits=())
313
+ cirq.act_on(cirq.X, ExampleSimulationState(), qubits=())
314
314
  original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
315
315
  flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)
316
316
 
@@ -359,7 +359,7 @@ class MinusOnePhaseGate(cirq.testing.SingleQubitGate):
359
359
 
360
360
  def test_y_act_on_tableau():
361
361
  with pytest.raises(TypeError, match="Failed to act"):
362
- cirq.act_on(cirq.Y, DummySimulationState(), qubits=())
362
+ cirq.act_on(cirq.Y, ExampleSimulationState(), qubits=())
363
363
  original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
364
364
  flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)
365
365
 
@@ -397,9 +397,9 @@ def test_y_act_on_tableau():
397
397
 
398
398
  def test_z_h_act_on_tableau():
399
399
  with pytest.raises(TypeError, match="Failed to act"):
400
- cirq.act_on(cirq.Z, DummySimulationState(), qubits=())
400
+ cirq.act_on(cirq.Z, ExampleSimulationState(), qubits=())
401
401
  with pytest.raises(TypeError, match="Failed to act"):
402
- cirq.act_on(cirq.H, DummySimulationState(), qubits=())
402
+ cirq.act_on(cirq.H, ExampleSimulationState(), qubits=())
403
403
  original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
404
404
  flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)
405
405
 
@@ -450,7 +450,7 @@ def test_z_h_act_on_tableau():
450
450
 
451
451
  def test_cx_act_on_tableau():
452
452
  with pytest.raises(TypeError, match="Failed to act"):
453
- cirq.act_on(cirq.CX, DummySimulationState(), qubits=())
453
+ cirq.act_on(cirq.CX, ExampleSimulationState(), qubits=())
454
454
  original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
455
455
 
456
456
  state = cirq.CliffordTableauSimulationState(
@@ -494,7 +494,7 @@ def test_cx_act_on_tableau():
494
494
 
495
495
  def test_cz_act_on_tableau():
496
496
  with pytest.raises(TypeError, match="Failed to act"):
497
- cirq.act_on(cirq.CZ, DummySimulationState(), qubits=())
497
+ cirq.act_on(cirq.CZ, ExampleSimulationState(), qubits=())
498
498
  original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
499
499
 
500
500
  state = cirq.CliffordTableauSimulationState(
@@ -446,10 +446,10 @@ def test_controlled_operation_gate():
446
446
  class Gateless(cirq.Operation):
447
447
  @property
448
448
  def qubits(self):
449
- return () # coverage: ignore
449
+ return () # pragma: no cover
450
450
 
451
451
  def with_qubits(self, *new_qubits):
452
- return self # coverage: ignore
452
+ return self # pragma: no cover
453
453
 
454
454
  def _has_mixture_(self):
455
455
  return True
@@ -570,6 +570,9 @@ class MutableDensePauliString(BaseDensePauliString):
570
570
  def __str__(self) -> str:
571
571
  return super().__str__() + ' (mutable)'
572
572
 
573
+ def _value_equality_values_(self):
574
+ return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
575
+
573
576
  @classmethod
574
577
  def inline_gaussian_elimination(cls, rows: 'List[MutableDensePauliString]') -> None:
575
578
  if not rows:
@@ -201,8 +201,7 @@ def test_trace_distance_bound():
201
201
  assert cirq.approx_eq(cirq.trace_distance_bound(CExpZinGate(2)), 1)
202
202
 
203
203
  class E(cirq.EigenGate):
204
- def _num_qubits_(self):
205
- # coverage: ignore
204
+ def _num_qubits_(self): # pragma: no cover
206
205
  return 1
207
206
 
208
207
  def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
@@ -227,7 +226,6 @@ def test_extrapolate():
227
226
 
228
227
 
229
228
  def test_matrix():
230
-
231
229
  for n in [1, 2, 3, 4, 0.0001, 3.9999]:
232
230
  assert cirq.has_unitary(CExpZinGate(n))
233
231
 
@@ -146,8 +146,7 @@ class PhaseGradientGate(raw_types.Gate):
146
146
 
147
147
  def __pow__(self, power):
148
148
  new_exponent = cirq.mul(self.exponent, power, NotImplemented)
149
- if new_exponent is NotImplemented:
150
- # coverage: ignore
149
+ if new_exponent is NotImplemented: # pragma: no cover
151
150
  return NotImplemented
152
151
  return PhaseGradientGate(num_qubits=self._num_qubits, exponent=new_exponent)
153
152
 
cirq/ops/fsim_gate.py CHANGED
@@ -81,7 +81,7 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
81
81
  $$
82
82
 
83
83
  $$
84
- c = e^{i \phi}
84
+ c = e^{-i \phi}
85
85
  $$
86
86
 
87
87
  Note the difference in sign conventions between FSimGate and the
@@ -53,7 +53,7 @@ def test_qasm_output_args_format():
53
53
 
54
54
 
55
55
  def test_multi_qubit_gate_validate():
56
- class Dummy(cirq.Gate):
56
+ class Example(cirq.Gate):
57
57
  def _num_qubits_(self) -> int:
58
58
  return self._num_qubits
59
59
 
@@ -62,7 +62,7 @@ def test_multi_qubit_gate_validate():
62
62
 
63
63
  a, b, c, d = cirq.LineQubit.range(4)
64
64
 
65
- g = Dummy(3)
65
+ g = Example(3)
66
66
 
67
67
  assert g.num_qubits() == 3
68
68
  g.validate_args([a, b, c])
@@ -523,8 +523,7 @@ def test_gate_to_operation_to_gate_round_trips():
523
523
  if gate_cls in skip_classes:
524
524
  skipped.add(gate_cls)
525
525
  continue
526
- # coverage:ignore
527
- raise AssertionError(
526
+ raise AssertionError( # pragma: no cover
528
527
  f"{gate_cls} has no json file, please add a json file or add to the list of "
529
528
  "classes to be skipped if there is a reason this gate should not round trip "
530
529
  "to a gate via creating an operation."
@@ -0,0 +1,86 @@
1
+ # Copyright 2023 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Iterable, List, Set, TYPE_CHECKING
16
+
17
+ from cirq.ops import named_qubit, qid_util, qubit_manager
18
+
19
+ if TYPE_CHECKING:
20
+ import cirq
21
+
22
+
23
+ class GreedyQubitManager(qubit_manager.QubitManager):
24
+ """Greedy allocator that maximizes/minimizes qubit reuse based on a configurable parameter.
25
+
26
+ GreedyQubitManager can be configured, using `maximize_reuse` flag, to work in one of two modes:
27
+ - Minimize qubit reuse (maximize_reuse=False): For a fixed width, this mode uses a FIFO (First
28
+ in First out) strategy s.t. next allocated qubit is one which was freed the earliest.
29
+ - Maximize qubit reuse (maximize_reuse=True): For a fixed width, this mode uses a LIFO (Last in
30
+ First out) strategy s.t. the next allocated qubit is one which was freed the latest.
31
+
32
+ If the requested qubits are more than the set of free qubits, the qubit manager automatically
33
+ resizes the size of the managed qubit pool and adds new free qubits, that have their last
34
+ freed time to be -infinity.
35
+
36
+ For borrowing qubits, the qubit manager simply delegates borrow requests to `self.qalloc`, thus
37
+ always allocating new clean qubits.
38
+ """
39
+
40
+ def __init__(self, prefix: str, *, size: int = 0, maximize_reuse: bool = False):
41
+ """Initializes `GreedyQubitManager`
42
+
43
+ Args:
44
+ prefix: The prefix to use for naming new clean ancillas allocated by the qubit manager.
45
+ The i'th allocated qubit is of the type `cirq.NamedQubit(f'{prefix}_{i}')`.
46
+ size: The initial size of the pool of ancilla qubits managed by the qubit manager. The
47
+ qubit manager can automatically resize itself when the allocation request
48
+ exceeds the number of available qubits.
49
+ maximize_reuse: Flag to control a FIFO vs LIFO strategy, defaults to False (FIFO).
50
+ """
51
+ self._prefix = prefix
52
+ self._used_qubits: Set['cirq.Qid'] = set()
53
+ self._free_qubits: List['cirq.Qid'] = []
54
+ self._size = 0
55
+ self.maximize_reuse = maximize_reuse
56
+ self.resize(size)
57
+
58
+ def _allocate_qid(self, name: str, dim: int) -> 'cirq.Qid':
59
+ return qid_util.q(name) if dim == 2 else named_qubit.NamedQid(name, dimension=dim)
60
+
61
+ def resize(self, new_size: int, dim: int = 2) -> None:
62
+ if new_size <= self._size:
63
+ return
64
+ new_qubits: List['cirq.Qid'] = [
65
+ self._allocate_qid(f'{self._prefix}_{s}', dim) for s in range(self._size, new_size)
66
+ ]
67
+ self._free_qubits = new_qubits + self._free_qubits
68
+ self._size = new_size
69
+
70
+ def qalloc(self, n: int, dim: int = 2) -> List['cirq.Qid']:
71
+ if not n:
72
+ return []
73
+ self.resize(self._size + n - len(self._free_qubits), dim=dim)
74
+ ret_qubits = self._free_qubits[-n:] if self.maximize_reuse else self._free_qubits[:n]
75
+ self._free_qubits = self._free_qubits[:-n] if self.maximize_reuse else self._free_qubits[n:]
76
+ self._used_qubits.update(ret_qubits)
77
+ return ret_qubits
78
+
79
+ def qfree(self, qubits: Iterable['cirq.Qid']) -> None:
80
+ qs = list(dict(zip(qubits, qubits)).keys())
81
+ assert self._used_qubits.issuperset(qs), "Only managed qubits currently in-use can be freed"
82
+ self._used_qubits = self._used_qubits.difference(qs)
83
+ self._free_qubits.extend(qs)
84
+
85
+ def qborrow(self, n: int, dim: int = 2) -> List['cirq.Qid']:
86
+ return self.qalloc(n, dim)