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

Normalize two_qubit_decomposition for odd CNOTs to preserve determinant 1 #6999

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Qottmann
Copy link
Contributor

@Qottmann Qottmann commented Feb 24, 2025

The determinant is changed from 1 to -1 when the returned circuit uses an odd number of CNOT gates. This can be normalized by a global phase $\xi^4 = -1$, e.g. $e^{-i \pi /4}$ as indicated in https://arxiv.org/pdf/quant-ph/0308033 in the paragraph below Lemma II.1

Not sure we actually want this change, as it adds GlobalPhases that on a quantum computational level don't matter
Actually might have implications when doing a controlled op like this.

TODO

  • decide if we actually want this, then
  • changelog
  • tests

An alternative approach could be to remove the _convert_to_su4 step in the first place (not sure this works)

Copy link
Contributor

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

@Qottmann Qottmann added the do not merge ⚠️ Do not merge the pull request until this label is removed label Feb 24, 2025
@Qottmann
Copy link
Contributor Author

Qottmann commented Feb 24, 2025

When doing controlled ops the global phase missmatch becomes important so perhaps it would indeed be better to fix this

import numpy as np
import pennylane as qml

def U():
    qml.exp(-1j * qml.dot(np.arange(16)[1:], list(qml.pauli.pauli_group(2))[1:]))

Um = qml.matrix(U, wire_order=range(2))()

ops = qml.ops.two_qubit_decomposition(Um, range(2))
U_re = qml.QubitUnitary(qml.matrix(qml.tape.QuantumScript(ops, []), wire_order=range(2)), range(2))

ctrl_op_m = qml.matrix(qml.ctrl(U, [2]), wire_order=range(3))()
ctrl_op_m2 = qml.matrix(qml.ctrl(U_re, [2]), wire_order=range(3))
np.abs(np.trace(ctrl_op_m @ ctrl_op_m2.conj().T))/8 # not unitarily equivalent
# 0.9238795325112874

@JerryChen97
Copy link
Contributor

unitarily equivalent

I'm a bit confused here. What is the unitary equivalence we want to bootstrap here? Is it that there exists a unitary U such that $A = U^\dagger B U$ between equivalent A and B, or we only allow A and B to differ in global phase?

@JerryChen97
Copy link
Contributor

When doing controlled ops the global phase missmatch becomes important so perhaps it would indeed be better to fix this

import numpy as np
import pennylane as qml

def U():
    qml.exp(-1j * qml.dot(np.arange(16)[1:], list(qml.pauli.pauli_group(2))[1:]))

Um = qml.matrix(U, wire_order=range(2))()
ops = qml.ops.two_qubit_decomposition(Um, range(2))

def U_re():
    ops

ctrl_op_m = qml.matrix(qml.ctrl(U, [2]), wire_order=range(3))()
ctrl_op_m2 = qml.matrix(qml.ctrl(U_re, [2]), wire_order=range(3))()
np.abs(np.trace(ctrl_op_m @ ctrl_op_m2.conj().T))/8 # not unitarily equivalent
# 0.8261951643289711

Also, when I try this example, I see ctrol_op_m2 is an Identity 😱 maybe quite some trouble with our 2-site decomp

@Qottmann
Copy link
Contributor Author

Also, when I try this example, I see ctrol_op_m2 is an Identity 😱 maybe quite some trouble with our 2-site decomp

There was a bug in my code snippet in that the decomposition ops were not properly recorded, updated it. The result is the same - as in not unitarily equivalent, which I might not be using correctly here, but I just meant that they are the same up to a global phase. So they are the same unitary operation, but are not element-wise the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do not merge ⚠️ Do not merge the pull request until this label is removed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants