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

[BUG] Discrepancy between quantum_fisher and adjoint_metric_tensor depending on angle order #6345

Closed
1 task done
joeybarreto opened this issue Oct 4, 2024 · 3 comments · Fixed by #6350
Closed
1 task done
Labels
bug 🐛 Something isn't working

Comments

@joeybarreto
Copy link

joeybarreto commented Oct 4, 2024

Expected behavior

For a given circuit, I would expect that computing the QFIM via either quantum_fisher or adjoint_metric_tensor gives the same result, since according to here, quantum_fisher is supposed to default to adjoint_metric_tensor when shots=None and the device is default.qubit.

Given the circuit below, I can pass in an array angles and draw from its angles in one of two orderings:

  • $a[0], a[1], a[2], a[3], ..., a[N-1]$
  • $a[0], a[N/2], a[1], a[N/2 + 1], ... a[N/2 - 1], a[N-1]$
dev = qml.device("default.qubit", wires=1)
@qml.qnode(dev)
def qnode(angles, alternate=False):
    if alternate:
        thetas = angles[:len(angles)//2]
        phis = angles[len(angles)//2:]
        for ia in range(len(thetas)):
            qml.RY(thetas[ia], wires=0)
            qml.RZ(phis[ia], wires=0)
    else:
        for ia in range(0,len(angles),2):
            qml.RY(angles[ia], wires=0)
            qml.RZ(angles[ia+1], wires=0)
            
    return qml.expval(qml.PauliZ(0))

Actual behavior

I compute 4 different tests, using the two different orderings and two different QFIM functions:

pnp.random.seed(42)
angles = pnp.random.uniform(0, 2 * pnp.pi, 8)

qfim1 = qml.gradients.quantum_fisher(qnode)(angles, alternate=False)
qfim2 = 4*qml.adjoint_metric_tensor(qnode)(angles, alternate=False)
qfim3 = qml.gradients.quantum_fisher(qnode)(angles, alternate=True)
qfim4 = 4*qml.adjoint_metric_tensor(qnode)(angles, alternate=True)
qfims = [qfim1, qfim2, qfim3, qfim4]

check = np.zeros((4,4))
for i in range(4):
    for j in range(4):
        check[i,j] = np.linalg.norm(qfims[i]-qfims[j])
print(check)

The print statements return

[[0.         0.         4.49659944 5.33189179]
 [0.         0.         4.49659944 5.33189179]
 [4.49659944 4.49659944 0.         4.14895957]
 [5.33189179 5.33189179 4.14895957 0.        ]]

I find that when the ordering is alternate=False, i.e. when the order of the angles as-is matches the order in which they are actually applied/recorded on the qtape, then quantum_fisher returns the same matrix as adjoint_metric_tensor (up to a factor of 4, as expected). However, when the angles are alternating, the two QFIMs (i.e. qfim3 and qfim4 below) do not agree, and neither of these equal the alternate=False case. I suspect that one of these functions only respects the ordering on the qtape after the circuit has been built (which I think is the intended behavior), but the other is still aware of the original ordering of the input. And if that were the case, then whichever function respected the ordering of the original input should (I think) return the same QFIM as in the first case, since the circuit structure and input is the same across all 4 cases. For context, I am trying to study certain sub-blocks of the QFIM, so knowing which angles correspond to which row/column indices in the QFIM is important.

Additional information

No response

Source code

No response

Tracebacks

No response

System information

Name: PennyLane
Version: 0.38.0
Summary: 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.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /Users/joey/miniconda3/envs/lanl/lib/python3.12/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, toml, typing-extensions
Required-by: PennyLane_Lightning

Platform info:           macOS-14.4.1-arm64-arm-64bit
Python version:          3.12.6
Numpy version:           1.26.4
Scipy version:           1.14.1
Installed devices:
- lightning.qubit (PennyLane_Lightning-0.38.0)
- default.clifford (PennyLane-0.38.0)
- default.gaussian (PennyLane-0.38.0)
- default.mixed (PennyLane-0.38.0)
- default.qubit (PennyLane-0.38.0)
- default.qubit.autograd (PennyLane-0.38.0)
- default.qubit.jax (PennyLane-0.38.0)
- default.qubit.legacy (PennyLane-0.38.0)
- default.qubit.tf (PennyLane-0.38.0)
- default.qubit.torch (PennyLane-0.38.0)
- default.qutrit (PennyLane-0.38.0)
- default.qutrit.mixed (PennyLane-0.38.0)
- default.tensor (PennyLane-0.38.0)
- null.qubit (PennyLane-0.38.0)

Existing GitHub issues

  • I have searched existing GitHub issues to make sure the issue does not already exist.
@joeybarreto joeybarreto added the bug 🐛 Something isn't working label Oct 4, 2024
@dwierichs
Copy link
Contributor

dwierichs commented Oct 7, 2024

Hi @joeybarreto, thanks for the bug report!
here's what I found

  • I do not quite understand why you expect the alternate=True and alternate=False circuits to have the same QFIM? They correspond to different circuits, no?
  • For alternate=True there indeed seems to be some discrepancy between adjoint_metric_tensor and quantum_fisher. I will look into that in detail.

edit
The main bug is that quantum_fisher does not use a classical cotransform, but adjoint_metric_tensor does.
It seems to be fixed by setting the cotransform, see #6350 .

edit 2
With the bugfix PR, the test matrix looks like this:

[[0.         0.         2.02730729 2.02730729]
 [0.         0.         2.02730729 2.02730729]
 [2.02730729 2.02730729 0.         0.        ]
 [2.02730729 2.02730729 0.         0.        ]]

which is what I would expect. The methods are consistent between each other for the same value of alternate, but the circuits differ between values of alternate.

@joeybarreto
Copy link
Author

Hi @dwierichs, thanks for checking this! I don't expect the alternate=True and alternate=False cases to agree in general, but in this scenario I speculated that one qfim could be permuted to obtain the other, although now I see that that's not possible.

@dwierichs
Copy link
Contributor

Hi @joeybarreto,
ah, sorry, I misread the part about your expectation for the buggy function, it's clear to me now!
Thanks again for the bug report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants