qiboteam / qibo

A framework for quantum computing
https://qibo.science
Apache License 2.0
289 stars 60 forks source link

Bug: 2-qubit decomposition #1501

Open Sam-XiaoyueLi opened 15 hours ago

Sam-XiaoyueLi commented 15 hours ago

The following code throws an error on Mac (apple silicon, regardless of qibo backend) but no error on i7:

from qibo.symbols import *
import qibo
from qibo.transpiler.unitary_decompositions import two_qubit_decomposition
L = 7
H_def = sum([ Z(x)*Z(x+1) +X(x)*X(x+1) +Y(x)*Y(x+1) +0.5*X(x) for x in range(L-1)])
H_sym = qibo.hamiltonians.SymbolicHamiltonian(H_def)
circ = H_sym.circuit(.1)
for gate in circ.queue:
    gate_decomposition = two_qubit_decomposition(
        *gate.qubits, gate.matrix()
    )
    for gate_elem in gate_decomposition:
        print(gate_elem)

Error message:

[Qibo 0.2.12|ERROR|2024-10-23 16:27:51]: Given state is not real in the magic basis.
ERROR:qibo.config:Given state is not real in the magic basis.
renatomello commented 14 hours ago

This is not exactly a bug. The documentation of two_qubit_decomposition says that the function implements Eq. (24) of arXiv:quant-ph/0307177. In the paper, one can see that this particular decomposition is only valid when the Hamiltonian that generates the unitary has no component in the $Z$ direction. Thus, this particular decomposition will fail for unitaries generated by Hamiltonians that do have components in the $Z$ direction.

I gues that the issue here is that the current decomposition is not general enough. The same reference provides in Eq. (6) a more general decomposition for unitaries that are in the $SU(4)$. People that are working more closely with the transpiler could take a look into it, e.g. @Simone-Bordoni or @csookim.

In [1]: from qibo import set_backend
   ...: from qibo.backends import NumpyBackend
   ...: from qibo.hamiltonians import SymbolicHamiltonian
   ...: from qibo.symbols import *
   ...: from qibo.transpiler.unitary_decompositions import two_qubit_decomposition
   ...: 
   ...: set_backend("numpy")
   ...: 
   ...: backend = NumpyBackend()
   ...: 
   ...: L = 7
   ...: 
   ...: H_def = sum([ Z(x)*Z(x+1) +X(x)*X(x+1) +Y(x)*Y(x+1) +0.5*X(x) for x in range(L-1)])
   ...: H_sym = SymbolicHamiltonian(H_def)
   ...: 
   ...: circ = H_sym.circuit(.1)
   ...: 
   ...: for k, gate in enumerate(circ.queue):
   ...:     try:
   ...:         gate_decomposition = two_qubit_decomposition(
   ...:             *gate.qubits, gate.matrix(backend), backend=backend
   ...:         )
   ...:         print(f"worked {k}")
   ...:     except:
   ...:         print(f"fail {k}")
   ...: 
[Qibo 0.2.13|INFO|2024-10-23 14:28:25]: Using numpy backend on /CPU:0
[Qibo 0.2.13|ERROR|2024-10-23 14:28:25]: Given state is not real in the magic basis.
fail 0
worked 1
worked 2
worked 3
worked 4
worked 5
worked 6
worked 7
worked 8
worked 9
worked 10
[Qibo 0.2.13|ERROR|2024-10-23 14:28:25]: Given state is not real in the magic basis.
fail 11
marekgluza commented 13 hours ago

Thanks @renatomello !

Are you saying that two_qubit_decomposition the code enters into a 2 CZ decomposition(24) and not https://github.com/qiboteam/qibo/blob/45eae7f81d1fe0fe9c3cd5b39c98fa225a6c29e8/src/qibo/transpiler/unitary_decompositions.py#L212 which would be a 3 CZ decomposition?

What I mean is that two_qubit_decomposition should manage to enter here https://github.com/qiboteam/qibo/blob/45eae7f81d1fe0fe9c3cd5b39c98fa225a6c29e8/src/qibo/transpiler/unitary_decompositions.py#L292-L305 and decompose the 2 qubit unitary into 3 CZ.

It seems to fail in the magic basis decomposition though https://github.com/qiboteam/qibo/blob/45eae7f81d1fe0fe9c3cd5b39c98fa225a6c29e8/src/qibo/transpiler/unitary_decompositions.py#L271-L279

The two_qubit_decomposition function should manage to decompose into 3 CZs any 2 qubit unitary. If it throws an error for XXZ which is already in the canonical form then it seems it is a bug because it throws an error while the 3 CZ decomposition can be provided 'by hand' and exists

marekgluza commented 13 hours ago

Added notes: Set $A = X\otimes X + Y\otimes Y +Z\otimes Z$ then $A+0.5 Z$ has a 3 CZ decomposition which runs in the above codes. Then I can take that decomposition and conjugate by Hadamards $(H\otimes H)(A+0.5Z)(H\otimes H) = A +0.5 X$ so just by redifining the outer single-qubit unitaries I get the decomposition. To me this means that we should decide between: