<jupyter_start><jupyter_text>Updated by <NAME>        <NAME> | July 07, 2019 (updated)                This cell contains some macros. If there is a problem with displaying mathematical formulas, please run this cell to load these macros.    $ \newcommand{\bra}[1]{\langle 1|} $$ \newcommand{\ket}[1]{|1\rangle} $$ \newcommand{\braket}[2]{\langle 1|2\rangle} $$ \newcommand{\dot}[2]{ 1 \cdot 2} $$ \newcommand{\biginner}[2]{\left\langle 1,2\right\rangle} $$ \newcommand{\mymatrix}[2]{\left( \begin{array}{1} 2\end{array} \right)} $$ \newcommand{\myvector}[1]{\mymatrix{c}{1}} $$ \newcommand{\myrvector}[1]{\mymatrix{r}{1}} $$ \newcommand{\mypar}[1]{\left( 1 \right)} $$ \newcommand{\mybigpar}[1]{ \Big( 1 \Big)} $$ \newcommand{\sqrttwo}{\frac{1}{\sqrt{2}}} $$ \newcommand{\dsqrttwo}{\dfrac{1}{\sqrt{2}}} $$ \newcommand{\onehalf}{\frac{1}{2}} $$ \newcommand{\donehalf}{\dfrac{1}{2}} $$ \newcommand{\hadamard}{ \mymatrix{rr}{ \sqrttwo & \sqrttwo \\ \sqrttwo & -\sqrttwo }} $$ \newcommand{\vzero}{\myvector{1\\0}} $$ \newcommand{\vone}{\myvector{0\\1}} $$ \newcommand{\vhadamardzero}{\myvector{ \sqrttwo \\  \sqrttwo } } $$ \newcommand{\vhadamardone}{ \myrvector{ \sqrttwo \\ -\sqrttwo } } $$ \newcommand{\myarray}[2]{ \begin{array}{1}2\end{array}} $$ \newcommand{\X}{ \mymatrix{cc}{0 & 1 \\ 1 & 0}  } $$ \newcommand{\Z}{ \mymatrix{rr}{1 & 0 \\ 0 & -1}  } $$ \newcommand{\Htwo}{ \mymatrix{rrrr}{ \frac{1}{2} & \frac{1}{2} & \frac{1}{2} & \frac{1}{2} \\ \frac{1}{2} & -\frac{1}{2} & \frac{1}{2} & -\frac{1}{2} \\ \frac{1}{2} & \frac{1}{2} & -\frac{1}{2} & -\frac{1}{2} \\ \frac{1}{2} & -\frac{1}{2} & -\frac{1}{2} & \frac{1}{2} } } $$ \newcommand{\CNOT}{ \mymatrix{cccc}{1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0} } $$ \newcommand{\norm}[1]{ \left\lVert 1 \right\rVert } $  Quantum Operators  Once the quantum state is defined, the definition of quantum operator is very easy.Any length preserving (square) matrix is a quantum operator, and vice versa.Such matrices are called unitary when they are allowed to have complex entries and  orthonormal when they are restricted to have real entries.     So if $A$ is such a matrix and $v$ is any vector, $||Av||=||v||$.If $v$ represents a quantum state, then $||v||=1$ and application of a quantum operator results in another quantum state $v'$ with $||v'||=1$.  Unlike the classical operators, all quantum operators are reversible. Probabilistic vs Quantum                Probabilistic           Quantum          Vector representation      $\myvector{a\\b}$ $a+b=1$, $a,b \geq 0$     $\myvector{\alpha \\ \beta}$ $\alpha^2+\beta^2=1$, $\alpha, \beta \in [-1,1]$                    Stochastic vector      Unit vector           Operator        Stochastic      Unitary                Visual representation                                  IDENTITY operator  IDENTITY operator does not change the state of a qubit.      $ I = \mymatrix{rr}{1 & 0 \\0 & 1}$     (We use capital letter for the matrix form of the operators)  NOT operator NOT operator flips the value of a qubit.$ X = \X$ A technical note: Why is operator NOT referred as x-gate?Recall the Bloch Sphere. In three dimensions, we have axes: x, y, and z. X refers to the rotation with respect to x-axis.Similarly, we have the rotation with respect to y-axis and z-axis.In Bronze, we will also see the operator Z (z-gate).The operator Y is defined with complex numbers. The action of $ X $ on the qubit:$ X \ket{0} = \ket{1} $. More explicitly, $ X \ket{0} = \X \vzero = \vone = \ket{1} $.Similarly, $ X \ket{1} = \ket{0} $.More explicitly, $ X \ket{1} = \X \vone = \vzero = \ket{0} $.  Our first quantum circuit Having defined quantum operators, now we are ready to write our first quantum circuit.For our quantum programs, we will design quantum circuits.As a warm-up example, here we design a circuit with a single quantum bit.We also highlight the details on designing quantum circuits along with our codes.<jupyter_code># 
# A quantum circuit is composed by quantum and classical bits.
#

# here are the objects that we use to create a quantum circuit in qiskit
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

# we use a quantum register to keep our quantum bits.
qreg =  QuantumRegister(1) # in this example we will use a single quantum bit

# To get an information from a quantum bit, it must be measured. (More details will appear.)
#     The measurement result is stored classically.
#     Therefore, we also use a classical regiser with classical bit(s)
creg = ClassicalRegister(1) # in this example we will use a single classical bit

# now we can define our quantum circuit
# it is composed by a quantum and a classical registers
mycircuit1 = QuantumCircuit(qreg,creg)

# we apply operators on quantum bits
# operators are called as gates
# we apply NOT operator represented as "x" in qiskit
# operator is a part of the circuit, and we should specify the quantum bit as its parameter
mycircuit1.x(qreg[0]) # (quantum) bits are enumerated starting from 0
# NOT operator or x-gate is applied to the first qubit of the quantum register

# we run our codes until now, and then draw our circuit
print("Everything looks fine, let's continue ...")
# in qiskit, the circuit object has a method called "draw"
# the default drawing method uses ASCII art

# let's draw our circuit now 
mycircuit1.draw()

# re-execute this cell if you DO NOT see the circuit diagram<jupyter_output><empty_output><jupyter_text>Congratulations! if you see your diagram :-)  Remark: Qiskit has its own counters to enumerate the objects ($ q2_0 $, $ c2_0 $, etc.).      They might be useful for debugging, but currently you can simply discard this part.     You may also notice that when you re-run the same codes, the object numbers will be increased. You may also use matplotlib to draw your circuits.<jupyter_code>mycircuit1.draw(output='mpl')<jupyter_output><empty_output><jupyter_text>Initially, the value of the quantum bit is 0 or the quantum bit is in state 0. Initially, the value of the classical bit is also 0 or the classical bit is in state 0. Each quantum bit is represented as a single straight line. Each classical bit is represented as a double straight line. You may think of them as wires.The x-gate is shown as a square.The state of the quantum bit is expected to be $ \ket{1} $ after the operator.Let's measure the first qubit (define a mesurement operator), and then execute our circuit and see the result.<jupyter_code># measurement is defined by associating a quantum bit to a classical bit
mycircuit1.measure(qreg,creg)
# the result will be stored in the classical bit

print("Everything looks fine, let's continue ...")
# let's draw the circuit again to see how the measurement is defined
# we use drawing method "matplotlib" this time

mycircuit1.draw(output='mpl')
# reexecute this cell if you DO NOT see the circuit diagram
# we are done with designing of our circuit
# now we can execute it
# we usually execute quantum circuits many times (WHY?)

# we use the method "execute" and the object "Aer" from qiskit library
from qiskit import execute, Aer

# we create a job object for execution of the circuit
# there are three parameters
#     1. mycircuit
#     2. beckend on which it will be executed: we will use local simulator
#     3. how many times it will be executed, let's pick it as 1024
job = execute(mycircuit1,Aer.get_backend('qasm_simulator'),shots=1024)

# we can get the result of the outcome as follows
counts = job.result().get_counts(mycircuit1)
print(counts) # counts is a dictionary<jupyter_output>{'1': 1024}<jupyter_text>We expect to see 1 in each execution, and so the output should be $ \{\mbox{'1'}:~1024\} $. That is, the outcome 1 is measured 1024 times.The output is composed by pairs, and each pair showes (i) the measurement outcome and (ii) its frequency. For example, if the output is $ \{\mbox{'0': 500, '1': 524}\} $, then we know that the outcome 0 is measured 500 times and the outcome 1 is measured 524 times.  Quantum programs usually give probabilistic outcomes.     Therefore, we should execute them many times to get more reliable outcomes.    Open Quantum Assembly Language We can print qasm (Open Quantum Assembly Language) code of our circuit.On the simulators or real quantum computers, qasm codes are executed.<jupyter_code>#print qasm code of our program

print(mycircuit1.qasm())<jupyter_output>OPENQASM 2.0;
include "qelib1.inc";
qreg q0[1];
creg c0[1];
x q0[0];
measure q0[0] -> c0[0];<jupyter_text>Z-gate (operator) The indentity operator $ I = \mymatrix{cc}{1 & 0 \\ 0 & 1} $ does not affect the computation.What about the following operator?$ Z = \Z $.It is very similar to the identity operator. The action of $ Z $ on the qubit:$ Z \ket{0} = \ket{0} $. More explicitly, $ Z \ket{0} = \Z \vzero =  \myvector{1 \\ 0} = \ket{0} $. $ Z \ket{1} = -\ket{1} $.More explicitly, $ Z \ket{1} = \Z \vone = \myvector{0 \\ -1}  = -\ket{1} $. Consider the quantum state $ \ket{u} = \myvector{ \frac{3}{5} \\ \frac{4}{5} }  $. Let's calculate the new quantum state after applying $ Z $ to $ \ket{u} $:$ \ket{u'} = Z \ket{u} =  \Z  \myvector{ \frac{3}{5} \\ \frac{4}{5} } =  \myrvector{ \frac{3}{5} \\ -\frac{4}{5} } $.The quantum states $ \ket{u} $ and $ \ket{u'} $ look similar. The probabilities of observing state $\ket{0}$ and state $\ket{1}$ are the same when the system is in $ \ket{u} $ or $ \ket{u'} $.On the other hand, they are far away from each other as shown below:   Our second quantum circuit Let's create a circuit with a single qubit, first apply the x-gate and then the z-gate.<jupyter_code># 
# A quantum circuit is composed by quantum and classical bits.
#

# here are the objects that we use to create a quantum circuit in qiskit
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

# we use a quantum register to keep our quantum bits.
# we may also give a name to our register
qreg =  QuantumRegister(1) # in this example we willuse a single quantum bit

# To get an information from a quantum bit, it must be measured. (More details will appear.)
#     The measurement result is stored classically.
#     Therefore, we also use a classical regiser with classical bit(s)
creg = ClassicalRegister(1,name='c') # in this example we will use a single classical bit

# now we can define our quantum circuit
# it is composed by a quantum and a classical registers
mycircuit2 = QuantumCircuit(qreg,creg)

# we apply operators on quantum bits
# operators are called as gates
# we apply NOT operator represented as "x" in qiskit
# operator is a part of the circuit, and we should specify the quantum bit as its parameter
mycircuit2.x(qreg[0]) # (quantum) bits are enumerated starting from 0
# NOT operator or x-gate is applied to the first qubit of the quantum register

mycircuit2.z(qreg[0])
# z-gate is applied to the first qubit of the quantum register

# we run our codes until now, and then draw our circuit
print("Everything looks fine, let's continue ...")
# let's draw our circuit now 
mycircuit2.draw()

# re-execute this cell if you DO NOT see the circuit diagram<jupyter_output><empty_output><jupyter_text>Initially, the value of the quantum bit is 0 or the quantum bit is in state $\ket{0}$. Initially, the value of the classical bit is also 0 or the classical bit is in state 0. The state of the quantum bit is expected to be $ \ket{1} $ after the X operator and $- \ket{1}$ after the Z operator.Let's measure the first qubit (define a mesurement operator), and then execute our circuit and see the result.<jupyter_code># measurement is defined by associating a quantum bit to a classical bit
mycircuit2.measure(qreg[0],creg[0])
# the result will be stored in the classical bit


# let's draw the circuit again to see how the measurement is defined
# we use drawing method "matplotlib"

mycircuit2.draw(output='mpl')
# reexecute me if you DO NOT see the circuit diagram
# we are done with designing of our circuit
# now we can execute it
# we execute quantum circuits many times (WHY?)

# we use the method "execute" and the object "Aer" from qiskit library
from qiskit import execute, Aer

# we create a job object for execution of the circuit
# there are three parameters
#     1. mycircuit
#     2. beckend on which it will be executed: we will use local simulator
#     3. how many times it will be executed, let's pick it as 1024
job = execute(mycircuit2,Aer.get_backend('qasm_simulator'),shots=1024)

# we can get the result of the outcome as follows
counts = job.result().get_counts(mycircuit2)
print(counts) # counts is a dictionary<jupyter_output>{'1': 1024}<jupyter_text>We expect to see 1 in each execution since the amplitude of state $\ket{1}$ is -1 and the probability of observing $\ket{1}$ is therefore 1.So the output should be  {'1': 1024} .That is, the outcome 1 is measured 1024 times.  Hadamard operatorHadamard operator ($ H $ or h-gate) looks like a fair coin-flipping.$    H = \hadamard.$But, there are certain dissimilarities:     we have a negative entry, and     instead of $ \frac{1}{2} $, we have its square root $ \mypar{ \frac{1}{\sqrt{2}} } $. Quantum systems can have negative transitions. Can probabilistic system be extended with negative values?   One-step HadamardLet's start in $ \ket{0} $.After applying $ H $:$$  H \ket{0} =  \hadamard \vzero =  \vhadamardzero.$$After measurement, we observe the states $ \ket{0} $ and $ \ket{1} $ with equal probability $ \frac{1}{2} $.   Let's start in $ \ket{1} $.After applying $ H $:$$    H \ket{1} = \hadamard \vone = \vhadamardone.$$After measurement, we observe the states $ \ket{0} $ and $ \ket{1} $ with equal probability $ \frac{1}{2} $. We obtain the same values even when one of the values is negative.   In the above example, the amplitudes of states $\ket{0}$ and $ \ket{1} $ are respectively $ \sqrttwo $ and $ -\sqrttwo $.The probabilities of observing them after a measurement are $ \onehalf $.  Task 1Randomly create a 2-dimensional quantum state, and test whether Hadamard operator preserves its length or not.Repeat 10 times:     Randomly create a quantum state      Multiply Hadamard matrix with the randomly created quantum state      Check whether the quantum state in result is valid You may use the functions you have written  previously.<jupyter_code>#
# your code is here
#<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11114985008018967, 'fraction_numerical': 0.02133742416846803, 'mean_word_length': 3.856755841517101, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '279712', 'license': 'MIT', 'n_tokens_mistral': 4441, 'n_tokens_neox': 4138, 'n_words': 1919, 'path': 'bronze/B29_Quantum_Operators.ipynb', 'repo_name': 'HasanIjaz-HB/Quantum-Computing', 'size': '14359'}