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

Optimization level 2 and 3 result in a deeper circuit with 1.3.0rc1 and main branch #13438

Closed
t-imamichi opened this issue Nov 14, 2024 · 1 comment · Fixed by #13450
Closed
Assignees
Labels
bug Something isn't working mod: transpiler Issues and PRs related to Transpiler
Milestone

Comments

@t-imamichi
Copy link
Member

t-imamichi commented Nov 14, 2024

Environment

  • Qiskit version: 1.3.0rc1, main branch
  • Python version: 3.12.7
  • Operating system: 15.1

What is happening?

Transpilation with optimization level 2 and 3 result in a deeper circuit than optimization level 1.
The circuit of level 2 is deeper than that of level 1.
The circuit of level 3 is deeper than that of level 2.
This does not happen with Qiskit 1.2.4.

How can we reproduce the issue?

from qiskit import generate_preset_pass_manager, QuantumCircuit

qc = QuantumCircuit(2)
qc.cz(0, 1)
qc.sx([0, 1])
qc.cz(0, 1)

for level in [1, 2, 3]:
    pm = generate_preset_pass_manager(optimization_level=level, basis_gates=["rz", "rzz", "sx", "x", "rx"])
    qc2 = pm.run(qc)
    print('optimization level', level)
    print(qc2)
    print()
# 1.2.4
optimization level 1
global phase: π
     ┌─────────┐           ┌─────────┐┌─────────┐
q_0: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     ├─────────┤ │ZZ(-π/2) ├─────────┤├─────────┤ │ZZ(-π/2)
q_1: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     └─────────┘           └─────────┘└─────────┘

optimization level 2
global phase: π
     ┌─────────┐           ┌─────────┐┌─────────┐
q_0: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     ├─────────┤ │ZZ(-π/2) ├─────────┤├─────────┤ │ZZ(-π/2)
q_1: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     └─────────┘           └─────────┘└─────────┘

optimization level 3
global phase: π
     ┌─────────┐           ┌─────────┐┌─────────┐
q_0: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     ├─────────┤ │ZZ(-π/2) ├─────────┤├─────────┤ │ZZ(-π/2)
q_1: ┤ Rz(π/2) ├─■─────────┤ Rx(π/2) ├┤ Rz(π/2) ├─■─────────
     └─────────┘           └─────────┘└─────────┘
# 1.3.0rc1 and main branch
optimization level 1
global phase: 7π/4
               ┌──────────┐   ┌────┐            ┌──────────┐
q_0: ─■────────┤ Rz(-π/2) ├───┤ √X ├───■────────┤ Rz(-π/2) ├
      │ZZ(π/2) ├──────────┤┌──┴────┴─┐ │ZZ(π/2) ├──────────┤
q_1: ─■────────┤ Rz(-π/2) ├┤ Rx(π/2) ├─■────────┤ Rz(-π/2) ├
               └──────────┘└─────────┘          └──────────┘

optimization level 2
global phase: 3π/2
                                                     ┌──────────┐ ┌─────────┐ ┌─────────┐              ┌──────────┐  ┌─────────┐┌─────────┐
q_0: ──────────────────────────────────────■─────────┤ Rz(-π/2) ├─┤ Rx(π/2) ├─┤ Rz(π/2) ├───■──────────┤ Rz(-π/2) ├──┤ Rx(π/2) ├┤ Rz(π/2) ├
     ┌──────────┐┌─────────┐┌────────────┐ │ZZ(π/2) ┌┴──────────┴┐├─────────┤┌┴─────────┴─┐ │ZZ(π/2) ┌─┴──────────┴─┐└┬───────┬┘└─────────┘
q_1: ┤ Rz(-π/2) ├┤ Rx(π/2) ├┤ Rz(1.6719) ├─■────────┤ Rz(1.4697) ├┤ Rx(π/2) ├┤ Rz(1.6719) ├─■────────┤ Rz(-0.10111) ├─┤ Rx(π) ├────────────
     └──────────┘└─────────┘└────────────┘          └────────────┘└─────────┘└────────────┘          └──────────────┘ └───────┘

optimization level 3
global phase: π
     ┌─────────────┐┌────┐  ┌───────┐   ┌────┐┌────────────┐                                      ┌──────────┐┌─────────┐   ┌────┐  ┌──────────┐»
q_0: ┤ Rz(-1.9513) ├┤ √X ├──┤ Rz(π) ├───┤ √X ├┤ Rz(11.376) ├─────────────────────────────■────────┤ Rz(-π/2) ├┤ Rz(π/2) ├───┤ √X ├──┤ Rz(3π/2) ├»
     └─┬─────────┬─┘├────┤┌─┴───────┴──┐├────┤└┬──────────┬┘┌─────────┐┌────┐┌─────────┐ │ZZ(π/2) ├─────────┬┘└──┬────┬─┘┌──┴────┴─┐├──────────┤»
q_1: ──┤ Rz(π/2) ├──┤ √X ├┤ Rz(3.2427) ├┤ √X ├─┤ Rz(5π/2) ├─┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├─■────────┤ Rz(π/2) ├────┤ √X ├──┤ Rz(π/2) ├┤ Rx(-π/2) ├»
       └─────────┘  └────┘└────────────┘└────┘ └──────────┘ └─────────┘└────┘└─────────┘          └─────────┘    └────┘  └─────────┘└──────────┘»
«          ┌────┐    ┌────────┐                                                                        ┌──────────┐┌─────────┐   ┌────┐  ┌──────────┐»
«q_0: ─────┤ √X ├────┤ Rz(3π) ├───────────────────────────────────────────────────────────────■────────┤ Rz(-π/2) ├┤ Rz(π/2) ├───┤ √X ├──┤ Rz(3π/2) ├»
«     ┌────┴────┴───┐└─┬────┬─┘┌────────────┐┌────┐┌────────────┐┌─────────┐┌────┐┌─────────┐ │ZZ(π/2) ├─────────┬┘└──┬────┬─┘┌──┴────┴─┐├──────────┤»
«q_1: ┤ Rz(-3.1314) ├──┤ √X ├──┤ Rz(4.6118) ├┤ √X ├┤ Rz(10.894) ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├─■────────┤ Rz(π/2) ├────┤ √X ├──┤ Rz(π/2) ├┤ Rx(-π/2) ├»
«     └─────────────┘  └────┘  └────────────┘└────┘└────────────┘└─────────┘└────┘└─────────┘          └─────────┘    └────┘  └─────────┘└──────────┘»
«       ┌────┐  ┌────────┐
«q_0: ──┤ √X ├──┤ Rz(2π) ├────────────────────────────────
«     ┌─┴────┴─┐└─┬────┬─┘┌──────────┐┌────┐┌────────────┐
«q_1: ┤ Rz(-π) ├──┤ √X ├──┤ Rz(3π/2) ├┤ √X ├┤ Rz(7.7529) ├
«     └────────┘  └────┘  └──────────┘└────┘└────────────┘

What should happen?

Circuits of level 2 and 3 should be the same size as that of level 1 to be compatible with 1.2.4.

Any suggestions?

No response

@t-imamichi t-imamichi added bug Something isn't working mod: transpiler Issues and PRs related to Transpiler labels Nov 14, 2024
@raynelfss raynelfss added this to the 1.3.0 milestone Nov 14, 2024
@mtreinish
Copy link
Member

I took a brief look at this, I expect it's a bug introduced by #13141 when you don't use a Target for the backend's constraints. Since you just used basis_gates it's causing the UnitarySynthesis pass to not correctly synthesize the circuit. If you look at the circuit coming out of the BasisTranslator into the optimization loop at optimization_level=3 you see:

global phase: 3π/2
                                                                       ┌──────────┐┌────┐                                                                                                                 »
q_0: ─────────────────────────────────────────────────────────■────────┤ Rz(-π/2) ├┤ √X ├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────»
     ┌─────────┐┌────┐┌─────────┐┌─────────┐┌────┐┌─────────┐ │ZZ(π/2) ├─────────┬┘├────┤┌─────────┐┌──────────┐┌─────────┐┌────┐┌─────────┐┌────┐┌─────────┐┌────┐┌─────────┐┌─────────┐┌────┐┌─────────┐»
q_1: ┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├─■────────┤ Rz(π/2) ├─┤ √X ├┤ Rz(π/2) ├┤ Rx(-π/2) ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├»
     └─────────┘└────┘└─────────┘└─────────┘└────┘└─────────┘          └─────────┘ └────┘└─────────┘└──────────┘└─────────┘└────┘└─────────┘└────┘└─────────┘└────┘└─────────┘└─────────┘└────┘└─────────┘»
«               ┌──────────┐
«q_0: ─■────────┤ Rz(-π/2) ├─────────────────────────────────────────────────────────
«      │ZZ(π/2) ├─────────┬┘┌────┐┌─────────┐┌──────────┐┌─────────┐┌────┐┌─────────┐
«q_1: ─■────────┤ Rz(π/2) ├─┤ √X ├┤ Rz(π/2) ├┤ Rx(-π/2) ├┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├
«               └─────────┘ └────┘└─────────┘└──────────┘└─────────┘└────┘└─────────┘

Then the first thing the optimization stage runs is consolidate blocks which collects the entire 2q circuit into a single unitary:

global phase: 3π/2
     ┌──────────┐
q_0: ┤0         ├
     │  Unitary │
q_1: ┤1         ├
     └──────────┘

and immediately after unitary synthesis runs and does nothing with the circuit:

<qiskit.transpiler.passes.synthesis.unitary_synthesis.UnitarySynthesis object at 0x7111761906e0>
None
global phase: 3π/2
     ┌──────────┐
q_0: ┤0         ├
     │  Unitary │
q_1: ┤1         ├
     └──────────┘

Then that unitary gate for the circuit means none of the other optimization passes can do anything with the circuit, until we get to the if statement in the optimization loop looking for gates outside the basis which runs basis translation again to yield the returned circuit instead of optimizing the output as expected. @ElePT might have some thoughts on where this is going wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working mod: transpiler Issues and PRs related to Transpiler
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants