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.
- cirq/__init__.py +5 -0
- cirq/_compat.py +26 -11
- cirq/_compat_test.py +37 -3
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/circuit.py +106 -32
- cirq/circuits/circuit_operation.py +2 -2
- cirq/circuits/circuit_operation_test.py +1 -1
- cirq/circuits/circuit_test.py +109 -3
- cirq/circuits/frozen_circuit.py +80 -5
- cirq/circuits/frozen_circuit_test.py +47 -2
- cirq/circuits/qasm_output_test.py +9 -9
- cirq/conftest.py +1 -2
- cirq/contrib/acquaintance/devices.py +1 -1
- cirq/contrib/hacks/disable_validation_test.py +1 -1
- cirq/contrib/noise_models/noise_models.py +1 -2
- cirq/contrib/paulistring/clifford_optimize.py +1 -1
- cirq/contrib/paulistring/clifford_target_gateset_test.py +4 -4
- cirq/contrib/qcircuit/qcircuit_pdf.py +1 -1
- cirq/contrib/quimb/density_matrix.py +2 -3
- cirq/contrib/quimb/grid_circuits.py +3 -3
- cirq/contrib/quimb/state_vector.py +3 -5
- cirq/contrib/routing/utils.py +1 -2
- cirq/contrib/svg/svg.py +4 -6
- cirq/devices/grid_qubit.py +49 -38
- cirq/devices/grid_qubit_test.py +1 -3
- cirq/devices/insertion_noise_model.py +21 -1
- cirq/devices/insertion_noise_model_test.py +6 -0
- cirq/devices/line_qubit.py +67 -40
- cirq/devices/named_topologies.py +8 -14
- cirq/devices/noise_properties.py +1 -1
- cirq/devices/noise_utils.py +7 -5
- cirq/devices/noise_utils_test.py +7 -0
- cirq/experiments/fidelity_estimation_test.py +1 -1
- cirq/experiments/qubit_characterizations.py +6 -5
- cirq/experiments/random_quantum_circuit_generation.py +1 -1
- cirq/experiments/random_quantum_circuit_generation_test.py +28 -1
- cirq/experiments/readout_confusion_matrix.py +6 -6
- cirq/experiments/xeb_fitting.py +3 -5
- cirq/experiments/xeb_fitting_test.py +2 -2
- cirq/experiments/xeb_sampling.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +40 -38
- cirq/json_resolver_cache.py +2 -0
- cirq/linalg/decompositions.py +6 -5
- cirq/ops/__init__.py +2 -0
- cirq/ops/classically_controlled_operation.py +1 -1
- cirq/ops/clifford_gate.py +9 -9
- cirq/ops/clifford_gate_test.py +3 -4
- cirq/ops/common_channels.py +2 -5
- cirq/ops/common_channels_test.py +3 -5
- cirq/ops/common_gates_test.py +7 -7
- cirq/ops/controlled_operation_test.py +2 -2
- cirq/ops/dense_pauli_string.py +3 -0
- cirq/ops/eigen_gate_test.py +1 -3
- cirq/ops/fourier_transform.py +1 -2
- cirq/ops/fsim_gate.py +1 -1
- cirq/ops/gate_features_test.py +2 -2
- cirq/ops/gate_operation_test.py +1 -2
- cirq/ops/greedy_qubit_manager.py +86 -0
- cirq/ops/greedy_qubit_manager_test.py +98 -0
- cirq/ops/linear_combinations.py +1 -1
- cirq/ops/named_qubit.py +55 -18
- cirq/ops/parity_gates.py +65 -18
- cirq/ops/parity_gates_test.py +41 -2
- cirq/ops/pauli_gates.py +2 -2
- cirq/ops/pauli_string.py +3 -4
- cirq/ops/pauli_string_raw_types_test.py +3 -3
- cirq/ops/pauli_string_test.py +3 -4
- cirq/ops/random_gate_channel_test.py +3 -3
- cirq/ops/raw_types.py +1 -1
- cirq/ops/raw_types_test.py +5 -5
- cirq/ops/three_qubit_gates.py +12 -8
- cirq/protocols/act_on_protocol_test.py +9 -9
- cirq/protocols/apply_channel_protocol.py +9 -6
- cirq/protocols/apply_unitary_protocol_test.py +1 -1
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +2 -2
- cirq/protocols/has_stabilizer_effect_protocol.py +52 -6
- cirq/protocols/has_stabilizer_effect_protocol_test.py +21 -8
- cirq/protocols/has_unitary_protocol_test.py +1 -3
- cirq/protocols/json_serialization.py +6 -6
- cirq/protocols/json_serialization_test.py +7 -14
- cirq/protocols/json_test_data/InsertionNoiseModel.json +91 -0
- cirq/protocols/json_test_data/InsertionNoiseModel.repr +4 -0
- cirq/protocols/json_test_data/OpIdentifier.json +45 -10
- cirq/protocols/json_test_data/OpIdentifier.repr +7 -1
- cirq/protocols/json_test_data/spec.py +4 -0
- cirq/protocols/measurement_key_protocol_test.py +1 -1
- cirq/protocols/unitary_protocol_test.py +13 -16
- cirq/qis/clifford_tableau.py +7 -8
- cirq/qis/measures.py +1 -1
- cirq/qis/states.py +2 -3
- cirq/sim/__init__.py +2 -0
- cirq/sim/classical_simulator.py +107 -0
- cirq/sim/classical_simulator_test.py +207 -0
- cirq/sim/clifford/clifford_simulator_test.py +7 -7
- cirq/sim/clifford/stabilizer_simulation_state.py +2 -2
- cirq/sim/clifford/stabilizer_state_ch_form.py +7 -7
- cirq/sim/density_matrix_simulation_state.py +19 -4
- cirq/sim/density_matrix_simulator_test.py +5 -13
- cirq/sim/simulation_state_test.py +13 -14
- cirq/sim/simulator_test.py +6 -9
- cirq/sim/state_vector_simulation_state.py +1 -1
- cirq/study/resolver.py +41 -41
- cirq/study/resolver_test.py +13 -12
- cirq/testing/__init__.py +4 -1
- cirq/testing/circuit_compare.py +1 -1
- cirq/testing/circuit_compare_test.py +11 -11
- cirq/testing/consistent_controlled_gate_op.py +15 -1
- cirq/testing/consistent_controlled_gate_op_test.py +12 -3
- cirq/testing/consistent_decomposition.py +0 -1
- cirq/testing/consistent_protocols.py +6 -1
- cirq/testing/consistent_protocols_test.py +5 -10
- cirq/testing/consistent_qasm.py +2 -4
- cirq/testing/consistent_qasm_test.py +2 -3
- cirq/testing/consistent_specified_has_unitary_test.py +1 -3
- cirq/testing/equals_tester.py +1 -1
- cirq/testing/equals_tester_test.py +5 -5
- cirq/testing/equivalent_repr_eval_test.py +1 -3
- cirq/testing/gate_features_test.py +6 -6
- cirq/testing/order_tester_test.py +1 -3
- cirq/testing/random_circuit_test.py +1 -3
- cirq/transformers/__init__.py +3 -0
- cirq/transformers/analytical_decompositions/__init__.py +1 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +1 -2
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +2 -5
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +38 -0
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +18 -0
- cirq/transformers/expand_composite_test.py +4 -4
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +1 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +1 -2
- cirq/transformers/merge_k_qubit_gates_test.py +2 -2
- cirq/transformers/qubit_management_transformers.py +177 -0
- cirq/transformers/qubit_management_transformers_test.py +250 -0
- cirq/transformers/routing/route_circuit_cqc.py +23 -4
- cirq/transformers/routing/route_circuit_cqc_test.py +42 -0
- cirq/transformers/stratify.py +10 -11
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +10 -10
- cirq/transformers/target_gatesets/cz_gateset_test.py +8 -10
- cirq/transformers/transformer_primitives.py +138 -28
- cirq/value/abc_alt_test.py +4 -4
- cirq/value/duration.py +68 -37
- cirq/value/duration_test.py +2 -0
- cirq/value/measurement_key_test.py +1 -1
- cirq/value/product_state.py +4 -8
- cirq/value/value_equality_attr.py +12 -5
- cirq/vis/heatmap.py +7 -4
- cirq/vis/heatmap_test.py +14 -4
- cirq/vis/histogram.py +4 -4
- cirq/vis/state_histogram.py +10 -6
- cirq/vis/state_histogram_test.py +2 -0
- cirq/work/observable_measurement_data_test.py +1 -1
- cirq/work/observable_measurement_test.py +2 -2
- cirq/work/zeros_sampler.py +1 -1
- {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/METADATA +11 -19
- {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/RECORD +158 -150
- {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.2.0.dev20230717225858.dist-info → cirq_core-1.3.0.dist-info}/top_level.txt +0 -0
cirq/experiments/xeb_fitting.py
CHANGED
|
@@ -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 #
|
|
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: #
|
|
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
|
-
|
|
133
|
-
df = pd.DataFrame(
|
|
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
|
cirq/experiments/xeb_sampling.py
CHANGED
|
@@ -130,7 +130,7 @@ def _verify_two_line_qubits_from_circuits(circuits: Sequence['cirq.Circuit']):
|
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
class _NoProgress:
|
|
133
|
-
"""
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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.
|
cirq/json_resolver_cache.py
CHANGED
|
@@ -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,
|
cirq/linalg/decompositions.py
CHANGED
|
@@ -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
|
|
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[
|
|
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[
|
|
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 #
|
|
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): #
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
#
|
|
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
|
|
cirq/ops/clifford_gate_test.py
CHANGED
|
@@ -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
|
|
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
|
|
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,
|
|
881
|
+
cirq.act_on(cirq.CliffordGate.X, ExampleSimulationState(), qubits=())
|
|
883
882
|
|
|
884
883
|
|
|
885
884
|
def test_all_single_qubit_clifford_unitaries():
|
cirq/ops/common_channels.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
406
|
+
with
|
|
410
407
|
|
|
411
408
|
$$
|
|
412
409
|
\begin{aligned}
|
cirq/ops/common_channels_test.py
CHANGED
|
@@ -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
|
|
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(),
|
|
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),
|
|
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'))
|
cirq/ops/common_gates_test.py
CHANGED
|
@@ -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
|
|
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,
|
|
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,
|
|
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,
|
|
400
|
+
cirq.act_on(cirq.Z, ExampleSimulationState(), qubits=())
|
|
401
401
|
with pytest.raises(TypeError, match="Failed to act"):
|
|
402
|
-
cirq.act_on(cirq.H,
|
|
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,
|
|
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,
|
|
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 () #
|
|
449
|
+
return () # pragma: no cover
|
|
450
450
|
|
|
451
451
|
def with_qubits(self, *new_qubits):
|
|
452
|
-
return self #
|
|
452
|
+
return self # pragma: no cover
|
|
453
453
|
|
|
454
454
|
def _has_mixture_(self):
|
|
455
455
|
return True
|
cirq/ops/dense_pauli_string.py
CHANGED
|
@@ -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:
|
cirq/ops/eigen_gate_test.py
CHANGED
|
@@ -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
|
|
cirq/ops/fourier_transform.py
CHANGED
|
@@ -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
cirq/ops/gate_features_test.py
CHANGED
|
@@ -53,7 +53,7 @@ def test_qasm_output_args_format():
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def test_multi_qubit_gate_validate():
|
|
56
|
-
class
|
|
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 =
|
|
65
|
+
g = Example(3)
|
|
66
66
|
|
|
67
67
|
assert g.num_qubits() == 3
|
|
68
68
|
g.validate_args([a, b, c])
|
cirq/ops/gate_operation_test.py
CHANGED
|
@@ -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
|
-
#
|
|
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)
|