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

QASM and its implementation seem to have bugs. #65

Closed
DevelopDaily opened this issue Nov 3, 2019 · 6 comments
Closed

QASM and its implementation seem to have bugs. #65

DevelopDaily opened this issue Nov 3, 2019 · 6 comments
Labels
mismatch Code doesn't match the expected specs

Comments

@DevelopDaily
Copy link

I have two simple QASM files:

//test1.qasm
OPENQASM 2.0;
include "qelib1.inc";

qreg q[1];
h q;
//test2.qasm
OPENQASM 2.0;
include "qelib1.inc";

qreg q[1];
u2(0,pi) q;

Let's pass test1.qasm to this program to run first, then test2.qasm.

#include <iostream>
#include <cassert>
#include "qpp.h"

int main(int argc, char** argv) 
{
    assert (argc == 2);
    using namespace qpp;

    QCircuit qc = qasm::read_from_file(argv[1]);
    QEngine q_engine{qc};
    q_engine.execute();

    std::cout << disp(q_engine.get_psi()) << '\n';
}

Running test1.qasm produces this result:

0.707107
0.707107

and test2.qasm this result:

-0.707107i
-0.707107i

Logically, however, we should expect the same results because both the QASM specification and the Quantum++ implementation, which has faithfully followed the spec, define this:

// Clifford gate: Hadamard
gate h a { u2(0,pi) a; }

I did some analysis on the issue. Using Hadamard gate directly like the one in the test1.qasm is always correct because the H gate is hard-coded correctly in the Quantum++, bypassing the definition in the qelib1.inc.

So, the problem seems to be twofold. The QASM spec is wrong. Then, the implementation leads the API users to an illusion that the H gate is equivalent to gate h a { u2(0,pi) a; }. But, in fact, it does not use that definition at all.

By the way, I use this QASM paper as my reference.

@vsoftco
Copy link
Member

vsoftco commented Nov 3, 2019

This is an excellent point which I was not at all aware of, thanks! I frankly don't know what to do here. Most of the time the minus sign in front of the "true" Hadamard doesn't make a difference, but it may, e.g. in a case of a CTRL-Hadamard. I am tempted to leave it as is (and document it), so it uses the "true" Hadamard from the Q++. Other option is to just add a minus sign when parsing the QASM, so h behaves the way it's defined in QASM. I think asking QASM crew to change their definition is something that may take a while; any suggestions?

@vsoftco vsoftco added the mismatch Code doesn't match the expected specs label Nov 3, 2019
@DevelopDaily
Copy link
Author

IBM (Qiskit) is presumably the leading user of the QASM. If the fundamental H gate had been wrong, that would have affected thousands of users for a few years. I couldn't believe it. So, I take a look at the Qiskit QASM implementation. It turns out their code does not match their QASM specification either, the code being correct.

The root cause is not the gate h a { u2(0,pi) a; }, instead the U gate. The Qiskit uses the matrix here. It is drastically different from that in the spec.

Using the information of that matrix, I change the Quantum++ UGate::evaluate() in the ast.h and make the matrix look like this:

        cmat u{cmat::Zero(2, 2)};
        u << cos(theta / 2) ,
            -(sin(theta / 2)) * std::exp(1_i * lambda),
            sin(theta / 2) * std::exp(1_i * phi),
            cos(theta / 2) * std::exp(1_i * (phi + lambda));

Now, the u2(0,pi) q; works like a correct H gate. The new matrix is still unitary. So, I'd like to suggest you think about it.

Well, the U gate change would affect pretty much every single gate in the qelib1.inc. I am not sure if all other gates could pass the unit tests.

@vsoftco vsoftco closed this as completed in 92a9ed5 Nov 6, 2019
@vsoftco
Copy link
Member

vsoftco commented Nov 6, 2019

@DevelopDaily Fixed, now all gates in include/qasm/preprocessor.h are defined as they are in Qiskit, and the u3 (u matrix in include/qasm/ast.h) is defined also as in Qiskit (as you mention above). Thanks for the testing, please let me know if you find any issues with the fix.

vsoftco added a commit that referenced this issue Nov 6, 2019
@DevelopDaily
Copy link
Author

Here is a little piece of useful information.

I stated earlier that the Qiskit implementation is "drastically" different from that in the spec. As a matter of fact, my statement was inaccurate.

I just realize the matrix in the spec is not that different. If we divide the matrix by exp(-i * (phi + lambda) / 2), we get the matrix that is used by the implementations in both Quantum++ and Qiskit now. That is perfect because the division by that factor has no observable effects.

@vsoftco
Copy link
Member

vsoftco commented Jan 2, 2020

@DevelopDaily Thanks! So I hope that the fixes are also OK?

@DevelopDaily
Copy link
Author

Definitely, the fixes are perfect. I have been using them since they were released. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mismatch Code doesn't match the expected specs
Projects
None yet
Development

No branches or pull requests

2 participants