Qiskit / qiskit-aer

Aer is a high performance simulator for quantum circuits that includes noise models
https://qiskit.github.io/qiskit-aer/
Apache License 2.0
483 stars 358 forks source link

Stabilizer simulator gives wrong wrong answer sometimes #2125

Open zlatko-minev opened 4 months ago

zlatko-minev commented 4 months ago

Informations

What is the current behavior?

Expectation values or counts of Clifford circuits that should be +1 or -1 are sometimes flipped.

Steps to reproduce the problem

import qiskit
from qiskit import qpy
from qiskit_aer import AerSimulator

from qiskit import ClassicalRegister
from qiskit.quantum_info import random_clifford

nq = 5
# obs = 'IZ' + "I"*(nq-2)
qcs = []
for n in range(200):
    rc = random_clifford(nq)
    qc = rc.to_circuit()
    cr = ClassicalRegister(1)
    qc.add_bits(cr)
    qc.measure(1, cr[0])
    qcs += [qc]

shots = 1e4
simulator = AerSimulator(method="stabilizer")
result = simulator.run(qcs, shots=1e4)
counts_stab = result.result().get_counts()

simulator = AerSimulator(method="statevector")
result = simulator.run(qcs, shots=1e4)
counts_state = result.result().get_counts()

import numpy as np
from matplotlib import pyplot as plt
shots = 1e4
data0 = np.array([x.get("1",0)/shots for x in counts_stab])
data1 = np.array([x.get("1",0)/shots for x in counts_state])
plt.plot(data0, label ='stabilizer')
plt.plot(data1, label ='statevec')
plt.ylabel('Prob of 1')
plt.xlabel('Random clifford instance')
image

What is the expected behavior?

The stabilizer should agree with statvec, density matrix, etc. @smajumderibm and I find that this is not always the case.

Suggested solutions

aeddins-ibm commented 4 months ago

This bug reproduces on my end as well. I'm using qiskit_aer 0.13.3, i.e. an older version than above, but still seeing the same issue.

I played with one of the offending random circuits to look for clues, in case it helps the next person to work on this.

Here is a circuit that shows the problem:

image

These results should match, but don't:

image

Now I think we can interpret the final CNOT + measurement as a measurement of ZZ on qubits 0 and 1.

So it seems that should not be affected by the final S gate on qubit 1, which commutes with ZZ.

However, removing that gate changes the result of the stabilizer method:

image image

If the above reasoning is correct, then the stabilizer method is incorrectly processing (at least) that S gate.

Here is code to build this bug-reproducing circuit:

qc = QuantumCircuit(5,1)
qc.h([2,4])
qc.cx(2,0)
qc.s(0)
qc.cx(4,2)
qc.h(0)
qc.cx(2,3)
qc.s(4)
qc.cx(1,0)
qc.h([3,4])
qc.cx(3,2)
qc.h(3)
qc.cx(0,3)
qc.cx(3,1)
qc.s(0)
qc.s(1) # this one
qc.h(0)
qc.s(0)
qc.cx(4,0)
qc.cx(0,1)
qc.measure(1,0)
zlatko-minev commented 4 months ago

Thank you, Andrew. This is great.

I would label this as a high priority item since it's used all parts of our stack and demo testing for PEC utility and 5K scale

aeddins-ibm commented 4 months ago

Here is a much simpler circuit that reproduces the problem:

image
qc = QuantumCircuit(3,1)
qc.h([0,1])
qc.cx(1,2)
qc.cy(0,1)
qc.cy(0,2)
qc.h(0)
qc.measure(0,0)
image
doichanj commented 4 months ago

I found source of problem and I'm now fixing it

zlatko-minev commented 4 months ago

Wonderful thank you!

aeddins-ibm commented 4 months ago

Thank you @doichanj for your quick work on this!

Do you know what conditions would cause the stabilizer simulator to give the wrong answer? This info could help decide whether recent simulations need to be re-run with the fix. No worries if not.