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] StatePrep adjoint does not properly uncompute state #5099

Closed
1 task done
anthonysmaldone opened this issue Jan 24, 2024 · 4 comments
Closed
1 task done

[BUG] StatePrep adjoint does not properly uncompute state #5099

anthonysmaldone opened this issue Jan 24, 2024 · 4 comments
Labels
bug 🐛 Something isn't working

Comments

@anthonysmaldone
Copy link

Expected behavior

I expected that when I apply StatePrep to the ground state to prepare some arbitrary state, that qml.adjoint(qml.StatePrep)) will return me back to ground state with a phase angle of 0.

Actual behavior

The adjoint of StatePrep is off by a global.

Additional information

I need to perform the adjoint of StatePrep while being controlled by an ancilla qubit, so the global phase offset manifests into a problem. Manually adding a phase gate that corrects the phase with respect to the number of negative amplitudes in original state works, but leaves the circuit un-batchable.

Functional example that does not allow batching:

import pennylane as qml

state = np.array([-0.5, 0.2, 0.3, 0.9, 0.5, 0.2, 0.3, 0.9], requires_grad=True)
state = state / np.linalg.norm(state)

test = qml.device('default.qubit', wires=3)
@qml.qnode(test)
def test_circ(state):
    qml.StatePrep(state=state,wires=[0,1,2])
    qml.adjoint(qml.StatePrep(state=state,wires=[0,1,2]))
    #count the number of negative amplitudes in the initial state
    #to know how to adjust the global phase
    ang = np.sum(state < 0)/(state.shape[-1]) * np.pi
    
    qml.RZ(phi=ang*2)
    #qml.GlobalPhase(phi=ang)

    return qml.state()

Source code

import pennylane as qml

state = np.array([-0.5, 0.2, 0.3, 0.9, 0.5, 0.2, 0.3, 0.9], requires_grad=True)
state = state / np.linalg.norm(state)

test = qml.device('default.qubit', wires=3)

@qml.qnode(test)
def test_circ(state):
    qml.StatePrep(state=state,wires=[0,1,2])
    qml.adjoint(qml.StatePrep(state=state,wires=[0,1,2]))
    # optionally apply some RZ shift to correct the phase offset
    # in this specific case, it is off by pi/8
    # qml.RZ(phi=np.pi/4,wires=0)

    return qml.state()

print(test_circ(state))

Tracebacks

Output:
[ 9.23879533e-01+3.82683432e-01j -9.68859404e-18+5.12040449e-17j
  1.96261557e-16+1.27570012e-16j  1.70680150e-17+2.90657821e-17j
 -1.11022302e-16+0.00000000e+00j  9.68859404e-18-9.68859404e-18j
  3.92523115e-17-9.81307787e-18j -1.70680150e-17+1.70680150e-17j]

System information

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: /usr/local/lib/python3.10/dist-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-6.1.58+-x86_64-with-glibc2.35
Python version:          3.10.12
Numpy version:           1.23.5
Scipy version:           1.11.4
Installed devices:
- 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)
- lightning.qubit (PennyLane-Lightning-0.34.0)

Existing GitHub issues

  • I have searched existing GitHub issues to make sure the issue does not already exist.
@anthonysmaldone anthonysmaldone added the bug 🐛 Something isn't working label Jan 24, 2024
@anthonysmaldone anthonysmaldone changed the title [BUG] StatePrep adjoint does not properly undercomputer state [BUG] StatePrep adjoint does not properly uncompute state Jan 24, 2024
@timmysilv
Copy link
Contributor

Hi @anthonysmaldone, thanks for bringing this up! A few quick things to note:

  1. State-prep operations are decomposed when applied mid-circuit (plus, the adjoint of a state-prep op is not considered a state-prep op anyway), so the second operation gets decomposed using the Mottonen decomposition which I believe would introduce this phase
  2. There is certainly the option to consider adding a global phase to the decomposition, but I'm not entirely sure if this will be a straightforward thing to do given how we handle state-prep operations
  3. State-prep operations used mid-circuit are stated to not act as an arbitrary unitary that takes any state to any other state, but rather one that meets the requirement $U|0\rangle = |\psi\rangle$ as described in the operator's doc

@timmysilv
Copy link
Contributor

small follow-up: as indicated in its docs, StatePrep decomposes to MottonenStatePrep, and that is only correct up to a global phase. So my third point isn't quite right, in the sense that we actually land up with $e^{i \phi} |\psi\rangle$. I would categorize this as semi-expected behaviour, but not exceedingly obvious behaviour. The original author of the Möttönen decomposition chose to ignore the global phase, but given that we now support them in PennyLane, we can look into adding it to the decomposition. nice find!

albi3ro pushed a commit that referenced this issue Feb 7, 2024
**Context:**
Fixes this [bug](#5099)
by adding a global phase to `qml.MottonenStatePreparation`.

**Description of the Change:**

**Benefits:**

**Possible Drawbacks:**

**Related GitHub Issues:**

---------

Co-authored-by: Matthew Silverman <[email protected]>
@astralcai
Copy link
Contributor

Can we close this issue now?

@timmysilv
Copy link
Contributor

yep! fixed in #5166

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

No branches or pull requests

3 participants