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 585 forks source link

Error raised when calling `PauliRot` with identity Pauli #856

Closed glassnotes closed 3 years ago

glassnotes commented 3 years ago

Issue description

When calling PauliRot with the all-identity Pauli, an error is thrown when PennyLane tries to perform a decomposition of the operation. This operation technically has no effect except adding a global phase; the context in which this came up was while looping through terms of a Hamiltonian (one of which was identity), and trying to perform e^{-it P} for each Pauli P.

Example:

import pennylane as qml

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

pauli_string = 'II' 

@qml.qnode(dev)
def apply_pauli_rots(rotation_angle):
    qml.Hadamard(wires=0)
    qml.Hadamard(wires=1)
    qml.PauliRot(0.234, pauli_string, wires=range(dev.num_wires))
    return qml.expval(qml.PauliX(1))

print(apply_pauli_rots(0.345))
Version: 0.12.0.dev0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: None
Author-email: None
License: Apache License 2.0
Location: /home/olivia/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages
Requires: scipy, numpy, autograd, semantic-version, appdirs, toml, networkx
Required-by: PennyLane-qiskit, PennyLane-Lightning
Platform info:           Linux-5.3.0-64-generic-x86_64-with-glibc2.10
Python version:          3.8.5
Numpy version:           1.19.2
Scipy version:           1.5.2
Installed devices:
- default.gaussian (PennyLane-0.12.0.dev0)
- default.mixed (PennyLane-0.12.0.dev0)
- default.qubit (PennyLane-0.12.0.dev0)
- default.qubit.autograd (PennyLane-0.12.0.dev0)
- default.qubit.tf (PennyLane-0.12.0.dev0)
- default.tensor (PennyLane-0.12.0.dev0)
- default.tensor.tf (PennyLane-0.12.0.dev0)
- qiskit.aer (PennyLane-qiskit-0.11.0)
- qiskit.basicaer (PennyLane-qiskit-0.11.0)
- qiskit.ibmq (PennyLane-qiskit-0.11.0)
- lightning.qubit (PennyLane-Lightning-0.11.0)

Source code and tracebacks

----------------------------------------------------
ValueError         Traceback (most recent call last)
<ipython-input-27-611f77c1af9c> in <module>
     12     return qml.expval(qml.PauliX(1))
     13 
---> 14 print(apply_pauli_rots(0.345))

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/interfaces/autograd.py in __call__(self, *args, **kwargs)
     67             self.set_trainable(args)
     68             args = autograd.builtins.tuple(args)  # pylint: disable=no-member
---> 69             return self.evaluate(args, kwargs)
     70 
     71         @staticmethod

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/autograd/tracer.py in f_wrapped(*args, **kwargs)
     46             return new_box(ans, trace, node)
     47         else:
---> 48             return f_raw(*args, **kwargs)
     49     f_wrapped.fun = f_raw
     50     f_wrapped._is_autograd_primitive = True

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/base.py in evaluate(self, args, kwargs)
    817 
    818         if self.circuit is None or self.mutable:
--> 819             self._construct(args, kwargs)
    820 
    821         self.device.reset()

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/jacobian.py in _construct(self, args, kwargs)
     87         for each positional parameter.
     88         """
---> 89         super()._construct(args, kwargs)
     90         self.par_to_grad_method = {k: self._best_method(k) for k in self.variable_deps}
     91 

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/base.py in _construct(self, args, kwargs)
    574 
    575         # check the validity of the circuit
--> 576         self._check_circuit(res)
    577         del self.queue
    578         del self.obs_queue

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/base.py in _check_circuit(self, res)
    731         if self.device.operations:
    732             # replace operations in the queue with any decompositions if required
--> 733             queue = decompose_queue(self.queue, self.device)
    734 
    735         self.ops = queue + list(res)

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/base.py in decompose_queue(ops, device)
    123     for op in ops:
    124         try:
--> 125             new_ops.extend(_decompose_queue([op], device))
    126         except NotImplementedError:
    127             raise qml.DeviceError(

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/qnodes/base.py in _decompose_queue(ops, device)
     98             new_ops.append(op)
     99         else:
--> 100             decomposed_ops = op.decomposition(*op.data, wires=op.wires)
    101             if op.inverse:
    102                 decomposed_ops = qml.inv(decomposed_ops)

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/templates/decorator.py in wrapper(*args, **kwargs)
     59     def wrapper(*args, **kwargs):
     60         with OperationRecorder() as rec:
---> 61             func(*args, **kwargs)
     62 
     63         return rec.queue

~/Software/anaconda3/envs/test-xanadu/lib/python3.8/site-packages/pennylane/ops/qubit.py in decomposition(theta, pauli_word, wires)
    925     @template
    926     def decomposition(theta, pauli_word, wires):
--> 927         active_wires, active_gates = zip(
    928             *[(wire, gate) for wire, gate in zip(wires, pauli_word) if gate != "I"]
    929         )

ValueError: not enough values to unpack (expected 2, got 0)
antalszava commented 3 years ago

Nice catch @glassnotes! The logic for both decomposition and _matrix methods assumes that the input string will contain at least one Pauli operator (non-Identity).

glassnotes commented 3 years ago

I think this should be straightforward to fix then, I can give it a go! :+1:

antalszava commented 3 years ago

Great :) It's worth coordinating with @soranjh, as he also started picking up the details here.

glassnotes commented 3 years ago

This has been fixed in #860 :tada: