Error in Quantum Fisher information with noise

I want to calculate the Quantum Fisher Information (QFI) for the density matrix of a circuit that includes noise components. However, I encountered an error, which I suspect is due to the presence of mixed states. Is there a way to accurately compute the QFI in this context?

# import pennylane as qml
from pennylane import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

dev = qml.device("default.mixed", wires=2)
@qml.qnode(dev)
def circ(params):
    qml.RY(params[0], wires=1)
    qml.CNOT(wires=(1,0))
    qml.RY(params[1], wires=1)
    qml.RZ(params[2], wires=1)
    qml.PhaseFlip(1-p,wires=0)
    qml.PhaseFlip(1-p,wires=1)
    return qml.density_matrix(wires=[0,1])
params=np.random.uniform(0,1,3)
p=0.5
qfim = qml.qinfo.quantum_fisher(circ)(params)

Error Message full error message below:

# Put full error message here
```MatrixUndefinedError                      Traceback (most recent call last)
Cell In[11], line 1
----> 1 qfim = qml.qinfo.quantum_fisher(circ)(params)

File /opt/conda/lib/python3.10/site-packages/pennylane/qnode.py:1039, in QNode.__call__(self, *args, **kwargs)
   1034         full_transform_program._set_all_argnums(
   1035             self, args, kwargs, argnums
   1036         )  # pylint: disable=protected-access
   1038 # pylint: disable=unexpected-keyword-arg
-> 1039 res = qml.execute(
   1040     (self._tape,),
   1041     device=self.device,
   1042     gradient_fn=self.gradient_fn,
   1043     interface=self.interface,
   1044     transform_program=full_transform_program,
   1045     config=config,
   1046     gradient_kwargs=self.gradient_kwargs,
   1047     override_shots=override_shots,
   1048     **self.execute_kwargs,
   1049 )
   1051 res = res[0]
   1053 # convert result to the interface in case the qfunc has no parameters

File /opt/conda/lib/python3.10/site-packages/pennylane/interfaces/execution.py:635, in execute(tapes, device, gradient_fn, interface, transform_program, config, grad_on_execution, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform, device_vjp)
    632     tapes, post_processing = transform_program(tapes)
    633 else:
    634     # TODO: Remove once old device are removed
--> 635     tapes, program_post_processing = transform_program(tapes)
    636     tapes, program_pre_processing, config = _batch_transform(
    637         tapes, device, config, override_shots, device_batch_transform
    638     )
    640     def post_processing(results):

File /opt/conda/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py:435, in TransformProgram.__call__(self, tapes)
    433 if self._argnums is not None and self._argnums[i] is not None:
    434     tape.trainable_params = self._argnums[i][j]
--> 435 new_tapes, fn = transform(tape, *targs, **tkwargs)
    436 execution_tapes.extend(new_tapes)
    438 fns.append(fn)

File /opt/conda/lib/python3.10/site-packages/pennylane/qinfo/transforms.py:748, in quantum_fisher(tape, device, *args, **kwargs)
    744         return 4 * processing_fn(res)
    746     return tapes, processing_fn_multiply
--> 748 res = adjoint_metric_tensor(tape, *args, **kwargs)
    750 def processing_fn_multiply(r):  # pylint: disable=function-redefined
    751     r = qml.math.stack(r)

File /opt/conda/lib/python3.10/site-packages/pennylane/transforms/core/transform_dispatcher.py:112, in TransformDispatcher.__call__(self, *targs, **tkwargs)
    109         transformed_tapes, processing_fn = self._transform(obj, *targs, **tkwargs)
    111     if self.is_informative:
--> 112         return processing_fn(transformed_tapes)
    113     return transformed_tapes, processing_fn
    115 if isinstance(obj, qml.QNode):

File /opt/conda/lib/python3.10/site-packages/pennylane/gradients/adjoint_metric_tensor.py:227, in adjoint_metric_tensor.<locals>.processing_fn(tapes)
    225     psi = qml.devices.qubit.apply_operation(outer_op, psi)
    226     for op in group_after_trainable_op[j]:
--> 227         psi = qml.devices.qubit.apply_operation(op, psi)
    229 # postprocessing: combine L and T into the metric tensor.
    230 # We require outer(conj(T), T) here, but as we skipped the factor 1j above,
    231 # the stored T is real-valued. Thus we have -1j*1j*outer(T, T) = outer(T, T)
    232 metric_tensor = L - qml.math.tensordot(T, T, 0)

File /opt/conda/lib/python3.10/functools.py:889, in singledispatch.<locals>.wrapper(*args, **kw)
    885 if not args:
    886     raise TypeError(f'{funcname} requires at least '
    887                     '1 positional argument')
--> 889 return dispatch(args[0].__class__)(*args, **kw)

File /opt/conda/lib/python3.10/site-packages/pennylane/devices/qubit/apply_operation.py:198, in apply_operation(op, state, is_state_batched, debugger)
    150 @singledispatch
    151 def apply_operation(
    152     op: qml.operation.Operator, state, is_state_batched: bool = False, debugger=None
    153 ):
    154     """Apply and operator to a given state.
    155 
    156     Args:
   (...)
    196 
    197     """
--> 198     return _apply_operation_default(op, state, is_state_batched, debugger)

File /opt/conda/lib/python3.10/site-packages/pennylane/devices/qubit/apply_operation.py:208, in _apply_operation_default(op, state, is_state_batched, debugger)
    202 """The default behaviour of apply_operation, accessed through the standard dispatch
    203 of apply_operation, as well as conditionally in other dispatches."""
    204 if (
    205     len(op.wires) < EINSUM_OP_WIRECOUNT_PERF_THRESHOLD
    206     and math.ndim(state) < EINSUM_STATE_WIRECOUNT_PERF_THRESHOLD
    207 ) or (op.batch_size and is_state_batched):
--> 208     return apply_operation_einsum(op, state, is_state_batched=is_state_batched)
    209 return apply_operation_tensordot(op, state, is_state_batched=is_state_batched)

File /opt/conda/lib/python3.10/site-packages/pennylane/devices/qubit/apply_operation.py:72, in apply_operation_einsum(op, state, is_state_batched)
     60 def apply_operation_einsum(op: qml.operation.Operator, state, is_state_batched: bool = False):
     61     """Apply ``Operator`` to ``state`` using ``einsum``. This is more efficent at lower qubit
     62     numbers.
     63 
   (...)
     70         array[complex]: output_state
     71     """
---> 72     mat = op.matrix()
     74     total_indices = len(state.shape) - is_state_batched
     75     num_indices = len(op.wires)

File /opt/conda/lib/python3.10/site-packages/pennylane/operation.py:785, in Operator.matrix(self, wire_order)
    765 def matrix(self, wire_order=None):
    766     r"""Representation of the operator as a matrix in the computational basis.
    767 
    768     If ``wire_order`` is provided, the numerical representation considers the position of the
   (...)
    783         tensor_like: matrix representation
    784     """
--> 785     canonical_matrix = self.compute_matrix(*self.parameters, **self.hyperparameters)
    787     if wire_order is None or self.wires == Wires(wire_order):
    788         return canonical_matrix

File /opt/conda/lib/python3.10/site-packages/pennylane/operation.py:754, in Operator.compute_matrix(*params, **hyperparams)
    738 @staticmethod
    739 def compute_matrix(*params, **hyperparams):  # pylint:disable=unused-argument
    740     r"""Representation of the operator as a canonical matrix in the computational basis (static method).
    741 
    742     The canonical matrix is the textbook matrix representation that does not consider wires.
   (...)
    752         tensor_like: matrix representation
    753     """
--> 754     raise MatrixUndefinedError

MatrixUndefinedError: 
And, finally, make sure to include the versions of your packages. Specifically, show us the output of `qml.about()`. 

Name: PennyLane
Version: 0.34.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /opt/conda/lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane-Lightning

Platform info:           Linux-4.14.336-253.554.amzn2.x86_64-x86_64-with-glibc2.35
Python version:          3.10.13
Numpy version:           1.26.2
Scipy version:           1.11.4
Installed devices:
- lightning.qubit (PennyLane-Lightning-0.34.0)
- default.gaussian (PennyLane-0.34.0)
- default.mixed (PennyLane-0.34.0)
- default.qubit (PennyLane-0.34.0)
- default.qubit.autograd (PennyLane-0.34.0)
- default.qubit.jax (PennyLane-0.34.0)
- default.qubit.legacy (PennyLane-0.34.0)
- default.qubit.tf (PennyLane-0.34.0)
- default.qubit.torch (PennyLane-0.34.0)
- default.qutrit (PennyLane-0.34.0)
- null.qubit (PennyLane-0.34.0)

Hey @Aaqib_Ali,

I’ll have to get back to you! Need to investigate :male_detective:

Thanks isaac , i am waiting for your response

Hi Issac is there any solution …

:sob:Its a long long wait

Hey @Aaqib_Ali, there’s a national holiday here in Canada today, so we will be able to respond to you by tomorrow at the earliest. Thank you for your patience!

1 Like

Hey @Aaqib_Ali, I think this is a bug :bug:. Theoretically this should work. Would you mind making a bug report on our github repository? Here’s the link you can use:

v0.35 is going to be released in March, so I can’t guarantee that a bug fix will be included in v0.35 (most likely it will be v0.36). But, when you make a bug report we’ll post updates there and if there’s a fix you can install PennyLane from source to access the fix :slight_smile:. Write back to me here if that happens!