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

Better decomposition for multi-controlled 1-qubit gates #13801

Merged
merged 5 commits into from
Feb 10, 2025

Conversation

ShellyGarion
Copy link
Member

Summary

close #13514

Reduce the CX count of the multi-controlled 1-qubit unitary gates for the gates: H, SX, SXdg and U,
based on the efficient synthesis of MCRX, MCRY, MCRZ, MCX and MCPhase gates.

Details and comments

<style> </style>
gate name num controls cx count (main) cx count (new) reduction
y 1 1 1 1
y 2 24 6 0.25
y 3 60 14 0.233333
y 4 112 36 0.321429
y 5 206 84 0.407767
y 6 298 128 0.42953
y 7 496 208 0.419355
y 8 728 312 0.428571
y 9 984 432 0.439024
         
h 1 1 1 1
h 2 18 18 1
h 3 54 34 0.62963
h 4 106 60 0.566038
h 5 200 124 0.62
h 6 292 172 0.589041
h 7 490 288 0.587755
h 8 722 416 0.576177
h 9 978 552 0.564417
         
sx 1 2 2 1
sx 2 28 6 0.214286
sx 3 100 20 0.2
sx 4 214 44 0.205607
sx 5 408 84 0.205882
sx 6 626 128 0.204473
sx 7 1032 208 0.20155
sx 8 1554 312 0.200772
sx 9 2154 432 0.200557
         
sxdg 1 2 2 1
sxdg 2 28 6 0.214286
sxdg 3 100 20 0.2
sxdg 4 214 44 0.205607
sxdg 5 408 84 0.205882
sxdg 6 626 128 0.204473
sxdg 7 1032 208 0.20155
sxdg 8 1554 312 0.200772
sxdg 9 2154 432 0.200557
         
u 1 2 2 1
u 2 24 22 0.916667
u 3 60 51 0.85
u 4 112 92 0.821429
u 5 206 164 0.796117
u 6 298 216 0.724832
u 7 496 368 0.741935
u 8 728 520 0.714286
u 9 984 672 0.682927

@ShellyGarion ShellyGarion requested a review from a team as a code owner February 6, 2025 13:14
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Feb 6, 2025

Pull Request Test Coverage Report for Build 13237981288

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 20 of 21 (95.24%) changed or added relevant lines in 1 file are covered.
  • 502 unchanged lines in 27 files lost coverage.
  • Overall coverage decreased (-0.3%) to 88.277%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/circuit/add_control.py 20 21 95.24%
Files with Coverage Reduction New Missed Lines %
qiskit/pulse/schedule.py 1 88.42%
qiskit/utils/parallel.py 1 80.7%
qiskit/pulse/instruction_schedule_map.py 1 95.9%
qiskit/providers/fake_provider/fake_openpulse_3q.py 1 92.86%
qiskit/transpiler/passes/scheduling/alignments/check_durations.py 1 77.78%
crates/accelerate/src/euler_one_qubit_decomposer.rs 1 91.5%
crates/accelerate/src/target_transpiler/nullable_index_map.rs 1 67.17%
crates/accelerate/src/unitary_synthesis.rs 1 93.09%
crates/accelerate/src/two_qubit_decompose.rs 2 92.03%
qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py 3 96.2%
Totals Coverage Status
Change from base Build 13179280654: -0.3%
Covered Lines: 78634
Relevant Lines: 89076

💛 - Coveralls

@ShellyGarion ShellyGarion added this to the 2.0.0 milestone Feb 6, 2025
Copy link
Member

@alexanderivrii alexanderivrii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ShellyGarion. The results look really good. I have left two comments inline. And you need release notes.

@@ -250,20 +250,40 @@ def apply_basic_controlled_gate(circuit, gate, controls, target):
elif theta == 0 and phi == 0:
circuit.mcp(lamb, controls, target)
else:
circuit.mcp(lamb, controls, target)
circuit.mcrz(lamb, controls, target, use_basis_gates=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I recall correctly, setting use_basis_gates=True recursively calls transpile. It's not a problem, but I am wondering whether this can be avoided.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in f0c7e31.
I also updated other places.

Comment on lines +282 to +286
elif gate.name == "sxdg":
circuit.h(target)
circuit.mcp(3 * pi / 2, controls, target)
circuit.h(target)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these 4 new elif statements covered by existing tests (you can check the coverage report for that)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since test_controlled_gate.py already contains (too) many tests, I don't want to add extra unnecessary tests.
I've looked at the coverage reports and checked that the new cases are covered.
Moreover, I added some printouts to check that controlled h / y / sx / sxdg are checked for 2 and 3 controls.

@ShellyGarion ShellyGarion added the Changelog: New Feature Include in the "Added" section of the changelog label Feb 9, 2025
Copy link
Member

@alexanderivrii alexanderivrii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Shelly. Just a few minor suggestions for the release notes, otherwise it's good to go.

Copy link
Member

@alexanderivrii alexanderivrii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@alexanderivrii alexanderivrii added this pull request to the merge queue Feb 10, 2025
Merged via the queue into Qiskit:main with commit 94504f2 Feb 10, 2025
17 checks passed
@ACE07-Sev
Copy link

ACE07-Sev commented Feb 10, 2025

I was wondering, I have been using the same formulation for MCY (I think I may have even mentioned it before in Slack), but I get 705 for 9 controlled gate instead of 432. Could I please see the depth table for MCX? I have a feeling that's why mine is different.

Although, I just upgraded my qiskit to latest version, and it gives the exact same depth as I do.

from qiskit import QuantumCircuit, transpile


qc = QuantumCircuit(10)
qc.mcx(list(range(9)), 9)

qc = transpile(qc, basis_gates=['cx', 'u3'])

qc.depth()
>>> 703

which becomes 705 when sandwiched between sdg and s.

OHH. Nevermind. I'm stupid, you're just counting the number of CX.

@ACE07-Sev
Copy link

By the way, could you kindly try this for MCH? I think this one gives better results.

circuit.s(target)
circuit.h(target)
circuit.t(target)
circuit.mcx(controls, target)
circuit.tdg(target)
circuit.h(target)
circuit.sdg(target)

@ACE07-Sev
Copy link

I still feel we could do a bit better on MCU3.

@ShellyGarion
Copy link
Member Author

@ACE07-Sev - thank you very much for your comments!

  1. This is my benchmarking code, you can try both CX count and circuit depth:

from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import *

a=0.123
b=0.456
c=0.789

for gate in [XGate(), YGate(), ZGate(), HGate(), TGate(), TdgGate(), SGate(), SdgGate(), SXGate(), SXdgGate(),
             RXGate(a), RYGate(a), RZGate(a), PhaseGate(a), UGate(a,b,c)]:
    for n in range(2, 11):
        qc = QuantumCircuit(n)
        qc.append(gate.control(n-1), range(n))
        qct = transpile(qc, basis_gates=['cx','u'], optimization_level=3)
        print("gate_name=", gate.name, "num_controls=", n-1, "cx_count=", qct.count_ops()['cx'], "depth=", qct.depth())

for MCX the results are:

gate_name= x num_controls= 1 cx_count= 1 depth= 1
gate_name= x num_controls= 2 cx_count= 6 depth= 11
gate_name= x num_controls= 3 cx_count= 14 depth= 27
gate_name= x num_controls= 4 cx_count= 36 depth= 65
gate_name= x num_controls= 5 cx_count= 84 depth= 130
gate_name= x num_controls= 6 cx_count= 128 depth= 192
gate_name= x num_controls= 7 cx_count= 208 depth= 328
gate_name= x num_controls= 8 cx_count= 312 depth= 506
gate_name= x num_controls= 9 cx_count= 432 depth= 719
  1. You are correct that we can improve the synthesis of MCH gate, I opened another PR based on your suggestion:
    Small improvement for multi-controlled 1-qubit gates #13824

  2. Please let us know if you can come up with a better synthesis method for MCU in general.
    See also these synthesis methods for single-qubit unitaries: https://docs.quantum.ibm.com/api/qiskit/qiskit.synthesis.OneQubitEulerDecomposer
    Note that all these methods require a global phase, and an n-controlled global-phase gate is equivalent to an (n-1)-controlled phase gate.

@ACE07-Sev
Copy link

My pleasure. I am honored to have been of some use. I am actively working on it. The way I am going about it is by working on MCX a bit more (I think I mentioned it on Slack). If I get any improvement I'll let you know and will open a new Issue for it and reference this one there.

@ACE07-Sev
Copy link

For my MCX I got

gate_name= x num_controls= 1 cx_count= 1 depth= 1
gate_name= x num_controls= 2 cx_count= 6 depth= 11
gate_name= x num_controls= 3 cx_count= 14 depth= 27
gate_name= x num_controls= 4 cx_count= 36 depth= 65
gate_name= x num_controls= 5 cx_count= 84 depth= 130
gate_name= x num_controls= 6 cx_count= 140 depth= 192
gate_name= x num_controls= 7 cx_count= 220 depth= 331
gate_name= x num_controls= 8 cx_count= 324 depth= 499
gate_name= x num_controls= 9 cx_count= 444 depth= 703

I guess I have missed a small PR that has improved MCX compilation slightly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog synthesis
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Better decomposition for multi-controlled 1-qubit gates
5 participants