cirq-core 1.6.0.dev20250505215959__py3-none-any.whl → 1.6.0.dev20250507223949__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/_compat_test.py +4 -1
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/insert_strategy.py +7 -5
- cirq/contrib/acquaintance/gates_test.py +3 -1
- cirq/contrib/graph_device/hypergraph.py +3 -1
- cirq/contrib/paulistring/clifford_optimize.py +2 -2
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +9 -3
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +2 -0
- cirq/contrib/paulistring/pauli_string_optimize.py +2 -0
- cirq/contrib/paulistring/recombine.py +1 -1
- cirq/contrib/paulistring/separate.py +5 -4
- cirq/contrib/qasm_import/qasm.py +2 -0
- cirq/contrib/quimb/density_matrix.py +4 -1
- cirq/contrib/quimb/state_vector.py +4 -1
- cirq/contrib/quirk/quirk_gate.py +3 -1
- cirq/contrib/routing/router.py +2 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +4 -0
- cirq/experiments/fidelity_estimation.py +11 -5
- cirq/linalg/combinators.py +4 -2
- cirq/linalg/predicates.py +6 -1
- cirq/linalg/tolerance.py +4 -1
- cirq/neutral_atoms/convert_to_neutral_atom_gates.py +9 -3
- cirq/ops/clifford_gate_test.py +3 -1
- cirq/ops/pauli_string.py +3 -4
- cirq/ops/pauli_string_phasor.py +20 -3
- cirq/ops/pauli_string_phasor_test.py +2 -5
- cirq/ops/pauli_string_test.py +0 -147
- cirq/ops/projector.py +13 -8
- cirq/transformers/gauge_compiling/cphase_gauge.py +2 -0
- cirq/vis/heatmap.py +1 -1
- cirq/work/sampler.py +33 -34
- cirq/work/sampler_test.py +6 -2
- cirq/work/zeros_sampler.py +3 -1
- cirq/work/zeros_sampler_test.py +3 -1
- {cirq_core-1.6.0.dev20250505215959.dist-info → cirq_core-1.6.0.dev20250507223949.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250505215959.dist-info → cirq_core-1.6.0.dev20250507223949.dist-info}/RECORD +40 -40
- {cirq_core-1.6.0.dev20250505215959.dist-info → cirq_core-1.6.0.dev20250507223949.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250505215959.dist-info → cirq_core-1.6.0.dev20250507223949.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250505215959.dist-info → cirq_core-1.6.0.dev20250507223949.dist-info}/top_level.txt +0 -0
cirq/_compat_test.py
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import collections
|
|
15
18
|
import dataclasses
|
|
16
19
|
import importlib.metadata
|
|
@@ -635,7 +638,7 @@ _repeated_child_deprecation_msg = [
|
|
|
635
638
|
] + _deprecation_origin
|
|
636
639
|
|
|
637
640
|
|
|
638
|
-
def _trace_unhandled_exceptions(*args, queue:
|
|
641
|
+
def _trace_unhandled_exceptions(*args, queue: multiprocessing.Queue, func: Callable):
|
|
639
642
|
try:
|
|
640
643
|
func(*args)
|
|
641
644
|
queue.put(None)
|
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/circuits/insert_strategy.py
CHANGED
|
@@ -14,16 +14,18 @@
|
|
|
14
14
|
|
|
15
15
|
"""Hard-coded options for adding multiple operations to a circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class InsertStrategy:
|
|
19
21
|
"""Indicates preferences on how to add multiple operations to a circuit."""
|
|
20
22
|
|
|
21
|
-
NEW:
|
|
22
|
-
NEW_THEN_INLINE:
|
|
23
|
-
INLINE:
|
|
24
|
-
EARLIEST:
|
|
23
|
+
NEW: InsertStrategy
|
|
24
|
+
NEW_THEN_INLINE: InsertStrategy
|
|
25
|
+
INLINE: InsertStrategy
|
|
26
|
+
EARLIEST: InsertStrategy
|
|
25
27
|
|
|
26
|
-
def __new__(cls, name: str, doc: str) ->
|
|
28
|
+
def __new__(cls, name: str, doc: str) -> InsertStrategy:
|
|
27
29
|
inst = getattr(cls, name, None)
|
|
28
30
|
if not inst or not isinstance(inst, cls):
|
|
29
31
|
inst = super().__new__(cls)
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from itertools import combinations, product
|
|
16
18
|
from random import randint
|
|
17
19
|
from string import ascii_lowercase as alphabet
|
|
@@ -257,7 +259,7 @@ class OtherOperation(cirq.Operation):
|
|
|
257
259
|
def qubits(self) -> Tuple[cirq.Qid, ...]:
|
|
258
260
|
return self._qubits
|
|
259
261
|
|
|
260
|
-
def with_qubits(self, *new_qubits: cirq.Qid) ->
|
|
262
|
+
def with_qubits(self, *new_qubits: cirq.Qid) -> OtherOperation:
|
|
261
263
|
return type(self)(self._qubits)
|
|
262
264
|
|
|
263
265
|
def __eq__(self, other):
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import itertools
|
|
16
18
|
import random
|
|
17
19
|
from typing import Any, Dict, FrozenSet, Hashable, Iterable, Mapping, Optional, Set, Tuple, Union
|
|
@@ -103,7 +105,7 @@ class UndirectedHypergraph:
|
|
|
103
105
|
@classmethod
|
|
104
106
|
def random(
|
|
105
107
|
cls, vertices: Union[int, Iterable], edge_probs: Mapping[int, float]
|
|
106
|
-
) ->
|
|
108
|
+
) -> UndirectedHypergraph:
|
|
107
109
|
"""A random hypergraph.
|
|
108
110
|
|
|
109
111
|
Every possible edge is included with probability edge_prob[len(edge)].
|
|
@@ -65,7 +65,7 @@ def clifford_optimized_circuit(circuit: circuits.Circuit, atol: float = 1e-8) ->
|
|
|
65
65
|
furthest_i = i
|
|
66
66
|
break
|
|
67
67
|
if cont_cond == CONTINUE:
|
|
68
|
-
modified_op = modified_op.
|
|
68
|
+
modified_op = modified_op.conjugated_by(protocols.inverse(op))
|
|
69
69
|
num_passed_over += 1
|
|
70
70
|
if len(modified_op.pauli_string) == 1:
|
|
71
71
|
furthest_op = modified_op
|
|
@@ -122,7 +122,7 @@ def clifford_optimized_circuit(circuit: circuits.Circuit, atol: float = 1e-8) ->
|
|
|
122
122
|
all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
|
|
123
123
|
elif isinstance(other_op, ops.PauliStringPhasor):
|
|
124
124
|
# Pass over a non-Clifford gate
|
|
125
|
-
mod_op = other_op.
|
|
125
|
+
mod_op = other_op.conjugated_by([part_cliff_gate(qubit)])
|
|
126
126
|
all_ops[merge_i] = mod_op
|
|
127
127
|
all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
|
|
128
128
|
elif merge_i > start_i + 1 and num_passed > 0:
|
|
@@ -11,19 +11,25 @@
|
|
|
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
|
"""Tools for measuring expectation values of Pauli strings with readout error mitigation."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
15
19
|
import itertools
|
|
16
20
|
import time
|
|
17
|
-
from typing import cast, Dict, FrozenSet, List, Optional, Sequence, Tuple, Union
|
|
21
|
+
from typing import cast, Dict, FrozenSet, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
18
22
|
|
|
19
23
|
import attrs
|
|
20
24
|
import numpy as np
|
|
21
25
|
|
|
22
26
|
from cirq import circuits, ops, work
|
|
23
27
|
from cirq.contrib.shuffle_circuits import run_shuffled_with_readout_benchmarking
|
|
24
|
-
from cirq.experiments import SingleQubitReadoutCalibrationResult
|
|
25
28
|
from cirq.experiments.readout_confusion_matrix import TensoredConfusionMatrices
|
|
26
|
-
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from cirq.experiments import SingleQubitReadoutCalibrationResult
|
|
32
|
+
from cirq.study import ResultDict
|
|
27
33
|
|
|
28
34
|
|
|
29
35
|
@attrs.frozen
|
|
@@ -53,7 +53,7 @@ def _sorted_best_string_placements(
|
|
|
53
53
|
):
|
|
54
54
|
# This is as far through as this Pauli string can move
|
|
55
55
|
break
|
|
56
|
-
string_op = string_op.
|
|
56
|
+
string_op = string_op.conjugated_by(protocols.inverse(out_op))
|
|
57
57
|
curr = (string_op, i + 1, possible_node)
|
|
58
58
|
if sort_key(curr) > sort_key(node_max):
|
|
59
59
|
node_max = curr
|
|
@@ -89,8 +89,9 @@ def pauli_string_half(circuit: circuits.Circuit) -> circuits.Circuit:
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
def _pull_non_clifford_before(circuit: circuits.Circuit) -> Iterator[ops.OP_TREE]:
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
|
|
93
|
+
def _iter_ops_range(moment_end):
|
|
94
|
+
for i in range(moment_end):
|
|
94
95
|
moment = circuit[i]
|
|
95
96
|
for op in moment.operations:
|
|
96
97
|
if not isinstance(op, ops.PauliStringPhasor):
|
|
@@ -99,5 +100,5 @@ def _pull_non_clifford_before(circuit: circuits.Circuit) -> Iterator[ops.OP_TREE
|
|
|
99
100
|
for i, moment in enumerate(circuit):
|
|
100
101
|
for op in moment.operations:
|
|
101
102
|
if isinstance(op, ops.PauliStringPhasor):
|
|
102
|
-
ops_to_cross =
|
|
103
|
-
yield op.
|
|
103
|
+
ops_to_cross = _iter_ops_range(i)
|
|
104
|
+
yield op.conjugated_by(ops_to_cross)
|
cirq/contrib/qasm_import/qasm.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
2
5
|
from functools import lru_cache
|
|
3
6
|
from typing import Dict, List, Optional, Sequence, Tuple, Union
|
|
4
7
|
|
|
@@ -77,7 +80,7 @@ def _add_to_positions(
|
|
|
77
80
|
|
|
78
81
|
def circuit_to_density_matrix_tensors(
|
|
79
82
|
circuit: cirq.Circuit, qubits: Optional[Sequence[cirq.Qid]] = None
|
|
80
|
-
) -> Tuple[List[qtn.Tensor], Dict[
|
|
83
|
+
) -> Tuple[List[qtn.Tensor], Dict[cirq.Qid, int], Dict[Tuple[str, str], Tuple[float, float]]]:
|
|
81
84
|
"""Given a circuit with mixtures or channels, construct a tensor network
|
|
82
85
|
representation of the density matrix.
|
|
83
86
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
2
5
|
import warnings
|
|
3
6
|
from typing import cast, Dict, List, Optional, Sequence, Tuple, Union
|
|
4
7
|
|
|
@@ -28,7 +31,7 @@ def circuit_to_tensors(
|
|
|
28
31
|
circuit: cirq.Circuit,
|
|
29
32
|
qubits: Optional[Sequence[cirq.Qid]] = None,
|
|
30
33
|
initial_state: Union[int, None] = 0,
|
|
31
|
-
) -> Tuple[List[qtn.Tensor], Dict[
|
|
34
|
+
) -> Tuple[List[qtn.Tensor], Dict[cirq.Qid, int], None]:
|
|
32
35
|
"""Given a circuit, construct a tensor network representation.
|
|
33
36
|
|
|
34
37
|
Indices are named "i{i}_q{x}" where i is a time index and x is a
|
cirq/contrib/quirk/quirk_gate.py
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import Any, Callable, cast, Dict, Optional, Union
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
@@ -46,7 +48,7 @@ class QuirkOp:
|
|
|
46
48
|
self.keys = keys
|
|
47
49
|
self.can_merge = can_merge
|
|
48
50
|
|
|
49
|
-
def controlled(self, control_count: int = 1) ->
|
|
51
|
+
def controlled(self, control_count: int = 1) -> QuirkOp:
|
|
50
52
|
return QuirkOp(*['•'] * control_count, *self.keys, can_merge=False)
|
|
51
53
|
|
|
52
54
|
|
cirq/contrib/routing/router.py
CHANGED
|
@@ -11,7 +11,11 @@
|
|
|
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
|
"""Tools for running circuits in a shuffled order with readout error benchmarking."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
15
19
|
import time
|
|
16
20
|
from typing import Dict, List, Optional, Tuple, Union
|
|
17
21
|
|
|
@@ -11,16 +11,22 @@
|
|
|
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
|
"""Estimation of fidelity associated with experimental circuit executions."""
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Callable, Mapping, Optional, Sequence, TYPE_CHECKING
|
|
16
20
|
|
|
17
21
|
import numpy as np
|
|
18
22
|
|
|
19
|
-
from cirq.circuits import Circuit
|
|
20
23
|
from cirq.ops import QubitOrder, QubitOrderOrList
|
|
21
24
|
from cirq.sim import final_state_vector
|
|
22
25
|
from cirq.value import state_vector_to_probabilities
|
|
23
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
import cirq
|
|
29
|
+
|
|
24
30
|
|
|
25
31
|
def linear_xeb_fidelity_from_probabilities(
|
|
26
32
|
hilbert_space_dimension: int, probabilities: Sequence[float]
|
|
@@ -132,7 +138,7 @@ def hog_score_xeb_fidelity_from_probabilities(
|
|
|
132
138
|
|
|
133
139
|
|
|
134
140
|
def xeb_fidelity(
|
|
135
|
-
circuit: Circuit,
|
|
141
|
+
circuit: cirq.Circuit,
|
|
136
142
|
bitstrings: Sequence[int],
|
|
137
143
|
qubit_order: QubitOrderOrList = QubitOrder.DEFAULT,
|
|
138
144
|
amplitudes: Optional[Mapping[int, complex]] = None,
|
|
@@ -197,7 +203,7 @@ def xeb_fidelity(
|
|
|
197
203
|
|
|
198
204
|
|
|
199
205
|
def linear_xeb_fidelity(
|
|
200
|
-
circuit: Circuit,
|
|
206
|
+
circuit: cirq.Circuit,
|
|
201
207
|
bitstrings: Sequence[int],
|
|
202
208
|
qubit_order: QubitOrderOrList = QubitOrder.DEFAULT,
|
|
203
209
|
amplitudes: Optional[Mapping[int, complex]] = None,
|
|
@@ -213,7 +219,7 @@ def linear_xeb_fidelity(
|
|
|
213
219
|
|
|
214
220
|
|
|
215
221
|
def log_xeb_fidelity(
|
|
216
|
-
circuit: Circuit,
|
|
222
|
+
circuit: cirq.Circuit,
|
|
217
223
|
bitstrings: Sequence[int],
|
|
218
224
|
qubit_order: QubitOrderOrList = QubitOrder.DEFAULT,
|
|
219
225
|
amplitudes: Optional[Mapping[int, complex]] = None,
|
cirq/linalg/combinators.py
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Utility methods for combining matrices."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
import functools
|
|
18
20
|
from typing import TYPE_CHECKING, Union
|
|
19
21
|
|
|
@@ -107,7 +109,7 @@ def kron_with_controls(*factors: Union[np.ndarray, complex]) -> np.ndarray:
|
|
|
107
109
|
return product
|
|
108
110
|
|
|
109
111
|
|
|
110
|
-
def dot(*values:
|
|
112
|
+
def dot(*values: ArrayLike) -> np.ndarray:
|
|
111
113
|
"""Computes the dot/matrix product of a sequence of values.
|
|
112
114
|
|
|
113
115
|
Performs the computation in serial order without regard to the matrix
|
|
@@ -136,7 +138,7 @@ def dot(*values: 'ArrayLike') -> np.ndarray:
|
|
|
136
138
|
return result
|
|
137
139
|
|
|
138
140
|
|
|
139
|
-
def _merge_dtypes(dtype1:
|
|
141
|
+
def _merge_dtypes(dtype1: DTypeLike, dtype2: DTypeLike) -> np.dtype:
|
|
140
142
|
return (np.zeros(0, dtype1) + np.zeros(0, dtype2)).dtype
|
|
141
143
|
|
|
142
144
|
|
cirq/linalg/predicates.py
CHANGED
|
@@ -11,7 +11,12 @@
|
|
|
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
|
"""Utility methods for checking properties of matrices."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from types import EllipsisType
|
|
15
20
|
from typing import cast, List, Optional, Sequence, Tuple, Union
|
|
16
21
|
|
|
17
22
|
import numpy as np
|
|
@@ -228,7 +233,7 @@ def slice_for_qubits_equal_to(
|
|
|
228
233
|
big_endian_qureg_value: int = 0,
|
|
229
234
|
num_qubits: Optional[int] = None,
|
|
230
235
|
qid_shape: Optional[Tuple[int, ...]] = None,
|
|
231
|
-
) -> Tuple[Union[slice, int,
|
|
236
|
+
) -> Tuple[Union[slice, int, EllipsisType], ...]:
|
|
232
237
|
"""Returns an index corresponding to a desired subset of an np.ndarray.
|
|
233
238
|
|
|
234
239
|
It is assumed that the np.ndarray's shape is of the form (2, 2, 2, ..., 2).
|
cirq/linalg/tolerance.py
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
"""Utility for testing approximate equality of matrices and scalars within
|
|
16
16
|
tolerances."""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
17
20
|
from typing import Iterable, TYPE_CHECKING, Union
|
|
18
21
|
|
|
19
22
|
import numpy as np
|
|
@@ -22,7 +25,7 @@ if TYPE_CHECKING:
|
|
|
22
25
|
from numpy.typing import ArrayLike
|
|
23
26
|
|
|
24
27
|
|
|
25
|
-
def all_near_zero(a:
|
|
28
|
+
def all_near_zero(a: ArrayLike, *, atol: float = 1e-8) -> bool:
|
|
26
29
|
"""Checks if the tensor's elements are all near zero.
|
|
27
30
|
|
|
28
31
|
Args:
|
|
@@ -12,15 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
|
+
|
|
16
19
|
from cirq.neutral_atoms import neutral_atom_devices
|
|
17
20
|
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
import cirq
|
|
23
|
+
|
|
18
24
|
|
|
19
|
-
def is_native_neutral_atom_op(operation:
|
|
25
|
+
def is_native_neutral_atom_op(operation: cirq.Operation) -> bool:
|
|
20
26
|
"""Returns true if the operation is in the default neutral atom gateset."""
|
|
21
27
|
return operation in neutral_atom_devices.neutral_atom_gateset()
|
|
22
28
|
|
|
23
29
|
|
|
24
|
-
def is_native_neutral_atom_gate(gate:
|
|
30
|
+
def is_native_neutral_atom_gate(gate: cirq.Gate) -> bool:
|
|
25
31
|
"""Returns true if the gate is in the default neutral atom gateset."""
|
|
26
32
|
return gate in neutral_atom_devices.neutral_atom_gateset()
|
cirq/ops/clifford_gate_test.py
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import functools
|
|
16
18
|
import itertools
|
|
17
19
|
from typing import Tuple, Type
|
|
@@ -59,7 +61,7 @@ def _all_rotation_pairs():
|
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
@functools.lru_cache()
|
|
62
|
-
def _all_clifford_gates() -> Tuple[
|
|
64
|
+
def _all_clifford_gates() -> Tuple[cirq.SingleQubitCliffordGate, ...]:
|
|
63
65
|
return tuple(
|
|
64
66
|
cirq.SingleQubitCliffordGate.from_xz_map(trans_x, trans_z)
|
|
65
67
|
for trans_x, trans_z in _all_rotation_pairs()
|
cirq/ops/pauli_string.py
CHANGED
|
@@ -45,6 +45,7 @@ import numpy as np
|
|
|
45
45
|
import sympy
|
|
46
46
|
|
|
47
47
|
from cirq import _compat, linalg, protocols, qis, value
|
|
48
|
+
from cirq._compat import deprecated
|
|
48
49
|
from cirq._doc import document
|
|
49
50
|
from cirq._import import LazyLoader
|
|
50
51
|
from cirq.ops import (
|
|
@@ -1070,9 +1071,10 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
1070
1071
|
"""
|
|
1071
1072
|
return self.conjugated_by(ops)
|
|
1072
1073
|
|
|
1074
|
+
@deprecated(deadline="v2.0", fix="Use conjuagetd_by()/before()/after() instead.")
|
|
1073
1075
|
def pass_operations_over(
|
|
1074
1076
|
self, ops: Iterable[cirq.Operation], after_to_before: bool = False
|
|
1075
|
-
) -> PauliString:
|
|
1077
|
+
) -> PauliString: # pragma: no cover
|
|
1076
1078
|
"""Determines how the Pauli string changes when conjugated by Cliffords.
|
|
1077
1079
|
|
|
1078
1080
|
The output and input pauli strings are related by a circuit equivalence.
|
|
@@ -1099,9 +1101,6 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
1099
1101
|
pauli string, instead of before (and so are moving in the
|
|
1100
1102
|
opposite direction).
|
|
1101
1103
|
"""
|
|
1102
|
-
# TODO(#6946): deprecate this method.
|
|
1103
|
-
# Note: This method is supposed to be replaced by conjugated_by()
|
|
1104
|
-
# (see #2351 for details).
|
|
1105
1104
|
if after_to_before:
|
|
1106
1105
|
return self.after(ops)
|
|
1107
1106
|
|
cirq/ops/pauli_string_phasor.py
CHANGED
|
@@ -30,7 +30,7 @@ from typing import (
|
|
|
30
30
|
import sympy
|
|
31
31
|
|
|
32
32
|
from cirq import protocols, value
|
|
33
|
-
from cirq._compat import proper_repr
|
|
33
|
+
from cirq._compat import deprecated, proper_repr
|
|
34
34
|
from cirq.ops import (
|
|
35
35
|
common_gates,
|
|
36
36
|
dense_pauli_string as dps,
|
|
@@ -199,9 +199,21 @@ class PauliStringPhasor(gate_operation.GateOperation):
|
|
|
199
199
|
syms = tuple(sym(qubit) for qubit in qubits)
|
|
200
200
|
return protocols.CircuitDiagramInfo(wire_symbols=syms, exponent=self.exponent_relative)
|
|
201
201
|
|
|
202
|
+
def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliStringPhasor':
|
|
203
|
+
r"""Returns the Pauli string conjugated by a clifford operation.
|
|
204
|
+
|
|
205
|
+
The PauliStringPhasor $P$ conjugated by the Clifford operation $C$ is
|
|
206
|
+
$C^\dagger P C$.
|
|
207
|
+
"""
|
|
208
|
+
new_pauli_string: ps.PauliString = self.pauli_string.conjugated_by(clifford)
|
|
209
|
+
pp = self.exponent_pos
|
|
210
|
+
pn = self.exponent_neg
|
|
211
|
+
return PauliStringPhasor(new_pauli_string, exponent_pos=pp, exponent_neg=pn)
|
|
212
|
+
|
|
213
|
+
@deprecated(deadline="v2.0", fix="Use conjuagetd_by() instead.")
|
|
202
214
|
def pass_operations_over(
|
|
203
215
|
self, ops: Iterable[raw_types.Operation], after_to_before: bool = False
|
|
204
|
-
) -> PauliStringPhasor:
|
|
216
|
+
) -> PauliStringPhasor: # pragma: no cover
|
|
205
217
|
"""Determines how the Pauli phasor changes when conjugated by Cliffords.
|
|
206
218
|
|
|
207
219
|
The output and input pauli phasors are related by a circuit equivalence.
|
|
@@ -228,7 +240,12 @@ class PauliStringPhasor(gate_operation.GateOperation):
|
|
|
228
240
|
pauli string, instead of before (and so are moving in the
|
|
229
241
|
opposite direction).
|
|
230
242
|
"""
|
|
231
|
-
new_pauli_string =
|
|
243
|
+
new_pauli_string: ps.PauliString = ps.PauliString()
|
|
244
|
+
if after_to_before:
|
|
245
|
+
new_pauli_string = self.pauli_string.after(ops)
|
|
246
|
+
else:
|
|
247
|
+
all_ops = list(op_tree.flatten_to_ops(ops))
|
|
248
|
+
new_pauli_string = self.pauli_string.before(all_ops[::-1])
|
|
232
249
|
pp = self.exponent_pos
|
|
233
250
|
pn = self.exponent_neg
|
|
234
251
|
return PauliStringPhasor(new_pauli_string, exponent_pos=pp, exponent_neg=pn)
|
|
@@ -155,7 +155,7 @@ def test_consistent():
|
|
|
155
155
|
cirq.testing.assert_implements_consistent_protocols(p)
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def
|
|
158
|
+
def test_conjugated_by():
|
|
159
159
|
q0, q1 = _make_qubits(2)
|
|
160
160
|
op = cirq.SingleQubitCliffordGate.from_double_map(
|
|
161
161
|
{cirq.Z: (cirq.X, False), cirq.X: (cirq.Z, False)}
|
|
@@ -164,10 +164,7 @@ def test_pass_operations_over():
|
|
|
164
164
|
ps_after = cirq.PauliString({q0: cirq.Z, q1: cirq.Y}, -1)
|
|
165
165
|
before = cirq.PauliStringPhasor(ps_before, exponent_neg=0.1)
|
|
166
166
|
after = cirq.PauliStringPhasor(ps_after, exponent_neg=0.1)
|
|
167
|
-
assert before.
|
|
168
|
-
assert (
|
|
169
|
-
after.pass_operations_over([op], after_to_before=True).pauli_string == before.pauli_string
|
|
170
|
-
)
|
|
167
|
+
assert before.conjugated_by(op).pauli_string == after.pauli_string
|
|
171
168
|
|
|
172
169
|
|
|
173
170
|
def test_extrapolate_effect():
|