Skip to content

[Decomposition] Clean up custom logic for adjoint and pow #7352

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

Open
wants to merge 20 commits into
base: symbolic-rules-01
Choose a base branch
from

Conversation

astralcai
Copy link
Contributor

Context:

Description of the Change:

Benefits:

Possible Drawbacks:

Related GitHub Issues:

[sc-90114]

Copy link
Contributor

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

Copy link

codecov bot commented Apr 29, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.65%. Comparing base (8bd5e8f) to head (87a7ea6).

Additional details and impacted files
@@                 Coverage Diff                 @@
##           symbolic-rules-01    #7352    +/-   ##
===================================================
  Coverage              99.65%   99.65%            
===================================================
  Files                    529      529            
  Lines                  50600    50840   +240     
===================================================
+ Hits                   50424    50664   +240     
  Misses                   176      176            

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@astralcai astralcai requested a review from albi3ro May 1, 2025 21:10
Comment on lines -234 to -233
if base_class in same_type_adjoint_ops():
return [same_type_adjoint_decomp]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This branch is now generalized away into operator specific symbolic decomposition rules

Comment on lines -228 to -230
if (
issubclass(base_class, qml.ops.Pow)
and base_params["base_class"] in same_type_adjoint_ops()
):
return [adjoint_pow_decomp]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is removed. There is no reason why we need to switch the order of adjoint and pow such that the adjoint is applied first.

Comment on lines -237 to -239
if (
issubclass(base_class, qml.ops.Controlled)
and base_params["base_class"] in same_type_adjoint_ops()
):
return [adjoint_controlled_decomp]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is also removed. There is no reason why we need to switch the order of ctrl and adjoint such that adjoint is applied first.

try:
decomp_resource = rule.compute_resources(**op_node.params)
d_node_idx = self._recursively_add_decomposition_node(rule, decomp_resource)
self._graph.add_edge(d_node_idx, op_node_idx, 0)
d_node = _DecompositionNode(rule, decomp_resource)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This section is moved from another method.

Comment on lines +273 to +275
# Special case: power of an adjoint
if issubclass(base_class, qml.ops.Adjoint):
return [flip_pow_adjoint]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually apply the pow first, then adjoint, because typically adjoint does not turn the operator into a different type, but pow might. For example, pow(SX, 2) is a PauliX. If we apply the adjoint on the SX first, SX gets decomposed, while we could've just had PauliX.



class AdjointDecomp(DecompositionRule): # pylint: disable=too-few-public-methods
"""The adjoint version of a decomposition rule."""
def make_adjoint_decomp(base_decomposition: DecompositionRule):
Copy link
Contributor Author

@astralcai astralcai May 2, 2025

Choose a reason for hiding this comment

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

This is the same as before. What's previously a subclass is now a method. There was no reason why it had to be a separate class.



@functools.lru_cache(maxsize=1)
def same_type_adjoint_ops():
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is completely removed, generalized to operator-specific adjoint decomposition rules.

@astralcai astralcai requested a review from JerryChen97 May 7, 2025 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant