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

Add pauli_rep properties for common static gates #6243

Open
dwierichs opened this issue Sep 9, 2024 · 7 comments
Open

Add pauli_rep properties for common static gates #6243

dwierichs opened this issue Sep 9, 2024 · 7 comments
Labels
enhancement ✨ New feature or request

Comments

@dwierichs
Copy link
Contributor

Feature details

The pauli_rep property allows to represent an operator as a PauliSentence instance.
Currently, it is mostly implemented for qml.X, qml.Y, qml.Z and for operator math classes.
It would be great to have pauli_rep attributes for, e.g., Clifford gates (Hadamard, S, CNOT), but also for other ops.
This would simplify manipulation of qml.pauli objects.

This came up while writing this demo, where we currently have to do

new_op = qml.CNOT([0, 1]) @ original_op @ qml.CNOT([0, 1])
new_op = qml.pauli_decompose(new_op.matrix())

i.e., we have to go via the dense matrix representation to obtain the new operator. With qml.CNOT.pauli_rep implemented, we could stay in the more efficient Pauli representation.

Implementation

Basically trivial, as far as I can tell.

How important would you say this feature is?

1: Not important. Would be nice to have.

Additional information

No response

@dwierichs dwierichs added the enhancement ✨ New feature or request label Sep 9, 2024
@ldi18
Copy link

ldi18 commented Nov 4, 2024

Hi, I’d like to work on this issue as my first contribution.

ldi18 pushed a commit to ldi18/pennylane-with-more-pauli-decomps that referenced this issue Nov 5, 2024
@dwierichs
Copy link
Contributor Author

Hi @ldi18,
That's great to hear!
Let me start an internal discussion to see which operators should be included in this, and which constraints might apply.
I'll get back to you asap.

@dwierichs
Copy link
Contributor Author

Hey @ldi18
we'd be happy for you to contribute this feature.
I think a nice goal could be to include a Pauli representation for all gates in pennylane/ops/qubit/non_parametric_ops.py, and if you'd like you could also tackle pennylane/ops/qubit/parametric_ops_single_qubit.py.
After discussing internally, it would be favourable to evaluate the Pauli representations lazily, i.e., only when they are needed and not when the Operation is created, in order to avoid overhead for unrelated workflows.
Let me know in case you require any help with this. :)
As this is your first contribution, it will probably be helpful to take a look at our how-to-PR page.

@ldi18
Copy link

ldi18 commented Nov 7, 2024

Hi @dwierichs ,
I implemented Pauli representations for all ops in non_parametric_ops and parametric_ops_single_qubit as for the Hadamard gate here:

@property
def _pauli_rep(self):
    if self._pauli_rep_cached is None:
        self._pauli_rep_cached = qml.pauli.PauliSentence(
            {
                qml.pauli.PauliWord({self.wires[0]: "X"}): INV_SQRT2,
                qml.pauli.PauliWord({self.wires[0]: "Z"}): INV_SQRT2,
            }
        )
    return self._pauli_rep_cached

def __init__(self, wires: WiresLike, id: Optional[str] = None):
    super().__init__(wires=wires, id=id)
    self._pauli_rep_cached = None

I defined the test

def test(gate):
    dim = gate.matrix().shape[0]
    if dim == 2:
        id_str = 'I(0)'
    if dim == 4:
        id_str = 'I(0)@I(1)'
    gate_in_pauli_decomp = eval(str(gate.pauli_rep).replace('\n', ' ').replace('I', id_str)).matrix()
    return np.allclose(gate.matrix(), gate_in_pauli_decomp)

All ops pass the test, but only if I comment out the assignment in the operator constructor as shown below:

class Operator(abc.ABC, meta class=ABCCaptureMeta):
...
...
    def __init__(
        self,
        *params: TensorLike,
        wires: Optional[WiresLike] = None,
        id: Optional[str] = None,
    ):
        # pylint: disable=too-many-branches

        self._name: str = self.__class__.__name__  #: str: name of the operator
        self._id: str = id
        
        # Can this be commented out?
        # self._pauli_rep: Optional[qml.pauli.PauliSentence] = (
        #     None  # Union[PauliSentence, None]: Representation of the operator as a pauli sentence, if applicable
        # )
...
...)

Would it cause any issues elsewhere when I just remove the part I commented out above? To check this I tried running the tests as described in https://docs.pennylane.ai/en/stable/development/guide/tests.html . Actually this returns 11 errors, even for the current version in the GitHub - without any changes from me.

Is this a problem with my testing environment or just normal? I'd just create a pull request now so that you can have a look.

@dwierichs
Copy link
Contributor Author

dwierichs commented Nov 7, 2024

Hi @ldi18
That sounds great!
So we do not want to have any breaking change with the Operator API here. What I would suggest is trying to modify (instead of remove) the logic in Operator such that it is more permissive and allows you to do what you are already doing with the newly added (nice and lazy :) ) method. Probably you want to overwrite the property pauli_rep rather than _pauli_rep, no? :)
Then you can also just use the existing _pauli_rep attribute instead of _pauli_rep_cached

ldi18 pushed a commit to ldi18/pennylane-with-more-pauli-decomps that referenced this issue Nov 9, 2024
ldi18 pushed a commit to ldi18/pennylane-with-more-pauli-decomps that referenced this issue Nov 10, 2024
@ldi18
Copy link

ldi18 commented Nov 10, 2024

Hi @dwierichs,

Thanks for the hint! Using pauli_rep resolved the issue in the operator class. During testing, however, test_parametric_ops:TestDecompositions:test_pc_phase_decomposition_broadcasted resulted in a shape error. Using an outer product in pauli_arithmetic.py for tensor-like phases (as in my pull request) would fix this.

My changes pass all pytest checks. Pylint still shows a few errors/warnings related to the number of parameters, but many of these also appear in the developer version without any changes from me.

@dwierichs
Copy link
Contributor Author

Hi @ldi18 ,
Nice, happy to hear this worked.
At this point it's probably best to open the pull request :)
Then we can chat concretely about more nichy test failures and CI checks like pylint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ✨ New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants