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

BUG: measurement after transpilation level 3 in Grover circuit #25

Open
MattePalte opened this issue Mar 22, 2023 · 1 comment
Open

Comments

@MattePalte
Copy link

Environment

  • qiskit.version: 0.22.0
  • Python version: 3.8.0
  • Operating system: Ubuntu 18.04

What is happening?

The quantum circuit in file groverFuncs.py is transpiled and then gets the measurement gate added to it.
Unfortunately, the transpilation is done with the optimization_level=3 option, which means that the measurements plays an important role in the optimization.
For example, OptimizeSwapBeforeMeasure is a pass that removes the swap gates before the measurement, leading to a non-equivalent circuit (See the doc regarding this level 3: here).

How can we reproduce the issue?

If you run this code, you can see whether the result is affected by the mistake of adding the measurement after the transpilation.

import numpy as np
from qiskit import *

def markedListGrover(markedList,N):
    oracleList = np.ones(2**N)
    for element in markedList:
        oracleList[element] = -1
    return oracleList.tolist()

def getOracle(markedList,N):
    oracleList = np.eye(2**N)
    for element in markedList:
        oracleList[element][element] = -1
    return oracleList

def oracleGrover(markedList,N):
    qreg = QuantumRegister(N)
    qc = QuantumCircuit(qreg,name='Oracle')
    qc.diagonal(markedList,qreg)

    qc=transpile(qc,optimization_level=3)
    return qc


def diffusionGrover(N):
    qreg = QuantumRegister(N)
    difCirc = QuantumCircuit(qreg,name='Diffusion')
    difCirc.h(qreg)
    aux = markedListGrover([0],N)
    qcAux = oracleGrover(aux,N)
    difCirc.append(qcAux,range(N))
    difCirc.h(qreg)
    difCirc=transpile(difCirc,optimization_level=3)
    return difCirc

def grover(marked,N,backend,steps):
    qc = QuantumCircuit(N,N)
    qcOracle = oracleGrover(markedListGrover(marked,N),N)
    qcDiffusion = diffusionGrover(N)
    qc.h(range(N))
    for i in range(steps):
        qc.append(qcOracle,range(N))
        qc.barrier()
        qc.append(qcDiffusion,range(N))
        qc.barrier()
    qc = transpile(qc,basis_gates=['cx','u3','u2','u1','id'],backend=backend,optimization_level=3)
    qc.barrier()
    qc.measure(range(N),range(N))
    return qc

def grover_transpile_after_measurement(marked,N,backend,steps):
    qc = QuantumCircuit(N,N)
    qcOracle = oracleGrover(markedListGrover(marked,N),N)
    qcDiffusion = diffusionGrover(N)
    qc.h(range(N))
    for i in range(steps):
        qc.append(qcOracle,range(N))
        qc.barrier()
        qc.append(qcDiffusion,range(N))
        qc.barrier()
    qc.barrier()
    qc.measure(range(N),range(N))
    qc = transpile(qc,basis_gates=['cx','u3','u2','u1','id'],backend=backend,optimization_level=3)
    return qc

def simul(qc):
    backend = Aer.get_backend('qasm_simulator')
    result = execute(qc,backend,shots=3000).result().get_counts()
    return result

N = 4
n = N-1

backend = Aer.get_backend('qasm_simulator')
qcG_w_transpile = grover([1],N,backend,2)
qcG_w_transpile_after_measurement = grover_transpile_after_measurement([1],N,backend,2)

gQasm_w_transpile = simul(qcG_w_transpile)
gQasm_w_transpile_after_measurement = simul(qcG_w_transpile_after_measurement)

print("Grover size (transpiled): ", qcG_w_transpile.size())
print("Grover size (transpiled after measurement): ", qcG_w_transpile_after_measurement.size())
assert qcG_w_transpile.qasm() != qcG_w_transpile_after_measurement.qasm(), 'the two qasm files are identical'

Output:

Grover size (transpiled):  135
Grover size (transpiled after measurement):  135
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
/home/user/Test.ipynb Cell 19 in 1
    109 print("Grover size (transpiled): ", qcG_w_transpile.size())
    110 print("Grover size (transpiled after measurement): ", qcG_w_transpile_after_measurement.size())
--> 111 assert qcG_w_transpile.qasm() != qcG_w_transpile_after_measurement.qasm(), 'the two qasm files are identical'

AssertionError: the two qasm files are identical

In this case, luckily the optimization did not affected the result, but it might have happened.

What should happen?

I would have expected the version with transpilation as last step, since it is more robust.

Any suggestions?

I would recommend to move the measurement before the transpilation. Following the recommendation of Qiskit developers. See here

@JaimePSantos
Copy link
Owner

Hi!
It has been a while since I've work on this code, but I will look into this once i've got some free time.
I might just end up recreating this notebook in the qwak project, but i'll mention this git issue if i do.

Thank you for the detailed feedback!

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

2 participants