-
Notifications
You must be signed in to change notification settings - Fork 97
Working with Jupyter Notebooks
The qsharp
pip package provides seamless interoperability between Q# and Python. You can execute Q# code right from your Python script or Jupyter notebook.
For an overview of what you can do with Q# and Python, you can browse the sample Jupyter notebooks at pip/samples/sample.ipynb, pip/samples/azure_submission.ipynb and pip/samples/project.ipynb.
In this tutorial we will use VS Code, Q#, Python and Jupyter Notebooks to build a quantum random bit generator, simulate it locally, then submit it to Azure Quantum.
- Install VS Code and extensions
- Create a Jupyter Notebook
- Install
qsharp
- Run Q# in a notebook cell
- Use Q# operation results from Python
- Run multiple shots of the simulation
- Plot simulation results in a histogram
- Compile your program using the Base profile
- Submit to Azure Quantum
VS Code can be downloaded at: Visual Studio Code - Code Editing. Redefined
You will also need to install the following extensions for VS Code:
- Python: Python - Visual Studio Marketplace
- Jupyter extension pack: Jupyter - Visual Studio Marketplace
- Azure Quantum Developer Kit: Azure Quantum Developer Kit (QDK) Preview - Visual Studio Marketplace
For more information on getting started with Jupyter Notebooks in VS Code, see the documentation at VS Code: Working with Jupyter Notebooks in Visual Studio Code
From the command palette in VS Code, select "Create: New Jupyter Notebook".
In the upper right hand corner of the notebook, VS Code will display the version of Python and the virtual Python environment that was selected for the notebook.
If VS Code could not find a suitable Python environment, there will be a button instead to select a Jupyter kernel. Click on it and follow the prompts to create or select a Python environment.
It's time to install the Q# package, qsharp
.
In your notebook, create a Code cell and type:
%pip install --upgrade qsharp
Click the "play" button to execute the cell. The qsharp
pip package will be installed.
In the next cell, you can import the package you just installed by running:
import qsharp
Now you're ready to add a Q# cell to the notebook to implement your quantum program!
Importing the qsharp
module as you did above initializes a Jupyter Notebook cell magic named %%qsharp
. This allows you to run Q# code right within a Jupyter cell, interleaved with Python code cells if you like.
Create a new code cell and paste the following code into it:
%%qsharp
// This makes the DumpMachine() function available.
open Microsoft.Quantum.Diagnostics;
operation RandomBit() : Result {
// Qubits are only accesible for the duration of the scope where they
// are allocated and are automatically released at the end of the scope.
use qubit = Qubit();
// Set the qubit in superposition by applying a Hadamard transformation.
H(qubit);
DumpMachine();
// Measure the qubit. There is a 50% probability of measuring either
// `Zero` or `One`.
let result = M(qubit);
Message($"The result of the measurement is {result}.");
// Reset the qubit so it can be safely released.
Reset(qubit);
return result;
}
// Call the operation we defined above.
RandomBit();
Run the cell by clicking the "play" button or by pressing ctrl+Enter:
Here, we created a Q# operation named RandomBit()
which allocates a qubit, puts it in a superposition state, measures it, and returns the result. We then called the operation we just defined.
Note a couple of things in the cell output.
Quantum state visualization: The table shown is the output from the DumpMachine()
call. It displays the internal state of the simulator, including the measurement probabilities of all the qubits currently allocated.
Message: You can use Message()
function to output a string into the cell output.
These two functions are useful for debugging your Q# programs as you develop them.
While running Q# in its own notebook cell is a powerful way to develop quantum programs, sometimes you will want to access the results from Q# programs in Python code.
Using qsharp.eval()
, you can call any Q# operation that you previously defined in a Q# cell.
Create a new code cell and type:
r = qsharp.eval("RandomBit()")
if r == qsharp.Result.One:
i = 1
else:
i = 0
print(f"Python: Got integer {i}!")
Note how we switched back to Python here. Calling qsharp.run()
runs the Q# expression passed in and converts the result into a Python value. Since the return value is of type Result
here, we use the qsharp.Result
Python enum to compare the result and convert it to an integer we can use.
To validate that we are in fact generating a random bit, we may want to run the same simulation a number of times, independently. Each independent simulation is called a "shot". Try passing a shots
parameter to run()
to run your simulation 1000 times:
results = qsharp.run("RandomBit()", shots=1000)
Note how the results are aggregated in a Python list. You can now process the results of the Q# simulation using your favorite Python libraries!
Now we can use the result list to generate a histogram using Python's handy matplotlib
library. For the next step, we'll need to install the ipympl
package so that we can generate interactive widget:
%pip install ipympl
Now, paste the following into a new code cell to generate a histogram:
%matplotlib widget
import matplotlib.pyplot as plt
import numpy as np
from collections import Counter
# Sort the results so that the histogram labels appear in the correct order
results.sort()
# Count the number of times each result appears
counts = Counter(results)
(values, counts) = counts.keys(), counts.values()
xlabels = np.arange(len(counts))
plt.title("RandomBit() Results")
plt.bar(xlabels, counts)
plt.xticks(xlabels, values)
plt.show()
Just as we would expect, the number of occurrences of One
and Zero
are about equal.
We can now run our program on real quantum hardware or simulators hosted on Azure Quantum.
Unlike the local quantum simulator, Azure Quantum backends do not yet support the full capabilities required to run any Q# programs. In order to compile and submit Q# programs to Azure Quantum, we need to set our target profile to tell Q# which capabilities that our target hardware supports.
In a new Python code cell, reinitialize the Q# interpreter with the base profile:
qsharp.init(target_profile=qsharp.TargetProfile.Base)
This reconfigures the Q# interpreter so that only operations included in the Base target profile are permitted in our program.
In the next code cell, let's redefine our random number generator operation to get ready to compile and submit it to Azure Quantum.
%%qsharp
operation Random() : Result {
use q = Qubit();
H(q);
let result = M(q);
Reset(q);
return result
}
operation RandomNBits(N: Int): Result[] {
mutable results = [];
for i in 0 .. N - 1 {
let r = Random();
set results += [r];
}
return results
}
For this part, you'll need the azure-quantum
package. Install it using pip:
%pip install azure-quantum
You will also need an Azure Quantum workspace set up if you don't already have one. For instructions on how to create a workspace, see the documentation at: Create an Azure Quantum workspace
In your notebook, run a code cell initializing the following variables for your own workspace:
subscription_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
resource_group = 'myresourcegroup'
workspace_name = 'myworkspace'
location = 'mylocation'
Now, connect to Azure Quantum and submit your Q# program:
import azure.quantum
operation = qsharp.compile("RandomNBits(4)")
workspace = azure.quantum.Workspace(
subscription_id=subscription_id,
resource_group=resource_group,
name=workspace_name,
location=location,
)
target = workspace.get_targets("rigetti.sim.qvm")
job = target.submit(operation, "my-azure-quantum-job", input_params={ "count": 100 })
job.get_results()
Running this cell may cause a browser window to open up, or display instructions on how to sign in to Azure Quantum in the cell output. Follow the instructions for signing in to allow the script to continue.
Let's take a closer look at the call to Q# above:
operation = qsharp.compile("RandomNBits(4)")
The string "RandomNBits(4)"
is called an entry expression, and it's exactly what it reads like: a call into the RandomNBits
function with 4
as the argument. This expression is treated as the entry point to the program submitted to Azure Quantum. You can pass any valid Q# expression as the entry expression.
Once the job is done executing on Azure Quantum, the results will be shown in the cell output:
You can now generate a histogram from these results just like we did above with the local simulation, or post-process the results using any Python library of your choosing.
This tutorial showed you how to use Q# and Python in our favorite editor, VS Code. If you are an experienced Python developer, you may want to use Q# with your notebook editor of choice, such as JupyterLab. This is certainly possible, as qsharp-lang
is a pip package without any dependencies that can be invoked from any Python environment.
If you do use JupyterLab, don't forget to install qsharp-jupyterlab
, our JupyterLab extension that provides syntax highlighting in Q# cells:
pip install qsharp-jupyterlab
If you prefer not to use Jupyter notebooks, qsharp-lang
works well in Python scripts as well.
Now that you've gotten started with Q# and Python, explore the Q# playground (microsoft.github.io) for more Q# samples and tutorials. All of the code samples found on the playground are runnable in Jupyter notebooks as well.