Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
4.85k stars 2.29k forks source link

An interesting behavior when use `initialize` operator with different `optimization_level` #8050

Open weucode opened 2 years ago

weucode commented 2 years ago

Environment

What is happening?

When initialize the qubits in a circuit as follows,it will fail to simulate with optimization_level=0,1,and fail to transpile with optimization_level=2,and run successfully with optimization_level=3.The reasons are as follows.

When optimization_level=0,1,the transpilation step will not modify initialize into other operator,so it failed in simulation step.

When optimization_level=2,it fail to transpile the circuit when run the CommutationAnalysisza pass.The code snippet to trigger transpile error is in the operator.py.

if obj.definition is None:
    raise QiskitError(f"Cannot apply Instruction: {obj.name}")

The defination attribution of the initialize operator in this program is shown below:

0 = {tuple: 3} (<qiskit.circuit.reset.Reset object at 0x000001D611C39A08>, [Qubit(QuantumRegister(3, 'q'), 0)], [])
1 = {tuple: 3} (<qiskit.circuit.library.standard_gates.x.XGate object at 0x000001D611C39A48>, [Qubit(QuantumRegister(3, 'q'), 0)], [])
2 = {tuple: 3} (<qiskit.circuit.reset.Reset object at 0x000001D611C39A88>, [Qubit(QuantumRegister(3, 'q'), 1)], [])
3 = {tuple: 3} (<qiskit.circuit.reset.Reset object at 0x000001D611C39AC8>, [Qubit(QuantumRegister(3, 'q'), 2)], [])

In the CommutationAnalysisza pass,it tried to get defination of every object,but the defination in reset object is None,so it raise a QiskitError.

When optimization_level=3,it replace initialize operator into X gate,so it run successfully.

How can we reproduce the issue?

from qiskit import QuantumCircuit, transpile
from qiskit.providers.aer import QasmSimulator

circuit = QuantumCircuit(3)
circuit.initialize("001", circuit.qubits)
circuit.cx(0, 1)
circuit.measure_all()

simulator = QasmSimulator()
optimization_level = 2
compiled_circuit = transpile(circuit, simulator, optimization_level=optimization_level)
print("compiled-circuit:\n", compiled_circuit)
job = simulator.run(compiled_circuit, shots=1000)
result = job.result()
print("result:", result.get_counts())

What should happen?

The results should be consistent with different optimization_level.

Any suggestions?

Maybe it is feasible to add initialize into the check in line 94~96 in commutation_analysis.py,or give reset a defination.

for nd in [node1, node2]:
    if nd.op._directive or nd.name in {"measure", "reset", "delay"}:
        return False
jakelishman commented 2 years ago

I know @1ucian0 and @alexanderivrii have been looking a bit at unifying some logic in CommutativeAnalysis and a couple of other places in Qiskit, so this might be something they can sensible wrap up into that work. That said, I have a feeling that the issues with simulation at low optimisation levels might be a bug in Aer that was fixed in Qiskit/qiskit-aer#1519 - unfortunately you'll either need to build Aer from source, or wait for Aer 0.11 to be released for those bits to work, sorry.

alexanderivrii commented 2 years ago

The problem persists even without simulator, that is the following code

qc = QuantumCircuit(3)
qc.initialize("001", qc.qubits)
qc.cx(0, 1)
qc.measure_all()
print(qc)
qc2 = transpile(qc, optimization_level=2)

still produces the same error.

BTW, does it make sense that when transpiling with optimization_level = 0 or 1, the Initialize gate still remains in the circuit? Don't we want it to be expanded into the basic gates?

jakelishman commented 2 years ago

Your call doesn't specify any basis gates there, so there's nothing to expand to. The errors with Aer I was talkig about were for the cases in the original post where the transpilation succeeded, but simulation then failed.