Quantum Computing and Q # for Beginners

Original author: Frances Tibble
  • Transfer
  • Tutorial
Perhaps you learned about the release of the Quantum Development Kit, a package of quantum development tools, and thought that it sounds insanely cool ... and then you remembered that you know almost nothing about quantum mechanics. But that's okay. After 30 minutes, you will know enough about qubits, superposition, and quantum entanglement to write your first program and, more importantly, to understand what it does.



Articles from the cycle:


  1. Quantum Computing and Q # for Beginners
  2. Introduction to Quantum Computing
  3. Quantum Circuits and Gates - Introductory Course
  4. The basics of quantum computing: pure and mixed states
  5. Q # quantum teleportation
  6. Quantum Computing: Reference

Frances is a graduate of Imperial College London with a degree in Computing. She wrote her graduation project while working at Microsoft Research. Frances now works at Microsoft as a software engineer. The main areas of her activity are machine learning, big data and quantum computing.

The content of the article


  • Repeat the basics
  • Measure qubit
  • Quantum valves
  • Important valves
  • Few qubits
  • Another important valve
  • Bell's condition
  • Writing a quantum program
  • What's next?
  • application
  • Additional materials

Repeat the basics


If you do not program at the lowest level, then you may well forget that any programs, in fact, only manipulate the zeros and ones that are stored in our "classic" computers. These zeros and ones correspond to discrete binary states of physical systems. Quantum computers operate with continuous ranges of states. Partly their capabilities are due to this.

The classic bit can take only one of two states - “on” or “off”, like a normal incandescent lamp. The qubits, the basis of quantum computers, are more like a dimmable lamp.



To record two states of qubits, we can use the notation bra and ket (Dirac notation), which correspond to the following vectors:



Using a linear combination of these two states, any possible combination of the vectors | 0〉 and | 1〉 can be expressed. In quantum mechanics, such a combination is called superposition. The corresponding entry in the Dirac notation will look like this:

| ψ⟩ = α | 0〉 + β | 1〉

The quantities α and β are related to probabilities (with one slight difference - these coefficients can be expressed as complex numbers). You can consider them real numbers, but in this case, remember that they can take negative values. However, the sum of their squares is always 1.

Measure qubit


Quantum states are a strange thing. As a result of measurement (or, as they say, "in the presence of an observer"), the qubit immediately collapses. What does it mean? Suppose a qubit is in a superposition state. If you measure it, then it will take one specific value - | 0〉 or | 1〉 (both measurements cannot show both results at once!). After measuring the qubit, the coefficients α and β, which characterized its previous state, will, in fact, be lost.

Therefore, the probability theory apparatus is used to describe the measurements of qubits. In the general case, the probability that measuring the state of the qubit will show the result | 0〉 is equal , and the probability of getting the state | 1〉 is equal . Consider an example. Suppose we have the following qubit:



If we measure its state, then in 50% of cases we will get the value 0, because:



That is, after the measurement it will be in the state | 0〉 (that is, α = 1, β = 0). For the same reason, the probability of getting state 1 is 50%. In this case, after the measurement, the qubit will go into the state | 1〉 (that is, α = 0, β = 1).



For the first time, all this is very confusing (for the second, third and fourth time, nothing will change). The main idea here is that probabilistic quantum states can be used for calculations, and in some cases, their quantum “strangeness” allows us to obtain systems with efficiencies higher than classical ones. Now let's see how these qubits can be used for calculations, like classical bits.

Quantum valves


Let us return to more familiar things. In the classical theory of computation, logic gates are used to perform operations on bits. To manipulate qubits, similar designs are used - quantum gates. For example, the NOT gate performs the transformations 0 → 1 and 1 → 0. The quantum NOT gate is similar to its classical ancestor: it performs the transformations | 0〉 → | 1〉 and | 1〉 → | 0〉. This means that after passing through such a gate, the qubit from the state α | 0〉 + β | 1〉 will go into the state α | 1〉 + β | 0〉. The NOT gate can be written in the form of a matrix (X), which interchanges 0 and 1 in the state matrix:



As we see, X | 0〉 = | 1〉, and X | 1〉 = | 0〉:



Since | 0〉 and | 1 > vector form are written as and, the first column of the matrix X can be considered as a transformation of the vector | 0〉, and the second - as the transformation of the vector | 1〉.

It would seem that the difference from the classical case is not so great. But do not forget what we talked about in the previous section: the measurement of the state of a qubit is probabilistic. As is known from the elementary theory of probability, the sum of the probabilities of a complete group of incompatible events is unity. Therefore, for the quantum state, α | 0〉 + β | 1〉.

It follows that not all conceivable gates may exist in the quantum world. Here is one of the restrictions: the condition for normalizing the quantum state of the qubit,, must be observed both before and after the passage of the gate. In terms of matrix algebra, this condition will be satisfied if the matrix is ​​unitary.

I will try to explain what the mathematical concept of unitarity means. If you read it fast enough, you will simply find yourself on the next sentence. A gate is called unitary if it is obtained by transposition and complex conjugation and is a unit matrix of rank 2. Speaking in human language, this means that the transformation does not change the length of the vector. If the length of the vector does not change with time, then the sum of all the probabilities is invariably equal to unity, or 100% (as it should be). The calculations, as a result of which the sum of all the probabilities is equal to 200% or 25%, would be meaningless. Unitary matrices protect at least from such madness (although in the quantum world it remains abundant).

Good news: this restriction is the only one. Due to this condition, some classical gates do not have a quantum analogue, however, some quantum gates do not have a classical prototype. Next, we will analyze the most important of the quantum gates.

Important valves: valve Z and Hadamard valve


The gates described below will be used in our first quantum program, so try to remember them. Gate Z works very simply: it saves the component | 0〉 and changes the sign of the component | 1〉. It can be written in the form of a matrix



that transforms the states of qubits as follows: | 0〉 → | 0〉, | 1〉 → - | 1, (remember that the first column of the matrix describes the transformation of the vector | 0〉, the second - the transformation of the vector | 1〉 )

The Hadamard valve creates a superposition of the states | 0〉 and | 1〉, similar to those considered above. Its matrix notation is as follows:



which corresponds to the following transformations of states of qubits: ,

More detailed information about unitary matrices and methods of visual representation of gates is given in the resources, links to which are contained in the "Additional Materials" section.

Few qubits


Consider something more familiar. Classic bits exist not only one by one, but also in the form of combinations: for example, 00, 01, 10 and 11. In quantum calculations, similar combinations are used: | 00〉, | 01〉, | 10〉 and | 11〉. The state of two qubits can be described using the following vector:



As before, the probability of getting the value 00 as a result of the measurement is equal ,
for 01 the probability is equal , etc.

Suppose now that we want to measure the state of not both qubits, but only the first. The probability of getting 0 is equal to . As we remember, the measurement changes state, so after it the vector will matter



Pay attention to the numerator: we removed all terms for which the first bit is 1 (since, by condition, the measurement result is 0). In order for the vector to describe the admissible quantum state, it is necessary that the square of the sums of amplitudes be equal to unity (both before and after the transformation). In order for this condition to be fulfilled, we add a normalization factor, a value inverse to the square root of the determinant.

Another important valve


We have already disassembled the operation of the NOT valve. Next in line is the CNOT (controlled-NOT). Two qubits are fed to its input. The first is called the manager, the second is managed. If the control qubit is | 0〉, then the state of the controlled qubit does not change. If the control qubit is | 1〉, then the NOT operation is applied to the controlled qubit.

The CNOT operation can be interpreted in several ways. Like the gates X, Z and H, it can be written in matrix form, which is denoted by the letter U.



You can notice that the columns of the matrix correspond to the following transformations: | 00〉 → | 00〉, | 01〉 → | 01〉, | 10〉 → | 11〉, | 11〉 → | 10〉. Like the matrices that we analyzed in , it is unitary, which means .

The following designation is also used for this valve (the upper part corresponds to the controlling qubit, the lower one to the controlled one):



It looks like an exhibit of an exhibition of contemporary art.

Bell's fortunes


A whole section should be devoted to this important topic. There are four Bell states in total. One of them (| ϕ +⟩) will be used in the quantum program below. Let's look at it.



Suppose we measure the state of the first qubit. The result | 0〉 we get with probability . This means that the state after measuring | ψ '⟩ = | 00〉, or | 1〉 with the same probability (0.5), and the state after measuring | ψ' '= | 11〉. For the curious, we present a complete set of Bell states (they are the simplest cases of quantum entanglement):



Now suppose we measured the state of the second qubit. According to the same reasoning, after measuring the steam will be in the state | 00〉 or | 11〉. If after this we decide to measure the state of the first qubit, the probabilities will no longer be 0.5. We get | 0〉 with a probability of 1 or 0, depending on what the measurement result was. It is important to understand that these results are related. The first to notice this were Albert Einstein, Boris Podolsky and Nathan Rosen (therefore, these states are sometimes called “EPR pairs”). Subsequently, their theory was developed by John Bell.

One final observation: Bell states can be generated using the Hadamard valve and CNOT valve. In my opinion, this is admirable. The Hadamard valve puts the first qubit into a superposition state. This qubit is then fed to the control input of the CNOT valve. Here is how this process can be represented using a circuit diagram:



To learn more about how each of these transformations works, refer to additional materials (the list is given below). We already know enough about qubit states, quantum gates, and Bell states to write our first qubit program.

Writing a quantum program


We will follow the instructions from the documentation .

This tutorial will help you do the following: install the quantum program development package (steps 1–2), select a qubit and perform a number of simple manipulations on it — for example, set it to a certain state and measure it (steps 3–5), then translate qubits into a superposition state (step 6), and then convert two qubits into an entangled state — the Bell state, or a pair of EPRs (step 7).

It is recommended that you follow the instructions in the manual referenced above, and return to this material if you need tips or additional explanations.

Stage 1. Project Creation and Solutions


Q # is at the bottom of this list.



Stage 2 (optional). Updating NuGet Packages


We followed this advice, but this is not necessary, especially if you like to take risks.

Step 3. Enter the Q # code


namespace Quantum.Bell
{
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;
    operation Set (desired: Result, q1: Qubit) : ()
    {
        body
        {
            let current = M(q1);
            if (desired != current)
            {
                X(q1);
            }
        }
    }
}

This operation transfers our qubit to the state (chosen by us) - 0 or 1. First we measure the qubit (this operation is indicated by the letter M), and it collapses to state 0 or 1. If the measured state does not correspond to the desired one, we change it with the valve NOT, X. Otherwise, nothing needs to be done.
operation BellTest (count : Int, initial: Result) : (Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            using (qubits = Qubit[1])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    let res = M (qubits[0]);
                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }
                Set(Zero, qubits[0]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes);
        }
    }

This small piece of code is designed to test the operation we just wrote. This is a very simple program: it checks that the qubit has been transferred to the state we need.

To do this, she takes a measurement in a loop and counts the number of results 1 using the variable numOnes.

The notation “Qubit [1]” means “create an array of qubits from one element”. Indexing array elements is from scratch. To distinguish two qubits (we will need to do this later), we need to write “Qubit [2]”. The qubits in such an array correspond to the numbers 0 and 1.

In the for loop, we set the qubit allocated for a certain initial state, One or Zero (in the Driver.cs file, to which we will soon pass, this is done explicitly). We measure this state, and if it is One, we increase the counter value by one. The function then returns the number of observed states of One and Zero. At the end, the qubit is put into the Zero state (just to leave it in some known state).

Step 4. Entering the C # Driver Code


            using (var sim = new QuantumSimulator())
            {
                // Try initial values
                Result[] initials = new Result[] { Result.Zero, Result.One };
                foreach (Result initial in initials)
                {
                    var res = BellTest.Run(sim, 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...");
            System.Console.ReadKey();

This driver creates a quantum simulator and an array of initial values ​​to check (Zero and One). Then the simulation is repeated 1000 times, and the result for debugging is displayed using the System.Console.WriteLine function.

Stage 5. Assembly and implementation


Init:Zero 0s=1000 1s=0
Init:One 0s=0 1s=1000
Press any key to continue...

If everything is in order, the output on the screen should look like the one shown above. This result means that if we transfer the initial qubit to the Zero state and perform a thousand repetitions, then the number of states | 0〉 according to the observation results will be 1000. The same should be done for the One state.

Step 6. Creating a Superposition


Let's try something more interesting. Here we change the state of the qubit with the NOT gate.
                    X(qubits[0]);
                    let res = M (qubits[0]);

Then we run the program again and see that the results are reversed. Then, replace the NOT valve with the Hadamard valve (H). As a result, as we know, the qubit will go into a superposition of states, and the result of its measurement can be equal to | 0〉, and | 1〉, with some probability.
Init:Zero 0s=0 1s=1000
Init:One 0s=1000 1s=0



                    H(qubits[0]);
                    let res = M (qubits[0]);

If you run the program again, we will get a rather interesting result. The number of measurements | 0〉 and | 1〉 will be approximately equal.
Init:Zero 0s=484 1s=516
Init:One 0s=522 1s=478



Step 7. Preparing the Entangled State


Now we will create the Bell state. Check out the code below. First, we create an array of two qubits (Qubit [2]). The first qubit (in the previous diagram of the circuit it was denoted by the symbol x) we translate into some initial state, and the second (y in the diagram) is set to Zero. This is roughly the same as entering | 00〉 or | 10〉 depending on X:
operation BellTest (count : Int, initial: Result) : (Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            using (qubits = Qubit[2])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);
                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);
                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }
                Set(Zero, qubits[0]);
                Set(Zero, qubits[1]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes);
        }
    }

According to the diagram, the first qubit, qubits [0], must be passed through the Hadamard valve. As a result, he will be in superposition. Then we pass the qubits through the CNOT valve (qubits [0] - control qubit, qubits [1] - controlled) and measure the result.

To understand what the result is to be expected, let us repeat once again how our Bell state works. If we measure the first qubit, we get the value | 0〉 with probability. This means that the state after measuring | ψ '⟩ = | 00〉 or | 1〉 with the same probabilities (0.5), and the state after measuring | ψ'⟩ = | 11〉. Thus, the result of measuring the state of the second qubit will be | 0〉 if the first qubit was in the state | 0〉, and | 1〉 if the first qubit was in the state | 1〉. If the states of two qubits were successfully confused, then our results should show that the first and second qubits are in the same states.

In our code, we check if the measurement result qubits [1] is equal to the measurement result qubits [0] using the if statement.
operation BellTest (count : Int, initial: Result) : (Int,Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            mutable agree = 0;
            using (qubits = Qubit[2])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);
                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);
                    if (M (qubits[1]) == res) 
                    {
                        set agree = agree + 1;
                    }
                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }
                Set(Zero, qubits[0]);
                Set(Zero, qubits[1]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes, agree);
        }
    }


Before checking the results, you need to make one more change to the Driver.cs file: add the agree variable.
using (var sim = new QuantumSimulator())
            {
                // Try initial values
                Result[] initials = new Result[] { Result.Zero, Result.One };
                foreach (Result initial in initials)
                {
                    var res = BellTest.Run(sim, 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...");
            System.Console.ReadKey();

Now the program can be launched. What do these results mean? If the first qubit was initially placed in the Zero state (that is, we entered the value | 00〉), then the Hadamard valve puts the qubits into a superposition state, and the measurement result is | 0〉 in 50% of cases and | 1〉 in 50% of cases . The fulfillment of this condition can be estimated by the number of zeros and ones. If the measurement of the state of the first bit did not affect the state of the second, then it would remain equal to | 0〉, and consistency would be achieved only in 499 cases.

But, as we see, the states of the first and second qubits are completely consistent: the number of results | 0〉 and | 1〉 (approximately) coincide. Thus, the results are consistent in each of 1000 cases. That is how Bell's states should work.
Init:Zero 0s=499 1s=501 agree=1000
Init:One 0s=490 1s=510 agree=1000

On this we will end. You wrote your first quantum program and (since you got to the end), you probably understood what it was doing. It is worth noting a good cup of tea.



What's next?


There are many examples available on the GitHub repository .

In the next article, we will talk about the theory of quantum teleportation and study a code example.

Quantum gates are discussed in more detail on Anita's blog (note: Anita is just awesome).

Additional materials


If you want to delve into the topics discussed, the following is a list of resources that have been very useful to us. The first of them is the book “Quantum Computing and Quantum Information” (M. Nielsen, I. Chang). The second is the Microsoft SDK documentation .

If it will be interesting to readers (leave a comment!), We can write a separate publication about other resources.

Application. Bell's fortunes




Bell states can be generated using the Hadamard valve and CNOT valve. The Hadamard valve puts the first qubit into a superposition state. This qubit is then fed to the control input of the CNOT valve. On the circuit diagram, it looks like this:
Let's start from the first case, when a pair of qubits in the state | 00〉 is supplied to the input. The first qubit, | 0〉, passes through the Hadamard valve and turns into . The second qubit does not change. Result:



Then the qubits pass through the CNOT gate (which performs the transformations | 00〉 → | 00〉 and | 10〉 → | 11〉). Now their state will be described by the formula The



second case: qubits | 01〉 are supplied to the input. The Hadamard gate transfers the first qubit | 0〉 to the state . The second qubit does not change. Result:



Now let the qubits pass through the CNOT gate, which performs the transformations | 01〉 → | 01〉 and | 11〉 → | 10〉. The final state of a pair of qubits will look like this:



Third case: qubits | 10〉 are input. The Hadamard gate puts the first qubit | 1⟩ into state . The second qubit does not change. Result:



Then the qubits pass through the CNOT gate (which performs the transformations | 00〉 → | 00〉 and | 10〉 → | 11〉). Now their state will be described by the formula



The fourth case: qubits | 11〉 are fed to the input. The Hadamard gate puts the first qubit | 1⟩ into state . The second qubit does not change. Result:



Now we pass the qubits through the CNOT gate, which performs the transformations | 01〉 → | 01〉 and | 11〉 → | 10〉. The final state of a pair of qubits will look like this:



Done, we sorted out all the cases.

Also popular now: