The Q# quantum programming language user guide
The Q# quantum programming language is part of Microsoft's Quantum Development Kit, which provides rich IDE support and tools for program visualization and analysis. With Q# and the Quantum Development Kit (QDK) you can write your quantum programs and run them on real quantum hardware using Azure Quantum.
For more information, see how to configure your quantum development environment and how to submit Q# jobs to Azure Quantum.
Tip
If you want to accelerate your quantum computing journey, check out Code with Azure Quantum, a unique feature of the Azure Quantum website. Here, you can run built-in Q# samples or your own Q# programs, generate new Q# code from your prompts, open and run your code in VS Code for the Web, and ask Copilot any questions about quantum computing.
The Q# user guide contains:
Ways to run a Q# program: A Q# program can be run as a standalone application, or with an additional host program, written in Python or a .NET language.
Testing and debugging Q# programs: As with classical programming, it is essential to be able to check that quantum programs act as intended, and to be able to diagnose incorrect behavior. The Quantum Development Kit is for testing and debugging quantum programs.
The Q# language guide: Q# is a stand-alone language offering a high level of abstraction. There is no notion of a quantum state or a circuit; instead, Q# implements programs in terms of statements and expressions, much like classical programming languages. The Q# language guide provides a full specification and documentation of the Q# quantum programming language.
Quantum simulators documentation: Quantum simulators are software programs that run on classical computers and act as the target machine for a Q# program, making it possible to run and test quantum programs on classical computers.
The Q# library documentation: The Quantum Development Kit provides additional domain-specific functionality through NuGet packages that can be added to your Q# projects. The documentation includes operations, functions, user-defined types, examples, and concepts that make up the standard Q# library, as well as the quantum chemistry, quantum machine learning, and quantum numerics libraries.
What is in a Q# program?
Let's explore the general pieces that fit within a Q# program. Consider the following Q# program:
namespace HelloQuantum {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
@EntryPoint()
operation SayHelloQ() : Unit {
Message("Hello quantum world!");
}
}
EntryPoint
tells the Q# compiler where to begin executing the program. The program prints this message:
Hello quantum world!
Namespaces
Every Q# file typically starts with a namespace. Here's an example:
namespace HelloQuantum {
// Your code goes here.
}
Namespaces help you organize related functionality. Their use becomes important when you use Q# libraries in your programs and when you write your own libraries.
Libraries
Q# makes extensive use of libraries. A library is a package that contains functions and operations that you can use in quantum programs.
For example, the Microsoft.Quantum.Chemistry library helps you perform quantum calculations that relate to chemistry. There are several standard libraries that include all sorts of basic operations.
When you call a function or operation from a library, you specify the library's namespace. Here's an example that calls the Message
function from the Microsoft.Quantum.Intrinsic library to print a message to the console:
namespace HelloQuantum {
@EntryPoint()
operation SayHelloQ() : Unit {
Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
}
}
More commonly, you use the open
directive to make your code more succinct and easier to read.
This example does the same thing as the previous example, except this one uses the open
directive to bring the Microsoft.Quantum.Intrinsic
namespace into the program:
namespace HelloQuantum {
open Microsoft.Quantum.Intrinsic;
@EntryPoint()
operation SayHelloQ() : Unit {
Message("Hello quantum world!");
}
}
Here, you simply specify Message
and the compiler understands which namespace it belongs to.
The Q# documentation provides complete reference documentation for each built-in library. For more information, see the Q# libraries documentation.
Types
Q# provides many built-in types you're already familiar with, including Int
, Double
, Bool
, and String
, along with types that are specific to quantum computing. For example, the Result
type represents the result of a qubit measurement and can have one of two possible values: One
and Zero
. Q# also provides types that define ranges, arrays, and tuples. You can even define your own custom types.
All in all, the Q# type system is fairly minimalist, in the sense that there isn't an explicit notion of classes or interfaces as one might be used to from classical languages like C# or Java.
Allocating qubits
In Q#, qubits are allocated through the use
keyword. You can allocate one or many qubits at a time.
Here's an example that allocates one qubit:
// Allocate a qubit.
use q = Qubit();
// Do something with q here.
By default, every qubit you allocate with the use
keyword starts in the zero state.
Quantum operations
Once allocated, a qubit can be passed to operations and functions, also referred to as callables. In some sense, this is all that a Q# program can do with a qubit. Operations are the basic building blocks of a Q# program. A Q# operation is a quantum subroutine. That is, it's a callable routine that contains quantum operations that modify the state of the qubit register.
To define a Q# operation, you specify a name for the operation along with its inputs and its output. Here's a basic example:
operation SayHelloQ() : Unit {
Message("Hello quantum world!");
}
Here, SayHelloQ
is the name of the operation. It takes zero arguments as its input and returns type Unit
, which means that the operation returns no information.
The Q# libraries also provide operations that you can use in your programs, for example the Hadamard or H
operation. Given a qubit in Z-basis, the H
operation puts the qubit into an even superposition. Once in superposition, the qubit has a 50% chance of being measured as zero or one.
Any direct actions on state of a qubit are all defined by intrinsic callables such as X
and H
- that is, callables whose implementations are not defined within Q# but are instead defined by the target machine. What these operations actually do is only made concrete by the target machine you choose to run the particular Q# program. For more information, see Q# program implementation.
For example, if running the program on the full-state simulator, the simulator performs the corresponding mathematical operations to the simulated quantum system. But looking toward the future, when the target machine is a real quantum computer, calling such operations in Q# will direct the quantum computer to perform the corresponding real operations on the real quantum hardware. For example, in a trapped-ion quantum computer the quantum operations are realized by precisely timed laser pulses.
A Q# program recombines these operations as defined by a target machine to create new, higher-level operations to express quantum computation. In this way, Q# makes it easy to express the logic underlying quantum and hybrid quantum–classical algorithms, while also being general with respect to the structure of a target machine or simulator.
Measuring qubits
There are many sorts of quantum measurements, but Q# focuses on projective measurements on single qubits, also known as Pauli measurements. Upon measurement in a given basis (for example, the computational basis $\ket{0},\ket{1}$) the qubit state is projected onto whichever basis state was measured, hence destroying any superposition between the two.
In Q#, Pauli measurements are done by applying Measure
operation, which performs a joint measurement of one or more qubits in the specified Pauli bases. Measure
operation returns a Result
type.
Note
If the basis array and qubit array are different lengths, then the Measure
operation will fail.
To implement a measurement in the computational basis $\ket{0},\ket{1}$, you can also use the M
operation, which performs a measurement of a single qubit in the Pauli Z basis. Therefore M
operation is equivalent to applying Measure([PauliZ], [qubit])
.
A simple example is the following program, which allocates one qubit in the $\ket{0}$ state, then applies a Hadamard operation H
to it and measures the result in the PauliZ
basis.
@EntryPoint()
operation MeasureOneQubit() : Result {
// Allocate a qubit, by default it is in zero state
use q = Qubit();
// We apply a Hadamard operation H to the state
// It now has a 50% chance of being measured 0 or 1
H(q);
// Now we measure the qubit in Z-basis.
let result = M(q);
// We reset the qubit before releasing it.
if result == One { X(q); }
// Finally, we return the result of the measurement.
return result;
}
For performing measurements beyond a single joint measurement, the Microsoft.Quantum.Measurement
namespace includes more specific operations. For example, the MultiM
operation takes an array of qubits and returns an array of measurement results in the computational basis.
Next steps
Feedback
Submit and view feedback for