# Wrong expected value from cirq PauliString

I have to compute the exact expectation value from a state vector obtained after running a circuit. While I was running my code, I found different weird outcome so I decided to create few tests and I got the following results.

If I implement the Hamiltonian $$H = \sigma_{0}^{z}+\sigma_{1}^{z}$$:

import cirq

q0 = cirq.NamedQubit('q0')
q1 = cirq.NamedQubit('q1')

qc = cirq.Circuit()
qc.append(cirq.X(q0))
qc.append(cirq.X(q1))

hamiltonian = 0
hamiltonian += cirq.Z(q0)
hamiltonian += cirq.Z(q1)

num_var = { q0: 0, q1: 1 }
expectation_value = cirq.PauliString(hamiltonian).expectation_from_state_vector(qc.final_state_vector(), num_var).real


The outcome of print(expectation_value) is:

1.0


The correct result should be -2.0 instead. I tried out different combinations and what I obtained is:

qc.append(cirq.I(q0))
qc.append(cirq.I(q1))

# here insert the hamiltonian computation

print(expectation_value) --> 1.0


Does somebody know what is going on? What is it wrong with my code? I am using cirq 0.13.1 but I tested oncirq 0.9.1 as well and it gave me the same results.

Thank you in advance! :)

I write down a more complex example with the Hamiltonian $$H = \sigma_{0}^{z} + \sigma_{1}^{z} + \sigma_{0}^{z}\,\sigma_{1}^{z}$$

import cirq

q0 = cirq.NamedQubit('q0')
q1 = cirq.NamedQubit('q1')

qc = cirq.Circuit()
qc.append(cirq.X(q0))
qc.append(cirq.I(q1))

hamiltonian = 0
hamiltonian += cirq.Z(q0)
hamiltonian += cirq.Z(q1)
hamiltonian += cirq.Z(q0)*cirq.Z(q1)

num_var = { q0: 0, q1: 1 }
expectation_value = cirq.PauliString(hamiltonian).expectation_from_state_vector(qc.final_state_vector(), num_var).real


The resulr of print(expectation_value) is 1.0 instead of -1.0.

You want cirq.PauliSum instead of cirq.PauliString. Actually you had exactly that... but then asked for it to be converted to a cirq.PauliString.
It all got confusing because cirq.PauliString "helpfully" saw a class it didn't have an explicit conversion defined for, and tried a fallback strategy based on iterating that class looking for Pauli terms to multiply together. Which worked!... except it was iterating over terms that were supposed to be added together. Oops. So you get I because the sum (Z0) + (Z1) + (Z1*Z0) gets seen as the list [Z0, Z1, Z1*Z0] which is then interpreted in context as the product (Z0) * (Z1) * (Z1*Z0) which equals I. I opened a cirq bug to raise an error instead when this occurs.