cirq-core 1.1.0.dev20221219200817__py3-none-any.whl → 1.2.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.
- cirq/__init__.py +8 -0
- cirq/_compat.py +29 -4
- cirq/_compat_test.py +24 -26
- cirq/_version.py +32 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/_block_diagram_drawer_test.py +4 -3
- cirq/circuits/circuit.py +109 -63
- cirq/circuits/circuit_operation.py +2 -3
- cirq/circuits/circuit_operation_test.py +4 -4
- cirq/circuits/circuit_test.py +11 -0
- cirq/circuits/frozen_circuit.py +13 -1
- cirq/circuits/frozen_circuit_test.py +5 -1
- cirq/circuits/moment.py +39 -14
- cirq/circuits/moment_test.py +7 -0
- cirq/circuits/text_diagram_drawer.py +1 -1
- cirq/circuits/text_diagram_drawer_test.py +3 -7
- cirq/conftest.py +8 -0
- cirq/contrib/acquaintance/bipartite.py +1 -1
- cirq/contrib/acquaintance/devices.py +2 -2
- cirq/contrib/acquaintance/executor.py +5 -2
- cirq/contrib/acquaintance/gates.py +3 -2
- cirq/contrib/acquaintance/permutation.py +13 -2
- cirq/contrib/acquaintance/testing.py +3 -5
- cirq/contrib/paulistring/recombine.py +3 -6
- cirq/contrib/qasm_import/_parser.py +17 -21
- cirq/contrib/qasm_import/_parser_test.py +30 -45
- cirq/contrib/qcircuit/qcircuit_test.py +3 -7
- cirq/contrib/quantum_volume/quantum_volume.py +3 -3
- cirq/contrib/quimb/mps_simulator.py +1 -1
- cirq/contrib/quimb/state_vector.py +2 -0
- cirq/contrib/quirk/quirk_gate.py +1 -0
- cirq/contrib/svg/svg.py +4 -7
- cirq/contrib/svg/svg_test.py +29 -1
- cirq/devices/grid_qubit.py +26 -28
- cirq/devices/grid_qubit_test.py +21 -5
- cirq/devices/line_qubit.py +10 -12
- cirq/devices/line_qubit_test.py +9 -2
- cirq/devices/named_topologies.py +1 -1
- cirq/devices/noise_model.py +4 -1
- cirq/devices/superconducting_qubits_noise_properties.py +1 -3
- cirq/experiments/n_qubit_tomography.py +1 -1
- cirq/experiments/qubit_characterizations.py +2 -2
- cirq/experiments/single_qubit_readout_calibration.py +1 -1
- cirq/experiments/t2_decay_experiment.py +1 -1
- cirq/experiments/xeb_simulation_test.py +2 -2
- cirq/interop/quirk/cells/testing.py +1 -1
- cirq/json_resolver_cache.py +1 -0
- cirq/linalg/__init__.py +2 -0
- cirq/linalg/decompositions_test.py +4 -4
- cirq/linalg/diagonalize_test.py +5 -6
- cirq/linalg/transformations.py +72 -9
- cirq/linalg/transformations_test.py +23 -7
- cirq/ops/__init__.py +4 -0
- cirq/ops/arithmetic_operation.py +4 -6
- cirq/ops/classically_controlled_operation.py +10 -3
- cirq/ops/clifford_gate.py +1 -7
- cirq/ops/common_channels.py +21 -15
- cirq/ops/common_gate_families.py +2 -3
- cirq/ops/common_gates.py +48 -11
- cirq/ops/common_gates_test.py +4 -0
- cirq/ops/controlled_gate.py +44 -18
- cirq/ops/controlled_operation.py +13 -5
- cirq/ops/dense_pauli_string.py +14 -19
- cirq/ops/diagonal_gate.py +3 -4
- cirq/ops/eigen_gate.py +8 -10
- cirq/ops/eigen_gate_test.py +6 -0
- cirq/ops/gate_operation.py +11 -6
- cirq/ops/gate_operation_test.py +11 -2
- cirq/ops/gateset.py +2 -1
- cirq/ops/gateset_test.py +38 -5
- cirq/ops/global_phase_op.py +28 -2
- cirq/ops/global_phase_op_test.py +21 -0
- cirq/ops/identity.py +1 -1
- cirq/ops/kraus_channel_test.py +2 -2
- cirq/ops/linear_combinations.py +7 -6
- cirq/ops/linear_combinations_test.py +26 -10
- cirq/ops/matrix_gates.py +8 -4
- cirq/ops/matrix_gates_test.py +25 -3
- cirq/ops/measure_util.py +13 -5
- cirq/ops/measure_util_test.py +8 -2
- cirq/ops/measurement_gate.py +1 -1
- cirq/ops/measurement_gate_test.py +9 -4
- cirq/ops/mixed_unitary_channel_test.py +4 -4
- cirq/ops/named_qubit.py +2 -4
- cirq/ops/parity_gates.py +5 -1
- cirq/ops/parity_gates_test.py +6 -0
- cirq/ops/pauli_gates.py +9 -9
- cirq/ops/pauli_string.py +4 -2
- cirq/ops/pauli_string_raw_types.py +4 -11
- cirq/ops/pauli_string_test.py +13 -13
- cirq/ops/pauli_sum_exponential.py +6 -1
- cirq/ops/qubit_manager.py +97 -0
- cirq/ops/qubit_manager_test.py +66 -0
- cirq/ops/raw_types.py +75 -33
- cirq/ops/raw_types_test.py +34 -0
- cirq/ops/three_qubit_gates.py +16 -10
- cirq/ops/three_qubit_gates_test.py +4 -2
- cirq/ops/two_qubit_diagonal_gate.py +3 -3
- cirq/ops/wait_gate.py +1 -1
- cirq/protocols/__init__.py +1 -0
- cirq/protocols/act_on_protocol.py +3 -3
- cirq/protocols/act_on_protocol_test.py +5 -5
- cirq/protocols/apply_channel_protocol.py +9 -8
- cirq/protocols/apply_mixture_protocol.py +8 -8
- cirq/protocols/apply_mixture_protocol_test.py +1 -1
- cirq/protocols/apply_unitary_protocol.py +66 -19
- cirq/protocols/apply_unitary_protocol_test.py +50 -0
- cirq/protocols/circuit_diagram_info_protocol.py +7 -9
- cirq/protocols/decompose_protocol.py +167 -125
- cirq/protocols/decompose_protocol_test.py +132 -2
- cirq/protocols/has_stabilizer_effect_protocol.py +2 -1
- cirq/protocols/inverse_protocol.py +2 -2
- cirq/protocols/json_serialization_test.py +3 -3
- cirq/protocols/json_test_data/Linspace.json +20 -7
- cirq/protocols/json_test_data/Linspace.repr +4 -1
- cirq/protocols/json_test_data/Points.json +19 -8
- cirq/protocols/json_test_data/Points.repr +4 -1
- cirq/protocols/json_test_data/Result.repr_inward +1 -1
- cirq/protocols/json_test_data/ResultDict.repr +1 -1
- cirq/protocols/json_test_data/ResultDict.repr_inward +1 -1
- cirq/protocols/json_test_data/TrialResult.repr_inward +1 -1
- cirq/protocols/json_test_data/XPowGate.json +13 -5
- cirq/protocols/json_test_data/XPowGate.repr +1 -1
- cirq/protocols/json_test_data/ZPowGate.json +13 -5
- cirq/protocols/json_test_data/ZPowGate.repr +1 -1
- cirq/protocols/json_test_data/ZipLongest.json +19 -0
- cirq/protocols/json_test_data/ZipLongest.repr +1 -0
- cirq/protocols/json_test_data/spec.py +1 -0
- cirq/protocols/kraus_protocol.py +3 -4
- cirq/protocols/measurement_key_protocol.py +3 -1
- cirq/protocols/mixture_protocol.py +3 -2
- cirq/protocols/phase_protocol.py +3 -3
- cirq/protocols/pow_protocol.py +1 -2
- cirq/protocols/qasm.py +4 -4
- cirq/protocols/qid_shape_protocol.py +8 -8
- cirq/protocols/resolve_parameters.py +8 -3
- cirq/protocols/resolve_parameters_test.py +3 -3
- cirq/protocols/unitary_protocol.py +19 -11
- cirq/protocols/unitary_protocol_test.py +37 -0
- cirq/qis/channels.py +1 -1
- cirq/qis/clifford_tableau.py +4 -5
- cirq/qis/quantum_state_representation.py +7 -9
- cirq/qis/states.py +21 -13
- cirq/qis/states_test.py +7 -0
- cirq/sim/clifford/clifford_simulator.py +3 -3
- cirq/sim/density_matrix_simulation_state.py +2 -1
- cirq/sim/density_matrix_simulator.py +1 -1
- cirq/sim/density_matrix_simulator_test.py +9 -5
- cirq/sim/density_matrix_utils.py +7 -32
- cirq/sim/mux.py +2 -2
- cirq/sim/simulation_state.py +58 -18
- cirq/sim/simulation_state_base.py +5 -2
- cirq/sim/simulation_state_test.py +121 -9
- cirq/sim/simulation_utils.py +59 -0
- cirq/sim/simulation_utils_test.py +32 -0
- cirq/sim/simulator.py +2 -1
- cirq/sim/simulator_base_test.py +3 -3
- cirq/sim/sparse_simulator.py +1 -1
- cirq/sim/sparse_simulator_test.py +5 -5
- cirq/sim/state_vector.py +7 -36
- cirq/sim/state_vector_simulation_state.py +18 -1
- cirq/sim/state_vector_simulator.py +3 -2
- cirq/sim/state_vector_simulator_test.py +24 -2
- cirq/sim/state_vector_test.py +46 -15
- cirq/study/__init__.py +1 -0
- cirq/study/flatten_expressions.py +2 -2
- cirq/study/resolver.py +2 -0
- cirq/study/resolver_test.py +1 -1
- cirq/study/result.py +1 -1
- cirq/study/sweeps.py +103 -9
- cirq/study/sweeps_test.py +64 -0
- cirq/testing/__init__.py +4 -0
- cirq/testing/circuit_compare.py +15 -18
- cirq/testing/consistent_act_on.py +4 -4
- cirq/testing/consistent_controlled_gate_op_test.py +1 -1
- cirq/testing/consistent_decomposition.py +11 -2
- cirq/testing/consistent_decomposition_test.py +8 -1
- cirq/testing/consistent_protocols.py +2 -0
- cirq/testing/consistent_protocols_test.py +8 -4
- cirq/testing/consistent_qasm.py +8 -15
- cirq/testing/consistent_specified_has_unitary.py +1 -1
- cirq/testing/consistent_unitary.py +85 -0
- cirq/testing/consistent_unitary_test.py +96 -0
- cirq/testing/equivalent_repr_eval.py +10 -10
- cirq/testing/json.py +3 -3
- cirq/testing/logs.py +1 -1
- cirq/testing/order_tester.py +4 -5
- cirq/testing/random_circuit.py +3 -5
- cirq/testing/sample_gates.py +79 -0
- cirq/testing/sample_gates_test.py +59 -0
- cirq/transformers/__init__.py +2 -0
- cirq/transformers/analytical_decompositions/__init__.py +8 -0
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +130 -0
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +58 -0
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +230 -0
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +112 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -3
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
- cirq/transformers/expand_composite.py +1 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +4 -4
- cirq/transformers/measurement_transformers.py +4 -4
- cirq/transformers/merge_single_qubit_gates.py +17 -4
- cirq/transformers/routing/route_circuit_cqc.py +2 -2
- cirq/transformers/stratify.py +125 -62
- cirq/transformers/stratify_test.py +20 -16
- cirq/transformers/transformer_api.py +1 -1
- cirq/transformers/transformer_primitives.py +3 -2
- cirq/transformers/transformer_primitives_test.py +11 -0
- cirq/value/abc_alt.py +3 -2
- cirq/value/abc_alt_test.py +1 -0
- cirq/value/classical_data.py +10 -10
- cirq/value/digits.py +2 -2
- cirq/value/linear_dict.py +18 -19
- cirq/value/product_state.py +7 -6
- cirq/value/value_equality_attr.py +2 -2
- cirq/vis/heatmap.py +1 -1
- cirq/vis/heatmap_test.py +2 -2
- cirq/work/collector.py +2 -2
- cirq/work/observable_measurement_data.py +5 -5
- cirq/work/observable_readout_calibration.py +3 -1
- cirq/work/observable_settings.py +1 -1
- cirq/work/pauli_sum_collector.py +9 -8
- cirq/work/sampler.py +2 -0
- cirq/work/zeros_sampler.py +2 -2
- {cirq_core-1.1.0.dev20221219200817.dist-info → cirq_core-1.2.0.dist-info}/METADATA +7 -15
- {cirq_core-1.1.0.dev20221219200817.dist-info → cirq_core-1.2.0.dist-info}/RECORD +229 -215
- {cirq_core-1.1.0.dev20221219200817.dist-info → cirq_core-1.2.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.1.0.dev20221219200817.dist-info → cirq_core-1.2.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.1.0.dev20221219200817.dist-info → cirq_core-1.2.0.dist-info}/top_level.txt +0 -0
cirq/__init__.py
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
from cirq import _import
|
|
18
18
|
|
|
19
|
+
from cirq._compat import __cirq_debug__, with_debug
|
|
20
|
+
|
|
19
21
|
# A module can only depend on modules imported earlier in this list of modules
|
|
20
22
|
# at import time. Pytest will fail otherwise (enforced by
|
|
21
23
|
# dev_tools/import_test.py).
|
|
@@ -236,6 +238,7 @@ from cirq.ops import (
|
|
|
236
238
|
LinearCombinationOfOperations,
|
|
237
239
|
MatrixGate,
|
|
238
240
|
MixedUnitaryChannel,
|
|
241
|
+
M,
|
|
239
242
|
measure,
|
|
240
243
|
measure_each,
|
|
241
244
|
measure_paulistring_terms,
|
|
@@ -281,9 +284,11 @@ from cirq.ops import (
|
|
|
281
284
|
qft,
|
|
282
285
|
Qid,
|
|
283
286
|
QuantumFourierTransformGate,
|
|
287
|
+
QubitManager,
|
|
284
288
|
QubitOrder,
|
|
285
289
|
QubitOrderOrList,
|
|
286
290
|
QubitPermutationGate,
|
|
291
|
+
R,
|
|
287
292
|
reset,
|
|
288
293
|
reset_each,
|
|
289
294
|
ResetChannel,
|
|
@@ -366,6 +371,7 @@ from cirq.transformers import (
|
|
|
366
371
|
parameterized_2q_op_to_sqrt_iswap_operations,
|
|
367
372
|
prepare_two_qubit_state_using_cz,
|
|
368
373
|
prepare_two_qubit_state_using_sqrt_iswap,
|
|
374
|
+
quantum_shannon_decomposition,
|
|
369
375
|
RouteCQC,
|
|
370
376
|
routed_circuit_with_mapping,
|
|
371
377
|
SqrtIswapTargetGateset,
|
|
@@ -498,6 +504,7 @@ from cirq.study import (
|
|
|
498
504
|
Result,
|
|
499
505
|
UnitSweep,
|
|
500
506
|
Zip,
|
|
507
|
+
ZipLongest,
|
|
501
508
|
)
|
|
502
509
|
|
|
503
510
|
from cirq.value import (
|
|
@@ -561,6 +568,7 @@ from cirq.protocols import (
|
|
|
561
568
|
decompose,
|
|
562
569
|
decompose_once,
|
|
563
570
|
decompose_once_with_qubits,
|
|
571
|
+
DecompositionContext,
|
|
564
572
|
DEFAULT_RESOLVERS,
|
|
565
573
|
definitely_commutes,
|
|
566
574
|
equal_up_to_global_phase,
|
cirq/_compat.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
"""Workarounds for compatibility issues between versions and libraries."""
|
|
16
16
|
import contextlib
|
|
17
|
+
import contextvars
|
|
17
18
|
import dataclasses
|
|
18
19
|
import functools
|
|
19
20
|
import importlib
|
|
@@ -24,15 +25,41 @@ import sys
|
|
|
24
25
|
import traceback
|
|
25
26
|
import warnings
|
|
26
27
|
from types import ModuleType
|
|
27
|
-
from typing import Any, Callable, Dict, Optional, overload, Set, Tuple, Type, TypeVar
|
|
28
|
+
from typing import Any, Callable, Dict, Iterator, Optional, overload, Set, Tuple, Type, TypeVar
|
|
28
29
|
|
|
29
30
|
import numpy as np
|
|
30
31
|
import pandas as pd
|
|
31
32
|
import sympy
|
|
32
33
|
import sympy.printing.repr
|
|
33
34
|
|
|
35
|
+
from cirq._doc import document
|
|
36
|
+
|
|
34
37
|
ALLOW_DEPRECATION_IN_TEST = 'ALLOW_DEPRECATION_IN_TEST'
|
|
35
38
|
|
|
39
|
+
__cirq_debug__ = contextvars.ContextVar('__cirq_debug__', default=__debug__)
|
|
40
|
+
document(
|
|
41
|
+
__cirq_debug__,
|
|
42
|
+
"A cirq specific flag which can be used to conditionally turn off all validations across Cirq "
|
|
43
|
+
"to boost performance in production mode. Defaults to python's built-in constant __debug__. "
|
|
44
|
+
"The flag is implemented as a `ContextVar` and is thread safe.",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@contextlib.contextmanager
|
|
49
|
+
def with_debug(value: bool) -> Iterator[None]:
|
|
50
|
+
"""Sets the value of global constant `cirq.__cirq_debug__` within the context.
|
|
51
|
+
|
|
52
|
+
If `__cirq_debug__` is set to False, all validations in Cirq are disabled to optimize
|
|
53
|
+
performance. Users should use the `cirq.with_debug` context manager instead of manually
|
|
54
|
+
mutating the value of `__cirq_debug__` flag. On exit, the context manager resets the
|
|
55
|
+
value of `__cirq_debug__` flag to what it was before entering the context manager.
|
|
56
|
+
"""
|
|
57
|
+
token = __cirq_debug__.set(value)
|
|
58
|
+
try:
|
|
59
|
+
yield
|
|
60
|
+
finally:
|
|
61
|
+
__cirq_debug__.reset(token)
|
|
62
|
+
|
|
36
63
|
|
|
37
64
|
try:
|
|
38
65
|
from functools import cached_property # pylint: disable=unused-import
|
|
@@ -138,9 +165,7 @@ def proper_repr(value: Any) -> str:
|
|
|
138
165
|
return Printer().doprint(value)
|
|
139
166
|
|
|
140
167
|
if isinstance(value, np.ndarray):
|
|
141
|
-
|
|
142
|
-
return f'np.array({value.tolist()!r}, dtype=np.{value.dtype!r})'
|
|
143
|
-
return f'np.array({value.tolist()!r}, dtype=np.{value.dtype})'
|
|
168
|
+
return f'np.array({value.tolist()!r}, dtype=np.{value.dtype!r})'
|
|
144
169
|
|
|
145
170
|
if isinstance(value, pd.MultiIndex):
|
|
146
171
|
return f'pd.MultiIndex.from_tuples({repr(list(value))}, names={repr(list(value.names))})'
|
cirq/_compat_test.py
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import collections
|
|
15
15
|
import dataclasses
|
|
16
|
-
import importlib
|
|
16
|
+
import importlib.metadata
|
|
17
17
|
import logging
|
|
18
18
|
import multiprocessing
|
|
19
19
|
import os
|
|
@@ -51,6 +51,16 @@ from cirq._compat import (
|
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
def test_with_debug():
|
|
55
|
+
assert cirq.__cirq_debug__.get()
|
|
56
|
+
with cirq.with_debug(False):
|
|
57
|
+
assert not cirq.__cirq_debug__.get()
|
|
58
|
+
with cirq.with_debug(True):
|
|
59
|
+
assert cirq.__cirq_debug__.get()
|
|
60
|
+
assert not cirq.__cirq_debug__.get()
|
|
61
|
+
assert cirq.__cirq_debug__.get()
|
|
62
|
+
|
|
63
|
+
|
|
54
64
|
def test_proper_repr():
|
|
55
65
|
v = sympy.Symbol('t') * 3
|
|
56
66
|
v2 = eval(proper_repr(v))
|
|
@@ -88,7 +98,7 @@ def test_proper_repr_data_frame():
|
|
|
88
98
|
pd.testing.assert_frame_equal(df2, df)
|
|
89
99
|
|
|
90
100
|
|
|
91
|
-
def test_dataclass_repr_simple():
|
|
101
|
+
def test_dataclass_repr_simple() -> None:
|
|
92
102
|
@dataclasses.dataclass
|
|
93
103
|
class TestClass1:
|
|
94
104
|
x: int
|
|
@@ -101,7 +111,7 @@ def test_dataclass_repr_simple():
|
|
|
101
111
|
assert repr(TestClass1(5, 'hi')) == "cirq.TestClass1(x=5, y='hi')"
|
|
102
112
|
|
|
103
113
|
|
|
104
|
-
def test_dataclass_repr_numpy():
|
|
114
|
+
def test_dataclass_repr_numpy() -> None:
|
|
105
115
|
@dataclasses.dataclass
|
|
106
116
|
class TestClass2:
|
|
107
117
|
x: np.ndarray
|
|
@@ -110,7 +120,10 @@ def test_dataclass_repr_numpy():
|
|
|
110
120
|
return dataclass_repr(self, namespace='cirq.testing')
|
|
111
121
|
|
|
112
122
|
tc = TestClass2(np.ones(3))
|
|
113
|
-
assert
|
|
123
|
+
assert (
|
|
124
|
+
repr(tc)
|
|
125
|
+
== "cirq.testing.TestClass2(x=np.array([1.0, 1.0, 1.0], dtype=np.dtype('float64')))"
|
|
126
|
+
)
|
|
114
127
|
|
|
115
128
|
|
|
116
129
|
def test_proper_eq():
|
|
@@ -187,9 +200,8 @@ def test_deprecated():
|
|
|
187
200
|
|
|
188
201
|
with pytest.raises(AssertionError, match='deadline should match vX.Y'):
|
|
189
202
|
# pylint: disable=unused-variable
|
|
190
|
-
# coverage: ignore
|
|
191
203
|
@deprecated(deadline='invalid', fix='Roll some dice.')
|
|
192
|
-
def badly_deprecated_func(*args, **kwargs):
|
|
204
|
+
def badly_deprecated_func(*args, **kwargs): # pragma: no cover
|
|
193
205
|
return new_func(*args, **kwargs)
|
|
194
206
|
|
|
195
207
|
# pylint: enable=unused-variable
|
|
@@ -245,8 +257,7 @@ def test_deprecated_parameter():
|
|
|
245
257
|
rewrite=lambda args, kwargs: (args, {'new_count': kwargs['double_count'] * 2}),
|
|
246
258
|
)
|
|
247
259
|
# pylint: disable=unused-variable
|
|
248
|
-
#
|
|
249
|
-
def f_with_badly_deprecated_param(new_count):
|
|
260
|
+
def f_with_badly_deprecated_param(new_count): # pragma: no cover
|
|
250
261
|
return new_count
|
|
251
262
|
|
|
252
263
|
# pylint: enable=unused-variable
|
|
@@ -358,9 +369,8 @@ def test_deprecated_class():
|
|
|
358
369
|
|
|
359
370
|
with pytest.raises(AssertionError, match='deadline should match vX.Y'):
|
|
360
371
|
# pylint: disable=unused-variable
|
|
361
|
-
# coverage: ignore
|
|
362
372
|
@deprecated_class(deadline='invalid', fix='theFix', name='foo')
|
|
363
|
-
class BadlyDeprecatedClass(NewClass):
|
|
373
|
+
class BadlyDeprecatedClass(NewClass): # pragma: no cover
|
|
364
374
|
...
|
|
365
375
|
|
|
366
376
|
# pylint: enable=unused-variable
|
|
@@ -606,8 +616,6 @@ def subprocess_context(test_func):
|
|
|
606
616
|
"it to this method?"
|
|
607
617
|
)
|
|
608
618
|
|
|
609
|
-
import os
|
|
610
|
-
|
|
611
619
|
ctx = multiprocessing.get_context('spawn' if os.name == 'nt' else 'fork')
|
|
612
620
|
|
|
613
621
|
exception = ctx.Queue()
|
|
@@ -619,8 +627,7 @@ def subprocess_context(test_func):
|
|
|
619
627
|
p.start()
|
|
620
628
|
p.join()
|
|
621
629
|
result = exception.get()
|
|
622
|
-
if result:
|
|
623
|
-
# coverage: ignore
|
|
630
|
+
if result: # pragma: no cover
|
|
624
631
|
ex_type, msg, ex_trace = result
|
|
625
632
|
if ex_type == "Skipped":
|
|
626
633
|
warnings.warn(f"Skipping: {ex_type}: {msg}\n{ex_trace}")
|
|
@@ -709,21 +716,12 @@ def test_metadata_search_path():
|
|
|
709
716
|
subprocess_context(_test_metadata_search_path_inner)()
|
|
710
717
|
|
|
711
718
|
|
|
712
|
-
def _test_metadata_search_path_inner():
|
|
719
|
+
def _test_metadata_search_path_inner(): # pragma: no cover
|
|
713
720
|
# initialize the DeprecatedModuleFinders
|
|
714
721
|
# pylint: disable=unused-import
|
|
715
722
|
import cirq.testing._compat_test_data.module_a
|
|
716
723
|
|
|
717
|
-
|
|
718
|
-
# importlib.metadata for python 3.8+
|
|
719
|
-
# coverage: ignore
|
|
720
|
-
import importlib.metadata as m
|
|
721
|
-
except: # coverage: ignore
|
|
722
|
-
# coverage: ignore
|
|
723
|
-
# importlib_metadata for python <3.8
|
|
724
|
-
m = pytest.importorskip("importlib_metadata")
|
|
725
|
-
|
|
726
|
-
assert m.metadata('flynt')
|
|
724
|
+
assert importlib.metadata.metadata('numpy')
|
|
727
725
|
|
|
728
726
|
|
|
729
727
|
def test_metadata_distributions_after_deprecated_submodule():
|
|
@@ -990,7 +988,7 @@ def test_cached_property():
|
|
|
990
988
|
|
|
991
989
|
|
|
992
990
|
class Bar:
|
|
993
|
-
def __init__(self):
|
|
991
|
+
def __init__(self) -> None:
|
|
994
992
|
self.foo_calls: Dict[int, int] = collections.Counter()
|
|
995
993
|
self.bar_calls: Dict[int, int] = collections.Counter()
|
|
996
994
|
|
cirq/_version.py
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
# Copyright 2018 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
|
+
"""Define version number here, read it from setup.py automatically,
|
|
16
|
+
and warn users that the latest version of cirq uses python 3.9+"""
|
|
17
|
+
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
if sys.version_info < (3, 9, 0):
|
|
21
|
+
# coverage: ignore
|
|
22
|
+
raise SystemError(
|
|
23
|
+
"You installed the latest version of cirq but aren't on python 3.9+.\n"
|
|
24
|
+
'To fix this error, you need to either:\n'
|
|
25
|
+
'\n'
|
|
26
|
+
'A) Update to python 3.9 or later.\n'
|
|
27
|
+
'- OR -\n'
|
|
28
|
+
'B) Explicitly install an older deprecated-but-compatible version '
|
|
29
|
+
'of cirq (e.g. "python -m pip install cirq==1.1.*")'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__version__ = "1.2.0"
|
cirq/_version_test.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
|
import itertools
|
|
15
16
|
|
|
16
17
|
import pytest
|
|
@@ -31,13 +32,13 @@ def _assert_same_diagram(actual: str, expected: str):
|
|
|
31
32
|
"Diagram differs from the desired diagram.\n"
|
|
32
33
|
'\n'
|
|
33
34
|
'Actual diagram:\n'
|
|
34
|
-
'{}\n'
|
|
35
|
+
f'{actual}\n'
|
|
35
36
|
'\n'
|
|
36
37
|
'Desired diagram:\n'
|
|
37
|
-
'{}\n'
|
|
38
|
+
f'{expected}\n'
|
|
38
39
|
'\n'
|
|
39
40
|
'Highlighted differences:\n'
|
|
40
|
-
'{
|
|
41
|
+
f'{cirq.testing.highlight_text_differences(actual, expected)}\n'
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
|
cirq/circuits/circuit.py
CHANGED
|
@@ -47,6 +47,7 @@ from typing import (
|
|
|
47
47
|
TypeVar,
|
|
48
48
|
Union,
|
|
49
49
|
)
|
|
50
|
+
from typing_extensions import Self
|
|
50
51
|
|
|
51
52
|
import networkx
|
|
52
53
|
import numpy as np
|
|
@@ -236,15 +237,15 @@ class AbstractCircuit(abc.ABC):
|
|
|
236
237
|
pass
|
|
237
238
|
|
|
238
239
|
@overload
|
|
239
|
-
def __getitem__(self
|
|
240
|
+
def __getitem__(self, key: slice) -> Self:
|
|
240
241
|
pass
|
|
241
242
|
|
|
242
243
|
@overload
|
|
243
|
-
def __getitem__(self
|
|
244
|
+
def __getitem__(self, key: Tuple[slice, 'cirq.Qid']) -> Self:
|
|
244
245
|
pass
|
|
245
246
|
|
|
246
247
|
@overload
|
|
247
|
-
def __getitem__(self
|
|
248
|
+
def __getitem__(self, key: Tuple[slice, Iterable['cirq.Qid']]) -> Self:
|
|
248
249
|
pass
|
|
249
250
|
|
|
250
251
|
def __getitem__(self, key):
|
|
@@ -305,7 +306,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
305
306
|
return None
|
|
306
307
|
|
|
307
308
|
def next_moment_operating_on(
|
|
308
|
-
self,
|
|
309
|
+
self,
|
|
310
|
+
qubits: Iterable['cirq.Qid'],
|
|
311
|
+
start_moment_index: int = 0,
|
|
312
|
+
max_distance: Optional[int] = None,
|
|
309
313
|
) -> Optional[int]:
|
|
310
314
|
"""Finds the index of the next moment that touches the given qubits.
|
|
311
315
|
|
|
@@ -910,9 +914,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
910
914
|
"""
|
|
911
915
|
return (op for moment in self for op in moment.operations)
|
|
912
916
|
|
|
913
|
-
def map_operations(
|
|
914
|
-
self: CIRCUIT_TYPE, func: Callable[['cirq.Operation'], 'cirq.OP_TREE']
|
|
915
|
-
) -> CIRCUIT_TYPE:
|
|
917
|
+
def map_operations(self, func: Callable[['cirq.Operation'], 'cirq.OP_TREE']) -> Self:
|
|
916
918
|
"""Applies the given function to all operations in this circuit.
|
|
917
919
|
|
|
918
920
|
Args:
|
|
@@ -1284,9 +1286,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1284
1286
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
1285
1287
|
return {name for op in self.all_operations() for name in protocols.parameter_names(op)}
|
|
1286
1288
|
|
|
1287
|
-
def _resolve_parameters_(
|
|
1288
|
-
self: CIRCUIT_TYPE, resolver: 'cirq.ParamResolver', recursive: bool
|
|
1289
|
-
) -> CIRCUIT_TYPE:
|
|
1289
|
+
def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> Self:
|
|
1290
1290
|
changed = False
|
|
1291
1291
|
resolved_moments: List['cirq.Moment'] = []
|
|
1292
1292
|
for moment in self:
|
|
@@ -1458,7 +1458,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1458
1458
|
are placed one after the other and then moved inward until just before
|
|
1459
1459
|
their operations would collide. If any of the circuits do not share
|
|
1460
1460
|
qubits and so would not collide, the starts or ends of the circuits will
|
|
1461
|
-
be aligned,
|
|
1461
|
+
be aligned, according to the given align parameter.
|
|
1462
1462
|
|
|
1463
1463
|
Beware that this method is *not* associative. For example:
|
|
1464
1464
|
|
|
@@ -1537,7 +1537,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1537
1537
|
uf.union(*op.qubits)
|
|
1538
1538
|
return sorted([qs for qs in uf.to_sets()], key=min)
|
|
1539
1539
|
|
|
1540
|
-
def factorize(self
|
|
1540
|
+
def factorize(self) -> Iterable[Self]:
|
|
1541
1541
|
"""Factorize circuit into a sequence of independent circuits (factors).
|
|
1542
1542
|
|
|
1543
1543
|
Factorization is possible when the circuit's qubits can be divided
|
|
@@ -1776,12 +1776,10 @@ class Circuit(AbstractCircuit):
|
|
|
1776
1776
|
Non-moment entries will be inserted according to the EARLIEST
|
|
1777
1777
|
insertion strategy.
|
|
1778
1778
|
"""
|
|
1779
|
-
# These are dicts from the qubit/key to the greatest moment index that has it.
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
mkey_indexes: Dict['cirq.MeasurementKey', int] = defaultdict(lambda: -1)
|
|
1784
|
-
ckey_indexes: Dict['cirq.MeasurementKey', int] = defaultdict(lambda: -1)
|
|
1779
|
+
# These are dicts from the qubit/key to the greatest moment index that has it.
|
|
1780
|
+
qubit_indices: Dict['cirq.Qid', int] = {}
|
|
1781
|
+
mkey_indices: Dict['cirq.MeasurementKey', int] = {}
|
|
1782
|
+
ckey_indices: Dict['cirq.MeasurementKey', int] = {}
|
|
1785
1783
|
|
|
1786
1784
|
# We also maintain the dict from moment index to moments/ops that go into it, for use when
|
|
1787
1785
|
# building the actual moments at the end.
|
|
@@ -1793,46 +1791,17 @@ class Circuit(AbstractCircuit):
|
|
|
1793
1791
|
|
|
1794
1792
|
# "mop" means current moment-or-operation
|
|
1795
1793
|
for mop in ops.flatten_to_ops_or_moments(contents):
|
|
1796
|
-
mop_qubits = mop.qubits
|
|
1797
|
-
mop_mkeys = protocols.measurement_key_objs(mop)
|
|
1798
|
-
mop_ckeys = protocols.control_keys(mop)
|
|
1799
1794
|
|
|
1800
|
-
#
|
|
1795
|
+
# Identify the index of the moment to place this `mop` into.
|
|
1796
|
+
placement_index = get_earliest_accommodating_moment_index(
|
|
1797
|
+
mop, qubit_indices, mkey_indices, ckey_indices, length
|
|
1798
|
+
)
|
|
1799
|
+
length = max(length, placement_index + 1) # update the length of the circuit thus far
|
|
1800
|
+
|
|
1801
1801
|
if isinstance(mop, Moment):
|
|
1802
|
-
|
|
1803
|
-
i = length
|
|
1804
|
-
moments_by_index[i] = mop
|
|
1802
|
+
moments_by_index[placement_index] = mop
|
|
1805
1803
|
else:
|
|
1806
|
-
|
|
1807
|
-
# the initial conflict, and we search for larger ones. Once we get the largest one,
|
|
1808
|
-
# we increment i by 1 to set the placement index.
|
|
1809
|
-
i = -1
|
|
1810
|
-
|
|
1811
|
-
# Look for the maximum conflict; i.e. a moment that has a qubit the same as one of
|
|
1812
|
-
# this op's qubits, that has a measurement or control key the same as one of this
|
|
1813
|
-
# op's measurement keys, or that has a measurement key the same as one of this op's
|
|
1814
|
-
# control keys. (Control keys alone can commute past each other). The `ifs` are
|
|
1815
|
-
# logically unnecessary but seem to make this slightly faster.
|
|
1816
|
-
if mop_qubits:
|
|
1817
|
-
i = max(i, *[qubit_indexes[q] for q in mop_qubits])
|
|
1818
|
-
if mop_mkeys:
|
|
1819
|
-
i = max(i, *[mkey_indexes[k] for k in mop_mkeys])
|
|
1820
|
-
i = max(i, *[ckey_indexes[k] for k in mop_mkeys])
|
|
1821
|
-
if mop_ckeys:
|
|
1822
|
-
i = max(i, *[mkey_indexes[k] for k in mop_ckeys])
|
|
1823
|
-
i += 1
|
|
1824
|
-
op_lists_by_index[i].append(mop)
|
|
1825
|
-
|
|
1826
|
-
# Update our dicts with data from the latest mop placement. Note `i` will always be
|
|
1827
|
-
# greater than the existing value for all of these, by construction, so there is no
|
|
1828
|
-
# need to do a `max(i, existing)`.
|
|
1829
|
-
for q in mop_qubits:
|
|
1830
|
-
qubit_indexes[q] = i
|
|
1831
|
-
for k in mop_mkeys:
|
|
1832
|
-
mkey_indexes[k] = i
|
|
1833
|
-
for k in mop_ckeys:
|
|
1834
|
-
ckey_indexes[k] = i
|
|
1835
|
-
length = max(length, i + 1)
|
|
1804
|
+
op_lists_by_index[placement_index].append(mop)
|
|
1836
1805
|
|
|
1837
1806
|
# Finally, once everything is placed, we can construct and append the actual moments for
|
|
1838
1807
|
# each index.
|
|
@@ -1861,9 +1830,8 @@ class Circuit(AbstractCircuit):
|
|
|
1861
1830
|
pass
|
|
1862
1831
|
|
|
1863
1832
|
def __setitem__(self, key, value):
|
|
1864
|
-
if isinstance(key, int):
|
|
1865
|
-
|
|
1866
|
-
raise TypeError('Can only assign Moments into Circuits.')
|
|
1833
|
+
if isinstance(key, int) and not isinstance(value, Moment):
|
|
1834
|
+
raise TypeError('Can only assign Moments into Circuits.')
|
|
1867
1835
|
|
|
1868
1836
|
if isinstance(key, slice):
|
|
1869
1837
|
value = list(value)
|
|
@@ -2160,7 +2128,7 @@ class Circuit(AbstractCircuit):
|
|
|
2160
2128
|
self,
|
|
2161
2129
|
early_frontier: Dict['cirq.Qid', int],
|
|
2162
2130
|
late_frontier: Dict['cirq.Qid', int],
|
|
2163
|
-
update_qubits: Iterable['cirq.Qid'] = None,
|
|
2131
|
+
update_qubits: Optional[Iterable['cirq.Qid']] = None,
|
|
2164
2132
|
) -> Tuple[int, int]:
|
|
2165
2133
|
"""Inserts moments to separate two frontiers.
|
|
2166
2134
|
|
|
@@ -2230,7 +2198,10 @@ class Circuit(AbstractCircuit):
|
|
|
2230
2198
|
)
|
|
2231
2199
|
|
|
2232
2200
|
def insert_at_frontier(
|
|
2233
|
-
self,
|
|
2201
|
+
self,
|
|
2202
|
+
operations: 'cirq.OP_TREE',
|
|
2203
|
+
start: int,
|
|
2204
|
+
frontier: Optional[Dict['cirq.Qid', int]] = None,
|
|
2234
2205
|
) -> Dict['cirq.Qid', int]:
|
|
2235
2206
|
"""Inserts operations inline at frontier.
|
|
2236
2207
|
|
|
@@ -2421,7 +2392,9 @@ class Circuit(AbstractCircuit):
|
|
|
2421
2392
|
|
|
2422
2393
|
|
|
2423
2394
|
def _pick_inserted_ops_moment_indices(
|
|
2424
|
-
operations: Sequence['cirq.Operation'],
|
|
2395
|
+
operations: Sequence['cirq.Operation'],
|
|
2396
|
+
start: int = 0,
|
|
2397
|
+
frontier: Optional[Dict['cirq.Qid', int]] = None,
|
|
2425
2398
|
) -> Tuple[Sequence[int], Dict['cirq.Qid', int]]:
|
|
2426
2399
|
"""Greedily assigns operations to moments.
|
|
2427
2400
|
|
|
@@ -2595,8 +2568,7 @@ def _get_global_phase_and_tags_for_op(op: 'cirq.Operation') -> Tuple[Optional[co
|
|
|
2595
2568
|
elif isinstance(op.untagged, CircuitOperation):
|
|
2596
2569
|
op_phase, op_tags = _get_global_phase_and_tags_for_ops(op.untagged.circuit.all_operations())
|
|
2597
2570
|
return op_phase, list(op.tags) + op_tags
|
|
2598
|
-
|
|
2599
|
-
return None, []
|
|
2571
|
+
return None, []
|
|
2600
2572
|
|
|
2601
2573
|
|
|
2602
2574
|
def _get_global_phase_and_tags_for_ops(op_list: Any) -> Tuple[Optional[complex], List[Any]]:
|
|
@@ -2755,3 +2727,77 @@ def _group_until_different(items: Iterable[_TIn], key: Callable[[_TIn], _TKey],
|
|
|
2755
2727
|
Tuples containing the group key and item values.
|
|
2756
2728
|
"""
|
|
2757
2729
|
return ((k, [val(i) for i in v]) for (k, v) in itertools.groupby(items, key))
|
|
2730
|
+
|
|
2731
|
+
|
|
2732
|
+
def get_earliest_accommodating_moment_index(
|
|
2733
|
+
moment_or_operation: Union['cirq.Moment', 'cirq.Operation'],
|
|
2734
|
+
qubit_indices: Dict['cirq.Qid', int],
|
|
2735
|
+
mkey_indices: Dict['cirq.MeasurementKey', int],
|
|
2736
|
+
ckey_indices: Dict['cirq.MeasurementKey', int],
|
|
2737
|
+
length: Optional[int] = None,
|
|
2738
|
+
) -> int:
|
|
2739
|
+
"""Get the index of the earliest moment that can accommodate the given moment or operation.
|
|
2740
|
+
|
|
2741
|
+
Updates the dictionaries keeping track of the last moment index addressing a given qubit,
|
|
2742
|
+
measurement key, and control key.
|
|
2743
|
+
|
|
2744
|
+
Args:
|
|
2745
|
+
moment_or_operation: The moment operation in question.
|
|
2746
|
+
qubit_indices: A dictionary mapping qubits to the latest moments that address them.
|
|
2747
|
+
mkey_indices: A dictionary mapping measureent keys to the latest moments that address them.
|
|
2748
|
+
ckey_indices: A dictionary mapping control keys to the latest moments that address them.
|
|
2749
|
+
length: The length of the circuit that we are trying to insert a moment or operation into.
|
|
2750
|
+
Should probably be equal to the maximum of the values in `qubit_indices`,
|
|
2751
|
+
`mkey_indices`, and `ckey_indices`.
|
|
2752
|
+
|
|
2753
|
+
Returns:
|
|
2754
|
+
The integer index of the earliest moment that can accommodate the given moment or operation.
|
|
2755
|
+
"""
|
|
2756
|
+
mop_qubits = moment_or_operation.qubits
|
|
2757
|
+
mop_mkeys = protocols.measurement_key_objs(moment_or_operation)
|
|
2758
|
+
mop_ckeys = protocols.control_keys(moment_or_operation)
|
|
2759
|
+
|
|
2760
|
+
if isinstance(moment_or_operation, Moment):
|
|
2761
|
+
# For consistency with `Circuit.append`, moments always get placed at the end of a circuit.
|
|
2762
|
+
if length is not None:
|
|
2763
|
+
last_conflict = length - 1
|
|
2764
|
+
else:
|
|
2765
|
+
last_conflict = max(
|
|
2766
|
+
[*qubit_indices.values(), *mkey_indices.values(), *ckey_indices.values(), -1]
|
|
2767
|
+
)
|
|
2768
|
+
|
|
2769
|
+
else:
|
|
2770
|
+
# We start by searching for the `latest_conflict` moment index, which we will increment by
|
|
2771
|
+
# `1` to identify the earliest moment that *does not* conflict with the given operation.
|
|
2772
|
+
# The `latest_conflict` is initialized to `-1` before searching for later conflicting
|
|
2773
|
+
# moments.
|
|
2774
|
+
last_conflict = -1
|
|
2775
|
+
|
|
2776
|
+
# Look for the maximum conflict; i.e. a moment that has a qubit the same as one of this op's
|
|
2777
|
+
# qubits, that has a measurement or control key the same as one of this op's measurement
|
|
2778
|
+
# keys, or that has a measurement key the same as one of this op's control keys. (Control
|
|
2779
|
+
# keys alone can commute past each other). The `ifs` are logically unnecessary but seem to
|
|
2780
|
+
# make this slightly faster.
|
|
2781
|
+
if mop_qubits:
|
|
2782
|
+
last_conflict = max(
|
|
2783
|
+
last_conflict, *[qubit_indices.get(qubit, -1) for qubit in mop_qubits]
|
|
2784
|
+
)
|
|
2785
|
+
if mop_mkeys:
|
|
2786
|
+
last_conflict = max(last_conflict, *[mkey_indices.get(key, -1) for key in mop_mkeys])
|
|
2787
|
+
last_conflict = max(last_conflict, *[ckey_indices.get(key, -1) for key in mop_mkeys])
|
|
2788
|
+
if mop_ckeys:
|
|
2789
|
+
last_conflict = max(last_conflict, *[mkey_indices.get(key, -1) for key in mop_ckeys])
|
|
2790
|
+
|
|
2791
|
+
# The index of the moment to place this moment or operaton ("mop") into.
|
|
2792
|
+
mop_index = last_conflict + 1
|
|
2793
|
+
|
|
2794
|
+
# Update our dicts with data from this `mop` placement. Note `mop_index` will always be greater
|
|
2795
|
+
# than the existing value for all of these, by construction.
|
|
2796
|
+
for qubit in mop_qubits:
|
|
2797
|
+
qubit_indices[qubit] = mop_index
|
|
2798
|
+
for key in mop_mkeys:
|
|
2799
|
+
mkey_indices[key] = mop_index
|
|
2800
|
+
for key in mop_ckeys:
|
|
2801
|
+
ckey_indices[key] = mop_index
|
|
2802
|
+
|
|
2803
|
+
return mop_index
|
|
@@ -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
|
"""A structure for encapsulating entire circuits in an operation.
|
|
15
16
|
|
|
16
17
|
A CircuitOperation is an Operation object that wraps a FrozenCircuit. When
|
|
@@ -459,9 +460,7 @@ class CircuitOperation(ops.Operation):
|
|
|
459
460
|
# TODO: support out-of-line subcircuit definition in string format.
|
|
460
461
|
msg_lines = str(self.circuit).split('\n')
|
|
461
462
|
msg_width = max([len(line) for line in msg_lines])
|
|
462
|
-
circuit_msg = '\n'.join(
|
|
463
|
-
'[ {line:<{width}} ]'.format(line=line, width=msg_width) for line in msg_lines
|
|
464
|
-
)
|
|
463
|
+
circuit_msg = '\n'.join(f'[ {line:<{msg_width}} ]' for line in msg_lines)
|
|
465
464
|
args = []
|
|
466
465
|
|
|
467
466
|
def dict_str(d: Mapping) -> str:
|
|
@@ -274,7 +274,7 @@ def test_recursive_params():
|
|
|
274
274
|
|
|
275
275
|
@pytest.mark.parametrize('add_measurements', [True, False])
|
|
276
276
|
@pytest.mark.parametrize('use_default_ids_for_initial_rep', [True, False])
|
|
277
|
-
def test_repeat(add_measurements, use_default_ids_for_initial_rep):
|
|
277
|
+
def test_repeat(add_measurements: bool, use_default_ids_for_initial_rep: bool) -> None:
|
|
278
278
|
a, b = cirq.LineQubit.range(2)
|
|
279
279
|
circuit = cirq.Circuit(cirq.H(a), cirq.CX(a, b))
|
|
280
280
|
if add_measurements:
|
|
@@ -327,9 +327,9 @@ def test_repeat(add_measurements, use_default_ids_for_initial_rep):
|
|
|
327
327
|
_ = op_base.repeat()
|
|
328
328
|
|
|
329
329
|
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
|
|
330
|
-
_ = op_base.repeat(1.3)
|
|
331
|
-
assert op_base.repeat(3.00000000001).repetitions == 3
|
|
332
|
-
assert op_base.repeat(2.99999999999).repetitions == 3
|
|
330
|
+
_ = op_base.repeat(1.3) # type: ignore[arg-type]
|
|
331
|
+
assert op_base.repeat(3.00000000001).repetitions == 3 # type: ignore[arg-type]
|
|
332
|
+
assert op_base.repeat(2.99999999999).repetitions == 3 # type: ignore[arg-type]
|
|
333
333
|
|
|
334
334
|
|
|
335
335
|
@pytest.mark.parametrize('add_measurements', [True, False])
|
cirq/circuits/circuit_test.py
CHANGED
|
@@ -834,6 +834,17 @@ def test_insert_moment():
|
|
|
834
834
|
assert c.operation_at(qubit, actual_index) == operation[0]
|
|
835
835
|
|
|
836
836
|
|
|
837
|
+
def test_circuit_length_inference():
|
|
838
|
+
# tests that `get_earliest_accommodating_moment_index` properly computes circuit length
|
|
839
|
+
circuit = cirq.Circuit(cirq.X(cirq.q(0)))
|
|
840
|
+
qubit_indices = {cirq.q(0): 0}
|
|
841
|
+
mkey_indices = {}
|
|
842
|
+
ckey_indices = {}
|
|
843
|
+
assert circuits.circuit.get_earliest_accommodating_moment_index(
|
|
844
|
+
cirq.Moment(), qubit_indices, mkey_indices, ckey_indices
|
|
845
|
+
) == len(circuit)
|
|
846
|
+
|
|
847
|
+
|
|
837
848
|
def test_insert_inline_near_start():
|
|
838
849
|
a = cirq.NamedQubit('a')
|
|
839
850
|
b = cirq.NamedQubit('b')
|