qiskit icon indicating copy to clipboard operation
qiskit copied to clipboard

Commuting2qGateGrouper pass

Open 1ucian0 opened this issue 3 years ago • 8 comments

The pass Commuting2qGateGrouper groups the commuting multi-qubit gates into Commuting2qBlock.

from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import CommutationAnalysis
from qiskit.transpiler.passes.routing import Commuting2qGateGrouper

from qiskit.circuit.library import TwoLocal

circuit = TwoLocal(5, "ry", "cz", entanglement='pairwise').decompose()
print(circuit.draw('text', fold=-1))

passmanager = PassManager()
passmanager.append([Commuting2qGateGrouper()])
result = passmanager.run(circuit)
print(result.draw('text', fold=-1))
     ┌──────────┐   ┌──────────┐               ┌───────────┐                ┌───────────┐             
q_0: ┤ Ry(θ[0]) ├─■─┤ Ry(θ[5]) ├─────────────■─┤ Ry(θ[10]) ├──────────────■─┤ Ry(θ[15]) ├─────────────
     ├──────────┤ │ └──────────┘┌──────────┐ │ └───────────┘┌───────────┐ │ └───────────┘┌───────────┐
q_1: ┤ Ry(θ[1]) ├─■──────■──────┤ Ry(θ[6]) ├─■───────■──────┤ Ry(θ[11]) ├─■───────■──────┤ Ry(θ[16]) ├
     ├──────────┤        │      ├──────────┤         │      ├───────────┤         │      ├───────────┤
q_2: ┤ Ry(θ[2]) ├─■──────■──────┤ Ry(θ[7]) ├─■───────■──────┤ Ry(θ[12]) ├─■───────■──────┤ Ry(θ[17]) ├
     ├──────────┤ │             ├──────────┤ │              ├───────────┤ │              ├───────────┤
q_3: ┤ Ry(θ[3]) ├─■──────■──────┤ Ry(θ[8]) ├─■───────■──────┤ Ry(θ[13]) ├─■───────■──────┤ Ry(θ[18]) ├
     ├──────────┤        │      ├──────────┤         │      ├───────────┤         │      ├───────────┤
q_4: ┤ Ry(θ[4]) ├────────■──────┤ Ry(θ[9]) ├─────────■──────┤ Ry(θ[14]) ├─────────■──────┤ Ry(θ[19]) ├
     └──────────┘               └──────────┘                └───────────┘                └───────────┘
     ┌──────────┐┌─────────────────────┐┌──────────┐┌─────────────────────┐┌───────────┐┌─────────────────────┐┌───────────┐
q_0: ┤ Ry(θ[0]) ├┤0                    ├┤ Ry(θ[5]) ├┤0                    ├┤ Ry(θ[10]) ├┤0                    ├┤ Ry(θ[15]) ├
     ├──────────┤│                     │├──────────┤│                     │├───────────┤│                     │├───────────┤
q_1: ┤ Ry(θ[1]) ├┤1                    ├┤ Ry(θ[6]) ├┤1                    ├┤ Ry(θ[11]) ├┤1                    ├┤ Ry(θ[16]) ├
     ├──────────┤│                     │├──────────┤│                     │├───────────┤│                     │├───────────┤
q_2: ┤ Ry(θ[2]) ├┤2 Commuting 2q gates ├┤ Ry(θ[7]) ├┤2 Commuting 2q gates ├┤ Ry(θ[12]) ├┤2 Commuting 2q gates ├┤ Ry(θ[17]) ├
     ├──────────┤│                     │├──────────┤│                     │├───────────┤│                     │├───────────┤
q_3: ┤ Ry(θ[3]) ├┤3                    ├┤ Ry(θ[8]) ├┤3                    ├┤ Ry(θ[13]) ├┤3                    ├┤ Ry(θ[18]) ├
     ├──────────┤│                     │├──────────┤│                     │├───────────┤│                     │├───────────┤
q_4: ┤ Ry(θ[4]) ├┤4                    ├┤ Ry(θ[9]) ├┤4                    ├┤ Ry(θ[14]) ├┤4                    ├┤ Ry(θ[19]) ├
     └──────────┘└─────────────────────┘└──────────┘└─────────────────────┘└───────────┘└─────────────────────┘└───────────┘

Testing is needed

1ucian0 avatar May 09 '22 21:05 1ucian0

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core

qiskit-bot avatar May 09 '22 21:05 qiskit-bot

Pull Request Test Coverage Report for Build 2423044318

  • 76 of 77 (98.7%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 84.408%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_grouper.py 66 67 98.51%
<!-- Total: 76 77
Totals Coverage Status
Change from base Build 2409841148: 0.02%
Covered Lines: 54635
Relevant Lines: 64727

💛 - Coveralls

coveralls avatar May 09 '22 22:05 coveralls

this is fine but at some point we should really do the generic things described here: https://github.com/Qiskit/qiskit-terra/issues/5775

Because all these things that we collect can be described by some condition on the gates inspected, to see whether they should be placed in the bucket or not. Here the condition is being a 2-qubit gate and commuting with the block, in #7361 the condition is being a linear gate (cx, swap, etc.), in Collect2qBlocks the condition is being a 2-qubit gate. Soon we will need to collect all cliffords. etc.

ajavadia avatar May 10 '22 02:05 ajavadia

we should really do the generic things described here: #5775

I agree, at least with the general principle. However, that seems to be a bigger project than this one.

1ucian0 avatar May 10 '22 10:05 1ucian0

Some preliminary testing from my end. First comment is that this plays nicely with the commuting gate router. For instance:

from qiskit.transpiler import PassManager, CouplingMap, Layout
from qiskit.transpiler.passes import CommutationAnalysis
from qiskit.transpiler.passes.routing.swap_strategies import Commuting2qGateGrouper, SwapStrategy
from qiskit.transpiler.passes import FullAncillaAllocation
from qiskit.transpiler.passes import EnlargeWithAncilla
from qiskit.transpiler.passes import ApplyLayout
from qiskit.transpiler.passes import SetLayout
from qiskit.transpiler.passes import Commuting2qGateRouter
from qiskit.circuit.library import TwoLocal

circuit = TwoLocal(5, "ry", "cz", entanglement='full', reps=2).decompose()
circuit.draw('mpl', fold=-1)

swap_strat = SwapStrategy.from_line([0, 1, 2, 3, 4])
backend_cmap = CouplingMap(couplinglist=[(0, 1), (1, 2), (1, 3), (3, 4), (4, 5), (5, 6)])
initial_layout = Layout.from_intlist([0, 1, 3, 4, 5], *circuit.qregs)

passmanager = PassManager(
    [
        CommutationAnalysis(), 
        Commuting2qGateGrouper(),
        Commuting2qGateRouter(swap_strat),
        SetLayout(initial_layout),
        FullAncillaAllocation(backend_cmap),
        EnlargeWithAncilla(),
        ApplyLayout(),
    ]
)

result = passmanager.run(circuit)
result.draw('mpl', fold=-1)

transpiles this

image

into this

image

eggerdj avatar May 25 '22 14:05 eggerdj

This also looks good:

from qiskit import QuantumCircuit
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import CommutationAnalysis
from qiskit.transpiler.passes.routing.swap_strategies import Commuting2qGateGrouper

circ = QuantumCircuit(8)
circ.cz(0, 1)
circ.cz(2, 3)
circ.cz(0, 2)
circ.cz(1, 3)
circ.cz(0, 3)

circ.cz(5, 6)
circ.cz(6, 7)
circ.cz(5, 7)
print(circ.draw("text"))

passmanager = PassManager(
    [
        CommutationAnalysis(), 
        Commuting2qGateGrouper(),
    ]
)

print(passmanager.run(circ).draw("text"))

results in

q_0: ─■──■─────■─
      │  │     │ 
q_1: ─■──┼──■──┼─
         │  │  │ 
q_2: ─■──■──┼──┼─
      │     │  │ 
q_3: ─■─────■──■─
                 
q_4: ────────────
                 
q_5: ─■─────■────
      │     │    
q_6: ─■──■──┼────
         │  │    
q_7: ────■──■────
                 
     ┌─────────────────────┐
q_0: ┤0                    ├
     │                     │
q_1: ┤1                    ├
     │  Commuting 2q gates │
q_2: ┤2                    ├
     │                     │
q_3: ┤3                    ├
     └─────────────────────┘
q_4: ───────────────────────
     ┌─────────────────────┐
q_5: ┤0                    ├
     │                     │
q_6: ┤1 Commuting 2q gates ├
     │                     │
q_7: ┤2                    ├
     └─────────────────────┘

eggerdj avatar May 25 '22 14:05 eggerdj

The second example posted by @eggerdj highlights that this is not quite grouping the commuting 2-qubit gates (because the top gates and bottom gates also commute). Rather it is grouping 2q gates that commute and act on contiguous qubits. This should be in the docstrings.

ajavadia avatar Jun 16 '22 16:06 ajavadia

I agree, at least with the general principle. However, that seems to be a bigger project than this one.

Only slightly bigger. But it simplifies the transpiler quite a lot and prevents a bunch of ad-hoc passes that keep creeping in. I just saw another pass today that groups 2-qubit clifford gates.

ajavadia avatar Jun 16 '22 16:06 ajavadia