microsoft / qsharp-compiler

Q# compiler, command line tool, and Q# language server
https://docs.microsoft.com/quantum
MIT License
683 stars 170 forks source link

Error standard output about the PermuteQubits function. #1353

Open QuXing9 opened 2 years ago

QuXing9 commented 2 years ago

Description

As shown in the below testcase, there is an incorrect operation call in line 12. When executing the testcase, it reports an error normally. But the description of the error line in the output message is wrong. The error line should be 12 and 17 instead of 0. Is this a correct behavior of the QDK? Looking forward to your reply. Thank you!

Testcase

namespace NISLNameSpace {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Logical;
    open Microsoft.Quantum.Canon;

    operation NISLOperation () : Unit {
        mutable NISLVariable8 = [0,1,3,2];
        use NISLVariable9 = Qubit[5];
        PermuteQubits(NISLVariable8,NISLVariable9);
    }

    @EntryPoint()
    operation main() : Unit {
        mutable result = NISLOperation();
    }
}

Output

Unhandled exception. Microsoft.Quantum.Simulation.Core.ExecutionFailException: The new ordering has an incorrect number of elements
    Expected:   5
    Actual: 4
 ---> Microsoft.Quantum.Canon.PermuteQubits on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/D:\a\1\s\submodules\QuantumLibraries\Standard\src\Canon\CommonGates.qs:line 0
   at NISLNameSpace.NISLOperation on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/Program.qs:line 0
   at NISLNameSpace.main on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/Program.qs:line 0

Expected Output

Unhandled exception. Microsoft.Quantum.Simulation.Core.ExecutionFailException: The new ordering has an incorrect number of elements
    Expected:   5
    Actual: 4
 ---> Microsoft.Quantum.Canon.PermuteQubits on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/D:\a\1\s\submodules\QuantumLibraries\Standard\src\Canon\CommonGates.qs:line 0
   at NISLNameSpace.NISLOperation on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/Program.qs:line 12
   at NISLNameSpace.main on /home/nisl1/nisl8121/qx/quantumCompiler/compilerFuzzing/src/Fuzzing/qsharpPattern/Program.qs:line 17

Environment

Operating system: Windows 10

dotnet version: 3.1.408

QDK: 0.21.2111177148

Command

dotnet run

bettinaheim commented 2 years ago

@QuXing9 With this test case you are hitting a runtime failure, specifically the following assertion fails due to 5 qubits being reordered but only 4 indices given: https://github.com/microsoft/QuantumLibraries/blob/5cb1f4323e8e81196fdd2a6e07867597c62a9ef2/Standard/src/Canon/CommonGates.qs#L305 What you are seeing in the error message is hence the stack trace of this exception, and based on what I see I think you are running this using our C# runtime. This means that the stack trace is generated based on the information in the C# code that the Q# program is translated into for this setup. While the C# generation makes some effort to propagate information about the original source code, in the end what we can do with that setup is somewhat limited and suboptimal. The way to full solve the problem and achieve a good debugging experience is by generating debug symbols. We would hence like to address this (only) as part of switching to a QIR-based stack, where we have indeed started looking at also emitting some amount of debug symbols. I believe it is a good path to significantly improve cases such as this. However, local execution via QIR right now is not yet officially supported, and the move towards the new infrastructure will only happen gradually. How much of an issue has this been for you with the current setup?

QuXing9 commented 2 years ago

Hello! @bettinaheim Thanks for your timely reply! It has no effect on my work. I just want to know why this happens. By the way, you mentioned that the Q# program is translated into C# code and the stack trace is generated based on the C# code. Could you tell me how Q# code is translated into C# code? My previous understanding of Q# program execution is that Q# programs are first compiled to QIR, and then use the C# runtime to support the execution of QIR code. But according to your description, it seems that Q# code isn‘t compiled to QIR but translated into C# code and run. Is that so? Please forgive me if I misunderstood.

bettinaheim commented 2 years ago

@QuXing9 There are currently two setups for compiling and running Q# code, and we are gradually moving everything from one to the other. For both mechanisms, the Q# compiler first translates Q# code into a data structure (the Q# AST), which is then processed further.

The original setup had been to walk the AST produced by the initial compilation steps to generate C# code. This C# code is then compiled along with the dotnet runtime for Q# (written in C#) and additional libraries (e.g. containing the implementation of simulators) using the C# compiler to produce a .NET executable. This setup is what is currently used by default when you build and run a Q# program locally. The Microsoft.Quantum.Sdk takes care of handling all that, meaning it ensures that the necessary packages are referenced, it invokes and configures the Q# compiler, and finally invokes the C# compiler.

The new setup that we gradually move over to is to walk the AST produced by the initial compilation steps to generate QIR (LLVM bitcode). Right now, this setup is under active development, and we don't officially support producing a native executable from the bitcode and running it locally. Official support aside, that bitcode is then fed into the QIR compiler, which further compiles and targets it (if necessary). This compilation stage leverages the LLVM infrastructure, takes QIR as input and produces (potentially target specific) QIR as output. You can read more about it here: https://qir-alliance.github.io/qat. After this stage, the produced QIR is either sent to a hardware provider for further processing and execution, or linked together with a native runtime library (such as this one written in C++, but here are also other QIR runtime implementations) and additional libraries to produce a native executable. We use the llvm toolchain to link the bitcode and produce a native executable. This is how the Azure Quantum simulator works that is currently in private preview. Local execution with the described setup will be officially supported when we have added the necessary automation to require a single command for this whole process (like dotnet run in the original setup), and require no manual installation of llvm or other prerequisites. Today, QIR can be executed locally as long as you are comfortable doing these steps manually and installing llvm e.g. via chocolatey. You may find the following interesting to read if you would like to explore this setup: https://github.com/microsoft/qsharp-compiler/tree/main/examples/QIR/Optimization.

Does that clarify things a bit?

QuXing9 commented 2 years ago

@bettinaheim Thanks! Your reply is very clear. It's very interesting and I will study Q# in depth.