Repository: quantumlib/qsim (language: python)

Issue:
QSimSimulator.simulate_expectation_values for identity operators is wrong
QSimSimulator.simulate_expectation_values returns wrong results for identity operators in observables.
As the following example shows, identity operators in observables seem to be regarded as zero matrices.

This is a straightforward example.
```
import cirq
import qsimcirq

circuit = cirq.Circuit()
q = cirq.LineQubit.range(1)
ps = cirq.PauliString(cirq.I(q[0]))

sim = qsimcirq.QSimSimulator()
evs = sim.simulate_expectation_values(
    circuit, ps)
print("qsim", evs)

cirq_sim = cirq.Simulator()
evs = cirq_sim.simulate_expectation_values(
    circuit, ps)
print("cirq", evs)
```

And the result is here.
```
qsim [0j]
cirq [(1+0j)]
```




Discussion / hints:

Fix patch:
diff --git a/pybind_interface/pybind_main.cpp b/pybind_interface/pybind_main.cpp
index 74fa3a31..94d7cefa 100644
--- a/pybind_interface/pybind_main.cpp
+++ b/pybind_interface/pybind_main.cpp
@@ -795,7 +795,10 @@ class SimulatorHelper {
     for (const auto& opsum_qubit_count_pair : opsums_and_qubit_counts) {
       const auto& opsum = std::get<0>(opsum_qubit_count_pair);
       const auto& opsum_qubits = std::get<1>(opsum_qubit_count_pair);
-      if (opsum_qubits <= 6) {
+      if (opsum_qubits == 0) {
+        // This represents an identity, which always has EV=1.
+        results.push_back(std::complex<double>(1.0, 0.0));
+      } else if (opsum_qubits <= 6) {
         results.push_back(ExpectationValue<IO, Fuser>(opsum, simulator, state));
       } else {
         Fuser::Parameter params;


Test patch:
diff --git a/qsimcirq_tests/qsimcirq_test.py b/qsimcirq_tests/qsimcirq_test.py
index 8a92537f..26e4f7d8 100644
--- a/qsimcirq_tests/qsimcirq_test.py
+++ b/qsimcirq_tests/qsimcirq_test.py
@@ -523,18 +523,19 @@ def test_expectation_values(mode: str):
     ]
     psum1 = cirq.Z(a) + 3 * cirq.X(b)
     psum2 = cirq.X(a) - 3 * cirq.Z(b)
+    psum3 = cirq.I(a)
 
     if mode == "noisy":
         circuit.append(NoiseTrigger().on(a))
 
     qsim_simulator = qsimcirq.QSimSimulator()
     qsim_result = qsim_simulator.simulate_expectation_values_sweep(
-        circuit, [psum1, psum2], params
+        circuit, [psum1, psum2, psum3], params
     )
 
     cirq_simulator = cirq.Simulator()
     cirq_result = cirq_simulator.simulate_expectation_values_sweep(
-        circuit, [psum1, psum2], params
+        circuit, [psum1, psum2, psum3], params
     )
 
     assert cirq.approx_eq(qsim_result, cirq_result, atol=1e-6)