In the previous part of this tutorial, we learned about how a quantum computer works, and we created our first simple quantum application. Now it’s time to complicate things!

To start with the second part of this tutorial, you need to check out this ready-to-use code repository, which contains the Q# application that we are going to analyse in this article. Once cloned, open the Visual Studio solution inside.

Now let’s start analysing the *Driver.cs* file.

The *Main* function allows the running of the following procedures:

*Run_Measurement**Run_Superposition**Run_Entanglement*

Each of these functions allows us to execute a different quantum operation: the first one sets a qubit in a well-known state, then tries to read (measure) it. In the same way, the second one sets a qubit in a **superposition **state, then tries to read it. The third one activates the **entanglement **between two different qubits, also sets the first one in a superposition state, and checks that every time a measurement is taken, the second one has the same state.

By taking a look at the *Operations.qs* file, we can see the mentioned quantum operations, plus one more named *Set*:

```
operation Set(desired: Result, q: Qubit) : Unit
{
// Read the qubit state
if (desired != M(q))
{
// Flip the qubit state if it isn't the desired one
X(q);
}
}
```

This method allows us to set a qubit in a particular state by using the **X** gate. This logic operator flips the qubit state from *Zero* to *One *and vice-versa. So, after reading the current qubit state by using the **M** (*Measurement*) operator, we can flip its state if it isn’t the desired one. Let’s now analyse the second quantum operation, *Measurement*:

```
operation Measurement(count: Int, initial: Result) : (Int, Int)
{
// Variables are represented by the 'mutable' type
mutable numOnes = 0;
using (qubit = Qubit())
{
for (test in 1..count)
{
// Set the qubit in a well-known initial state
Set (initial, qubit);
let res = M (qubit);
// Count the number of |1>
if (res == One)
{
// The 'set' operation allows updating the 'mutable' type value
set numOnes += 1;
}
}
// We have to set the used qubit to the Zero state before release it
Set(Zero, qubit);
}
// Return the number of times that we saw a |0> or a |1>
return (count-numOnes, numOnes);
}
```

For “*count*” times, this method sets a qubit in a well-known state, then tries then to read it. At the end of the execution, the process will print out the read number of 0s and 1s. As expected, by running the *Run_Measurement* function, we can obtain the following result:

```
Running: Measurement Test
Init:Zero 0s=1000 1s=0
Init:One 0s=0 1s=1000
```

So far, nothing special. But, by analysing the third quantum operation, named *Superposition*, we can see the following line of code:

```
// Enable the qubit superposition by using the 'Hadamard' gate
H(qubit);
```

And here is where the magic starts! Thanks to the **H** (*Hadamard*) gate, we can set a qubit in a superposition state, so, until the next measurement, its state can be *Zero* and *One* simultaneously. By running the *Run_Superposition *function, we can now obtain the following result:

```
Running: Superposition Test
Init:Zero 0s=507 1s=493
Init:One 0s=484 1s=516
```

Mind-blowing! As you can see now, the result of the qubit measurement doesn’t always match the initial state. This situation happens because of superposition. Now, let’s analyse the last quantum operation, *Entanglement*:

```
operation Entanglement(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);
// Activate the entanglement between qubits
CNOT(q0,q1);
let res = M (q0);
// Count the number of times that the qubits state is the same for both
if (M(q1) == res)
{
set agree += 1;
}
if (res == One)
{
set numOnes += 1;
}
}
Set(Zero, q0);
Set(Zero, q1);
}
return (count-numOnes, numOnes, agree);
}
```

For “*count*” times, this method sets two qubits in a well-known state, then enables the superposition for the first one, and activates the entanglement between both by using the **CNOT **gate (*ControlNOT*). This gate works as follow: given two qubits, if the measurement of the first one (the *control* qubit) is *Zero*, the state of the second one remains unchanged, or else its state becomes inverted. So, in this way, running the *Run_Entanglement *function, we can obtain the following result:

```
Running: Entanglement Test
Init:Zero 0s=514 1s=486 agree=1000
Init:One 0s=497 1s=503 agree=1000
```

As you can see by the “*agree*” value, for each cycle, the result of the measurement is the same for both qubits. This situation happens because of entanglement, which flips the state of the second qubit from *Zero* to *One*, each time the measurement of the first one is *One*.

The described quantum algorithms can be represented by a graphical notation, which allows us to intuitively build quantum circuits composed of gates and operations. This type of annotation is also used by the IBM Q Experience web tool, helping to develop and testing quantum applications on a real (physic) quantum computer. Below are the graphical notations of the *Superposition *and *Entanglement *quantum operations, described before:

#### Let’s take a look at the mathematics behind

Before we conclude this tutorial, it will be useful to take a look at the mathematical aspect of the gates operators that we have seen. Recalling the definition of qubit *state*, we can see both the *Zero* and the *One* states in a vectorial way, as follow:

Applying a logic gate to a qubit essentially means computing the product between its current state vector and the matrix associated with the logic gate. For example, if we take a look at the **X** gate matrix, we can apply it to the *Zero* state, like this:

Consequently, the resulting state is exactly the inverse of the first one (*One)*. Below are the matrices associated with the **H** and the **CNOT **gates:

Our tutorial ends here!

In the future, I will write more articles about quantum programming, through the implementation of some of the most popular algorithms. Don’t miss them!

Happy coding!