# Writing a Quantum Program

## What You'll Learn

• How to set up a quantum solution and project
• The components of a Q# operation
• How to call a Q# operation from C#
• How to build and execute your quantum algorithm

Applications developed with Microsoft's Quantum Development Kit typically consists of two parts:

1. One or more quantum algorithms, implemented using the Q# quantum programming language.
2. A classical program, implemented in a classical programming language like Python or C#, that serves as the main entry point and will invoke Q# operations when it wants to execute a quantum algorithm.

This guide will walk you through how to create applications using Q#, and using C# as the classical component in Visual Studio or Visual Studio Code.

## Creating a Bell State in Q#

Now that you’ve installed the Microsoft Quantum Development Kit, let’s write your first quantum application. We'll start with the simplest program possible and build it up to demonstrate quantum superposition and quantum entanglement. We will start with a qubit in a basis state $\ket{0}$, perform some operations on it and then measure the result.

The instructions on the page are written for both the command line and Visual Studio. For Visual Studio, it assumes you have installed the Microsoft Quantum Development Kit Visual Studio extension. If you are using a different development environment, like Visual Studio Code, please follow the instructions to call the .NET Core SDK from the command line.

### Step 1: Create a Project and Solution

Run the following commands in your favorite command line (e.g.: PowerShell or Bash):

$dotnet new console -lang Q# --output Bell$ cd Bell
$code . # To open in Visual Studio Code.  ### Step 2: Enter the Q# Code Our goal is to create a Bell State showing entanglement. We will build this up piece by piece to show the concepts of qubit state, gates and measurement. #### Source files for a quantum application Your development environment should have two files open: Driver.cs, which will hold the C# driver for your quantum code, and Operations.qs, which will hold the quantum code itself. #### Q# source The first step is to rename the Q# file to Bell.qs. Right-click on Operations.qs in the Visual Studio Solution Explorer (Ctrl+Alt+L to focus) or the Visual Studio Code Explorer (Ctrl/⌘+Shift+E to focus), and select the Rename option. Replace Operations with Bell and hit return. To enter the Q# code, make sure that you are editing the Bell.qs window. The Bell.qs file should have the following contents: namespace Quantum.Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation HelloQ () : Unit { Message("Hello quantum world!"); } }  #### Q# operation First, replace the string HelloQ with Set, and change the operation parameters (the content of the parentheses) to contain the string desired: Result, q1: Qubit. The file should now look like: namespace Quantum.Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation Set (desired: Result, q1: Qubit) : Unit { Message("Hello quantum world!"); } }  Now, replace Message("Hello quantum world!"); with the following code between the braces that enclose the operation body:  if (desired != M(q1)) { X(q1); }  The file should now look like: namespace Quantum.Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation Set (desired: Result, q1: Qubit) : Unit { if (desired != M(q1)) { X(q1); } } }  #### Set or flip a qubit This operation may now be called to set a qubit in a known state (Zero or One). We measure the qubit, if it's in the state we want, we leave it alone, otherwise, we flip it with the X gate. Note This code defines a Q# operation. An operation is the basic unit of quantum execution in Q#. It is roughly equivalent to a function in C or C++ or Python, or a static method in C# or Java. The arguments to an operation are specified as a tuple, within parentheses. The return type of the operation is specified after a colon. In this case, the Set operation has no return, so it is marked as returning Unit. This is the Q# equivalent of unit in F#, which is roughly analogous to void in C#. An operation has a body section, which contains the implementation of the operation. An operation may also have adjoint, controlled, and controlled adjoint sections. These are used to specify specific variants of appropriate operations. See the Q# language reference for more information. #### Measure a qubit Add the following operation to the namespace, after the end of the Set operation:  operation BellTest (count : Int, initial: Result) : (Int, Int) { mutable numOnes = 0; using (qubit = Qubit()) { for (test in 1..count) { Set (initial, qubit); let res = M (qubit); // Count the number of ones we saw: if (res == One) { set numOnes += 1; } } Set(Zero, qubit); } // Return number of times we saw a |0> and number of times we saw a |1> return (count-numOnes, numOnes); }  This operation (BellTest) will loop for count iterations, set a specified initial value on a qubit and then measure (M) the result. It will gather statistics on how many zeros and ones we've measured and return them to the caller. It performs one other necessary operation. It resets the qubit to a known state (Zero) before returning it allowing others to allocate this qubit in a known state. This is required by the using statement. All of these calls use intrinsic quantum operations that are defined in the Microsoft.Quantum.Intrinsic namespace. For instance, the M operation measures its argument qubit in the computational (Z) basis, and X applies a state flip around the x axis to its argument qubit. Note As you can see, Q# uses C#-like semicolons and braces to indicate program structure. Q# has an if statement that is very much like C#. Q# deals with variables in a unique way. By default, variables in Q# are immutable; their value may not be changed after they are bound. The let keyword is used to indicate the binding of an immutable variable. Operation arguments are always immutable. If you need a variable whose value can change, such as numOnes in the example, you can declare the variable with the mutable keyword. A mutable variable's value may be changed using a set statement. In both cases, the type of a variable is inferred by the compiler. Q# doesn't require any type annotations for variables. The using statement is also special to Q#. It is used to allocate qubits for use in a block of code. In Q#, all qubits are dynamically allocated and released, rather than being fixed resources that are there for the entire lifetime of a complex algorithm. A using statement allocates a set of qubits at the start and releases those qubits at the end of the block. There is an analogous borrowing statement that is used to allocate potentially dirty ancilla qubits. A for loop in Q# iterates through a range or array. There is no Q# equivalent to a traditional C-style computer for statement. A range may be specified by the first and last integers in the range, as in the example: 1..10 is the range 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. If a step other than +1 is needed, then three integers with .. between them is used: 1..2..10 is the range 1, 3, 5, 7, and 9. Note that ranges are inclusive at both ends. The BellTest operation returns two values as a tuple. The operation's return type is (Int, Int), and the return statement has an explicit tuple containing two integer variables. Q# uses tuples as a way to pass multiple values, rather than using structures or records. ### Step 3: Enter the C# Driver Code Switch to the Driver.cs file in your development environment. This file should have the following contents: using System; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators; namespace Quantum.Bell { class Driver { static void Main(string[] args) { using (var qsim = new QuantumSimulator()) { HelloQ.Run(qsim).Wait(); } } } }  #### Run quantum operations from a C# host program Replace the body of the Main method with the following code:  using (var qsim = new QuantumSimulator()) { // Try initial values Result[] initials = new Result[] { Result.Zero, Result.One }; foreach (Result initial in initials) { var res = BellTest.Run(qsim, 1000, initial).Result; var (numZeros, numOnes) = res; System.Console.WriteLine($"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4}");
}
}

System.Console.WriteLine("Press any key to continue...");


Note

The C# driver has four parts:

• Construct a quantum simulator. In the example, qsim is the simulator.

• Compute any arguments required for the quantum algorithm. In the example, count is fixed at a 1000 and initial is the initial value of the qubit.

• Run the quantum algorithm. Each Q# operation generates a C# class with the same name. This class has a Run method that asynchronously executes the operation. The execution is asynchronous because execution on actual hardware will be asynchronous.

Because the Run method is asynchronous, we fetch the Result property; this blocks execution until the task completes and returns the result synchronously.

• Process the result of the operation. In the example, res receives the result of the operation. Here the result is a tuple of the number of zeros (numZeros) and number of ones (numOnes) measured by the simulator. This is returned as a ValueTuple in C#. We deconstruct the tuple to get the two fields, print the results, and wait for a keypress.

### Step 4: Build and Run

Run the following at your terminal:

$dotnet run  This will automatically download all required packages, build the application, then run it at the commmand line. Alternatively, press F1 to open the Command Palette and select "Debug: Start Without Debugging." You may be prompted to create a new launch.json file describing how to start the program. The default launch.json should work well for most applications. The results should be: Init:Zero 0s=1000 1s=0 Init:One 0s=0 1s=1000 Press any key to continue...  The program will exit after you press a key. ### Step 5: Creating Superposition Now we want to manipulate the qubit. First we'll just try to flip it. This is accomplished by performing an X gate before we measure it in BellTest:  X(qubit); let res = M (qubit);  Now the results (after pressing F5) are reversed: Init:Zero 0s=0 1s=1000 Init:One 0s=1000 1s=0  However, everything we've seen so far is classical. Let's get a quantum result. All we need to do is replace the X gate in the previous run with an H or Hadamard gate. Instead of flipping the qubit all the way from 0 to 1, we will only flip it halfway. The replaced lines in BellTest now look like:  H(qubit); let res = M (qubit);  Now the results get more interesting: Init:Zero 0s=484 1s=516 Init:One 0s=522 1s=478  Every time we measure, we ask for a classical value, but the qubit is halfway between 0 and 1, so we get (statistically) 0 half the time and 1 half the time. This is known as superposition and gives us our first real view into a quantum state. ### Step 6: Creating Entanglement Now we'll make the promised Bell State and show off entanglement. The first thing we'll need to do is allocate 2 qubits instead of one in BellTest:  using ((q0, q1) = (Qubit(), Qubit())) {  This will allow us to add a new gate (CNOT) before we measure (M) in BellTest:  Set (initial, q0); Set (Zero, q1); H(q0); CNOT(q0,q1); let res = M (q0);  We've added another Set operation to initialize qubit 1 to make sure that it's always in the Zero state when we start. We also need to reset the second qubit before releasing it (this could also be done with a for loop). We'll add a line after qubit 0 is reset:  Set(Zero, q0); Set(Zero, q1);  The full routine now looks like this:  operation BellTest (count : Int, initial: Result) : (Int,Int) { mutable numOnes = 0; using ((q0, q1) = (Qubit(), Qubit())) { { for (test in 1..count) { Set (initial, q0); Set (Zero, q1); H(q0); CNOT(q0,q1); let res = M(q0); // Count the number of ones we saw: if (res == One) { set numOnes += 1; } } Set(Zero, q0); Set(Zero, q1); } // Return number of times we saw a |0> and number of times we saw a |1> return (count-numOnes, numOnes); }  If we run this, we'll get exactly the same 50-50 result we got before. However, what we're really interested in is how the second qubit reacts to the first being measured. We'll add this statistic with a new version of the BellTest operation:  operation BellTest (count : Int, initial: Result) : (Int, Int, Int) { mutable numOnes = 0; mutable agree = 0; using ((q0, q1) = (Qubit(), Qubit())) { for (test in 1..count) { Set (initial, q0); Set (Zero, q1); H(q0); CNOT(q0,q1); let res = M (q0); if (M (q1) == res) { set agree += 1; } // Count the number of ones we saw: if (res == One) { set numOnes += 1; } } Set(Zero, q0); Set(Zero, q1); } // Return number of times we saw a |0> and number of times we saw a |1> return (count-numOnes, numOnes, agree); }  There is now a new return value (agree) that will keep track of every time the measurement from the first qubit matches the measurement of the second qubit. Of course, we also have to update the Driver.cs file accordingly:  using (var qsim = new QuantumSimulator()) { // Try initial values Result[] initials = new Result[] { Result.Zero, Result.One }; foreach (Result initial in initials) { var res = BellTest.Run(qsim, 1000, initial).Result; var (numZeros, numOnes, agree) = res; System.Console.WriteLine($"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4} agree={agree,-4}");
}
}

System.Console.WriteLine("Press any key to continue...");


Now when we run, we get something pretty amazing:

Init:Zero 0s=499  1s=501  agree=1000
Init:One  0s=490  1s=510  agree=1000


Our statistics for the first qubit haven't changed (50-50 chance of a 0 or a 1), but now when we measure the second qubit, it is always the same as what we measured for the first qubit. Our CNOT has entangled the two qubits, so that whatever happens to one of them, happens to the other. If you reversed the measurements (did the second qubit before the first), the same thing would happen. The first measurement would be random and the second would be in lock step with whatever was discovered for the first.

## Estimating Resources

Sometimes the quantum program is impossible to simulate on a classical computer (for example, if it uses too many qubits). In this case the researchers need to get an estimate of how many resources (qubits or certain gates) the program will use on a quantum computer as it would be impossible to simulate the program on a classical computer. We can do this without changing the Q# operation but using a different target machine, a ResourcesEstimator, for executing it in the C# host code; for example, modify the code in the the Driver.cs file to be:

            var estimator = new ResourcesEstimator();
BellTest.Run(estimator, 1000, Result.Zero).Wait();

System.Console.WriteLine(estimator.ToTSV());

System.Console.WriteLine("Press any key to continue...");


This change indicates to run the BellTest operation using the estimator as the target machine. When completed, we output the results to the console in TSV (tab-seperated values) format using the ResourcesEstimator's ToTSV() method. The output of the program is:

Metric          Sum
CNOT            1000
QubitClifford   1000
R               0
Measure         4002
T               0
Depth           0
Width           2
BorrowedWidth   0


For more information about the metrics reported and accessing the data programmatically, take a look at the ResourcesEstimator documentation.

To learn more about the other type of simulators and target machines provided in the Quantum Development Kit, how they work and how to use them, take a look at the Managing Quantum machines and drivers topic in the documentation.