Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qiskit statevector simulator returns wrong result when skipping classical bits. #142

Open
nathanieltornow opened this issue Jun 26, 2024 · 3 comments
Assignees

Comments

@nathanieltornow
Copy link

nathanieltornow commented Jun 26, 2024

Hi!

I noticed that when "skipping" a classical bit, meaning not measuring to some bit $x$ but to bit $y$ with $ind(x) < ind(y)$, the cusvaer-enabled statevector simulator returns the wrong result, simply ignoring the result on bit $y$. This does not happen when not enabling cusvaer.

See the example below:

from qiskit.circuit import QuantumCircuit
from qiskit_aer import Aer

sim = Aer.get_backend("aer_simulator_statevector")
sim.set_option("cusvaer_enable", True)

circuit = QuantumCircuit(4, 5)
circuit.h(0)
circuit.cx(range(3), range(1, 4))
circuit.measure([0, 1, 2, 3], [0, 1, 2, 4])

print(circuit)

wrong_result = sim.run(circuit, shots=10000).result().get_counts()
print("Wrong:", wrong_result)

sim.set_option("cusvaer_enable", False)

correct_result = sim.run(circuit, shots=10000).result().get_counts()
print("Correct:", correct_result)
     ┌───┐          ┌─┐              
q_0: ┤ H ├──■───────┤M├──────────────
     └───┘┌─┴─┐     └╥┘     ┌─┐      
q_1: ─────┤ X ├──■───╫──────┤M├──────
          └───┘┌─┴─┐ ║      └╥┘┌─┐   
q_2: ──────────┤ X ├─╫───■───╫─┤M├───
               └───┘ ║ ┌─┴─┐ ║ └╥┘┌─┐
q_3: ────────────────╫─┤ X ├─╫──╫─┤M├
                     ║ └───┘ ║  ║ └╥┘
c: 5/════════════════╩═══════╩══╩══╩═
                     0       1  2  4 
Wrong: {'00000': 4993, '00111': 5007}
Correct: {'10111': 5026, '00000': 4974}

I suspect there might be some missing bookkeeping of the indices of classical registers in the cusvaer backend.

Thanks!
Nate

@yangcal
Copy link
Collaborator

yangcal commented Jun 26, 2024

Thanks for reporting. @ymagchi can you take a look?

@nathanieltornow
Copy link
Author

Perhaps, something like this could be done on the frontend:

def clbit_mapping(circuit: QuantumCircuit) -> tuple[QuantumCircuit, list[int]]:
    active_clbit_indices = sorted(
        set(circuit.clbits.index(clbit) for instr in circuit for clbit in instr.clbits),
    )
    mapping = {clbit: i for i, clbit in enumerate(active_clbit_indices)}

    new_creg = ClassicalRegister(len(active_clbit_indices), name="c")
    new_circuit = QuantumCircuit(*circuit.qregs, new_creg)
    for instr in circuit:
        new_circuit.append(
            instr.operation,
            instr.qubits,
            [mapping[circuit.clbits.index(clbit)] for clbit in instr.clbits],
        )

    return new_circuit, active_clbit_indices


def remap_results(bitstr: str, num_clbits: int, active_indices: list[int]) -> str:
    assert len(bitstr) <= num_clbits
    bits = ["0"] * num_clbits
    for i, idx in enumerate(active_indices):
        bits[-idx - 1] = bitstr[i]
    return "".join(bits)


circuit2, active_indices = clbit_mapping(circuit)
corrected_res = sim.run(circuit2, shots=10000).result().get_counts()
print("corrected:", corrected_res)
print({remap_results(k, circuit.num_clbits, active_indices): v for k, v in corrected_res.items()})

@ymagchi
Copy link
Collaborator

ymagchi commented Jun 26, 2024

@nathanieltornow Thank you so much for reporting this. I confirmed that it is reproducible with 24.03 images. We will work on its fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants