question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Help device plugin developers deal with the Operation refactor

See original GitHub issue

Feature details

As was discussed in #2023 with @josh146 and @mariaschuld in the light of the Operation refactor a smooth transition with useful deprecation warnings should be ensured so that device developers have time to update their devices and custom Operations and support at least a few versions of PennyLane.

Currently this has not been fully achieved.

Assume that some third party code (e.g a device plugin) defines a “old style” custom Operation as follows:

import pennylane as qml
from pennylane.operation import Operation

class MyOp(Operation):
    num_wires = 1
    num_params = 2
    par_domain = "R"
    grad_method = "F"

    @staticmethod
    def decomposition(*params, wires):
        qml.RY(params[0], wires=wires[0])
        qml.PauliZ(wires=wires[0])
        qml.RX(params[1], wires=wires[0])

dev = qml.device('default.qubit', wires=1)

@qml.qnode(dev)
def qnode(*params):
    MyOp(*params, wires=0)
    return qml.state()

print(qml.draw(qnode)(0.1, 0.2))
print(qnode(0.1, 0.2))

This works until v0.21.0 but with master the user gets the unspecific error message:

TypeError: decomposition() missing 1 required keyword-only argument: 'wires'

Converting the implementation to “new style” will break the code with all PL versions prior to and including v0.21.0.

This is not nice.

Due to the smart re-naming of functions in #2023 it is indeed possible to define the above operation in a way that is compatible with both the old and the new style:

    def decomposition(self, *params, wires=None):
        if wires is None:
            wires = self.wires
        if not params:
            params = self.parameters
        qml.RY(params[0], wires=wires[0])
        qml.PauliZ(wires=wires[0])
        qml.RX(params[1], wires=wires[0])

Alternatively one can also directly implement the new compute_decomposition() and patch in a suitable preparation() if one is running on an old PL version. The following also works with both 0.21 and the current master:

class MyOp(Operation):
    num_wires = 1
    num_params = 2
    par_domain = "R"
    grad_method = "F"

    if not hasattr(Operation, 'get_eigvals'): # pennylane <= v0.21
        @classmethod
        def decomposition(cls, *params, wires):
            return cls.compute_decomposition(*params, wires=wires)

    @staticmethod
    def compute_decomposition(*params, wires=None):
        qml.RY(params[0], wires=wires[0])
        qml.PauliZ(wires=wires[0])
        qml.RX(params[1], wires=wires[0])

There are of course a few further variants…

It would be nice to replace the above unspecific error message with a useful error that gives a hint for how the implementations can be made compatible across the 0.21/0.22 cut so that plugin developers can at all times support at least some range of PennyLane versions.

Implementation

No response

How important would you say this feature is?

3: Very important! Blocking work.

Additional information

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:27 (27 by maintainers)

github_iconTop GitHub Comments

1reaction
cvjjmcommented, Apr 5, 2022

I can confirm that this works! Awesome! So me and other plugin developers actually have a good update path! Thanks for making this possible!

1reaction
josh146commented, Feb 23, 2022

If we can do the same with generator and settle on the return format of generator before v0.22.0 is released

I plan to have a PR merged before 0.22 that:

  • has a top-level qml.generator() function as the main UI/public API
  • renames generator() to get_generator() temporarily
  • supports both return styles via a keyword argument

It would be nice if compute_matrix and compute_decposition (and decomposition) were “upgraded” to @classmethods

I’ll have to think if there are any implications here - one reason for preferring staticmethods is that we make use of caching (e.g., via @lrucache()) down the line.

because then more complex Operations can call other @classmethods, from those functions which will allow a better structuring of code

I’m not 100% I follow here - are you wishing to call a class method from inside compute_matrix for example? Would you be able to do something like?

@staticmethod
def compute_matrix(*params, wires, **hyperparameters):
    return SomeOperatorClass.a_class_method()
Read more comments on GitHub >

github_iconTop Results From Across the Web

Refactoring Android-specific Energy Smells - Fabio Palomba
For these reasons, an automated energy smell refactoring tool has the potential to be used in practice to help developers dealing with energy...
Read more >
Code Refactoring - What is it and Why is it important?
It helps to keep it consistent, prevent unnecessary duplication of code and standardize the code written by several developers.
Read more >
7 Code Refactoring Techniques in Software Engineering
Red-Green is the most popular and widely used code refactoring technique in the Agile software development process.
Read more >
Code refactoring - Wikipedia
In computer programming and software design, code refactoring is the process of restructuring existing computer code—changing the factoring—without changing ...
Read more >
NVIDIA device plugin for Kubernetes - GitHub
NVIDIA device plugin for Kubernetes. Table of Contents. About; Prerequisites; Quick Start. Preparing your GPU Nodes; Enabling GPU Support in Kubernetes ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found