PennyLaneAI / pennylane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
https://pennylane.ai
Apache License 2.0
2.27k stars 586 forks source link

[BUG] Incorrect expval from `Tensor` on same wire #2866

Closed meenu-kri closed 2 years ago

meenu-kri commented 2 years ago

Expected behavior

The expectation value of qml.PauliZ(0)@qml.PauliZ(0) should always be 1 as the square of PauliZ operator is identity.

Actual behavior

The output of qml.expval(qml.PauliZ(0)@qml.PauliZ(0)) (with as well as without shots) for state|1> is -1.

Additional information

No response

Source code

import pennylane as qml

dev = qml.device('default.qubit',shots=100,wires=3)

@qml.qnode(dev)               
def my_circ():                
        qml.PauliX(0)
        return qml.expval(qml.PauliZ(0)@qml.PauliZ(0))

print("Result of my_circ() is:", my_circ())

>>> Result of my_circ() is: -1.0

Tracebacks

No response

System information

Name: PennyLane
Version: 0.25.0.dev0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /Users/mkumari/qml/pennylane
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, retworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning
Platform info:           macOS-10.16-x86_64-i386-64bit
Python version:          3.8.3
Numpy version:           1.23.1
Scipy version:           1.8.1
Installed devices:
- lightning.qubit (PennyLane-Lightning-0.24.0)
- default.gaussian (PennyLane-0.25.0.dev0)
- default.mixed (PennyLane-0.25.0.dev0)
- default.qubit (PennyLane-0.25.0.dev0)
- default.qubit.autograd (PennyLane-0.25.0.dev0)
- default.qubit.jax (PennyLane-0.25.0.dev0)
- default.qubit.tf (PennyLane-0.25.0.dev0)
- default.qubit.torch (PennyLane-0.25.0.dev0)

Existing GitHub issues

CatalinaAlbornoz commented 2 years ago

Hi @meenu-kri, thanks for reporting this. If you used qml.PauliZ(0) in the circuit, as a gate, surely applying it twice would give the identity. However here we're doing a measurement and you shouldn't be able to make multiple measurements on the same wire. In any case this is something that we should look into. Thank you for reporting it!

Jaybsoni commented 2 years ago

This is another manifestation of the assumption that the tensor class does not represent / support representing matrix composition. The explicit source of this can be found in operations.py, in the eigvals method of the Tensor class. Notice that the method doesn't perform any product calculation of the eigvals, it simply concatenates the eigvals of the pauli observables which act on different wires. For this reason the eigvals remain [1, -1].

We are currently working on a new class which will represent the product of two operators in general; such class will address these issues with a more permanent fix. I think the best fix for this would be to add a warning in the documentation or raise a warning telling the user that such behaviour exists and that it will be addressed by a new object to come.

Let me know if you have any other questions or clarifications 👍🏼

AlbertMitjans commented 2 years ago

Hi @meenu-kri, in the last commits to master we added the capability of using the new operator arithmetic classes as observables. Thus now you can do:

import pennylane as qml

dev = qml.device('default.qubit',shots=100,wires=3)

@qml.qnode(dev)               
def my_circ():                
        qml.PauliX(0)
        return qml.expval(qml.prod(qml.PauliZ(0), qml.PauliZ(0)))

print("Result of my_circ() is:", my_circ())
Result of my_circ() is: 1.0