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

Update cancel_inverses to have better support for Adjoint #6752

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

mudit2812
Copy link
Contributor

@mudit2812 mudit2812 commented Jan 2, 2025

Context:
cancel_inverses does not cancel Adjoint ops if the ops to be cancelled are symmetric on all wires. This PR fixes that, and also cleans up the code in cancel_inverses.py a bit.

Description of the Change:

  • Remove check from _ops_equal for wires as we check for wire equality/symmetry later.
  • Move cancellation logic into helper _can_cancel_ops function, which can be used by both cancel_inverses and CancelInversesInterpreter.

Benefits:
cancel_inverses is better at cancelling Adjoint ops.

Possible Drawbacks:

Related GitHub Issues:
#6729
[sc-80821]

Copy link

codecov bot commented Jan 2, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.60%. Comparing base (37abd58) to head (1b9d43a).
Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6752      +/-   ##
==========================================
- Coverage   99.60%   99.60%   -0.01%     
==========================================
  Files         476      476              
  Lines       45210    45196      -14     
==========================================
- Hits        45033    45019      -14     
  Misses        177      177              

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

@andrijapau andrijapau self-requested a review January 3, 2025 15:06
Comment on lines 33 to 38
"""Checks if two operators are equal up to class, data, and hyperparameters"""
return (
op1.__class__ is op2.__class__
and (op1.data == op2.data)
and (op1.hyperparameters == op2.hyperparameters)
and (op1.wires == op2.wires)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we just use qml.equal now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

qml.equal checks for wire equality as well, we want to compare all attributes except for wires.

Copy link
Contributor

Choose a reason for hiding this comment

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

Potentially rename this function to _non_wires_equality?

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we instead update our definition of "equal" to take into consideration operations that are symmetric?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the name of the function locally.

Should we instead update our definition of "equal" to take into consideration operations that are symmetric?

I feel like this is a tangential discussion to object vs numerical equality. It certainly shouldn't be hard to integrate wire symmetry into qml.equal since we already have Attributes containing a set of such ops. Maybe worth including more people in this discussion. Could be a potential "good first issue" if we decide it's worthwhile.

@PietropaoloFrisoni PietropaoloFrisoni added this to the v0.40 milestone Jan 3, 2025
@mudit2812 mudit2812 requested a review from albi3ro January 3, 2025 16:03
Copy link
Contributor

@andrijapau andrijapau left a comment

Choose a reason for hiding this comment

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

I can't comment on that part of the file for some reason but the example in the transform docstring could be updated as well.

import pennylane as qml

@qml.transforms.cancel_inverses
@qml.qnode(device=qml.device('default.qubit'))
def circuit(x, y, z):
    qml.Hadamard(wires=0)
    qml.Hadamard(wires=1)
    qml.Hadamard(wires=0)
    qml.RX(x, wires=2)
    qml.RY(y, wires=1)
    qml.X(1)
    qml.RZ(z, wires=0)
    qml.RX(y, wires=2)
    qml.CNOT(wires=[0, 2])
    qml.X(1)
    return qml.expval(qml.Z(0))

>>> circuit(0.1, 0.2, 0.3)
1.0
# 0.999999999 in the example

doc/releases/changelog-dev.md Outdated Show resolved Hide resolved
are_inverses_without_wires = (
isinstance(op2, Adjoint)
and op1.__class__ == op2.base.__class__
and op1.data == op2.base.data
Copy link
Contributor

Choose a reason for hiding this comment

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

How is this not raising errors? I'm actually a bit hesitant about directly comparing numeric data like this.

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 don't have a lot of interface testing for cancel_inverses, but using equality for floating point data is fine as long as any arithmetic ops aren't applied to the data. The only issue I see with the use of == is that we will not have any tolerance for comparison, leading to potentially cancellable ops not being cancelled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we can add a tol parameter to cancel_inverses for comparing numerical data. 🤔

@PietropaoloFrisoni
Copy link
Contributor

@mudit2812 I added this PR in the 0.40 milestone last week, assuming it will be part of PL 0.40. If so, can you please change the target branch to the rc branch? Instead, if that is not the case, can you please remove this PR from the milestone? Thanks!

@mudit2812
Copy link
Contributor Author

mudit2812 commented Jan 6, 2025

@PietropaoloFrisoni Since it's feature freeze, I'll move it out of the 0.40 milestone.

@mudit2812 mudit2812 removed this from the v0.40 milestone Jan 6, 2025
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.

[BUG] cancel_inverses does not cancel adjoint operators with different wire order that are symmetric on wires
4 participants