def test_with_parameters_resolved_by(): op = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=sympy.Symbol('a')) resolver = cirq.ParamResolver({'a': 0.1}) actual = cirq.resolve_parameters(op, resolver) expected = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.1) assert actual == expected
def test_str(): q0, q1, q2 = _make_qubits(3) ps = cirq.PauliStringPhasor( cirq.PauliString({ q2: cirq.Z, q1: cirq.Y, q0: cirq.X }, +1))**0.5 assert str(ps) == '(X(q0)*Y(q1)*Z(q2))**0.5' ps = cirq.PauliStringPhasor( cirq.PauliString({ q2: cirq.Z, q1: cirq.Y, q0: cirq.X }, +1))**-0.5 assert str(ps) == '(X(q0)*Y(q1)*Z(q2))**-0.5' ps = cirq.PauliStringPhasor( cirq.PauliString({ q2: cirq.Z, q1: cirq.Y, q0: cirq.X }, -1))**-0.5 assert str(ps) == '(X(q0)*Y(q1)*Z(q2))**0.5' assert str(np.exp(0.5j * np.pi * cirq.X(q0) * cirq.Y(q1))) == 'exp(iπ0.5*X(q0)*Y(q1))' assert str(np.exp(-0.25j * np.pi * cirq.X(q0) * cirq.Y(q1))) == 'exp(-iπ0.25*X(q0)*Y(q1))' assert str(np.exp(0.5j * np.pi * cirq.PauliString())) == 'exp(iπ0.5*I)'
def test_map_qubits(): q0, q1, q2, q3, q4, q5 = _make_qubits(6) qubit_map = {q1: q2, q0: q3} before = cirq.PauliStringPhasor(cirq.PauliString({ q0: cirq.Z, q1: cirq.Y }), exponent_neg=0.1) after = cirq.PauliStringPhasor(cirq.PauliString({ q3: cirq.Z, q2: cirq.Y }), exponent_neg=0.1) assert before.map_qubits(qubit_map) == after qubit_map = {q1: q3, q0: q4, q2: q5} before = cirq.PauliStringPhasor(cirq.PauliString({ q0: cirq.Z, q1: cirq.Y }), qubits=[q0, q1, q2], exponent_neg=0.1) after = cirq.PauliStringPhasor(cirq.PauliString({ q4: cirq.Z, q3: cirq.Y }), qubits=[q4, q3, q5], exponent_neg=0.1) assert before.map_qubits(qubit_map) == after
def test_exponentiation_as_base(): a, b = cirq.LineQubit.range(2) p = cirq.PauliString({a: cirq.X, b: cirq.Y}) with pytest.raises(TypeError, match='unsupported'): _ = (2 * p)**5 with pytest.raises(TypeError, match='unsupported'): _ = p**'test' with pytest.raises(TypeError, match='unsupported'): _ = p**1j 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( math.e**(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25, exponent_pos=0.25)) assert cirq.approx_eq( 2**(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25 * math.log(2), exponent_pos=0.25 * math.log(2))) assert cirq.approx_eq( np.exp(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25, exponent_pos=0.25))
def test_exponentiation_as_exponent(): a, b = cirq.LineQubit.range(2) p = cirq.PauliString({a: cirq.X, b: cirq.Y}) with pytest.raises(NotImplementedError, match='non-hermitian'): _ = math.e**(math.pi * p) with pytest.raises(TypeError, match='unsupported'): _ = 'test'**p assert cirq.approx_eq( math.e**(-1j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=0.5, exponent_pos=-0.5)) assert cirq.approx_eq( math.e**(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25, exponent_pos=0.25)) assert cirq.approx_eq( 2**(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25 * math.log(2), exponent_pos=0.25 * math.log(2))) assert cirq.approx_eq( np.exp(0.5j * math.pi * p), cirq.PauliStringPhasor(p, exponent_neg=-0.25, exponent_pos=0.25))
def test_pow(): a = cirq.LineQubit(0) s = cirq.PauliString({a: cirq.X}) p = cirq.PauliStringPhasor(s, exponent_neg=0.25, exponent_pos=0.5) assert p ** 0.5 == cirq.PauliStringPhasor(s, exponent_neg=0.125, exponent_pos=0.25) with pytest.raises(TypeError, match='unsupported operand'): _ = p ** object() assert p ** 1 == p
def test_inverse(): i = cirq.PauliString({}) op1 = cirq.PauliStringPhasor(i, exponent_neg=0.25) op2 = cirq.PauliStringPhasor(i, exponent_neg=-0.25) op3 = cirq.PauliStringPhasor(i, exponent_neg=sympy.Symbol('s')) op4 = cirq.PauliStringPhasor(i, exponent_neg=-sympy.Symbol('s')) assert cirq.inverse(op1) == op2 assert cirq.inverse(op3, None) == op4
def test_pass_operations_over(): q0, q1 = _make_qubits(2) op = cirq.SingleQubitCliffordGate.from_double_map( {cirq.Z: (cirq.X, False), cirq.X: (cirq.Z, False)} )(q0) ps_before = cirq.PauliString({q0: cirq.X, q1: cirq.Y}, -1) ps_after = cirq.PauliString({q0: cirq.Z, q1: cirq.Y}, -1) before = cirq.PauliStringPhasor(ps_before, exponent_neg=0.1) after = cirq.PauliStringPhasor(ps_after, exponent_neg=0.1) assert before.pass_operations_over([op]) == after assert after.pass_operations_over([op], after_to_before=True) == before
def test_qubit_order_mismatch(): q0, q1 = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='are not an ordered subset'): _ = cirq.PauliStringPhasor(1j * cirq.X(q0), qubits=[q1]) with pytest.raises(ValueError, match='are not an ordered subset'): _ = cirq.PauliStringPhasor(1j * cirq.X(q0) * cirq.X(q1), qubits=[q1]) with pytest.raises(ValueError, match='are not an ordered subset'): _ = cirq.PauliStringPhasor(1j * cirq.X(q0), qubits=[]) with pytest.raises(ValueError, match='are not an ordered subset'): _ = cirq.PauliStringPhasor(1j * cirq.X(q0) * cirq.X(q1), qubits=[q1, q0])
def test_manual_default_decompose(): q0, q1, q2 = _make_qubits(3) mat = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, cirq.Z(q0)**-0.25, ).unitary() cirq.testing.assert_allclose_up_to_global_phase(mat, np.eye(2), rtol=1e-7, atol=1e-7) mat = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Y}))**0.25, cirq.Y(q0)**-0.25, ).unitary() cirq.testing.assert_allclose_up_to_global_phase(mat, np.eye(2), rtol=1e-7, atol=1e-7) mat = cirq.Circuit( cirq.PauliStringPhasor( cirq.PauliString({ q0: cirq.Z, q1: cirq.Z, q2: cirq.Z }))).unitary() cirq.testing.assert_allclose_up_to_global_phase( mat, np.diag([1, -1, -1, 1, -1, 1, 1, -1]), rtol=1e-7, atol=1e-7) mat = cirq.Circuit( cirq.PauliStringPhasor( cirq.PauliString({ q0: cirq.Z, q1: cirq.Y, q2: cirq.X }))**0.5).unitary() cirq.testing.assert_allclose_up_to_global_phase( mat, np.array([ [1, 0, 0, -1, 0, 0, 0, 0], [0, 1, -1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 1], [0, 0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, -1, 1, 0], [0, 0, 0, 0, -1, 0, 0, 1], ]) / np.sqrt(2), rtol=1e-7, atol=1e-7, )
def test_decompose_with_symbol(): (q0,) = _make_qubits(1) ps = cirq.PauliString({q0: cirq.Y}) op = cirq.PauliStringPhasor(ps, exponent_neg=sympy.Symbol('a')) circuit = cirq.Circuit(op) cirq.ExpandComposite().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, "q0: ───X^0.5───Z^a───X^-0.5───") ps = cirq.PauliString({q0: cirq.Y}, -1) op = cirq.PauliStringPhasor(ps, exponent_neg=sympy.Symbol('a')) circuit = cirq.Circuit(op) cirq.ExpandComposite().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, "q0: ───X^0.5───X───Z^a───X───X^-0.5───")
def test_can_merge_with(): q0, q1 = _make_qubits(2) op1 = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.75) assert op1.can_merge_with(op2) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.75) assert op1.can_merge_with(op2) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Y}, -1), exponent_neg=0.75) assert not op1.can_merge_with(op2) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), qubits=[q0, q1], exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.75) assert not op1.can_merge_with(op2)
def test_with_parameters_resolved_by(resolve_fn): op = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=sympy.Symbol('a')) resolver = cirq.ParamResolver({'a': 0.1}) actual = resolve_fn(op, resolver) expected = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.1) assert actual == expected with pytest.raises(ValueError, match='complex'): resolve_fn(op, cirq.ParamResolver({'a': 0.1j})) op = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_pos=sympy.Symbol('a')) with pytest.raises(ValueError, match='complex'): resolve_fn(op, cirq.ParamResolver({'a': 0.1j}))
def test_map_qubits(): q0, q1, q2, q3 = _make_qubits(4) qubit_map = {q1: q2, q0: q3} before = cirq.PauliStringPhasor(cirq.PauliString({ q0: cirq.Z, q1: cirq.Y }), exponent_neg=0.1) after = cirq.PauliStringPhasor(cirq.PauliString({ q3: cirq.Z, q2: cirq.Y }), exponent_neg=0.1) assert before.map_qubits(qubit_map) == after
def test_repr(): q0, q1, q2 = _make_qubits(3) cirq.testing.assert_equivalent_repr( cirq.PauliStringPhasor( cirq.PauliString({q2: cirq.Z, q1: cirq.Y, q0: cirq.X}), exponent_neg=0.5, exponent_pos=0.25, ) ) cirq.testing.assert_equivalent_repr( cirq.PauliStringPhasor( -cirq.PauliString({q1: cirq.Y, q0: cirq.X}), exponent_neg=-0.5, exponent_pos=0.25 ) )
def test_init(): a = cirq.LineQubit(0) with pytest.raises(ValueError, match='eigenvalues'): _ = cirq.PauliStringPhasor(1j * cirq.X(a)) v1 = cirq.PauliStringPhasor(-cirq.X(a), exponent_neg=0.25, exponent_pos=-0.5) assert v1.pauli_string == cirq.X(a) assert v1.exponent_neg == -0.5 assert v1.exponent_pos == 0.25 v2 = cirq.PauliStringPhasor(cirq.X(a), exponent_neg=0.75, exponent_pos=-0.125) assert v2.pauli_string == cirq.X(a) assert v2.exponent_neg == 0.75 assert v2.exponent_pos == -0.125
def test_drop_negligible(): (q0, ) = _make_qubits(1) sym = sympy.Symbol('a') circuit = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**1e-10, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) expected = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) circuit = cirq.drop_negligible_operations(circuit) circuit = cirq.drop_empty_moments(circuit) assert circuit == expected
def test_drop_negligible(): q0, = _make_qubits(1) sym = sympy.Symbol('a') circuit = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**1e-10, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) expected = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) cirq.DropNegligible().optimize_circuit(circuit) cirq.DropEmptyMoments().optimize_circuit(circuit) assert circuit == expected
def test_default_decompose(paulis, phase_exponent_negative: float, sign: int): paulis = [pauli for pauli in paulis if pauli is not None] qubits = _make_qubits(len(paulis)) # Get matrix from decomposition pauli_string = cirq.PauliString( qubit_pauli_map={q: p for q, p in zip(qubits, paulis)}, coefficient=sign) actual = cirq.Circuit( cirq.PauliStringPhasor(pauli_string, exponent_neg=phase_exponent_negative)).unitary() # Calculate expected matrix to_z_mats = { cirq.X: cirq.unitary(cirq.Y**-0.5), cirq.Y: cirq.unitary(cirq.X**0.5), cirq.Z: np.eye(2) } expected_convert = np.eye(1) for pauli in paulis: expected_convert = np.kron(expected_convert, to_z_mats[pauli]) t = 1j**(phase_exponent_negative * 2 * sign) expected_z = np.diag([1, t, t, 1, t, 1, 1, t][:2**len(paulis)]) expected = expected_convert.T.conj().dot(expected_z).dot(expected_convert) cirq.testing.assert_allclose_up_to_global_phase(actual, expected, rtol=1e-7, atol=1e-7)
def test_already_converted(): q0 = cirq.LineQubit(0) circuit = cirq.Circuit(cirq.PauliStringPhasor(cirq.X.on(q0))) c_orig = cirq.Circuit(circuit) ConvertToPauliStringPhasors().optimize_circuit(circuit) assert circuit == c_orig
def test_old_json(): """Older versions of PauliStringPhasor did not have a qubit field.""" old_json = """ { "cirq_type": "PauliStringPhasor", "pauli_string": { "cirq_type": "PauliString", "qubit_pauli_map": [ [ { "cirq_type": "LineQubit", "x": 0 }, { "cirq_type": "_PauliX", "exponent": 1.0, "global_shift": 0.0 } ], [ { "cirq_type": "LineQubit", "x": 1 }, { "cirq_type": "_PauliY", "exponent": 1.0, "global_shift": 0.0 } ], [ { "cirq_type": "LineQubit", "x": 2 }, { "cirq_type": "_PauliZ", "exponent": 1.0, "global_shift": 0.0 } ] ], "coefficient": { "cirq_type": "complex", "real": 1.0, "imag": 0.0 } }, "exponent_neg": 0.2, "exponent_pos": 0.1 } """ phasor = cirq.read_json(json_text=old_json) assert phasor == cirq.PauliStringPhasor( ((1 + 0j) * cirq.X(cirq.LineQubit(0)) * cirq.Y(cirq.LineQubit(1)) * cirq.Z(cirq.LineQubit(2))), qubits=(cirq.LineQubit(0), cirq.LineQubit(1), cirq.LineQubit(2)), exponent_neg=0.2, exponent_pos=0.1, )
def test_already_converted(): q0 = cirq.LineQubit(0) circuit = cirq.Circuit.from_ops( cirq.PauliStringPhasor(cirq.PauliString.from_single(q0, cirq.X)), ) c_orig = cirq.Circuit(circuit) ConvertToPauliStringPhasors().optimize_circuit(circuit) assert circuit == c_orig
def test_consistent(): a, b = cirq.LineQubit.range(2) op = np.exp(1j * np.pi / 2 * cirq.X(a) * cirq.X(b)) cirq.testing.assert_implements_consistent_protocols(op) p = cirq.PauliStringPhasor(cirq.X(a), qubits=[a], exponent_neg=0.25, exponent_pos=0.5) cirq.testing.assert_implements_consistent_protocols(p)
def test_map_qubits_missing_qubits(): q0, q1, q2 = _make_qubits(3) qubit_map = {q1: q2} before = cirq.PauliStringPhasor(cirq.PauliString({ q0: cirq.Z, q1: cirq.Y }), exponent_neg=0.1) with pytest.raises(ValueError, match="have a key"): _ = before.map_qubits(qubit_map)
def test_equal_up_to_global_phase(): a, b = cirq.LineQubit.range(2) groups = [ [ cirq.PauliStringPhasor(cirq.PauliString({a: cirq.X}), exponent_neg=0.25), cirq.PauliStringPhasor(cirq.PauliString({a: cirq.X}), exponent_neg=0, exponent_pos=-0.25), cirq.PauliStringPhasor(cirq.PauliString({a: cirq.X}), exponent_pos=-0.125, exponent_neg=0.125), ], [ cirq.PauliStringPhasor(cirq.PauliString({a: cirq.X})), ], [ cirq.PauliStringPhasor(cirq.PauliString({a: cirq.Y}), exponent_neg=0.25), ], [ cirq.PauliStringPhasor(cirq.PauliString({ a: cirq.X, b: cirq.Y }), exponent_neg=0.25), ], ] for g1 in groups: for e1 in g1: assert not e1.equal_up_to_global_phase("not even close") for g2 in groups: for e2 in g2: assert e1.equal_up_to_global_phase(e2) == (g1 is g2)
def test_text_diagram(): q0, q1, q2 = _make_qubits(3) circuit = cirq.Circuit( cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z})), cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Y})) ** 0.25, cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z, q1: cirq.Z, q2: cirq.Z})), cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Z, q1: cirq.Y, q2: cirq.X}, -1)) ** 0.5, cirq.PauliStringPhasor( cirq.PauliString({q0: cirq.Z, q1: cirq.Y, q2: cirq.X}), exponent_neg=sympy.Symbol('a') ), cirq.PauliStringPhasor( cirq.PauliString({q0: cirq.Z, q1: cirq.Y, q2: cirq.X}, -1), exponent_neg=sympy.Symbol('b'), ), ) cirq.testing.assert_has_diagram( circuit, """ q0: ───[Z]───[Y]^0.25───[Z]───[Z]────────[Z]─────[Z]──────── │ │ │ │ q1: ────────────────────[Z]───[Y]────────[Y]─────[Y]──────── │ │ │ │ q2: ────────────────────[Z]───[X]^-0.5───[X]^a───[X]^(-b)─── """, )
def test_extrapolate_effect_with_symbol(): eq = cirq.testing.EqualsTester() eq.add_equality_group( cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=sympy.Symbol('a')), cirq.PauliStringPhasor(cirq.PauliString({})) ** sympy.Symbol('a'), ) eq.add_equality_group(cirq.PauliStringPhasor(cirq.PauliString({})) ** sympy.Symbol('b')) eq.add_equality_group( cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.5) ** sympy.Symbol('b') ) eq.add_equality_group( cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=sympy.Symbol('a')) ** 0.5 ) eq.add_equality_group( cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=sympy.Symbol('a')) ** sympy.Symbol('b') )
def test_eq_ne_hash(): q0, q1, q2 = _make_qubits(3) eq = cirq.testing.EqualsTester() ps1 = cirq.X(q0) * cirq.Y(q1) * cirq.Z(q2) ps2 = cirq.X(q0) * cirq.Y(q1) * cirq.X(q2) eq.make_equality_group( lambda: cirq.PauliStringPhasor(cirq.PauliString(), exponent_neg=0.5), lambda: cirq.PauliStringPhasor(cirq.PauliString(), exponent_neg=-1.5), lambda: cirq.PauliStringPhasor(cirq.PauliString(), exponent_neg=2.5)) eq.make_equality_group(lambda: cirq.PauliStringPhasor(-cirq.PauliString(), exponent_neg=-0.5)) eq.add_equality_group(cirq.PauliStringPhasor(ps1), cirq.PauliStringPhasor(ps1, exponent_neg=1)) eq.add_equality_group(cirq.PauliStringPhasor(-ps1, exponent_neg=1)) eq.add_equality_group(cirq.PauliStringPhasor(ps2), cirq.PauliStringPhasor(ps2, exponent_neg=1)) eq.add_equality_group(cirq.PauliStringPhasor(-ps2, exponent_neg=1)) eq.add_equality_group(cirq.PauliStringPhasor(ps2, exponent_neg=0.5)) eq.add_equality_group(cirq.PauliStringPhasor(-ps2, exponent_neg=-0.5)) eq.add_equality_group( cirq.PauliStringPhasor(ps1, exponent_neg=sympy.Symbol('a')))
def test_is_parameterized(): op = cirq.PauliStringPhasor(cirq.PauliString({})) assert not cirq.is_parameterized(op) assert not cirq.is_parameterized(op**0.1) assert cirq.is_parameterized(op**sympy.Symbol('a'))
def test_merge_with(): q0, = _make_qubits(1) op1 = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=0.75) op12 = cirq.PauliStringPhasor(cirq.PauliString({}), exponent_neg=1.0) assert op1.merged_with(op2).equal_up_to_global_phase(op12) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.75) op12 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=1.0) assert op1.merged_with(op2).equal_up_to_global_phase(op12) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.75) op12 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=-0.5) assert op1.merged_with(op2).equal_up_to_global_phase(op12) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.75) op12 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=-0.5) assert op1.merged_with(op2).equal_up_to_global_phase(op12) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=0.75) op12 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, -1), exponent_neg=1.0) assert op1.merged_with(op2).equal_up_to_global_phase(op12) op1 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.X}, +1), exponent_neg=0.25) op2 = cirq.PauliStringPhasor(cirq.PauliString({q0: cirq.Y}, -1), exponent_neg=0.75) with pytest.raises(ValueError): op1.merged_with(op2)