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

Raise an error or warning in qml.compile if basis_set contains operations instead of strings #6137

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

Conversation

AnuravModak
Copy link
Contributor

Towards #6132

This PR includes the following changes:

If the basis set contains any items that are not strings or subclasses of qml.operation.Operator, a ValueError will be raised. Additionally, if the basis set contains operator types instead of names and results in an empty set, an error will be raised.

Copy link

codecov bot commented Aug 24, 2024

Codecov Report

Attention: Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.

Project coverage is 99.66%. Comparing base (1f55c88) to head (9d212f8).
Report is 27 commits behind head on master.

Files Patch % Lines
pennylane/transforms/compile.py 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6137      +/-   ##
==========================================
- Coverage   99.67%   99.66%   -0.02%     
==========================================
  Files         432      445      +13     
  Lines       41839    42363     +524     
==========================================
+ Hits        41702    42220     +518     
- Misses        137      143       +6     

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

Signed-off-by: Anurav Modak <[email protected]>
Signed-off-by: Anurav Modak <[email protected]>
Signed-off-by: Anurav Modak <[email protected]>
Signed-off-by: Anurav Modak <[email protected]>
@AnuravModak AnuravModak force-pushed the addWarningErrorInqmlbasisState branch from ddb8c08 to 4ec8cbe Compare August 25, 2024 17:33
Signed-off-by: Anurav Modak <[email protected]>
@AnuravModak AnuravModak force-pushed the addWarningErrorInqmlbasisState branch from c358d6e to bbc1c4d Compare August 26, 2024 16:19
@AnuravModak
Copy link
Contributor Author

Hey @albi3ro , i have added the required code changes and mandatory tests, to throw an error for the prescribed scenario, kindly review it and let me know if any thing else has to be done on coding or implementation part!

@albi3ro
Copy link
Contributor

albi3ro commented Aug 26, 2024

Thanks for opening this PR @AnuravModak .

Sorry if there was confusion on the issue, but we don't currently support to contain operator types like:

qml.compile(circuit, basis_set={qml.X, qml.Y, qml.Z, qml.RX, qml.RY, qml.RZ})

Part of the suggestion was to start allowing such a syntax. Do you think you could expand the scope of the PR to include that change? If not, we should also raise an error if basis_set includes operator types.

Signed-off-by: Anurav Modak <[email protected]>
@AnuravModak AnuravModak force-pushed the addWarningErrorInqmlbasisState branch from 6185640 to 9d212f8 Compare August 27, 2024 16:05
@AnuravModak
Copy link
Contributor Author

Hey @albi3ro , thanks for clarifying!
Now i have made the necessary changes allowing such syntax:

Now the compile transform will handle both operation names and types within the basis_set.
Also the tests i have written checks this by using a simple quantum function with an RX operation. By setting the basis_set to ["RX"], the test ensures that the compile transform correctly stops at the RX operation and doesn't alter it, validating that our changes work as expected.

let me know if it matches your expectations!

@albi3ro
Copy link
Contributor

albi3ro commented Aug 27, 2024

Looks like it still doesn't accept class types as a valid way of specifying the basis set. Maybe we should limit the scope to just validating that the basis set only contains strings, and then do a follow up with the new feature allowing the specification of the basis set via class types.

The feature we are looking for would be allowing:

tape = qml.tape.QuantumScript([qml.Rot(1.2, 2.3, 3.4, 0)], [qml.probs()])
qml.compile(tape, basis_set=[qml.RX, qml.RY, qml.RZ])

Which we would expect to decompose the Rot into RY and RZ operations.

Signed-off-by: Anurav Modak <[email protected]>
@AnuravModak
Copy link
Contributor Author

Looks like it still doesn't accept class types as a valid way of specifying the basis set. Maybe we should limit the scope to just validating that the basis set only contains strings, and then do a follow up with the new feature allowing the specification of the basis set via class types.

The feature we are looking for would be allowing:

tape = qml.tape.QuantumScript([qml.Rot(1.2, 2.3, 3.4, 0)], [qml.probs()])
qml.compile(tape, basis_set=[qml.RX, qml.RY, qml.RZ])

Which we would expect to decompose the Rot into RY and RZ operations.

Hi @albi3ro ,

I think my new changes may align closer to your requrements:

Handling Class Types in basis_set:

  1. The code now checks if elements in the basis_set are either string-based names or operator class types.
  2. It converts the class types into their corresponding operation names and merges them with any string-based names.

Stopping Condition:
The stopping condition in stop_at now correctly checks whether an operation matches the names or types specified in basis_set

Now also i have deployed the code in my local and have tested it!

Let me know if the results are right or not!


def test_empty_basis_set():
    # Define a quantum tape with a Rot gate
    tape = qml.tape.QuantumScript([qml.Rot(1.2, 2.3, 3.4, 0)], [qml.probs()])

    # Create a basis set with only invalid types (e.g., an integer and a float)
    invalid_basis_set = [123, 4.56]

    try:
        # Attempt to compile with an invalid basis_set, expecting a ValueError
        qml.compile(tape, basis_set=invalid_basis_set)
    except ValueError as e:
        # Print the error message to confirm it was raised
        print("Caught expected ValueError:", e)

# Run the test
test_empty_basis_set()

output:

Caught expected ValueError: basis_set contains no valid operation names or types.

Or should i just simply implement this change that you have suggested?

class_types = tuple(o for o in basis_set if isinstance(o, type)
class_names = set(o for o in basis_set if isinstance(o, str))
def stopping_condition(obj):
    return obj.name in class_names or isinstance(obj, class_types)

@albi3ro albi3ro self-requested a review September 10, 2024 13:39
Copy link
Contributor

@albi3ro albi3ro left a comment

Choose a reason for hiding this comment

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

Sorry about not getting back to this quickly.

The code looks great!

For the tests, can we write a unit test for tape in -> batch, fn out? We would also want tests where the basis set is specified via types, and unit tests for the error if the basis set is invalid. The test should also cover an input tape that contains operations that should be decomposed.

Tests on the qnode/ qfunc can tend to hide a lot of incorrect behavior, since compile does not change the result output. And in this case, we aren't even checking the value of the output. So a lot can go wrong between executing the qnode and still getting a float out. I've seen this testing anti-pattern hide a lot of bugs.

Also, the basis set in the test includes all of the operations in the qfunc. It doesn't actually check that operations outside that basis set get decomposed. We could want to make sure something like CRX gets decomposed before the other compilation transforms get applied.

Hope that clarifies things.

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.

2 participants