The 1.32 release of the QDK is packed with new features and capabilities, along with numerous bug fixes and performance improvements. Highlights include new interactive learning content for quantum chemistry, a Bloch sphere visualizer, QDK-Stim support, non-Clifford stabilizer simulation, the new Q# parallel keyword, improved circuit rendering, and more.
QDK Learning Chemistry notebooks
We've expanded our learning content with a new Ground-state molecular energies with quantum phase estimation tutorial for the qdk-chemistry library. The course consists of several notebooks that are tightly integrated with advanced VS Code and GitHub Copilot features. (See the docs at https://aka.ms/qdk, or the walkthrough videos at https://aka.ms/qdk.install and https://aka.ms/qdk.copilot, for details on setting up VS Code, Python, and GitHub Copilot).
To get started, open a directory in VS Code where you'd like to save your progress, and ensure you have a Python environment with the qdk-chemistry package installed. (The new QDK Python environment creation command, described below, can help with this). Then go to the Microsoft Quantum area in the Activity Bar and select Start Learning. This adds both the Katas and Chemistry courses to your workspace, ready for you to work through at your own pace.
Note: If using a qdk-chemistry version earlier than 2.2, Python for Windows is not supported. On Windows, you must be using the Windows Subsystem for Linux (WSL) to install the required qdk-chemistry Python dependencies.
QDK Python environment creation command
Setting up a Python environment for the QDK is now easier. A new VS Code command creates a virtual environment named .venv in the current workspace and installs the QDK packages you select. This is especially useful for setting up the QDK Chemistry learning experience described above - just make sure qdk-chemistry[jupyter] is selected.
From the Command Palette, select QDK: Create a Microsoft Quantum Python virtual environment:
Then choose the Python packages you want to install. The packages selected by default are shown below:
If a virtual environment named .venv already exists, the command will offer to update it instead.
Bloch sphere visualizer
This release also introduces an interactive Bloch sphere visualizer, providing a new way to explore and understand single-qubit states and operations. In VS Code, launch it from the Command Palette using QDK: Bloch sphere. In Jupyter notebooks, use the BlochSphere widget.
The Bloch sphere animates rotations as gates are applied and can also show a trace of the state vector updates as unitary matrices are applied.
Rotations can be applied directly or through rotation synthesis, using a sequence of Hadamard and T gates.
In either the VS Code visualizer or Jupyter widget, you can specify a sequence of gates using a string. For example:
from qdk.widgets import BlochSphere
display(BlochSphere('H T H'))QDK-Stim
This release introduces experimental support for QDK-Stim, a Stim-like language in the QDK. QDK-Stim supports the instruction set made popular by Stim, additional non-Clifford operations similar to those supported by Cliftt and tsim, and several QDK-specific instructions as described below.
QDK-Stim programs are compiled to QIR and can then run on any of our simulators that accept QIR, including the CPU and GPU state-vector simulators, stabilizer decomposition simulator, and density matrix simulator.
Additional instructions unique to QDK-Stim include:
SELECT / REQUIRE / NOTLEAKEDfor post-selection or repeat-until-success patterns based on parity measurements and qubit-loss checks.PEEK_LOSS / LOSS_ERRORfor additional qubit-loss modeling and handling.
See the notebook at samples/notebooks/qdk_stim.ipynb for more details and usage examples.
Note: QDK-Stim is currently experimental, and its features will continue to be expanded and refined. Please log an issue if you encounter a problem or would like to request a feature.
Q# 'parallel' keyword
Q# now includes the parallel keyword, which can be used as a prefix on expressions to control the space/time trade-off in generated code. As a simple example, consider the following for loop:
operation Main() : Result[] {
mutable results = [];
for i in 1..4 {
use q = Qubit();
results += [MResetX(q)];
}
results
}By default, the compiler tries to minimize qubit requirements. In this example, it reuses the qubit allocated within the loop, resulting in the circuit below. This requires only one qubit, at the expense of serializing the operations and therefore taking more time:
Prefixing the loop with the parallel keyword tells the compiler to try to run iterations in parallel where possible. In this case, it uses a distinct qubit for each iteration — requiring more qubits, but reducing execution time:
operation Main() : Result[] {
mutable results = [];
parallel for i in 1..4 {
use q = Qubit();
results += [MResetX(q)];
}
results
}
See PRs #3298 and #3588 for more details.
Stabilizer decomposition (non-Clifford simulation)
The QDK's stabilizer simulator has always been able to scale to large numbers of qubits, but until now it was limited to Clifford operations. This release adds stabilizer branching, enabling the simulator to handle circuits containing a small number of non-Clifford operations while retaining the scalability of stabilizer simulation.
The required state space grows exponentially with the number of non-Clifford operations, so shot throughput decreases significantly as more non-Clifford operations are added. See samples/notebooks/stabilizer_branching.ipynb for an example of a 111-qubit OpenQASM circuit containing 10 non-Clifford operations, which can still achieve a few hundred shots per second on a typical laptop.
Circuit rendering options
You can now control how a circuit for a Q# operation is rendered by adding the @CircuitRenderingOptions attribute to the operation definition.
The following options are currently supported:
hideBox(trueorfalse): Iftrue, the operation's group box is omitted and its contents are rendered directly in the containing scope.inputSizes(array of positive integers): Specifies the lengths of qubit-array arguments (Qubit[],Qubit[][], etc.) used to render the operation. Values apply to inputs in declaration order and to each input's dimensions from outermost to innermost. Missing values default to 2, and extra values are ignored.
For example:
@CircuitRenderingOptions(hideBox=true, inputSizes=[3,4])
operation Foo(a: Qubit[], b: Qubit[]) : Unit {
for q in a { X(q); }
for q in b { H(q); }
}Pretty-printed circuit angles
Circuit diagrams are now easier to read, with common rotation angles rendered in a more natural mathematical form instead of as decimal floating-point values. For example, the image below shows the before-and-after rendering of a rotation by π/4:
Deprecation of the qsharp Python package
The qsharp Python package is now deprecated and will no longer receive updates. Install the QDK using the qdk Python package instead, and update imports to use qdk and its submodules.
Other noteable changes
- Circuit-Editor and Visualization Re-Architecting and Tests by Scott Carda (@ScottCarda-MS) in #3425
- Fix multiplatform pipeline error for macos-latest by João Boechat (@joao-boechat) in #3543
- Enable source maps in source/npm/qsharp/src by Andrew Casey (@amcasey) in #3542
- Allow overriding github deps with local deps using env variables by Dima Fedoriaka (@fedimser) in #3541
- Use a
+jsonmimetype for the Q# config output so executed notebooks stay nbformat-valid by Scott Carda (@ScottCarda-MS) in #3555 - Bloch Sphere Widget - Command and Dev Playground by Scott Carda (@ScottCarda-MS) in #3306
- Drop redundant document updates in the LS by Andrew Casey (@amcasey) in #3534
- Delay squiggles by Andrew Casey (@amcasey) in #3545
- Unified GPU shaders by Bill Ticehurst (@billti) in #3483
- Allow dynamic constant values to coerce to static across callable boundaries in RCA by Stefan J. Wernli (@swernli) in #3502
- Reject recursive user-defined types at type-check time by Ian Davis (@idavis) in #3546
- Remove CPU Full State Noiseless Simulator by João Boechat (@joao-boechat) in #3565
- Prevent code meant only for simulation from leaking into generated quantum programs and analysis by Ian Davis (@idavis) in #3540
- Emitted ir functions now have internal linkage by Ian Davis (@idavis) in #3571
- New
parallelexpression in Q# by Stefan J. Wernli (@swernli) in #3298 - Support emission of locally constant arrays with dynamic contents by Stefan J. Wernli (@swernli) in #3537
- Fix spec & perf issues, rename and decouple the OpenQASM crate (
qdk_openqasm_parser->qdk_openqasm) by Ian Davis (@idavis) in #3553 - Drop
qsharpPython Package by Scott Carda (@ScottCarda-MS) in #3579 - Fix OpenQASM file includes on Windows while preserving valid Unix paths by Ian Davis (@idavis) in #3590
- Introduce Python Notebook learning experience prototype by Andrew Casey (@amcasey) in #3526
- [QRE] Build trace from Q# program by Dima Fedoriaka (@fedimser) in #3421
- Fix learning notebook tree navigation by Andrew Casey (@amcasey) in #3601
- [STIM] Support Generalized Pauli Product Gates by João Boechat (@joao-boechat) in #3556
- Introduce command and tools for venv creation by Andrew Casey (@amcasey) in #3554
- add the chemistry active space notebook course by Dhairya Patel (@HABER7789) in #3568
- Support readout noise in simulators and stim compiler by João Boechat (@joao-boechat) in #3581
- Optimize execution graph with expression specific nodes by Stefan J. Wernli (@swernli) in #3603
- Add language samples for
parallel, update notebooks by Stefan J. Wernli (@swernli) in #3588 - Fix calculated compute properties for callables invoked from
parallelexprs by Stefan J. Wernli (@swernli) in #3592 - Guide the learning agent away from switching courses by Andrew Casey (@amcasey) in #3613
- [STIM] Support readout noise for MPP by João Boechat (@joao-boechat) in #3608
- Use relative import in QRE cirq interop to fix pyright by Stefan J. Wernli (@swernli) in #3625
- [QRE] Show errors in case when resource estimation has no results. by Dima Fedoriaka (@fedimser) in #3615
- Improve build build times by Ian Davis (@idavis) in #3622
- Use mapped qubit ids in constant arrays to respect
Relabelby Stefan J. Wernli (@swernli) in #3626 - Circuit-Editor Multi-Target Gate Support by Scott Carda (@ScottCarda-MS) in #3426
- Circuit-Editor Classical-Control Support by Scott Carda (@ScottCarda-MS) in #3596
- Use theme aware SVG diagrams in the chemistry QPE course by Dhairya Patel (@HABER7789) in #3631
- Add python widget for Bloch Sphere by Scott Carda (@ScottCarda-MS) in #3595
- RCA Perf: Remove early termination check in
analyze_expr_whileby Stefan J. Wernli (@swernli) in #3623 - Skip loop normalization when package uses no loop control by Stefan J. Wernli (@swernli) in #3628
- RCA Perf: Perform aggregation in-place rather than returning new instances. by Stefan J. Wernli (@swernli) in #3619
- Fix panic in
source/language_service/src/name_locator.rsby Stefan J. Wernli (@swernli) in #3636 - Add stabilizer branching for non-Clifford simulation by Bill Ticehurst (@billti) in #3594
- Add the
qdk.openqasmparser and semantic analysis Python API by Ian Davis (@idavis) in #3580 - [STIM] Support peek_loss by João Boechat (@joao-boechat) in #3550
- Use only cirq-core in integration tests by Stefan J. Wernli (@swernli) in #3642
- Enable user friendly angles in circuits by Ian Davis (@idavis) in #3599
- Stop expr ty errors from cascading in gate operands during OpenQASM lowering by Ian Davis (@idavis) in #3644
- [STIM] Introduce non-Clifford gates to qdk-stim by João Boechat (@joao-boechat) in #3643
- Fix panic caused by using wrong offset in trace logging by Andrew Casey (@amcasey) in #3648
- Fix OpenQASM errors when editing unsaved files by Ian Davis (@idavis) in #3650
- [Circuit renderer] Add attribute to hide wrapper operations from circuit diagrams by Dima Fedoriaka (@fedimser) in #3630
- Open notebooks at the top when switching courses or resetting a unit by Dhairya Patel (@HABER7789) in #3654
- Use
PackageSpanin Capability Errors to fix panic by Stefan J. Wernli (@swernli) in #3656 - Handle binop with dynamic constant
BigIntvalues by Stefan J. Wernli (@swernli) in #3660 - Pin ipykernel to 6.x to avoid Jupyter kernel startup hangs by Dhairya Patel (@HABER7789) in #3661
- Fix dynamic result bugs in GPU simulator by João Boechat (@joao-boechat) in #3663
- Add unit to unit navigation links to Chemistry QPE notebooks by Dhairya Patel (@HABER7789) in #3646
- Add Samples for Physical Qubit Addressing Mode by Scott Carda (@ScottCarda-MS) in #3657
- Fixed errors in teleportation kata by Filip W (@filipw) in #3651
- [QRE] Automatic error analysis for empty resource estimates by Dima Fedoriaka (@fedimser) in #3659
- Course authoring guide for QDK Learning courses by Dhairya Patel (@HABER7789) in #3655
- [STIM] Finalize non-Clifford support by João Boechat (@joao-boechat) in #3647
- [Circuit renderer] Support user-provided input sizes for circuit rendering by Dima Fedoriaka (@fedimser) in #3658
Full Changelog: v1.31.0...v1.32.0