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/ops/controlled_gate.py
CHANGED
|
@@ -28,7 +28,13 @@ from typing import (
|
|
|
28
28
|
import numpy as np
|
|
29
29
|
|
|
30
30
|
from cirq import protocols, value, _import
|
|
31
|
-
from cirq.ops import
|
|
31
|
+
from cirq.ops import (
|
|
32
|
+
raw_types,
|
|
33
|
+
controlled_operation as cop,
|
|
34
|
+
op_tree,
|
|
35
|
+
matrix_gates,
|
|
36
|
+
control_values as cv,
|
|
37
|
+
)
|
|
32
38
|
from cirq.type_workarounds import NotImplementedType
|
|
33
39
|
|
|
34
40
|
if TYPE_CHECKING:
|
|
@@ -51,7 +57,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
51
57
|
def __init__(
|
|
52
58
|
self,
|
|
53
59
|
sub_gate: 'cirq.Gate',
|
|
54
|
-
num_controls: int = None,
|
|
60
|
+
num_controls: Optional[int] = None,
|
|
55
61
|
control_values: Optional[
|
|
56
62
|
Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
|
|
57
63
|
] = None,
|
|
@@ -143,7 +149,14 @@ class ControlledGate(raw_types.Gate):
|
|
|
143
149
|
def _qid_shape_(self) -> Tuple[int, ...]:
|
|
144
150
|
return self.control_qid_shape + protocols.qid_shape(self.sub_gate)
|
|
145
151
|
|
|
146
|
-
def _decompose_(
|
|
152
|
+
def _decompose_(
|
|
153
|
+
self, qubits: Tuple['cirq.Qid', ...]
|
|
154
|
+
) -> Union[None, NotImplementedType, 'cirq.OP_TREE']:
|
|
155
|
+
return self._decompose_with_context_(qubits)
|
|
156
|
+
|
|
157
|
+
def _decompose_with_context_(
|
|
158
|
+
self, qubits: Tuple['cirq.Qid', ...], context: Optional['cirq.DecompositionContext'] = None
|
|
159
|
+
) -> Union[None, NotImplementedType, 'cirq.OP_TREE']:
|
|
147
160
|
if (
|
|
148
161
|
protocols.has_unitary(self.sub_gate)
|
|
149
162
|
and protocols.num_qubits(self.sub_gate) == 1
|
|
@@ -166,18 +179,27 @@ class ControlledGate(raw_types.Gate):
|
|
|
166
179
|
z_sub_gate = common_gates.ZPowGate(
|
|
167
180
|
exponent=self.sub_gate.exponent, global_shift=self.sub_gate.global_shift
|
|
168
181
|
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
'control_qid_shape': self.control_qid_shape + (2,),
|
|
173
|
-
}
|
|
182
|
+
num_controls = self.num_controls() + 1
|
|
183
|
+
control_values = self.control_values & cv.ProductOfSums(((1,),))
|
|
184
|
+
control_qid_shape = self.control_qid_shape + (2,)
|
|
174
185
|
controlled_z = (
|
|
175
|
-
z_sub_gate.controlled(
|
|
186
|
+
z_sub_gate.controlled(
|
|
187
|
+
num_controls=num_controls,
|
|
188
|
+
control_values=control_values,
|
|
189
|
+
control_qid_shape=control_qid_shape,
|
|
190
|
+
)
|
|
176
191
|
if protocols.is_parameterized(self)
|
|
177
|
-
else ControlledGate(
|
|
192
|
+
else ControlledGate(
|
|
193
|
+
z_sub_gate,
|
|
194
|
+
num_controls=num_controls,
|
|
195
|
+
control_values=control_values,
|
|
196
|
+
control_qid_shape=control_qid_shape,
|
|
197
|
+
)
|
|
178
198
|
)
|
|
179
199
|
if self != controlled_z:
|
|
180
|
-
return protocols.decompose_once_with_qubits(
|
|
200
|
+
return protocols.decompose_once_with_qubits(
|
|
201
|
+
controlled_z, qubits, NotImplemented, context=context
|
|
202
|
+
)
|
|
181
203
|
|
|
182
204
|
if isinstance(self.sub_gate, matrix_gates.MatrixGate):
|
|
183
205
|
# Default decompositions of 2/3 qubit `cirq.MatrixGate` ignores global phase, which is
|
|
@@ -185,17 +207,21 @@ class ControlledGate(raw_types.Gate):
|
|
|
185
207
|
return NotImplemented
|
|
186
208
|
|
|
187
209
|
result = protocols.decompose_once_with_qubits(
|
|
188
|
-
self.sub_gate,
|
|
210
|
+
self.sub_gate,
|
|
211
|
+
qubits[self.num_controls() :],
|
|
212
|
+
NotImplemented,
|
|
213
|
+
flatten=False,
|
|
214
|
+
context=context,
|
|
189
215
|
)
|
|
190
216
|
if result is NotImplemented:
|
|
191
217
|
return NotImplemented
|
|
192
218
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
)
|
|
198
|
-
|
|
219
|
+
return op_tree.transform_op_tree(
|
|
220
|
+
result,
|
|
221
|
+
lambda op: op.controlled_by(
|
|
222
|
+
*qubits[: self.num_controls()], control_values=self.control_values
|
|
223
|
+
),
|
|
224
|
+
)
|
|
199
225
|
|
|
200
226
|
def on(self, *qubits: 'cirq.Qid') -> cop.ControlledOperation:
|
|
201
227
|
if len(qubits) == 0:
|
cirq/ops/controlled_operation.py
CHANGED
|
@@ -34,6 +34,7 @@ from cirq.ops import (
|
|
|
34
34
|
eigen_gate,
|
|
35
35
|
gate_operation,
|
|
36
36
|
matrix_gates,
|
|
37
|
+
op_tree,
|
|
37
38
|
raw_types,
|
|
38
39
|
control_values as cv,
|
|
39
40
|
)
|
|
@@ -145,7 +146,12 @@ class ControlledOperation(raw_types.Operation):
|
|
|
145
146
|
)
|
|
146
147
|
|
|
147
148
|
def _decompose_(self):
|
|
148
|
-
|
|
149
|
+
return self._decompose_with_context_()
|
|
150
|
+
|
|
151
|
+
def _decompose_with_context_(self, context: Optional['cirq.DecompositionContext'] = None):
|
|
152
|
+
result = protocols.decompose_once_with_qubits(
|
|
153
|
+
self.gate, self.qubits, NotImplemented, flatten=False, context=context
|
|
154
|
+
)
|
|
149
155
|
if result is not NotImplemented:
|
|
150
156
|
return result
|
|
151
157
|
|
|
@@ -154,13 +160,15 @@ class ControlledOperation(raw_types.Operation):
|
|
|
154
160
|
# local phase in the controlled variant and hence cannot be ignored.
|
|
155
161
|
return NotImplemented
|
|
156
162
|
|
|
157
|
-
result = protocols.decompose_once(
|
|
163
|
+
result = protocols.decompose_once(
|
|
164
|
+
self.sub_operation, NotImplemented, flatten=False, context=context
|
|
165
|
+
)
|
|
158
166
|
if result is NotImplemented:
|
|
159
167
|
return NotImplemented
|
|
160
168
|
|
|
161
|
-
return
|
|
162
|
-
op.controlled_by(*self.controls, control_values=self.control_values)
|
|
163
|
-
|
|
169
|
+
return op_tree.transform_op_tree(
|
|
170
|
+
result, lambda op: op.controlled_by(*self.controls, control_values=self.control_values)
|
|
171
|
+
)
|
|
164
172
|
|
|
165
173
|
def _value_equality_values_(self):
|
|
166
174
|
sorted_controls, expanded_cvals = tuple(
|
cirq/ops/dense_pauli_string.py
CHANGED
|
@@ -27,11 +27,10 @@ from typing import (
|
|
|
27
27
|
overload,
|
|
28
28
|
Sequence,
|
|
29
29
|
Tuple,
|
|
30
|
-
Type,
|
|
31
30
|
TYPE_CHECKING,
|
|
32
|
-
TypeVar,
|
|
33
31
|
Union,
|
|
34
32
|
)
|
|
33
|
+
from typing_extensions import Self
|
|
35
34
|
|
|
36
35
|
import numpy as np
|
|
37
36
|
import sympy
|
|
@@ -53,8 +52,6 @@ PAULI_GATES: List[Union['cirq.Pauli', 'cirq.IdentityGate']] = [
|
|
|
53
52
|
pauli_gates.Z,
|
|
54
53
|
]
|
|
55
54
|
|
|
56
|
-
TCls = TypeVar('TCls', bound='BaseDensePauliString')
|
|
57
|
-
|
|
58
55
|
|
|
59
56
|
@value.value_equality(approximate=True, distinct_child_types=True)
|
|
60
57
|
class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
@@ -132,7 +129,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
132
129
|
return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
|
|
133
130
|
|
|
134
131
|
@classmethod
|
|
135
|
-
def one_hot(cls
|
|
132
|
+
def one_hot(cls, *, index: int, length: int, pauli: 'cirq.PAULI_GATE_LIKE') -> Self:
|
|
136
133
|
"""Creates a dense pauli string with only one non-identity Pauli.
|
|
137
134
|
|
|
138
135
|
Args:
|
|
@@ -149,7 +146,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
149
146
|
return concrete_cls(pauli_mask=mask)
|
|
150
147
|
|
|
151
148
|
@classmethod
|
|
152
|
-
def eye(cls
|
|
149
|
+
def eye(cls, length: int) -> Self:
|
|
153
150
|
"""Creates a dense pauli string containing only identity gates.
|
|
154
151
|
|
|
155
152
|
Args:
|
|
@@ -198,7 +195,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
198
195
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
199
196
|
return protocols.parameter_names(self.coefficient)
|
|
200
197
|
|
|
201
|
-
def _resolve_parameters_(self
|
|
198
|
+
def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> Self:
|
|
202
199
|
return self.copy(
|
|
203
200
|
coefficient=protocols.resolve_parameters(self.coefficient, resolver, recursive)
|
|
204
201
|
)
|
|
@@ -206,7 +203,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
206
203
|
def __pos__(self):
|
|
207
204
|
return self
|
|
208
205
|
|
|
209
|
-
def __pow__(self
|
|
206
|
+
def __pow__(self, power: Union[int, float]) -> Union[NotImplementedType, Self]:
|
|
210
207
|
concrete_class = type(self)
|
|
211
208
|
if isinstance(power, int):
|
|
212
209
|
i_group = [1, +1j, -1, -1j]
|
|
@@ -221,11 +218,11 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
221
218
|
return NotImplemented
|
|
222
219
|
|
|
223
220
|
@overload
|
|
224
|
-
def __getitem__(self
|
|
221
|
+
def __getitem__(self, item: int) -> Union['cirq.Pauli', 'cirq.IdentityGate']:
|
|
225
222
|
pass
|
|
226
223
|
|
|
227
224
|
@overload
|
|
228
|
-
def __getitem__(self
|
|
225
|
+
def __getitem__(self, item: slice) -> Self:
|
|
229
226
|
pass
|
|
230
227
|
|
|
231
228
|
def __getitem__(self, item):
|
|
@@ -304,7 +301,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
304
301
|
|
|
305
302
|
return NotImplemented
|
|
306
303
|
|
|
307
|
-
def tensor_product(self
|
|
304
|
+
def tensor_product(self, other: 'BaseDensePauliString') -> Self:
|
|
308
305
|
"""Concatenates dense pauli strings and multiplies their coefficients.
|
|
309
306
|
|
|
310
307
|
Args:
|
|
@@ -319,7 +316,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
319
316
|
pauli_mask=np.concatenate([self.pauli_mask, other.pauli_mask]),
|
|
320
317
|
)
|
|
321
318
|
|
|
322
|
-
def __abs__(self
|
|
319
|
+
def __abs__(self) -> Self:
|
|
323
320
|
coef = self.coefficient
|
|
324
321
|
return type(self)(
|
|
325
322
|
coefficient=sympy.Abs(coef) if isinstance(coef, sympy.Expr) else abs(coef),
|
|
@@ -405,10 +402,10 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
405
402
|
|
|
406
403
|
@abc.abstractmethod
|
|
407
404
|
def copy(
|
|
408
|
-
self
|
|
405
|
+
self,
|
|
409
406
|
coefficient: Optional[Union[sympy.Expr, int, float, complex]] = None,
|
|
410
407
|
pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
|
|
411
|
-
) ->
|
|
408
|
+
) -> Self:
|
|
412
409
|
"""Returns a copy with possibly modified contents.
|
|
413
410
|
|
|
414
411
|
Args:
|
|
@@ -492,17 +489,15 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
492
489
|
"""
|
|
493
490
|
|
|
494
491
|
@overload
|
|
495
|
-
def __setitem__(
|
|
496
|
-
self: 'MutableDensePauliString', key: int, value: 'cirq.PAULI_GATE_LIKE'
|
|
497
|
-
) -> 'MutableDensePauliString':
|
|
492
|
+
def __setitem__(self, key: int, value: 'cirq.PAULI_GATE_LIKE') -> Self:
|
|
498
493
|
pass
|
|
499
494
|
|
|
500
495
|
@overload
|
|
501
496
|
def __setitem__(
|
|
502
|
-
self
|
|
497
|
+
self,
|
|
503
498
|
key: slice,
|
|
504
499
|
value: Union[Iterable['cirq.PAULI_GATE_LIKE'], np.ndarray, BaseDensePauliString],
|
|
505
|
-
) ->
|
|
500
|
+
) -> Self:
|
|
506
501
|
pass
|
|
507
502
|
|
|
508
503
|
def __setitem__(self, key, value):
|
cirq/ops/diagonal_gate.py
CHANGED
|
@@ -147,7 +147,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
147
147
|
diag_str += ', '.join(proper_repr(angle) for angle in rounded_angles[-2:])
|
|
148
148
|
diag_str = f'diag({diag_str})'
|
|
149
149
|
return protocols.CircuitDiagramInfo(
|
|
150
|
-
[diag_str] + [
|
|
150
|
+
[diag_str] + [f"#{i}" for i in range(2, self._num_qubits_() + 1)]
|
|
151
151
|
)
|
|
152
152
|
|
|
153
153
|
def __pow__(self, exponent: Any) -> 'DiagonalGate':
|
|
@@ -213,6 +213,5 @@ class DiagonalGate(raw_types.Gate):
|
|
|
213
213
|
return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
|
|
214
214
|
|
|
215
215
|
def __repr__(self) -> str:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
)
|
|
216
|
+
angles = ','.join(proper_repr(angle) for angle in self._diag_angles_radians)
|
|
217
|
+
return f'cirq.DiagonalGate([{angles}])'
|
cirq/ops/eigen_gate.py
CHANGED
|
@@ -11,7 +11,10 @@
|
|
|
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
|
+
import abc
|
|
14
15
|
import fractions
|
|
16
|
+
import math
|
|
17
|
+
import numbers
|
|
15
18
|
from typing import (
|
|
16
19
|
AbstractSet,
|
|
17
20
|
Any,
|
|
@@ -23,25 +26,20 @@ from typing import (
|
|
|
23
26
|
Optional,
|
|
24
27
|
Tuple,
|
|
25
28
|
TYPE_CHECKING,
|
|
26
|
-
TypeVar,
|
|
27
29
|
Union,
|
|
28
30
|
)
|
|
29
|
-
import abc
|
|
30
|
-
import math
|
|
31
|
-
import numbers
|
|
32
31
|
|
|
33
32
|
import numpy as np
|
|
34
33
|
import sympy
|
|
35
34
|
|
|
36
35
|
from cirq import value, protocols
|
|
36
|
+
from cirq.linalg import tolerance
|
|
37
37
|
from cirq.ops import raw_types
|
|
38
38
|
from cirq.type_workarounds import NotImplementedType
|
|
39
39
|
|
|
40
40
|
if TYPE_CHECKING:
|
|
41
41
|
import cirq
|
|
42
42
|
|
|
43
|
-
TSelf = TypeVar('TSelf', bound='EigenGate')
|
|
44
|
-
|
|
45
43
|
|
|
46
44
|
EigenComponent = NamedTuple(
|
|
47
45
|
'EigenComponent',
|
|
@@ -135,7 +133,7 @@ class EigenGate(raw_types.Gate):
|
|
|
135
133
|
return self._global_shift
|
|
136
134
|
|
|
137
135
|
# virtual method
|
|
138
|
-
def _with_exponent(self
|
|
136
|
+
def _with_exponent(self, exponent: value.TParamVal) -> 'EigenGate':
|
|
139
137
|
"""Return the same kind of gate, but with a different exponent.
|
|
140
138
|
|
|
141
139
|
Child classes should override this method if they have an __init__
|
|
@@ -301,7 +299,7 @@ class EigenGate(raw_types.Gate):
|
|
|
301
299
|
real_periods = [abs(2 / e) for e in exponents if e != 0]
|
|
302
300
|
return _approximate_common_period(real_periods)
|
|
303
301
|
|
|
304
|
-
def __pow__(self
|
|
302
|
+
def __pow__(self, exponent: Union[float, sympy.Symbol]) -> 'EigenGate':
|
|
305
303
|
new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
|
|
306
304
|
if new_exponent is NotImplemented:
|
|
307
305
|
return NotImplemented
|
|
@@ -388,8 +386,8 @@ class EigenGate(raw_types.Gate):
|
|
|
388
386
|
return False
|
|
389
387
|
|
|
390
388
|
period = self_without_phase._period()
|
|
391
|
-
|
|
392
|
-
return
|
|
389
|
+
exponents_diff = exponents[0] - exponents[1]
|
|
390
|
+
return tolerance.near_zero_mod(exponents_diff, period, atol=atol)
|
|
393
391
|
|
|
394
392
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
395
393
|
return protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
|
cirq/ops/eigen_gate_test.py
CHANGED
|
@@ -363,6 +363,12 @@ class WeightedZPowGate(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
|
363
363
|
(cirq.X, cirq.Y, False),
|
|
364
364
|
(cirq.rz(np.pi), cirq.Z, True),
|
|
365
365
|
(cirq.X**0.3, cirq.Z**0.3, False),
|
|
366
|
+
(cirq.Z, cirq.Z ** (1 - 1e-10), True),
|
|
367
|
+
(cirq.Z, cirq.Z ** (1 + 1e-10), True),
|
|
368
|
+
(cirq.Z, cirq.Z ** (3 - 1e-10), True),
|
|
369
|
+
(cirq.Z, cirq.Z ** (3 + 1e-10), True),
|
|
370
|
+
(cirq.Z**2, cirq.Z ** (4 - 1e-10), True),
|
|
371
|
+
(cirq.Z**2, cirq.Z ** (4 + 1e-10), True),
|
|
366
372
|
],
|
|
367
373
|
)
|
|
368
374
|
def test_equal_up_to_global_phase(gate1, gate2, eq_up_to_global_phase):
|
cirq/ops/gate_operation.py
CHANGED
|
@@ -31,6 +31,7 @@ from typing import (
|
|
|
31
31
|
Union,
|
|
32
32
|
List,
|
|
33
33
|
)
|
|
34
|
+
from typing_extensions import Self
|
|
34
35
|
|
|
35
36
|
import numpy as np
|
|
36
37
|
|
|
@@ -42,9 +43,6 @@ if TYPE_CHECKING:
|
|
|
42
43
|
import cirq
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
TSelf = TypeVar('TSelf', bound='GateOperation')
|
|
46
|
-
|
|
47
|
-
|
|
48
46
|
@value.value_equality(approximate=True)
|
|
49
47
|
class GateOperation(raw_types.Operation):
|
|
50
48
|
"""An application of a gate to a sequence of qubits.
|
|
@@ -73,8 +71,8 @@ class GateOperation(raw_types.Operation):
|
|
|
73
71
|
"""The qubits targeted by the operation."""
|
|
74
72
|
return self._qubits
|
|
75
73
|
|
|
76
|
-
def with_qubits(self
|
|
77
|
-
return cast(
|
|
74
|
+
def with_qubits(self, *new_qubits: 'cirq.Qid') -> Self:
|
|
75
|
+
return cast(Self, self.gate.on(*new_qubits))
|
|
78
76
|
|
|
79
77
|
def with_gate(self, new_gate: 'cirq.Gate') -> 'cirq.Operation':
|
|
80
78
|
if self.gate is new_gate:
|
|
@@ -162,7 +160,14 @@ class GateOperation(raw_types.Operation):
|
|
|
162
160
|
return len(self._qubits)
|
|
163
161
|
|
|
164
162
|
def _decompose_(self) -> 'cirq.OP_TREE':
|
|
165
|
-
return
|
|
163
|
+
return self._decompose_with_context_()
|
|
164
|
+
|
|
165
|
+
def _decompose_with_context_(
|
|
166
|
+
self, context: Optional['cirq.DecompositionContext'] = None
|
|
167
|
+
) -> 'cirq.OP_TREE':
|
|
168
|
+
return protocols.decompose_once_with_qubits(
|
|
169
|
+
self.gate, self.qubits, NotImplemented, flatten=False, context=context
|
|
170
|
+
)
|
|
166
171
|
|
|
167
172
|
def _pauli_expansion_(self) -> value.LinearDict[str]:
|
|
168
173
|
getter = getattr(self.gate, '_pauli_expansion_', None)
|
cirq/ops/gate_operation_test.py
CHANGED
|
@@ -41,10 +41,19 @@ def test_immutable():
|
|
|
41
41
|
a, b = cirq.LineQubit.range(2)
|
|
42
42
|
op = cirq.X(a)
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# Match one of two strings. The second one is message returned since python 3.11.
|
|
45
|
+
with pytest.raises(
|
|
46
|
+
AttributeError,
|
|
47
|
+
match="(can't set attribute)|"
|
|
48
|
+
"(property 'gate' of 'SingleQubitPauliStringGateOperation' object has no setter)",
|
|
49
|
+
):
|
|
45
50
|
op.gate = cirq.Y
|
|
46
51
|
|
|
47
|
-
with pytest.raises(
|
|
52
|
+
with pytest.raises(
|
|
53
|
+
AttributeError,
|
|
54
|
+
match="(can't set attribute)|"
|
|
55
|
+
"(property 'qubits' of 'SingleQubitPauliStringGateOperation' object has no setter)",
|
|
56
|
+
):
|
|
48
57
|
op.qubits = [b]
|
|
49
58
|
|
|
50
59
|
|
cirq/ops/gateset.py
CHANGED
|
@@ -257,11 +257,12 @@ class GateFamily:
|
|
|
257
257
|
|
|
258
258
|
def _value_equality_values_(self) -> Any:
|
|
259
259
|
# `isinstance` is used to ensure the a gate type and gate instance is not compared.
|
|
260
|
+
description = self.description if self.description != self._default_description() else None
|
|
260
261
|
return (
|
|
261
262
|
isinstance(self.gate, raw_types.Gate),
|
|
262
263
|
self.gate,
|
|
263
264
|
self.name,
|
|
264
|
-
|
|
265
|
+
description,
|
|
265
266
|
self._ignore_global_phase,
|
|
266
267
|
self._tags_to_accept,
|
|
267
268
|
self._tags_to_ignore,
|
cirq/ops/gateset_test.py
CHANGED
|
@@ -37,8 +37,10 @@ class CustomXPowGate(cirq.EigenGate):
|
|
|
37
37
|
if self._exponent == 1:
|
|
38
38
|
return 'cirq.ops.gateset_test.CustomX'
|
|
39
39
|
return f'(cirq.ops.gateset_test.CustomX**{proper_repr(self._exponent)})'
|
|
40
|
-
return
|
|
41
|
-
|
|
40
|
+
return (
|
|
41
|
+
'cirq.ops.gateset_test.CustomXPowGate('
|
|
42
|
+
f'exponent={proper_repr(self._exponent)}, '
|
|
43
|
+
f'global_shift={self._global_shift!r})'
|
|
42
44
|
)
|
|
43
45
|
|
|
44
46
|
def _num_qubits_(self) -> int:
|
|
@@ -81,6 +83,27 @@ def test_gate_family_default_name_and_description(gate, tags_to_accept, tags_to_
|
|
|
81
83
|
assert (ignored_match is None) == (tags_to_ignore == [])
|
|
82
84
|
|
|
83
85
|
|
|
86
|
+
@pytest.mark.parametrize(
|
|
87
|
+
'tags_to_accept_fam1, tags_to_ignore_fam1, tags_to_accept_fam2, tags_to_ignore_fam2',
|
|
88
|
+
[
|
|
89
|
+
(tuple("ab"), tuple("cd"), tuple("ba"), tuple("dc")),
|
|
90
|
+
(tuple("ab"), [], tuple("ba"), []),
|
|
91
|
+
([], tuple("ab"), [], tuple("ba")),
|
|
92
|
+
],
|
|
93
|
+
)
|
|
94
|
+
def test_gate_family_equality_with_tags(
|
|
95
|
+
tags_to_accept_fam1, tags_to_ignore_fam1, tags_to_accept_fam2, tags_to_ignore_fam2
|
|
96
|
+
):
|
|
97
|
+
gate_fam1 = cirq.GateFamily(
|
|
98
|
+
cirq.X, tags_to_accept=tags_to_accept_fam1, tags_to_ignore=tags_to_ignore_fam1
|
|
99
|
+
)
|
|
100
|
+
gate_fam2 = cirq.GateFamily(
|
|
101
|
+
cirq.X, tags_to_accept=tags_to_accept_fam2, tags_to_ignore=tags_to_ignore_fam2
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
assert gate_fam1 == gate_fam2
|
|
105
|
+
|
|
106
|
+
|
|
84
107
|
def test_invalid_gate_family():
|
|
85
108
|
with pytest.raises(ValueError, match='instance or subclass of `cirq.Gate`'):
|
|
86
109
|
_ = cirq.GateFamily(gate=cirq.Operation)
|
|
@@ -94,11 +117,21 @@ def test_invalid_gate_family():
|
|
|
94
117
|
|
|
95
118
|
def test_gate_family_immutable():
|
|
96
119
|
g = cirq.GateFamily(CustomX)
|
|
97
|
-
|
|
120
|
+
# Match one of two strings. The second one is message returned since python 3.11.
|
|
121
|
+
with pytest.raises(
|
|
122
|
+
AttributeError,
|
|
123
|
+
match="(can't set attribute)|(property 'gate' of 'GateFamily' object has no setter)",
|
|
124
|
+
):
|
|
98
125
|
g.gate = CustomXPowGate
|
|
99
|
-
with pytest.raises(
|
|
126
|
+
with pytest.raises(
|
|
127
|
+
AttributeError,
|
|
128
|
+
match="(can't set attribute)|(property 'name' of 'GateFamily' object has no setter)",
|
|
129
|
+
):
|
|
100
130
|
g.name = 'new name'
|
|
101
|
-
with pytest.raises(
|
|
131
|
+
with pytest.raises(
|
|
132
|
+
AttributeError,
|
|
133
|
+
match="(can't set attribute)|(property 'description' of 'GateFamily' object has no setter)",
|
|
134
|
+
):
|
|
102
135
|
g.description = 'new description'
|
|
103
136
|
|
|
104
137
|
|
cirq/ops/global_phase_op.py
CHANGED
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""A no-qubit global phase operation."""
|
|
15
15
|
|
|
16
|
-
from typing import AbstractSet, Any, cast, Dict, Sequence, Tuple, Union
|
|
16
|
+
from typing import AbstractSet, Any, cast, Dict, Sequence, Tuple, Union, Optional, Collection
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
import sympy
|
|
20
20
|
|
|
21
21
|
import cirq
|
|
22
22
|
from cirq import value, protocols
|
|
23
|
-
from cirq.ops import raw_types
|
|
23
|
+
from cirq.ops import raw_types, controlled_gate, control_values as cv
|
|
24
24
|
from cirq.type_workarounds import NotImplementedType
|
|
25
25
|
|
|
26
26
|
|
|
@@ -91,6 +91,32 @@ class GlobalPhaseGate(raw_types.Gate):
|
|
|
91
91
|
coefficient = protocols.resolve_parameters(self.coefficient, resolver, recursive)
|
|
92
92
|
return GlobalPhaseGate(coefficient=coefficient)
|
|
93
93
|
|
|
94
|
+
def controlled(
|
|
95
|
+
self,
|
|
96
|
+
num_controls: Optional[int] = None,
|
|
97
|
+
control_values: Optional[
|
|
98
|
+
Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
|
|
99
|
+
] = None,
|
|
100
|
+
control_qid_shape: Optional[Tuple[int, ...]] = None,
|
|
101
|
+
) -> raw_types.Gate:
|
|
102
|
+
result = super().controlled(num_controls, control_values, control_qid_shape)
|
|
103
|
+
if (
|
|
104
|
+
not self._is_parameterized_()
|
|
105
|
+
and isinstance(result, controlled_gate.ControlledGate)
|
|
106
|
+
and isinstance(result.control_values, cv.ProductOfSums)
|
|
107
|
+
and result.control_values[-1] == (1,)
|
|
108
|
+
and result.control_qid_shape[-1] == 2
|
|
109
|
+
):
|
|
110
|
+
# A `GlobalPhaseGate` controlled on a qubit in state `|1>` is equivalent
|
|
111
|
+
# to applying a `ZPowGate`. This override ensures that `global_phase_gate.controlled()`
|
|
112
|
+
# returns a `ZPowGate` instead of a `ControlledGate(sub_gate=global_phase_gate)`.
|
|
113
|
+
coefficient = complex(self.coefficient)
|
|
114
|
+
exponent = float(np.angle(coefficient) / np.pi)
|
|
115
|
+
return cirq.ZPowGate(exponent=exponent).controlled(
|
|
116
|
+
result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]
|
|
117
|
+
)
|
|
118
|
+
return result
|
|
119
|
+
|
|
94
120
|
|
|
95
121
|
def global_phase_operation(
|
|
96
122
|
coefficient: 'cirq.TParamValComplex', atol: float = 1e-8
|
cirq/ops/global_phase_op_test.py
CHANGED
|
@@ -279,3 +279,24 @@ def test_resolve_error(resolve_fn):
|
|
|
279
279
|
gpt = cirq.GlobalPhaseGate(coefficient=t)
|
|
280
280
|
with pytest.raises(ValueError, match='Coefficient is not unitary'):
|
|
281
281
|
resolve_fn(gpt, {'t': -2})
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@pytest.mark.parametrize(
|
|
285
|
+
'coeff, exp', [(-1, 1), (1j, 0.5), (-1j, -0.5), (1 / np.sqrt(2) * (1 + 1j), 0.25)]
|
|
286
|
+
)
|
|
287
|
+
def test_global_phase_gate_controlled(coeff, exp):
|
|
288
|
+
g = cirq.GlobalPhaseGate(coeff)
|
|
289
|
+
op = cirq.global_phase_operation(coeff)
|
|
290
|
+
q = cirq.LineQubit.range(3)
|
|
291
|
+
for num_controls, target_gate in zip(range(1, 4), [cirq.Z, cirq.CZ, cirq.CCZ]):
|
|
292
|
+
assert g.controlled(num_controls) == target_gate**exp
|
|
293
|
+
np.testing.assert_allclose(
|
|
294
|
+
cirq.unitary(cirq.ControlledGate(g, num_controls)),
|
|
295
|
+
cirq.unitary(g.controlled(num_controls)),
|
|
296
|
+
)
|
|
297
|
+
assert op.controlled_by(*q[:num_controls]) == target_gate(*q[:num_controls]) ** exp
|
|
298
|
+
assert g.controlled(control_values=[0]) == cirq.ControlledGate(g, control_values=[0])
|
|
299
|
+
xor_control_values = cirq.SumOfProducts(((0, 0), (1, 1)))
|
|
300
|
+
assert g.controlled(control_values=xor_control_values) == cirq.ControlledGate(
|
|
301
|
+
g, control_values=xor_control_values
|
|
302
|
+
)
|
cirq/ops/identity.py
CHANGED
|
@@ -42,7 +42,7 @@ class IdentityGate(raw_types.Gate):
|
|
|
42
42
|
"""Inits IdentityGate.
|
|
43
43
|
|
|
44
44
|
Args:
|
|
45
|
-
num_qubits: The number of qubits for the
|
|
45
|
+
num_qubits: The number of qubits for the identity gate.
|
|
46
46
|
qid_shape: Specifies the dimension of each qid the measurement
|
|
47
47
|
applies to. The default is 2 for every qubit.
|
|
48
48
|
|
cirq/ops/kraus_channel_test.py
CHANGED
|
@@ -105,8 +105,8 @@ def test_kraus_channel_repr():
|
|
|
105
105
|
repr(x_meas)
|
|
106
106
|
== """\
|
|
107
107
|
cirq.KrausChannel(kraus_ops=[\
|
|
108
|
-
np.array([[(0.5+0j), (0.5+0j)], [(0.5+0j), (0.5+0j)]], dtype=np.complex64), \
|
|
109
|
-
np.array([[(0.5+0j), (-0.5+0j)], [(-0.5+0j), (0.5+0j)]], dtype=np.complex64)], \
|
|
108
|
+
np.array([[(0.5+0j), (0.5+0j)], [(0.5+0j), (0.5+0j)]], dtype=np.dtype('complex64')), \
|
|
109
|
+
np.array([[(0.5+0j), (-0.5+0j)], [(-0.5+0j), (0.5+0j)]], dtype=np.dtype('complex64'))], \
|
|
110
110
|
key='x_meas')"""
|
|
111
111
|
)
|
|
112
112
|
|
cirq/ops/linear_combinations.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
|
from collections import defaultdict
|
|
15
16
|
from typing import (
|
|
16
17
|
AbstractSet,
|
|
@@ -440,7 +441,7 @@ class PauliSum:
|
|
|
440
441
|
def wrap(val: PauliSumLike) -> 'PauliSum':
|
|
441
442
|
"""Convert a `cirq.PauliSumLike` object to a PauliSum
|
|
442
443
|
|
|
443
|
-
|
|
444
|
+
Attempts to convert an existing int, float, complex, `cirq.PauliString`,
|
|
444
445
|
`cirq.PauliSum` or `cirq.SingleQubitPauliStringGateOperation` into
|
|
445
446
|
a `cirq.PauliSum` object. For example:
|
|
446
447
|
|
|
@@ -651,7 +652,7 @@ class PauliSum:
|
|
|
651
652
|
if any(abs(p.coefficient.imag) > 0.0001 for p in self):
|
|
652
653
|
raise NotImplementedError(
|
|
653
654
|
"Cannot compute expectation value of a non-Hermitian "
|
|
654
|
-
"PauliString <{}>. Coefficient must be real."
|
|
655
|
+
f"PauliString <{self}>. Coefficient must be real."
|
|
655
656
|
)
|
|
656
657
|
|
|
657
658
|
# TODO: Avoid enforce specific complex type. This is necessary to
|
|
@@ -713,7 +714,7 @@ class PauliSum:
|
|
|
713
714
|
if any(abs(p.coefficient.imag) > 0.0001 for p in self):
|
|
714
715
|
raise NotImplementedError(
|
|
715
716
|
"Cannot compute expectation value of a non-Hermitian "
|
|
716
|
-
"PauliString <{}>. Coefficient must be real."
|
|
717
|
+
f"PauliString <{self}>. Coefficient must be real."
|
|
717
718
|
)
|
|
718
719
|
|
|
719
720
|
# FIXME: Avoid enforce specific complex type. This is necessary to
|
|
@@ -839,10 +840,10 @@ class PauliSum:
|
|
|
839
840
|
if exponent == 0:
|
|
840
841
|
return PauliSum(value.LinearDict({frozenset(): 1 + 0j}))
|
|
841
842
|
if exponent > 0:
|
|
842
|
-
|
|
843
|
+
result = self.copy()
|
|
843
844
|
for _ in range(exponent - 1):
|
|
844
|
-
|
|
845
|
-
return
|
|
845
|
+
result *= self
|
|
846
|
+
return result
|
|
846
847
|
return NotImplemented
|
|
847
848
|
|
|
848
849
|
def __truediv__(self, a: value.Scalar):
|