Skip to content

[unitaryHack 2025] Refactor gate decomposition to support controlled gates#1653

Merged
renatomello merged 63 commits intoqiboteam:masterfrom
GiacomoFrn:decomposition
Jun 16, 2025
Merged

[unitaryHack 2025] Refactor gate decomposition to support controlled gates#1653
renatomello merged 63 commits intoqiboteam:masterfrom
GiacomoFrn:decomposition

Conversation

@GiacomoFrn
Copy link
Contributor

@GiacomoFrn GiacomoFrn commented May 29, 2025

Description

This PR addresses the first step of issue #1585, which aims to generalize the decompose() method for all gates, including controlled gates.

Summary of changes

  • Refactored all custom gates in gates.py to implement a new internal method _base_decompose(), which defines their standard decomposition.
  • Modified the decompose() method in abstract.py to support controlled gates by:
    • Calling _base_decompose() on the base gate (i.e., the gate with no control qubits),
    • Using control_mask_after_stripping() to determine which gates in the decomposition require controls,
    • Adding controls only to the necessary gates, avoiding redundant controlled gates,
    • Preserving the correct qubit ordering and control structure.

Notes

  • The new _base_decompose() method is for internal use only and separates decomposition logic from control logic.
  • The behavior for non-controlled gates remains unchanged.
  • The new logic improves circuit efficiency by not applying controls to gates that cancel out.

GiacomoFrn and others added 5 commits May 29, 2025 10:53
- Updated Gate.decompose() in abstract.py to propagate controls to decomposed gates.
- Refactored gates in gates.py to use _base_decompose for consistency.
- Enhanced Gate.decompose() to apply controls only to non-cancelled gates using control_mask_after_stripping.
- Updated decomposition logic to avoid unnecessary controls on gates that cancel out.
@GiacomoFrn
Copy link
Contributor Author

Hi @renatomello,
I'm reaching out with a couple of doubts about how I could improve my PR. There are two main issues I’d like to clarify:

  1. Controlled gate behavior: I noticed that when a gate has a _controlled_gate defined (like U3), the expected behavior — adding a control to each gate in the decomposition — doesn't work as intended. Instead, I only get a single CU3 gate, and the decomposition is skipped. Also, when I inspect the resulting gate, the is_controlled_by flag is not set to True, which makes me think that the control is handled differently in this case (perhaps by directly creating the controlled version, like CU3). I'm unsure how to intercept or modify this behavior — do you have any suggestions?

  2. Control optimization: I’ve implemented a simple version of the control optimization that handles basic sandwich-like identity cases. However, I'm not sure how to scale this to more general decompositions, where the gate set might be arbitrary (e.g., universal gates). A numerical approach to identify identity-like patterns seems too costly, while hardcoding all possible identities feels inelegant. Do you have any thoughts on a better strategy?

Thanks in advance for your time and help!

@renatomello renatomello self-requested a review May 30, 2025 08:53
@renatomello renatomello added the unitaryHACK 2025 Issues related to the unitaryHACK 2025 label May 30, 2025
GiacomoFrn and others added 4 commits May 30, 2025 11:16
Co-authored-by: Renato M S Farias <renato.msf@gmail.com>
Co-authored-by: Renato M S Farias <renato.msf@gmail.com>
Co-authored-by: Renato M S Farias <renato.msf@gmail.com>
@scarrazza scarrazza added the run-workflow Forces github workflow execution label May 30, 2025
- Ensure that when decomposing a controlled gate, the base gate instance used for decomposition has the correct control and target qubits set.
- This allows the overlap check between free qubits and (control + target) qubits to work as intended.
@GiacomoFrn
Copy link
Contributor Author

Hi @scarrazza, now all tests should pass!

@scarrazza scarrazza added run-workflow Forces github workflow execution and removed run-workflow Forces github workflow execution labels May 30, 2025
@GiacomoFrn
Copy link
Contributor Author

Hi @scarrazza,
apologies — earlier I was only checking the failing tests related to my change, and while my fix resolved those, it caused other tests to fail.

I've now run the full test suite and confirmed that all tests pass. That said, I'm aware that the solution may not be the most elegant, so I’d be happy to improve it with your input.

Summary of the issue and fix:

  • The current strategy for decomposing multi-controlled gates involves first decomposing the uncontrolled base gate, then applying single controls to the resulting gates.
  • However, this approach broke the following test:
@pytest.mark.parametrize("use_toffolis", [True, False])
def test_x_decomposition_errors(use_toffolis):
    gate = gates.X(0).controlled_by(1, 2, 3, 4)
    with pytest.raises(ValueError):
        _ = gate.decompose(2, 3, use_toffolis=use_toffolis)
  • The test expects a ValueError to be raised by the X gate’s _base_decompose when invalid free qubits are provided. But with the new strategy, only the base X(0) is passed through _base_decompose, and the error was no longer triggered.
  • I initially tried to fix this by passing the control qubits to the decomposition, but that was a mistake.
  • The final fix: I now explicitly recreate the base gate before the decomposition step and check for this error condition directly, so that the test behaves as expected. Then I create a new base gate to run through the decomposition.

Let me know if you see a cleaner way to handle this — happy to revise it further.

@GiacomoFrn GiacomoFrn requested a review from renatomello June 3, 2025 09:32
@renatomello
Copy link
Contributor

@GiacomoFrn I'm sorry for the delay, I'll revisit this PR tomorrow.

@renatomello
Copy link
Contributor

renatomello commented Jun 8, 2025

@GiacomoFrn I like your solution the best. Can you comment on the issue so I can assign it to you, please? Could you also star our repo?

@renatomello renatomello removed the run-workflow Forces github workflow execution label Jun 8, 2025
@renatomello renatomello added run-workflow Forces github workflow execution and removed run-workflow Forces github workflow execution labels Jun 16, 2025
@renatomello renatomello added run-workflow Forces github workflow execution and removed run-workflow Forces github workflow execution labels Jun 16, 2025
@renatomello renatomello added run-workflow Forces github workflow execution and removed run-workflow Forces github workflow execution labels Jun 16, 2025
@renatomello renatomello added this pull request to the merge queue Jun 16, 2025
Merged via the queue into qiboteam:master with commit 1a83c2b Jun 16, 2025
1 check passed
@renatomello
Copy link
Contributor

BTW @GiacomoFrn: #1659

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working run-workflow Forces github workflow execution unitaryHACK 2025 Issues related to the unitaryHACK 2025

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug when using Gate.decompose on controlled gates

4 participants