Latest Q# notebooks visualization capabilities
Thanks to Mariia Mykhailova for topic suggesstion and to Microsoft Quantum team for implementing this long awaited feature!

Latest Q# notebooks visualization capabilities

Introduction

This post is written for joining the Q# Advent Calendar 2020 blogging event as the 25th entry. In this post, some recently introduced means of visualizing quantum computing circuits will be demonstrated. These capabilities can work in Jupyter notebook when you embedding quantum operations there for using with Q# kernel.

What are the capabilities

IQ# Magic Commands:

These commands were recently added and described by the links above, but this piece of documentation does not include any screenshot, not to say about video for giving idea and forming expectation. So one needs doing a couple of simple steps to see how they look like and what can they do with your own eyes and touch with one's own fingers. This post is intended to fill this gap by going through visualization demo notebook from diagnostics section of Microsoft Quantum samples. Definitely, this sample notebook should be (considered as) a part of the diagnostics means documentation.

How to evaluate the capabilities

There are two major options. The first does not require anything except being online in a standard modern web browser. The second will require having installed some software development tools and a bit of attention to cope with installing, building and running the demo notebook environment.

Option 1: In a web browser

The service of mybinder.org allows interactive opening Jupyter Notebooks directly from a public Git repository as a web page. No need in installing or cloning anything,

On the start page, you can construct a link like this:

GitHub repository name or URL: (GitHub) microsoft/Quantum

Git ref (branch, tag, or commit): main

Path to a notebook file: samples/diagnostics/visualization/Visualizing Quantum Programs.ipynb

Also you can use the pre-constructed link with one click here or on the binder badge below: 

No alt text provided for this image


The binder badge can also be found at the start page of the microsoft/Quantum:

No alt text provided for this image

After opening it, you will need to navigate to the location:

  • samples/diagnostics/visualization/Visualizing Quantum Programs.ipynb


Option 2: Using software development tools

The Requirements that I found optimal for a bare system installation look like this:

After installing the tools and extensions, you need to open Visual Studio Code and clone microsoft/Quantum at github there:

No alt text provided for this image



Those who like quick copy-pasing commands to shell, instead of opening GUI and clicking there, can do this using the following CLI shell commands:

git clone https://github.com/microsoft/Quantum.git
code Quantum


Once the code is open in Code, the extention should ask you to Reopen in Container:

No alt text provided for this image

Accept this answer. The first run will take some time to download and prepare the container.

The container contains every requirement for running Jupyter Notebook. Now you can open Terminal, navigate to the Visualizing Quantum Programs notebook and start jupyter there:

# cd samples/diagnostics/visualization/

# jupyter notebook

After start, VS Code should look like this:

No alt text provided for this image

Option 1 vs Option 2

To be honest, the second option is much more stable and reliable than using binder service. No wonder, binder is a public free service that has limited resources, and the notebook running there often fall into statuses like Dead Kernel, Not Connected, Kernel Restarting or gets unresponsive. At the same time, one-click zero-setup start is undoubtedly a benefit of the option 1.

Other options

More information or alternative ways to get ready to using Jupyter Notebook for Q# programming can be found starting from here and here in the repo. You can find there a way to proceed without Docker, if you cannot or don't want to install it for some reason. Anyway, all ways use QDK (Microsoft Quantum Development Kit), either explicitly or under the hood.

Visualizing Quantum Programs (videos)

Once the notebook is loaded and ready, you can start reading it and run the cells. If you find it too wise to follow all the how-tos above or just don't have spare time on it, you can watch a few short videos of how I interacted with this notebook to quickly figure out how it works.

If the notebook is not trusted yet in jupyter, just press Trust button and confirm your action as shown in the video fragment below. Then you can re-run the whole notebook or run each cell sequentially step by step. It is important to make a first run of the steps in an order as later steps often depend on some earlier.

Let's look at the process of passing all the cells of this notebook, till the epilogue. While the execution goes on, you can read the text that helps undestand how quantum computing and it's visualization work.

Visualizing an execution path of a Q# operation with %trace

According to the documentation, %trace magic command visualizes the execution path of the given operation. It does not declare interactivity, but its <HTML visualization of the operation> can be clickable. Let's see how can we reveal the depth of the traced operation. Notice that you cannot "unclick" the unfolded element.

operation MeasureEntangledState() : Result[] {
    using (qubits = Qubit[2]) {
        H(qubits[0]);
        CNOT(qubits[0], qubits[1]);
        return [M(qubits[0]), M(qubits[1])];
    }
}
open Microsoft.Quantum.Arrays;


operation MeasureEntangledStateModular() : Result[] {
    using (qubits = Qubit[2]) {
        PrepareEntangledState(qubits);
        return ForEach(M, qubits);
    }
}

Nested operation:

operation PrepareEntangledState(qubits : Qubit[]) : Unit is Adj {
    H(qubits[0]);
    CNOT(qubits[0], qubits[1]);
}

Execution paths are non-deterministic!

No wonder, measurement affects the path significantly. Let's see how does the static cover image of this post look in dynamic when we repeatedly run MeasureUntilOne operation.

operation MeasureUntilOne() : Unit {
    mutable result = Zero;
    using (q = Qubit()) {
        repeat {
            H(q);
            set result = M(q);
        }
        until (result == One);
    }
}

Stepping through a Q# operation with %debug

According to the documentation, %debug magic command steps through the execution of a given Q# operation or function. It is interactive by definition. Pay attention that the cell where this magic command running won't finish running until you click through all steps of the circuit being debugged. In othe words, if you fire running all cells in the notebook, running process will stop on such debug cell waiting for stepping through.

operation MeasureEntangledState() : Result[] {
    using (qubits = Qubit[2]) {
        H(qubits[0]);
        CNOT(qubits[0], qubits[1]);
        return [M(qubits[0]), M(qubits[1])];
    }
}

Watch how the elements of the operation's circuit appear on stepping forward.

Teleport: %trace vs %debug

This is the famous Teleport! No words needed, just stare!

First trace.

Then debug. Notice that if you clicked on a block to reveal its internals, after step this block gets folded again. Interesting!

Below goes relevant code from the notebook. As for me, the balance between working (functional) and instrumentation code is approximately equal here.

open Microsoft.Quantum.Math;
open Microsoft.Quantum.Random;


operation Teleport() : Unit {
    using ((source, intermediate, target) = (Qubit(), Qubit(), Qubit())) {
    
        // Store a random message in the source qubit and visualize its state.
        let randomAngle = DrawRandomDouble(0.0, 2.0*PI());
        Rx(randomAngle, source);
        Message("State of source qubit:");
        DumpRegister((), [source]);
    
        // Create some entanglement that we can use to send our message.
        PrepareEntangledState([intermediate, target]);


        // Entangle the source qubit with the intermediate qubit.
        CNOT(source, intermediate);
        H(source);


        // Measure the qubits and decode the message by applying corrections on the target qubit.
        if (M(source) == One) { Z(target); }
        if (M(intermediate) == One) { X(target); }
        
        // Visualize the current state of the target qubit.
        Message("State of target qubit:");
        DumpRegister((), [target]);
        Reset(target);
    }
}

Nested operation:

operation PrepareEntangledState(qubits : Qubit[]) : Unit is Adj {
    H(qubits[0]);
    CNOT(qubits[0], qubits[1]);
}

Conclusion

Visualisation means is worth trying and using. It looks adequate and applicable. Anyway, many examples and real-life circuits still awaiting to be properly traced and debugged. Let's keep moving on thus.

In next posts, I'll try to apply this visualization in practicing Quantum Katas.

#qsharp #QsAdvent

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics