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
|
@@ -1156,6 +1156,22 @@ def test_pauli_sum_pow():
|
|
|
1156
1156
|
for psum in [psum1, psum2, psum3, psum4]:
|
|
1157
1157
|
assert cirq.approx_eq(psum**0, identity)
|
|
1158
1158
|
|
|
1159
|
+
# tests for exponents greater than two for both even and odd
|
|
1160
|
+
psum5 = cirq.Z(q0) * cirq.Z(q1) + cirq.Z(q2) + cirq.Z(q3)
|
|
1161
|
+
correctresult = psum5.copy()
|
|
1162
|
+
for e in range(1, 9):
|
|
1163
|
+
assert correctresult == psum5**e
|
|
1164
|
+
correctresult *= psum5
|
|
1165
|
+
|
|
1166
|
+
psum6 = cirq.X(q0) * cirq.Y(q1) + cirq.Z(q2) + cirq.X(q3)
|
|
1167
|
+
assert psum6 * psum6 * psum6 * psum6 * psum6 * psum6 * psum6 * psum6 == psum6**8
|
|
1168
|
+
|
|
1169
|
+
# test to ensure pow doesn't make any change to the original value
|
|
1170
|
+
psum7 = cirq.X(q0) * cirq.Y(q1) + cirq.Z(q2)
|
|
1171
|
+
psum7copy = psum7.copy()
|
|
1172
|
+
assert psum7**5 == psum7 * psum7 * psum7 * psum7 * psum7
|
|
1173
|
+
assert psum7copy == psum7
|
|
1174
|
+
|
|
1159
1175
|
|
|
1160
1176
|
# Using the entries of table 1 of https://arxiv.org/abs/1804.09130 as golden values.
|
|
1161
1177
|
@pytest.mark.parametrize(
|
|
@@ -1302,7 +1318,7 @@ def test_expectation_from_state_vector_two_qubit_states():
|
|
|
1302
1318
|
psum1 = cirq.Z(q[0]) + 3.2 * cirq.Z(q[1])
|
|
1303
1319
|
psum2 = -1 * cirq.X(q[0]) + 2 * cirq.X(q[1])
|
|
1304
1320
|
wf1 = np.array([0, 1, 0, 0], dtype=complex)
|
|
1305
|
-
for state in [wf1, wf1.reshape(2, 2)]:
|
|
1321
|
+
for state in [wf1, wf1.reshape((2, 2))]:
|
|
1306
1322
|
np.testing.assert_allclose(
|
|
1307
1323
|
psum1.expectation_from_state_vector(state, qubit_map=q_map), -2.2, atol=1e-7
|
|
1308
1324
|
)
|
|
@@ -1311,7 +1327,7 @@ def test_expectation_from_state_vector_two_qubit_states():
|
|
|
1311
1327
|
)
|
|
1312
1328
|
|
|
1313
1329
|
wf2 = np.array([1, 1, 1, 1], dtype=complex) / 2
|
|
1314
|
-
for state in [wf2, wf2.reshape(2, 2)]:
|
|
1330
|
+
for state in [wf2, wf2.reshape((2, 2))]:
|
|
1315
1331
|
np.testing.assert_allclose(
|
|
1316
1332
|
psum1.expectation_from_state_vector(state, qubit_map=q_map), 0, atol=1e-7
|
|
1317
1333
|
)
|
|
@@ -1322,7 +1338,7 @@ def test_expectation_from_state_vector_two_qubit_states():
|
|
|
1322
1338
|
psum3 = cirq.Z(q[0]) + cirq.X(q[1])
|
|
1323
1339
|
wf3 = np.array([1, 1, 0, 0], dtype=complex) / np.sqrt(2)
|
|
1324
1340
|
q_map_2 = {q0: 1, q1: 0}
|
|
1325
|
-
for state in [wf3, wf3.reshape(2, 2)]:
|
|
1341
|
+
for state in [wf3, wf3.reshape((2, 2))]:
|
|
1326
1342
|
np.testing.assert_allclose(
|
|
1327
1343
|
psum3.expectation_from_state_vector(state, qubit_map=q_map), 2, atol=1e-7
|
|
1328
1344
|
)
|
|
@@ -1336,7 +1352,7 @@ def test_expectation_from_density_matrix_invalid_input():
|
|
|
1336
1352
|
psum = cirq.X(q0) + 2 * cirq.Y(q1) + 3 * cirq.Z(q3)
|
|
1337
1353
|
q_map = {q0: 0, q1: 1, q3: 2}
|
|
1338
1354
|
wf = np.array([1, 0, 0, 0, 0, 0, 0, 0], dtype=np.complex64)
|
|
1339
|
-
rho = np.kron(wf.conjugate().T, wf).reshape(8, 8)
|
|
1355
|
+
rho = np.kron(wf.conjugate().T, wf).reshape((8, 8))
|
|
1340
1356
|
|
|
1341
1357
|
im_psum = (1j + 1) * psum
|
|
1342
1358
|
with pytest.raises(NotImplementedError, match='non-Hermitian'):
|
|
@@ -1443,24 +1459,24 @@ def test_expectation_from_density_matrix_two_qubit_states():
|
|
|
1443
1459
|
psum1 = cirq.Z(q[0]) + 3.2 * cirq.Z(q[1])
|
|
1444
1460
|
psum2 = -1 * cirq.X(q[0]) + 2 * cirq.X(q[1])
|
|
1445
1461
|
wf1 = np.array([0, 1, 0, 0], dtype=complex)
|
|
1446
|
-
rho1 = np.kron(wf1, wf1).reshape(4, 4)
|
|
1447
|
-
for state in [rho1, rho1.reshape(2, 2, 2, 2)]:
|
|
1462
|
+
rho1 = np.kron(wf1, wf1).reshape((4, 4))
|
|
1463
|
+
for state in [rho1, rho1.reshape((2, 2, 2, 2))]:
|
|
1448
1464
|
np.testing.assert_allclose(
|
|
1449
1465
|
psum1.expectation_from_density_matrix(state, qubit_map=q_map), -2.2
|
|
1450
1466
|
)
|
|
1451
1467
|
np.testing.assert_allclose(psum2.expectation_from_density_matrix(state, qubit_map=q_map), 0)
|
|
1452
1468
|
|
|
1453
1469
|
wf2 = np.array([1, 1, 1, 1], dtype=complex) / 2
|
|
1454
|
-
rho2 = np.kron(wf2, wf2).reshape(4, 4)
|
|
1455
|
-
for state in [rho2, rho2.reshape(2, 2, 2, 2)]:
|
|
1470
|
+
rho2 = np.kron(wf2, wf2).reshape((4, 4))
|
|
1471
|
+
for state in [rho2, rho2.reshape((2, 2, 2, 2))]:
|
|
1456
1472
|
np.testing.assert_allclose(psum1.expectation_from_density_matrix(state, qubit_map=q_map), 0)
|
|
1457
1473
|
np.testing.assert_allclose(psum2.expectation_from_density_matrix(state, qubit_map=q_map), 1)
|
|
1458
1474
|
|
|
1459
1475
|
psum3 = cirq.Z(q[0]) + cirq.X(q[1])
|
|
1460
1476
|
wf3 = np.array([1, 1, 0, 0], dtype=complex) / np.sqrt(2)
|
|
1461
|
-
rho3 = np.kron(wf3, wf3).reshape(4, 4)
|
|
1477
|
+
rho3 = np.kron(wf3, wf3).reshape((4, 4))
|
|
1462
1478
|
q_map_2 = {q0: 1, q1: 0}
|
|
1463
|
-
for state in [rho3, rho3.reshape(2, 2, 2, 2)]:
|
|
1479
|
+
for state in [rho3, rho3.reshape((2, 2, 2, 2))]:
|
|
1464
1480
|
np.testing.assert_allclose(psum3.expectation_from_density_matrix(state, qubit_map=q_map), 2)
|
|
1465
1481
|
np.testing.assert_allclose(
|
|
1466
1482
|
psum3.expectation_from_density_matrix(state, qubit_map=q_map_2), 0
|
cirq/ops/matrix_gates.py
CHANGED
|
@@ -53,7 +53,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
53
53
|
self,
|
|
54
54
|
matrix: np.ndarray,
|
|
55
55
|
*,
|
|
56
|
-
name: str = None,
|
|
56
|
+
name: Optional[str] = None,
|
|
57
57
|
qid_shape: Optional[Iterable[int]] = None,
|
|
58
58
|
unitary_check: bool = True,
|
|
59
59
|
unitary_check_rtol: float = 1e-5,
|
|
@@ -114,11 +114,15 @@ class MatrixGate(raw_types.Gate):
|
|
|
114
114
|
return MatrixGate(self._matrix, name=name, qid_shape=self._qid_shape, unitary_check=False)
|
|
115
115
|
|
|
116
116
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
117
|
-
return {
|
|
117
|
+
return {
|
|
118
|
+
'matrix': self._matrix.tolist(),
|
|
119
|
+
'qid_shape': self._qid_shape,
|
|
120
|
+
**({'name': self._name} if self._name is not None else {}),
|
|
121
|
+
}
|
|
118
122
|
|
|
119
123
|
@classmethod
|
|
120
|
-
def _from_json_dict_(cls, matrix, qid_shape, **kwargs):
|
|
121
|
-
return cls(matrix=np.array(matrix), qid_shape=qid_shape)
|
|
124
|
+
def _from_json_dict_(cls, matrix, qid_shape, name=None, **kwargs):
|
|
125
|
+
return cls(matrix=np.array(matrix), qid_shape=qid_shape, name=name)
|
|
122
126
|
|
|
123
127
|
def _qid_shape_(self) -> Tuple[int, ...]:
|
|
124
128
|
return self._qid_shape
|
cirq/ops/matrix_gates_test.py
CHANGED
|
@@ -29,12 +29,12 @@ def test_single_qubit_init():
|
|
|
29
29
|
m = np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5)
|
|
30
30
|
x2 = cirq.MatrixGate(m)
|
|
31
31
|
assert cirq.has_unitary(x2)
|
|
32
|
-
assert np.
|
|
32
|
+
assert np.all(cirq.unitary(x2) == m)
|
|
33
33
|
assert cirq.qid_shape(x2) == (2,)
|
|
34
34
|
|
|
35
35
|
x2 = cirq.MatrixGate(PLUS_ONE, qid_shape=(3,))
|
|
36
36
|
assert cirq.has_unitary(x2)
|
|
37
|
-
assert np.
|
|
37
|
+
assert np.all(cirq.unitary(x2) == PLUS_ONE)
|
|
38
38
|
assert cirq.qid_shape(x2) == (3,)
|
|
39
39
|
|
|
40
40
|
with pytest.raises(ValueError, match='Not a .*unitary matrix'):
|
|
@@ -97,7 +97,7 @@ def test_single_qubit_extrapolate():
|
|
|
97
97
|
def test_two_qubit_init():
|
|
98
98
|
x2 = cirq.MatrixGate(QFT2)
|
|
99
99
|
assert cirq.has_unitary(x2)
|
|
100
|
-
assert np.
|
|
100
|
+
assert np.all(cirq.unitary(x2) == QFT2)
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
def test_two_qubit_eq():
|
|
@@ -388,3 +388,25 @@ def test_matrixgate_unitary_tolerance():
|
|
|
388
388
|
# very low atol -> the check never converges
|
|
389
389
|
with pytest.raises(ValueError):
|
|
390
390
|
_ = cirq.MatrixGate(np.array([[0.707, 0.707], [-0.707, 0.707]]), unitary_check_rtol=1e-10)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def test_matrixgate_name_serialization():
|
|
394
|
+
# https://github.com/quantumlib/Cirq/issues/5999
|
|
395
|
+
|
|
396
|
+
# Test name serialization
|
|
397
|
+
gate1 = cirq.MatrixGate(np.eye(2), name='test_name')
|
|
398
|
+
gate_after_serialization1 = cirq.read_json(json_text=cirq.to_json(gate1))
|
|
399
|
+
assert gate1._name == 'test_name'
|
|
400
|
+
assert gate_after_serialization1._name == 'test_name'
|
|
401
|
+
|
|
402
|
+
# Test name backwards compatibility
|
|
403
|
+
gate2 = cirq.MatrixGate(np.eye(2))
|
|
404
|
+
gate_after_serialization2 = cirq.read_json(json_text=cirq.to_json(gate2))
|
|
405
|
+
assert gate2._name is None
|
|
406
|
+
assert gate_after_serialization2._name is None
|
|
407
|
+
|
|
408
|
+
# Test empty name
|
|
409
|
+
gate3 = cirq.MatrixGate(np.eye(2), name='')
|
|
410
|
+
gate_after_serialization3 = cirq.read_json(json_text=cirq.to_json(gate3))
|
|
411
|
+
assert gate3._name == ''
|
|
412
|
+
assert gate_after_serialization3._name == ''
|
cirq/ops/measure_util.py
CHANGED
|
@@ -46,18 +46,22 @@ def measure_single_paulistring(
|
|
|
46
46
|
|
|
47
47
|
Raises:
|
|
48
48
|
ValueError: if the observable is not an instance of PauliString or if the coefficient
|
|
49
|
-
is not +1.
|
|
49
|
+
is not +1 or -1.
|
|
50
50
|
"""
|
|
51
51
|
if not isinstance(pauli_observable, pauli_string.PauliString):
|
|
52
52
|
raise ValueError(
|
|
53
53
|
f'Pauli observable {pauli_observable} should be an instance of cirq.PauliString.'
|
|
54
54
|
)
|
|
55
|
-
if pauli_observable.coefficient != 1:
|
|
56
|
-
raise ValueError(
|
|
55
|
+
if abs(pauli_observable.coefficient) != 1:
|
|
56
|
+
raise ValueError(
|
|
57
|
+
f"Pauli observable {pauli_observable} must have a coefficient of +1 or -1."
|
|
58
|
+
)
|
|
57
59
|
|
|
58
60
|
if key is None:
|
|
59
61
|
key = _default_measurement_key(pauli_observable)
|
|
60
|
-
return PauliMeasurementGate(pauli_observable.
|
|
62
|
+
return PauliMeasurementGate(pauli_observable.dense(list(pauli_observable.keys())), key).on(
|
|
63
|
+
*pauli_observable.keys()
|
|
64
|
+
)
|
|
61
65
|
|
|
62
66
|
|
|
63
67
|
def measure_paulistring_terms(
|
|
@@ -115,7 +119,8 @@ def measure(
|
|
|
115
119
|
) -> raw_types.Operation:
|
|
116
120
|
"""Returns a single MeasurementGate applied to all the given qubits.
|
|
117
121
|
|
|
118
|
-
The qubits are measured in the computational basis.
|
|
122
|
+
The qubits are measured in the computational basis. This can also be
|
|
123
|
+
used with the alias `cirq.M`.
|
|
119
124
|
|
|
120
125
|
Args:
|
|
121
126
|
*target: The qubits that the measurement gate should measure.
|
|
@@ -159,6 +164,9 @@ def measure(
|
|
|
159
164
|
return MeasurementGate(len(targets), key, invert_mask, qid_shape, confusion_map).on(*targets)
|
|
160
165
|
|
|
161
166
|
|
|
167
|
+
M = measure
|
|
168
|
+
|
|
169
|
+
|
|
162
170
|
@overload
|
|
163
171
|
def measure_each(
|
|
164
172
|
*qubits: raw_types.Qid, key_func: Callable[[raw_types.Qid], str] = str
|
cirq/ops/measure_util_test.py
CHANGED
|
@@ -95,6 +95,12 @@ def test_measure_single_paulistring():
|
|
|
95
95
|
ps.values(), key='a'
|
|
96
96
|
).on(*ps.keys())
|
|
97
97
|
|
|
98
|
+
# Test with negative coefficient
|
|
99
|
+
ps_neg = -cirq.Y(cirq.LineQubit(0)) * cirq.Y(cirq.LineQubit(1))
|
|
100
|
+
assert cirq.measure_single_paulistring(ps_neg, key='1').gate == cirq.PauliMeasurementGate(
|
|
101
|
+
cirq.DensePauliString('YY', coefficient=-1), key='1'
|
|
102
|
+
)
|
|
103
|
+
|
|
98
104
|
# Empty application
|
|
99
105
|
with pytest.raises(ValueError, match='should be an instance of cirq.PauliString'):
|
|
100
106
|
_ = cirq.measure_single_paulistring(cirq.I(q[0]) * cirq.I(q[1]))
|
|
@@ -103,9 +109,9 @@ def test_measure_single_paulistring():
|
|
|
103
109
|
with pytest.raises(ValueError, match='should be an instance of cirq.PauliString'):
|
|
104
110
|
_ = cirq.measure_single_paulistring(q)
|
|
105
111
|
|
|
106
|
-
# Coefficient != +1
|
|
112
|
+
# Coefficient != +1 or -1
|
|
107
113
|
with pytest.raises(ValueError, match='must have a coefficient'):
|
|
108
|
-
_ = cirq.measure_single_paulistring(-ps)
|
|
114
|
+
_ = cirq.measure_single_paulistring(-2 * ps)
|
|
109
115
|
|
|
110
116
|
|
|
111
117
|
def test_measure_paulistring_terms():
|
cirq/ops/measurement_gate.py
CHANGED
|
@@ -50,7 +50,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
50
50
|
num_qubits: Optional[int] = None,
|
|
51
51
|
key: Union[str, 'cirq.MeasurementKey'] = '',
|
|
52
52
|
invert_mask: Tuple[bool, ...] = (),
|
|
53
|
-
qid_shape: Tuple[int, ...] = None,
|
|
53
|
+
qid_shape: Optional[Tuple[int, ...]] = None,
|
|
54
54
|
confusion_map: Optional[Dict[Tuple[int, ...], np.ndarray]] = None,
|
|
55
55
|
) -> None:
|
|
56
56
|
"""Inits MeasurementGate.
|
|
@@ -317,23 +317,28 @@ def test_op_repr():
|
|
|
317
317
|
b,
|
|
318
318
|
key='out',
|
|
319
319
|
invert_mask=(False, True),
|
|
320
|
-
confusion_map={(0,): np.array([[0, 1], [1, 0]], dtype=np.int64)},
|
|
320
|
+
confusion_map={(0,): np.array([[0, 1], [1, 0]], dtype=np.dtype('int64'))},
|
|
321
321
|
)
|
|
322
322
|
) == (
|
|
323
323
|
"cirq.measure(cirq.LineQubit(0), cirq.LineQubit(1), "
|
|
324
324
|
"key=cirq.MeasurementKey(name='out'), "
|
|
325
325
|
"invert_mask=(False, True), "
|
|
326
|
-
"confusion_map={(0,): np.array([[0, 1], [1, 0]], dtype=np.int64)})"
|
|
326
|
+
"confusion_map={(0,): np.array([[0, 1], [1, 0]], dtype=np.dtype('int64'))})"
|
|
327
327
|
)
|
|
328
328
|
|
|
329
329
|
|
|
330
330
|
def test_repr():
|
|
331
331
|
gate = cirq.MeasurementGate(
|
|
332
|
-
3,
|
|
332
|
+
3,
|
|
333
|
+
'a',
|
|
334
|
+
(True, False),
|
|
335
|
+
(1, 2, 3),
|
|
336
|
+
{(2,): np.array([[0, 1], [1, 0]], dtype=np.dtype('int64'))},
|
|
333
337
|
)
|
|
334
338
|
assert repr(gate) == (
|
|
335
339
|
"cirq.MeasurementGate(3, cirq.MeasurementKey(name='a'), (True, False), "
|
|
336
|
-
"qid_shape=(1, 2, 3),
|
|
340
|
+
"qid_shape=(1, 2, 3), "
|
|
341
|
+
"confusion_map={(2,): np.array([[0, 1], [1, 0]], dtype=np.dtype('int64'))})"
|
|
337
342
|
)
|
|
338
343
|
|
|
339
344
|
|
|
@@ -95,16 +95,16 @@ def test_matrix_mixture_str():
|
|
|
95
95
|
|
|
96
96
|
def test_matrix_mixture_repr():
|
|
97
97
|
mix = [
|
|
98
|
-
(0.5, np.array([[1, 0], [0, 1]], dtype=np.complex64)),
|
|
99
|
-
(0.5, np.array([[0, 1], [1, 0]], dtype=np.complex64)),
|
|
98
|
+
(0.5, np.array([[1, 0], [0, 1]], dtype=np.dtype('complex64'))),
|
|
99
|
+
(0.5, np.array([[0, 1], [1, 0]], dtype=np.dtype('complex64'))),
|
|
100
100
|
]
|
|
101
101
|
half_flip = cirq.MixedUnitaryChannel(mix, key='flip')
|
|
102
102
|
assert (
|
|
103
103
|
repr(half_flip)
|
|
104
104
|
== """\
|
|
105
105
|
cirq.MixedUnitaryChannel(mixture=[\
|
|
106
|
-
(0.5, np.array([[(1+0j), 0j], [0j, (1+0j)]], dtype=np.complex64)), \
|
|
107
|
-
(0.5, np.array([[0j, (1+0j)], [(1+0j), 0j]], dtype=np.complex64))], \
|
|
106
|
+
(0.5, np.array([[(1+0j), 0j], [0j, (1+0j)]], dtype=np.dtype('complex64'))), \
|
|
107
|
+
(0.5, np.array([[0j, (1+0j)], [(1+0j), 0j]], dtype=np.dtype('complex64')))], \
|
|
108
108
|
key='flip')"""
|
|
109
109
|
)
|
|
110
110
|
|
cirq/ops/named_qubit.py
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import functools
|
|
15
|
-
from typing import Any, Dict, List, TYPE_CHECKING
|
|
15
|
+
from typing import Any, Dict, List, TYPE_CHECKING
|
|
16
16
|
|
|
17
17
|
from cirq import protocols
|
|
18
18
|
from cirq.ops import raw_types
|
|
@@ -21,10 +21,8 @@ from cirq.ops import raw_types
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
22
|
import cirq
|
|
23
23
|
|
|
24
|
-
TSelf = TypeVar('TSelf', bound='_BaseNamedQid')
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
@functools.total_ordering # type: ignore
|
|
25
|
+
@functools.total_ordering
|
|
28
26
|
class _BaseNamedQid(raw_types.Qid):
|
|
29
27
|
"""The base class for `NamedQid` and `NamedQubit`."""
|
|
30
28
|
|
cirq/ops/parity_gates.py
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"""Quantum gates that phase with respect to product-of-pauli observables."""
|
|
16
16
|
|
|
17
17
|
from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING
|
|
18
|
+
from typing_extensions import Self
|
|
18
19
|
|
|
19
20
|
import numpy as np
|
|
20
21
|
|
|
@@ -295,6 +296,9 @@ class ZZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
|
|
|
295
296
|
|
|
296
297
|
return args.target_tensor
|
|
297
298
|
|
|
299
|
+
def _phase_by_(self, phase_turns: float, qubit_index: int) -> "ZZPowGate":
|
|
300
|
+
return self
|
|
301
|
+
|
|
298
302
|
def __str__(self) -> str:
|
|
299
303
|
if self._exponent == 1:
|
|
300
304
|
return 'ZZ'
|
|
@@ -328,7 +332,7 @@ class MSGate(XXPowGate):
|
|
|
328
332
|
XXPowGate.__init__(self, exponent=rads * 2 / np.pi, global_shift=-0.5)
|
|
329
333
|
self.rads = rads
|
|
330
334
|
|
|
331
|
-
def _with_exponent(self
|
|
335
|
+
def _with_exponent(self, exponent: value.TParamVal) -> Self:
|
|
332
336
|
return type(self)(rads=exponent * np.pi / 2)
|
|
333
337
|
|
|
334
338
|
def _circuit_diagram_info_(
|
cirq/ops/parity_gates_test.py
CHANGED
|
@@ -195,6 +195,12 @@ def test_zz_pow():
|
|
|
195
195
|
assert (cirq.ZZ**-1) ** 0.5 == cirq.ZZ**-0.5
|
|
196
196
|
|
|
197
197
|
|
|
198
|
+
def test_zz_phase_by():
|
|
199
|
+
assert cirq.phase_by(cirq.ZZ, 0.25, 0) == cirq.phase_by(cirq.ZZ, 0.25, 1) == cirq.ZZ
|
|
200
|
+
assert cirq.phase_by(cirq.ZZ**0.5, 0.25, 0) == cirq.ZZ**0.5
|
|
201
|
+
assert cirq.phase_by(cirq.ZZ**-0.5, 0.25, 1) == cirq.ZZ**-0.5
|
|
202
|
+
|
|
203
|
+
|
|
198
204
|
def test_zz_str():
|
|
199
205
|
assert str(cirq.ZZ) == 'ZZ'
|
|
200
206
|
assert str(cirq.ZZ**0.5) == 'ZZ**0.5'
|
cirq/ops/pauli_gates.py
CHANGED
|
@@ -112,10 +112,10 @@ class _PauliX(Pauli, common_gates.XPowGate):
|
|
|
112
112
|
Pauli.__init__(self, index=0, name='X')
|
|
113
113
|
common_gates.XPowGate.__init__(self, exponent=1.0)
|
|
114
114
|
|
|
115
|
-
def __pow__(self
|
|
115
|
+
def __pow__(self, exponent: 'cirq.TParamVal') -> common_gates.XPowGate:
|
|
116
116
|
return common_gates.XPowGate(exponent=exponent) if exponent != 1 else _PauliX()
|
|
117
117
|
|
|
118
|
-
def _with_exponent(self
|
|
118
|
+
def _with_exponent(self, exponent: 'cirq.TParamVal') -> common_gates.XPowGate:
|
|
119
119
|
return self.__pow__(exponent)
|
|
120
120
|
|
|
121
121
|
@classmethod
|
|
@@ -125,7 +125,7 @@ class _PauliX(Pauli, common_gates.XPowGate):
|
|
|
125
125
|
return Pauli._XYZ[0]
|
|
126
126
|
|
|
127
127
|
@property
|
|
128
|
-
def basis(self
|
|
128
|
+
def basis(self) -> Dict[int, '_XEigenState']:
|
|
129
129
|
from cirq.value.product_state import _XEigenState
|
|
130
130
|
|
|
131
131
|
return {+1: _XEigenState(+1), -1: _XEigenState(-1)}
|
|
@@ -136,10 +136,10 @@ class _PauliY(Pauli, common_gates.YPowGate):
|
|
|
136
136
|
Pauli.__init__(self, index=1, name='Y')
|
|
137
137
|
common_gates.YPowGate.__init__(self, exponent=1.0)
|
|
138
138
|
|
|
139
|
-
def __pow__(self
|
|
139
|
+
def __pow__(self, exponent: 'cirq.TParamVal') -> common_gates.YPowGate:
|
|
140
140
|
return common_gates.YPowGate(exponent=exponent) if exponent != 1 else _PauliY()
|
|
141
141
|
|
|
142
|
-
def _with_exponent(self
|
|
142
|
+
def _with_exponent(self, exponent: 'cirq.TParamVal') -> common_gates.YPowGate:
|
|
143
143
|
return self.__pow__(exponent)
|
|
144
144
|
|
|
145
145
|
@classmethod
|
|
@@ -149,7 +149,7 @@ class _PauliY(Pauli, common_gates.YPowGate):
|
|
|
149
149
|
return Pauli._XYZ[1]
|
|
150
150
|
|
|
151
151
|
@property
|
|
152
|
-
def basis(self
|
|
152
|
+
def basis(self) -> Dict[int, '_YEigenState']:
|
|
153
153
|
from cirq.value.product_state import _YEigenState
|
|
154
154
|
|
|
155
155
|
return {+1: _YEigenState(+1), -1: _YEigenState(-1)}
|
|
@@ -160,10 +160,10 @@ class _PauliZ(Pauli, common_gates.ZPowGate):
|
|
|
160
160
|
Pauli.__init__(self, index=2, name='Z')
|
|
161
161
|
common_gates.ZPowGate.__init__(self, exponent=1.0)
|
|
162
162
|
|
|
163
|
-
def __pow__(self
|
|
163
|
+
def __pow__(self, exponent: 'cirq.TParamVal') -> common_gates.ZPowGate:
|
|
164
164
|
return common_gates.ZPowGate(exponent=exponent) if exponent != 1 else _PauliZ()
|
|
165
165
|
|
|
166
|
-
def _with_exponent(self
|
|
166
|
+
def _with_exponent(self, exponent: 'cirq.TParamVal') -> common_gates.ZPowGate:
|
|
167
167
|
return self.__pow__(exponent)
|
|
168
168
|
|
|
169
169
|
@classmethod
|
|
@@ -173,7 +173,7 @@ class _PauliZ(Pauli, common_gates.ZPowGate):
|
|
|
173
173
|
return Pauli._XYZ[2]
|
|
174
174
|
|
|
175
175
|
@property
|
|
176
|
-
def basis(self
|
|
176
|
+
def basis(self) -> Dict[int, '_ZEigenState']:
|
|
177
177
|
from cirq.value.product_state import _ZEigenState
|
|
178
178
|
|
|
179
179
|
return {+1: _ZEigenState(+1), -1: _ZEigenState(-1)}
|
cirq/ops/pauli_string.py
CHANGED
|
@@ -242,12 +242,14 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
242
242
|
def get(self, key: Any, default: TDefault) -> Union[pauli_gates.Pauli, TDefault]:
|
|
243
243
|
pass
|
|
244
244
|
|
|
245
|
-
def get(
|
|
245
|
+
def get(
|
|
246
|
+
self, key: Any, default: Optional[TDefault] = None
|
|
247
|
+
) -> Union[pauli_gates.Pauli, TDefault, None]:
|
|
246
248
|
"""Returns the `cirq.Pauli` operation acting on qubit `key` or `default` if none exists."""
|
|
247
249
|
return self._qubit_pauli_map.get(key, default)
|
|
248
250
|
|
|
249
251
|
@overload
|
|
250
|
-
def __mul__(
|
|
252
|
+
def __mul__(
|
|
251
253
|
self, other: 'cirq.PauliString[TKeyOther]'
|
|
252
254
|
) -> 'cirq.PauliString[Union[TKey, TKeyOther]]':
|
|
253
255
|
pass
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import abc
|
|
16
|
-
from typing import Any, Dict, Sequence, Tuple,
|
|
16
|
+
from typing import Any, Dict, Sequence, Tuple, TYPE_CHECKING
|
|
17
|
+
from typing_extensions import Self
|
|
17
18
|
|
|
18
19
|
from cirq import protocols
|
|
19
20
|
from cirq.ops import pauli_string as ps, raw_types
|
|
@@ -21,10 +22,6 @@ from cirq.ops import pauli_string as ps, raw_types
|
|
|
21
22
|
if TYPE_CHECKING:
|
|
22
23
|
import cirq
|
|
23
24
|
|
|
24
|
-
TSelf_PauliStringGateOperation = TypeVar(
|
|
25
|
-
'TSelf_PauliStringGateOperation', bound='PauliStringGateOperation'
|
|
26
|
-
)
|
|
27
|
-
|
|
28
25
|
|
|
29
26
|
class PauliStringGateOperation(raw_types.Operation, metaclass=abc.ABCMeta):
|
|
30
27
|
def __init__(self, pauli_string: ps.PauliString) -> None:
|
|
@@ -38,16 +35,12 @@ class PauliStringGateOperation(raw_types.Operation, metaclass=abc.ABCMeta):
|
|
|
38
35
|
if len(qubits) != len(self.pauli_string):
|
|
39
36
|
raise ValueError('Incorrect number of qubits for gate')
|
|
40
37
|
|
|
41
|
-
def with_qubits(
|
|
42
|
-
self: TSelf_PauliStringGateOperation, *new_qubits: 'cirq.Qid'
|
|
43
|
-
) -> TSelf_PauliStringGateOperation:
|
|
38
|
+
def with_qubits(self, *new_qubits: 'cirq.Qid') -> Self:
|
|
44
39
|
self.validate_args(new_qubits)
|
|
45
40
|
return self.map_qubits(dict(zip(self.pauli_string.qubits, new_qubits)))
|
|
46
41
|
|
|
47
42
|
@abc.abstractmethod
|
|
48
|
-
def map_qubits(
|
|
49
|
-
self: TSelf_PauliStringGateOperation, qubit_map: Dict[raw_types.Qid, raw_types.Qid]
|
|
50
|
-
) -> TSelf_PauliStringGateOperation:
|
|
43
|
+
def map_qubits(self, qubit_map: Dict[raw_types.Qid, raw_types.Qid]) -> Self:
|
|
51
44
|
"""Return an equivalent operation on new qubits with its Pauli string
|
|
52
45
|
mapped to new qubits.
|
|
53
46
|
|
cirq/ops/pauli_string_test.py
CHANGED
|
@@ -1030,17 +1030,17 @@ def test_expectation_from_state_vector_entangled_states():
|
|
|
1030
1030
|
x0x1 = cirq.PauliString(x0x1_pauli_map)
|
|
1031
1031
|
q_map = {q0: 0, q1: 1}
|
|
1032
1032
|
wf1 = np.array([0, 1, 1, 0], dtype=complex) / np.sqrt(2)
|
|
1033
|
-
for state in [wf1, wf1.reshape(2, 2)]:
|
|
1033
|
+
for state in [wf1, wf1.reshape((2, 2))]:
|
|
1034
1034
|
np.testing.assert_allclose(z0z1.expectation_from_state_vector(state, q_map), -1)
|
|
1035
1035
|
np.testing.assert_allclose(x0x1.expectation_from_state_vector(state, q_map), 1)
|
|
1036
1036
|
|
|
1037
1037
|
wf2 = np.array([1, 0, 0, 1], dtype=complex) / np.sqrt(2)
|
|
1038
|
-
for state in [wf2, wf2.reshape(2, 2)]:
|
|
1038
|
+
for state in [wf2, wf2.reshape((2, 2))]:
|
|
1039
1039
|
np.testing.assert_allclose(z0z1.expectation_from_state_vector(state, q_map), 1)
|
|
1040
1040
|
np.testing.assert_allclose(x0x1.expectation_from_state_vector(state, q_map), 1)
|
|
1041
1041
|
|
|
1042
1042
|
wf3 = np.array([1, 1, 1, 1], dtype=complex) / 2
|
|
1043
|
-
for state in [wf3, wf3.reshape(2, 2)]:
|
|
1043
|
+
for state in [wf3, wf3.reshape((2, 2))]:
|
|
1044
1044
|
np.testing.assert_allclose(z0z1.expectation_from_state_vector(state, q_map), 0)
|
|
1045
1045
|
np.testing.assert_allclose(x0x1.expectation_from_state_vector(state, q_map), 1)
|
|
1046
1046
|
|
|
@@ -1049,7 +1049,7 @@ def test_expectation_from_state_vector_qubit_map():
|
|
|
1049
1049
|
q0, q1, q2 = _make_qubits(3)
|
|
1050
1050
|
z = cirq.PauliString({q0: cirq.Z})
|
|
1051
1051
|
wf = np.array([0, 1, 0, 1, 0, 0, 0, 0], dtype=complex) / np.sqrt(2)
|
|
1052
|
-
for state in [wf, wf.reshape(2, 2, 2)]:
|
|
1052
|
+
for state in [wf, wf.reshape((2, 2, 2))]:
|
|
1053
1053
|
np.testing.assert_allclose(
|
|
1054
1054
|
z.expectation_from_state_vector(state, {q0: 0, q1: 1, q2: 2}), 1, atol=1e-8
|
|
1055
1055
|
)
|
|
@@ -1124,7 +1124,7 @@ def test_expectation_from_density_matrix_invalid_input():
|
|
|
1124
1124
|
q0, q1, q2, q3 = _make_qubits(4)
|
|
1125
1125
|
ps = cirq.PauliString({q0: cirq.X, q1: cirq.Y})
|
|
1126
1126
|
wf = cirq.testing.random_superposition(4)
|
|
1127
|
-
rho = np.kron(wf.conjugate().T, wf).reshape(4, 4)
|
|
1127
|
+
rho = np.kron(wf.conjugate().T, wf).reshape((4, 4))
|
|
1128
1128
|
q_map = {q0: 0, q1: 1}
|
|
1129
1129
|
|
|
1130
1130
|
im_ps = (1j + 1) * ps
|
|
@@ -1238,20 +1238,20 @@ def test_expectation_from_density_matrix_entangled_states():
|
|
|
1238
1238
|
q_map = {q0: 0, q1: 1}
|
|
1239
1239
|
|
|
1240
1240
|
wf1 = np.array([0, 1, 1, 0], dtype=complex) / np.sqrt(2)
|
|
1241
|
-
rho1 = np.kron(wf1, wf1).reshape(4, 4)
|
|
1242
|
-
for state in [rho1, rho1.reshape(2, 2, 2, 2)]:
|
|
1241
|
+
rho1 = np.kron(wf1, wf1).reshape((4, 4))
|
|
1242
|
+
for state in [rho1, rho1.reshape((2, 2, 2, 2))]:
|
|
1243
1243
|
np.testing.assert_allclose(z0z1.expectation_from_density_matrix(state, q_map), -1)
|
|
1244
1244
|
np.testing.assert_allclose(x0x1.expectation_from_density_matrix(state, q_map), 1)
|
|
1245
1245
|
|
|
1246
1246
|
wf2 = np.array([1, 0, 0, 1], dtype=complex) / np.sqrt(2)
|
|
1247
|
-
rho2 = np.kron(wf2, wf2).reshape(4, 4)
|
|
1248
|
-
for state in [rho2, rho2.reshape(2, 2, 2, 2)]:
|
|
1247
|
+
rho2 = np.kron(wf2, wf2).reshape((4, 4))
|
|
1248
|
+
for state in [rho2, rho2.reshape((2, 2, 2, 2))]:
|
|
1249
1249
|
np.testing.assert_allclose(z0z1.expectation_from_density_matrix(state, q_map), 1)
|
|
1250
1250
|
np.testing.assert_allclose(x0x1.expectation_from_density_matrix(state, q_map), 1)
|
|
1251
1251
|
|
|
1252
1252
|
wf3 = np.array([1, 1, 1, 1], dtype=complex) / 2
|
|
1253
|
-
rho3 = np.kron(wf3, wf3).reshape(4, 4)
|
|
1254
|
-
for state in [rho3, rho3.reshape(2, 2, 2, 2)]:
|
|
1253
|
+
rho3 = np.kron(wf3, wf3).reshape((4, 4))
|
|
1254
|
+
for state in [rho3, rho3.reshape((2, 2, 2, 2))]:
|
|
1255
1255
|
np.testing.assert_allclose(z0z1.expectation_from_density_matrix(state, q_map), 0)
|
|
1256
1256
|
np.testing.assert_allclose(x0x1.expectation_from_density_matrix(state, q_map), 1)
|
|
1257
1257
|
|
|
@@ -1260,9 +1260,9 @@ def test_expectation_from_density_matrix_qubit_map():
|
|
|
1260
1260
|
q0, q1, q2 = _make_qubits(3)
|
|
1261
1261
|
z = cirq.PauliString({q0: cirq.Z})
|
|
1262
1262
|
wf = np.array([0, 1, 0, 1, 0, 0, 0, 0], dtype=complex) / np.sqrt(2)
|
|
1263
|
-
rho = np.kron(wf, wf).reshape(8, 8)
|
|
1263
|
+
rho = np.kron(wf, wf).reshape((8, 8))
|
|
1264
1264
|
|
|
1265
|
-
for state in [rho, rho.reshape(2, 2, 2, 2, 2, 2)]:
|
|
1265
|
+
for state in [rho, rho.reshape((2, 2, 2, 2, 2, 2))]:
|
|
1266
1266
|
np.testing.assert_allclose(
|
|
1267
1267
|
z.expectation_from_density_matrix(state, {q0: 0, q1: 1, q2: 2}), 1
|
|
1268
1268
|
)
|
|
@@ -16,7 +16,7 @@ from typing import Any, Iterator, Tuple, Union, TYPE_CHECKING
|
|
|
16
16
|
import numpy as np
|
|
17
17
|
import sympy
|
|
18
18
|
|
|
19
|
-
from cirq import linalg, protocols, value
|
|
19
|
+
from cirq import linalg, protocols, value, _compat
|
|
20
20
|
from cirq.ops import linear_combinations, pauli_string_phasor
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
@@ -78,6 +78,10 @@ class PauliSumExponential:
|
|
|
78
78
|
def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'PauliSumExponential':
|
|
79
79
|
return PauliSumExponential(self._pauli_sum.with_qubits(*new_qubits), self._exponent)
|
|
80
80
|
|
|
81
|
+
@_compat.cached_method
|
|
82
|
+
def _is_parameterized_(self) -> bool:
|
|
83
|
+
return protocols.is_parameterized(self._exponent)
|
|
84
|
+
|
|
81
85
|
def _resolve_parameters_(
|
|
82
86
|
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
83
87
|
) -> 'PauliSumExponential':
|
|
@@ -109,6 +113,7 @@ class PauliSumExponential:
|
|
|
109
113
|
ret = np.kron(ret, protocols.unitary(pauli_string_exp))
|
|
110
114
|
return ret
|
|
111
115
|
|
|
116
|
+
@_compat.cached_method
|
|
112
117
|
def _has_unitary_(self) -> bool:
|
|
113
118
|
return linalg.is_unitary(self.matrix())
|
|
114
119
|
|