Structure of a Q# program
This article explores the general components that make up a Q# program. Note that Q# programs written in Jupyter Notebooks does not use some of these components - these differences are described in each section.
Consider the following Q# program:
namespace Superposition {
@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.
Reset(q);
// Finally, we return the result of the measurement.
return result;
}
}
By just reading the comments (//), you can tell that this program allocates a qubit, applies an operation to put it in superposition, measures the state of the qubit, then resets it and returns the result.
To run this program in Visual Studio Code, see Get started with Q# programs and VS Code.
User namespaces
Q# programs typically start with a user-named namespace, such as
namespace Superposition {
// Your code goes here.
}
Namespaces help you organize related functionality. Namespaces are user-named, and there can only be one namespace
per qsharp (*.qs) file.
The Q# standard library has predefined namespaces that contain functions and operations that you can use in quantum programs. For more information, see Built-in namespaces.
Jupyter Notebooks do not use user namespaces.
EntryPoint()
The @EntryPoint()
attribute tells the Q# compiler where to begin executing the program. In programs with multiple function and operation definitions, the @EntryPoint()
can be placed before any of the functions or operations and program flow starts from there and continues sequentially.
...
@EntryPoint()
operation MeasureOneQubit() : Result {
...
Jupyter Notebooks do not use entry points.
The %%qsharp command
By default, Q# programs in Jupyter Notebooks use the ipykernel Python kernel. In order to add Q# code to a notebook cell, you need to use the %%qsharp
command, which is enabled with the qsharp
Python package. For example, the previous sample code in a Jupyter Notebook looks like this:
import qsharp
%%qsharp
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.
Reset(q);
// Display the result
Message($"Result is {result}");
// Finally, we return the result of the measurement.
return result;
}
MeasureOneQubit();
Note the absence of a user namespace or an @EntryPoint()
, which are not needed for Jupyter Notebooks. Instead of an entry point, the operation is called directly in the last line. Also note that a Message
statement was added to the Jupyter Notebook code to display the result. When you run the earlier Q# program in VS Code, the built-in simulator displays the result by default.
When using the %%qsharp
command:
- You must run
import qsharp
first to enable the%%qsharp
command. - The
%%qsharp
command is scoped to the entire cell in which it appears. Note that it changes the notebook cell type from Python to Q#. - The Q# code that follows the command must adhere to standard Q# coding syntax. For example, you denote comments using
//
instead of#
within%%qsharp
cells, and code lines must end with a semi-colon;
. - The
%%qsharp
command cannot be preceded by or followed by a Python statement within its cell.
For an example of working with a Jupyter Notebook program, see Get started with Q# programs and VS Code.
Types
Q# provides many built-in types that are common to most languages, including Int
, Double
, Bool
, and String
, along with types that are specific to quantum computing. For example, the Result
type represents the result of any qubit measurement and can have one of two possible defined values: One
and Zero
. In the example program, the operation MeasureOneQubit()
expects a return type of Result
and the M
operation measures the qubit and returns the Result
.
...
// operation definition expecting a return type of Result
operation MeasureOneQubit() : Result {
...
// Now we measure the qubit in Z-basis, returning a Result type
let result = M(q);
...
}
Q# also provides types that define ranges, arrays, and tuples. You can even define your own custom types.
Allocating qubits
In Q#, qubits are allocated through the use
keyword.
Our example defines a single qubit:
// Allocate a qubit.
use q = Qubit();
...
but you can also allocate multiple qubits and access each one through its index:
...
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[0]);
...
By default, every qubit you allocate with the use
keyword starts in the zero state. Each qubit must be reset back the zero state before it is released at the end of the program. Failing to reset a qubit triggers a runtime error.
// Reset a qubit.
Reset(q);
...
Quantum operations
Once allocated, a qubit can be passed to operations and functions, also referred to as callables. 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. In our example, the single operation is essentially the entire program. It takes no parameters and expects a return type of Result
:
operation MeasureOneQubit() : Result {
...
}
Here's a basic example that takes no parameters and expects no return value. The Unit
value is equivalent to NULL
in other languages.
operation SayHelloQ() : Unit {
Message("Hello quantum world!");
}
The Q# standard library also provides operations that you can use in your programs, for example the Hadamard or the H
operation that is used in the example program. 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.
Measuring qubits
There are many types 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.
Our example program uses the M
operation, which performs a measurement of a single qubit in the Pauli Z basis and returns a Result
type.
Built-in namespaces
The standard Q# library makes use of built-in namespaces that contain functions and operations that you can use in quantum programs. For example, the namespace Microsoft.Quantum.Intrinsic
contains commonly used operations and functions such as M
, to measure results and Message
, to display user messages anywhere in the program.
You can call a function or operation by specifying the full namespace, or use an open
statement to make all the functions and operations for that namespace available, and to make your code easier to read. These two examples call the same operation:
Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
open Microsoft.Quantum.Intrinsic;
Message("Hello quantum world!");
Notice in the example program, there are no open
statements or calls with full namespaces. That is because the Q# development environment automatically loads two namespaces by default - Microsoft.Quantum.Core
and Microsoft.Quantum.Intrinsic
- which contain commonly used functions and operations.
You can take advantage of the Microsoft.Quantum.Measurement
namespace and use the MResetZ
operation to optimize the code in the example program. MResetZ
combines the measurement and reset operations into one step, as in the following example:
namespace Superposition {
// open the namespace for the MResetZ operation
open Microsoft.Quantum.Measurement;
@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);
// Measure and reset the qubit, and return the result value
return MResetZ(q);
}
}
الملاحظات
https://aka.ms/ContentUserFeedback.
قريبًا: خلال عام 2024، سنتخلص تدريجيًا من GitHub Issues بوصفها آلية إرسال ملاحظات للمحتوى ونستبدلها بنظام ملاحظات جديد. لمزيد من المعلومات، راجعإرسال الملاحظات وعرضها المتعلقة بـ