From 8ee4617d16d2343780c826a469a649564ce66f00 Mon Sep 17 00:00:00 2001 From: Dave Bacon Date: Wed, 6 Apr 2022 14:58:32 -0700 Subject: [PATCH 1/2] Fix error and add test for mutable pauli string --- cirq-core/cirq/ops/pauli_string.py | 6 +- cirq-core/cirq/ops/pauli_string_test.py | 94 ++++++++++++++++--------- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/cirq-core/cirq/ops/pauli_string.py b/cirq-core/cirq/ops/pauli_string.py index 9d146639143..bdd0891747e 100644 --- a/cirq-core/cirq/ops/pauli_string.py +++ b/cirq-core/cirq/ops/pauli_string.py @@ -693,7 +693,7 @@ def __pos__(self) -> 'PauliString': def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Override behavior of numpy's exp method.""" if ufunc == np.exp and len(inputs) == 1 and inputs[0] is self: - return math.e**self + return math.e ** self return NotImplemented def __pow__(self, power): @@ -701,7 +701,7 @@ def __pow__(self, power): return self if power == -1: return PauliString( - qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient**-1 + qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient ** -1 ) if isinstance(power, (int, float)): r, i = cmath.polar(self.coefficient) @@ -1546,6 +1546,6 @@ def _pauli_like_to_pauli_int(key: Any, pauli_gate_like: PAULI_GATE_LIKE): f'Expected {key!r}: {pauli_gate_like!r} to have a ' f'cirq.PAULI_GATE_LIKE value. ' f"But the value isn't in " - f"{list(PAULI_GATE_LIKE_TO_INDEX_MAP.values())!r}" + f"{set(PAULI_GATE_LIKE_TO_INDEX_MAP.keys())!r}" ) return cast(int, pauli_int) diff --git a/cirq-core/cirq/ops/pauli_string_test.py b/cirq-core/cirq/ops/pauli_string_test.py index 59f25e67f12..0e78a863950 100644 --- a/cirq-core/cirq/ops/pauli_string_test.py +++ b/cirq-core/cirq/ops/pauli_string_test.py @@ -172,13 +172,13 @@ def test_exponentiation_as_base(): _ = p ** 'test' with pytest.raises(TypeError, match='unsupported'): - _ = p**1j + _ = p ** 1j - assert p**-1 == p + assert p ** -1 == p - assert cirq.approx_eq(p**0.5, cirq.PauliStringPhasor(p, exponent_neg=0.5, exponent_pos=0)) + assert cirq.approx_eq(p ** 0.5, cirq.PauliStringPhasor(p, exponent_neg=0.5, exponent_pos=0)) - assert cirq.approx_eq(p**-0.5, cirq.PauliStringPhasor(p, exponent_neg=-0.5, exponent_pos=0)) + assert cirq.approx_eq(p ** -0.5, cirq.PauliStringPhasor(p, exponent_neg=-0.5, exponent_pos=0)) assert cirq.approx_eq( math.e ** (0.25j * math.pi * p), @@ -535,8 +535,8 @@ def test_pow(): assert cirq.PauliString({a: cirq.Z}) ** 0.25 == cirq.Z(a) ** 0.25 p = cirq.PauliString({a: cirq.X, b: cirq.Y}) - assert p**1 == p - assert p**-1 == p + assert p ** 1 == p + assert p ** -1 == p assert (-p) ** 1 == -p assert (-p) ** -1 == -p assert (1j * p) ** 1 == 1j * p @@ -593,7 +593,7 @@ def test_to_z_basis_ops(): initial_state = cirq.kron(x0, x1, y0, y1, z0, z1, shape_len=1) z_basis_state = circuit.final_state_vector(initial_state) - expected_state = np.zeros(2**6) + expected_state = np.zeros(2 ** 6) expected_state[0b010101] = 1 cirq.testing.assert_allclose_up_to_global_phase( @@ -618,7 +618,7 @@ def test_to_z_basis_ops_product_state(): ) z_basis_state = circuit.final_state_vector(initial_state) - expected_state = np.zeros(2**6) + expected_state = np.zeros(2 ** 6) expected_state[0b010101] = 1 cirq.testing.assert_allclose_up_to_global_phase( @@ -1320,8 +1320,8 @@ def test_pauli_string_expectation_from_density_matrix_pure_state_with_coef(): def test_pauli_string_expectation_from_state_vector_mixed_state_linearity(): n_qubits = 6 - state_vector1 = cirq.testing.random_superposition(2**n_qubits) - state_vector2 = cirq.testing.random_superposition(2**n_qubits) + state_vector1 = cirq.testing.random_superposition(2 ** n_qubits) + state_vector2 = cirq.testing.random_superposition(2 ** n_qubits) rho1 = np.outer(state_vector1, np.conj(state_vector1)) rho2 = np.outer(state_vector2, np.conj(state_vector2)) density_matrix = rho1 / 2 + rho2 / 2 @@ -1390,7 +1390,7 @@ def test_conjugated_by_incorrectly_powered_cliffords(): ] for c in cliffords: with pytest.raises(TypeError, match='not a known Clifford'): - _ = p.conjugated_by(c**0.1) + _ = p.conjugated_by(c ** 0.1) with pytest.raises(TypeError, match='not a known Clifford'): _ = p.conjugated_by(c ** sympy.Symbol('t')) @@ -1444,12 +1444,24 @@ def _decompose_(self, qubits): def test_conjugated_by_move_into_uninvolved(): a, b, c, d = cirq.LineQubit.range(4) p = cirq.X(a) * cirq.Z(b) - assert p.conjugated_by([cirq.SWAP(c, d), cirq.SWAP(b, c),]) == cirq.X( - a - ) * cirq.Z(d) - assert p.conjugated_by([cirq.SWAP(b, c), cirq.SWAP(c, d),]) == cirq.X( - a - ) * cirq.Z(c) + assert ( + p.conjugated_by( + [ + cirq.SWAP(c, d), + cirq.SWAP(b, c), + ] + ) + == cirq.X(a) * cirq.Z(d) + ) + assert ( + p.conjugated_by( + [ + cirq.SWAP(b, c), + cirq.SWAP(c, d), + ] + ) + == cirq.X(a) * cirq.Z(c) + ) def test_conjugated_by_common_single_qubit_gates(): @@ -1460,15 +1472,15 @@ def test_conjugated_by_common_single_qubit_gates(): cirq.X, cirq.Y, cirq.Z, - cirq.X**-0.5, - cirq.Y**-0.5, - cirq.Z**-0.5, - cirq.X**0.5, - cirq.Y**0.5, - cirq.Z**0.5, + cirq.X ** -0.5, + cirq.Y ** -0.5, + cirq.Z ** -0.5, + cirq.X ** 0.5, + cirq.Y ** 0.5, + cirq.Z ** 0.5, cirq.H, ] - single_qubit_gates = [g**i for i in range(4) for g in base_single_qubit_gates] + single_qubit_gates = [g ** i for i in range(4) for g in base_single_qubit_gates] for p in [cirq.X, cirq.Y, cirq.Z]: for g in single_qubit_gates: assert p.on(a).conjugated_by(g.on(b)) == p.on(a) @@ -1492,17 +1504,17 @@ def _decompose_(self, qubits): cirq.CNOT, cirq.CZ, cirq.ISWAP, - cirq.ISWAP**-1, + cirq.ISWAP ** -1, cirq.SWAP, - cirq.XX**0.5, - cirq.YY**0.5, - cirq.ZZ**0.5, + cirq.XX ** 0.5, + cirq.YY ** 0.5, + cirq.ZZ ** 0.5, cirq.XX, cirq.YY, cirq.ZZ, - cirq.XX**-0.5, - cirq.YY**-0.5, - cirq.ZZ**-0.5, + cirq.XX ** -0.5, + cirq.YY ** -0.5, + cirq.ZZ ** -0.5, ] two_qubit_gates.extend( [ @@ -1607,7 +1619,7 @@ def test_circuit_diagram_info(): cirq.X(a) * cirq.Z(c), 1j * cirq.X(a) * cirq.Y(b), -1j * cirq.Y(b), - 1j**0.5 * cirq.X(a) * cirq.Y(b), + 1j ** 0.5 * cirq.X(a) * cirq.Y(b), ), """ 0: ───PauliString(+X)───PauliString(-X)───PauliString(+X)───PauliString(iX)──────────────────────PauliString((0.707+0.707i)*X)─── @@ -1873,6 +1885,22 @@ def test_mutable_pauli_string_dict_functionality(): assert b not in p +@pytest.mark.parametrize( + 'pauli', (cirq.X, cirq.Y, cirq.Z, cirq.I, "I", "X", "Y", "Z", "i", "x", "y", "z", 0, 1, 2, 3) +) +def test_mutable_pauli_string_dict_pauli_like(pauli): + p = cirq.MutablePauliString() + # Check that is successfully converts. + p[0] = pauli + + +def test_mutable_pauli_string_dict_pauli_like_not_pauli_like(): + p = cirq.MutablePauliString() + # Check error string includes terms like "X" in error message. + with pytest.raises(TypeError, match="PAULI_GATE_LIKE.*X"): + p[0] = 1.2 + + def test_mutable_pauli_string_text(): p = cirq.MutablePauliString(cirq.X(cirq.LineQubit(0)) * cirq.Y(cirq.LineQubit(1))) assert str(cirq.MutablePauliString()) == "mutable I" @@ -1906,7 +1934,7 @@ def __rmul__(self, other): def test_coefficient_precision(): - qs = cirq.LineQubit.range(4 * 10**3) + qs = cirq.LineQubit.range(4 * 10 ** 3) r = cirq.MutablePauliString({q: cirq.X for q in qs}) r2 = cirq.MutablePauliString({q: cirq.Y for q in qs}) r2 *= r From 2d5ea01d41f67667164964ca7f9da69799e23097 Mon Sep 17 00:00:00 2001 From: Dave Bacon Date: Wed, 6 Apr 2022 15:02:37 -0700 Subject: [PATCH 2/2] Fix format --- cirq-core/cirq/ops/pauli_string.py | 4 +- cirq-core/cirq/ops/pauli_string_test.py | 78 +++++++++++-------------- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/cirq-core/cirq/ops/pauli_string.py b/cirq-core/cirq/ops/pauli_string.py index bdd0891747e..028a0d5d22d 100644 --- a/cirq-core/cirq/ops/pauli_string.py +++ b/cirq-core/cirq/ops/pauli_string.py @@ -693,7 +693,7 @@ def __pos__(self) -> 'PauliString': def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Override behavior of numpy's exp method.""" if ufunc == np.exp and len(inputs) == 1 and inputs[0] is self: - return math.e ** self + return math.e**self return NotImplemented def __pow__(self, power): @@ -701,7 +701,7 @@ def __pow__(self, power): return self if power == -1: return PauliString( - qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient ** -1 + qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient**-1 ) if isinstance(power, (int, float)): r, i = cmath.polar(self.coefficient) diff --git a/cirq-core/cirq/ops/pauli_string_test.py b/cirq-core/cirq/ops/pauli_string_test.py index 0e78a863950..c164d573b38 100644 --- a/cirq-core/cirq/ops/pauli_string_test.py +++ b/cirq-core/cirq/ops/pauli_string_test.py @@ -172,13 +172,13 @@ def test_exponentiation_as_base(): _ = p ** 'test' with pytest.raises(TypeError, match='unsupported'): - _ = p ** 1j + _ = p**1j - assert p ** -1 == p + assert p**-1 == p - assert cirq.approx_eq(p ** 0.5, cirq.PauliStringPhasor(p, exponent_neg=0.5, exponent_pos=0)) + assert cirq.approx_eq(p**0.5, cirq.PauliStringPhasor(p, exponent_neg=0.5, exponent_pos=0)) - assert cirq.approx_eq(p ** -0.5, cirq.PauliStringPhasor(p, exponent_neg=-0.5, exponent_pos=0)) + assert cirq.approx_eq(p**-0.5, cirq.PauliStringPhasor(p, exponent_neg=-0.5, exponent_pos=0)) assert cirq.approx_eq( math.e ** (0.25j * math.pi * p), @@ -535,8 +535,8 @@ def test_pow(): assert cirq.PauliString({a: cirq.Z}) ** 0.25 == cirq.Z(a) ** 0.25 p = cirq.PauliString({a: cirq.X, b: cirq.Y}) - assert p ** 1 == p - assert p ** -1 == p + assert p**1 == p + assert p**-1 == p assert (-p) ** 1 == -p assert (-p) ** -1 == -p assert (1j * p) ** 1 == 1j * p @@ -593,7 +593,7 @@ def test_to_z_basis_ops(): initial_state = cirq.kron(x0, x1, y0, y1, z0, z1, shape_len=1) z_basis_state = circuit.final_state_vector(initial_state) - expected_state = np.zeros(2 ** 6) + expected_state = np.zeros(2**6) expected_state[0b010101] = 1 cirq.testing.assert_allclose_up_to_global_phase( @@ -618,7 +618,7 @@ def test_to_z_basis_ops_product_state(): ) z_basis_state = circuit.final_state_vector(initial_state) - expected_state = np.zeros(2 ** 6) + expected_state = np.zeros(2**6) expected_state[0b010101] = 1 cirq.testing.assert_allclose_up_to_global_phase( @@ -1320,8 +1320,8 @@ def test_pauli_string_expectation_from_density_matrix_pure_state_with_coef(): def test_pauli_string_expectation_from_state_vector_mixed_state_linearity(): n_qubits = 6 - state_vector1 = cirq.testing.random_superposition(2 ** n_qubits) - state_vector2 = cirq.testing.random_superposition(2 ** n_qubits) + state_vector1 = cirq.testing.random_superposition(2**n_qubits) + state_vector2 = cirq.testing.random_superposition(2**n_qubits) rho1 = np.outer(state_vector1, np.conj(state_vector1)) rho2 = np.outer(state_vector2, np.conj(state_vector2)) density_matrix = rho1 / 2 + rho2 / 2 @@ -1390,7 +1390,7 @@ def test_conjugated_by_incorrectly_powered_cliffords(): ] for c in cliffords: with pytest.raises(TypeError, match='not a known Clifford'): - _ = p.conjugated_by(c ** 0.1) + _ = p.conjugated_by(c**0.1) with pytest.raises(TypeError, match='not a known Clifford'): _ = p.conjugated_by(c ** sympy.Symbol('t')) @@ -1444,24 +1444,12 @@ def _decompose_(self, qubits): def test_conjugated_by_move_into_uninvolved(): a, b, c, d = cirq.LineQubit.range(4) p = cirq.X(a) * cirq.Z(b) - assert ( - p.conjugated_by( - [ - cirq.SWAP(c, d), - cirq.SWAP(b, c), - ] - ) - == cirq.X(a) * cirq.Z(d) - ) - assert ( - p.conjugated_by( - [ - cirq.SWAP(b, c), - cirq.SWAP(c, d), - ] - ) - == cirq.X(a) * cirq.Z(c) - ) + assert p.conjugated_by([cirq.SWAP(c, d), cirq.SWAP(b, c),]) == cirq.X( + a + ) * cirq.Z(d) + assert p.conjugated_by([cirq.SWAP(b, c), cirq.SWAP(c, d),]) == cirq.X( + a + ) * cirq.Z(c) def test_conjugated_by_common_single_qubit_gates(): @@ -1472,15 +1460,15 @@ def test_conjugated_by_common_single_qubit_gates(): cirq.X, cirq.Y, cirq.Z, - cirq.X ** -0.5, - cirq.Y ** -0.5, - cirq.Z ** -0.5, - cirq.X ** 0.5, - cirq.Y ** 0.5, - cirq.Z ** 0.5, + cirq.X**-0.5, + cirq.Y**-0.5, + cirq.Z**-0.5, + cirq.X**0.5, + cirq.Y**0.5, + cirq.Z**0.5, cirq.H, ] - single_qubit_gates = [g ** i for i in range(4) for g in base_single_qubit_gates] + single_qubit_gates = [g**i for i in range(4) for g in base_single_qubit_gates] for p in [cirq.X, cirq.Y, cirq.Z]: for g in single_qubit_gates: assert p.on(a).conjugated_by(g.on(b)) == p.on(a) @@ -1504,17 +1492,17 @@ def _decompose_(self, qubits): cirq.CNOT, cirq.CZ, cirq.ISWAP, - cirq.ISWAP ** -1, + cirq.ISWAP**-1, cirq.SWAP, - cirq.XX ** 0.5, - cirq.YY ** 0.5, - cirq.ZZ ** 0.5, + cirq.XX**0.5, + cirq.YY**0.5, + cirq.ZZ**0.5, cirq.XX, cirq.YY, cirq.ZZ, - cirq.XX ** -0.5, - cirq.YY ** -0.5, - cirq.ZZ ** -0.5, + cirq.XX**-0.5, + cirq.YY**-0.5, + cirq.ZZ**-0.5, ] two_qubit_gates.extend( [ @@ -1619,7 +1607,7 @@ def test_circuit_diagram_info(): cirq.X(a) * cirq.Z(c), 1j * cirq.X(a) * cirq.Y(b), -1j * cirq.Y(b), - 1j ** 0.5 * cirq.X(a) * cirq.Y(b), + 1j**0.5 * cirq.X(a) * cirq.Y(b), ), """ 0: ───PauliString(+X)───PauliString(-X)───PauliString(+X)───PauliString(iX)──────────────────────PauliString((0.707+0.707i)*X)─── @@ -1934,7 +1922,7 @@ def __rmul__(self, other): def test_coefficient_precision(): - qs = cirq.LineQubit.range(4 * 10 ** 3) + qs = cirq.LineQubit.range(4 * 10**3) r = cirq.MutablePauliString({q: cirq.X for q in qs}) r2 = cirq.MutablePauliString({q: cirq.Y for q in qs}) r2 *= r