<jupyter_start><jupyter_text><NAME> | April 30, 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 } $ Multiple Rotations The trivial way of implementing more than one rotation in parallel is to use a separate qubit for each rotation.If we have $ t $ different rotations with angles $ \theta_1,\ldots,\theta_t $, then we can use $ t $ qubits.Alternatively, we can use $ \log_2 (t) + 1 $ qubits (assuming that $t$ is a power of 2) that implement the following unitary matrix: $$    R(\theta_1,\ldots,\theta_t) =     \mymatrix{rr|rr|cc|rr}{        \cos \theta_1 & -\sin \theta_1 & 0 & 0 & \cdots & \cdots & 0 & 0 \\         \sin \theta_1 & \cos \theta_1 & 0 & 0 & \cdots & \cdots & 0 & 0 \\ \hline        0 & 0 & \cos \theta_2 & -\sin \theta_2 & \cdots & \cdots  & 0 & 0  \\         0 & 0 & \sin \theta_2 & \cos \theta_2 & \cdots & \cdots  & 0 & 0 \\ \hline        \vdots & \vdots & \vdots & \vdots & \ddots & & \vdots & \vdots \\         \vdots & \vdots & \vdots & \vdots & & \ddots & \vdots & \vdots \\ \hline        0 & 0 & 0 & 0 & \cdots & \cdots & \cos \theta_t & -\sin \theta_t \\         0 & 0 & 0 & 0 & \cdots & \cdots & \sin \theta_t & \cos \theta_t \\     } .$$ We can use this idea to solve the problem $\sf MOD_p$ (see Rotation Automata). We implement $ t $ rotation automata in this way.At the beginning of the computation, we apply Hadamard operator in each qubit. Then, we apply the operator $ R(\theta_1,\ldots,\theta_t) $ for each symbol from the stream. Once the stream is finished, we apply Hadamard operator in each qubit again. If we observe only state 0 in each qubit, then we consider the stream having the length of a multiple of $\sf p$. Otherwise, we consider the stream having the length of not a multiple of $\sf p$.  Constructing $ R(\theta_1,\theta_2) $  When $t=2$, $ \log_2 (2) + 1 = 2 $. So, both implementations use the same number of qubits.But, it is a good starting point to construct the following unitary operator: $$    R(\theta_1,\theta_2) =    \mymatrix{rrrr}{         \cos \theta_1 & -\sin \theta_1 & 0 & 0 \\        \sin \theta_1 & \cos \theta_1 & 0 & 0 \\        0 & 0 & \cos \theta_2 & -\sin \theta_2 \\        0 & 0 & \sin \theta_2 & \cos \theta_2 \\    } .$$  Technical Remark:When two qubits are combined (tensored) in qiskit, say $  qreg[0] $ and $ qreg[1] $, they are ordered as $ qreg[1] \otimes qreg[0] $.If there are $n$ qubits, say $ qreg[0],\ldots,qreg[n-1] $ to be combined, they are ordered in qiskit as $$ qreg[n-1] \otimes \cdots \otimes qreg[0] .  $$ We use a controlled rotation gate $ cu3 $ in qiskit.  Gate $u3$: The gate $ u3 $ is a generic one-qubit gate for rotation on Bloch sphere. It takes three parameters, and if we pass zeros as the second and third parameters, we implement our rotation gate $ ry $:    u3(2*theta,0,0,qubit)is equivalent to    ry(2*theta,qubit)Both make a rotation with angle $\theta$ in the real-valued qubit in counter-clockwise direction.  Gate $cu3$: The two-qubit gate $ cu3 $ takes five parameters. We use it as follows:    cu3(2*theta,0,0,control_qubit,target_qubit)If the control gate is in state $ \ket{1} $, then the rotation        ry(2*theta,target_qubit)is applied (to the target qubit).    The base states of two qubits are ordered as $ \myarray{c}{00 \\ 01 \\ 10 \\ 11 } $ or equivalently grouped as $ \myarray{c}{ 0 \otimes \myvector{0 \\ 1} \\ \hline 1 \otimes \myvector{0 \\ 1} } $. We can apply a rotation to the first qubit controlled by the second qubit.To construct $ R(\theta_1,\theta_2) $:     When the second qubit is in state $ \ket{0} $, we can apply the rotation with angle $ \theta_1 $.      When the second qubit is in state $ \ket{1} $, we can apply the rotation with angle $ \theta_2 $. Now, we implement this by also printing the constructed unitary matrix.<jupyter_code>from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi

# the angles of rotations
theta1 = pi/4
theta2 = pi/6

# the circuit with two qubits
qreg =  QuantumRegister(2) 
creg = ClassicalRegister(2) 
mycircuit = QuantumCircuit(qreg,creg)


# when the second qubit is in |0>, the first qubit is rotated by theta1
mycircuit.x(qreg[1])
mycircuit.cu3(2*theta1,0,0,qreg[1],qreg[0])
mycircuit.x(qreg[1])

# when the second qubit is in |1>, the first qubit is rotated by theta2
mycircuit.cu3(2*theta2,0,0,qreg[1],qreg[0])
              
# we read the unitary matrix
job = execute(mycircuit,Aer.get_backend('unitary_simulator'))
u=job.result().get_unitary(mycircuit,decimals=3)
# we print the unitary matrix in nice format
for i in range(len(u)):
    s=""
    for j in range(len(u)):
        val = str(u[i][j].real)
        while(len(val)<8): val  = " "+val
        s = s + val
    print(s)<jupyter_output>0.707  -0.707     0.0     0.0
   0.707   0.707     0.0     0.0
     0.0     0.0   0.866    -0.5
     0.0     0.0     0.5   0.866<jupyter_text>Task 1Verify that the printed matrix is $ R(\pi/4,\pi/6) $.<jupyter_code>#
# your code is here
#
from math import pi, sin, cos

theta1 = pi/4
theta2 = pi/6

print(round(cos(theta1),3),-round(sin(theta1),3),0,0)
print(round(sin(theta1),3),-round(cos(theta1),3),0,0)
print(0,0,round(cos(theta2),3),-round(sin(theta2),3))
print(0,0,round(sin(theta2),3),-round(cos(theta2),3))<jupyter_output>0.707 -0.707 0 0
0.707 -0.707 0 0
0 0 0.866 -0.5
0 0 0.5 -0.866<jupyter_text>click for our solution  Constructing $ R(\theta_1,\theta_2,\theta_3,\theta_4) $  We can use $ \log_2(4) + 1 = 3 $ qubits to construct $ R(\theta_1,\theta_2,\theta_3,\theta_4) $. The base states of three qubits are ordered as $ \myarray{c}{000 \\ 001 \\ 010 \\ 011 \\ 100 \\ 101 \\ 110 \\ 111 } $ or equivalently grouped as $     \myarray{c}{     00 \otimes \myvector{0 \\ 1} \\ \hline     01 \otimes \myvector{0 \\ 1} \\ \hline     10 \otimes \myvector{0 \\ 1}  \\ \hline     11 \otimes \myvector{0 \\ 1}     } $.  By using a rotation gate controlled by two qubits, we can easily implement our unitary operator.But, if we have a rotation gate controlled by only one qubit, then we use additional tricks (and qubits) and controlled CNOT gate by two qubits (also called Toffoli gate):    circuit.ccx(control-qubit1,control-qubit2,target-qubit)In general, if $ t = 2^n $, then we can construct $ R(\theta_1,\ldots,\theta_t) $ by using no more than $ 2\log_2(t) $ qubits (instead of $t$ qubits).   Pseudo construction     We start with a construction using three angles.  Task 2Consider a quantum circuit with 3 qubits.When the third qubit is in state $ \ket{1} $, apply the gate     cu3(theta1,0,0,qreg[2],qreg[0]) When the second qubit is in state $ \ket{1} $, apply the gate        cu3(theta2,0,0,qreg[1],qreg[0])    When the third qubit is in state $ \ket{0} $, apply the gate    cu3(theta3,0,0,qreg[2],qreg[0])Guess the corresponding unitary matrix, which should be of the form:$$    \mymatrix{rr|rr|rr|rr}{        \cos a_1 & -\sin a_1 & 0 & 0 & 0 & 0 & 0 & 0 \\        \sin a_1 & \cos a_1 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline        0 & 0 & \cos a_2 & -\sin a_2 & 0 & 0 & 0 & 0  \\         0 & 0 & \sin a_2 & \cos a_2 & 0 & 0 & 0 & 0 \\ \hline        0 & 0 & 0 & 0 & \cos a_3 & -\sin a_3 & 0 & 0  \\         0 & 0 & 0 & 0 & \sin a_3 & \cos a_3 & 0 & 0  \\ \hline        0 & 0 & 0 & 0 & 0 & 0 & \cos a_4 & -\sin a_4 \\        0 & 0 & 0 & 0 & 0 & 0 & \sin a_4 & \cos a_4 \\     }$$In other words, find $a_1$, $ a_2 $, $a_3$, and $a_4$ in terms of $ \theta_1 $, $\theta_2$, and $ \theta_3 $. click for our solution Task 3Implement Task 2 by picking three angles, and verify the constructed matrix.<jupyter_code>#
# your solution is here
#
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi, sin, cos

# the angle of rotation
theta1 = pi/23
theta2 = 2*pi/23
theta3 = 4*pi/23

precision = 3

print("a1 = theta3 => sin(a1) = ",round(sin(theta3),precision))
print("a2 = theta2+theta3 => sin(a2) = ",round(sin(theta2+theta3),precision))
print("a3 = theta1 => sin(a3) = ",round(sin(theta1),precision))
print("a4 = theta1+theta2 => sin(a4) = ",round(sin(theta1+theta2),precision))
print()

qreg = QuantumRegister(3) 
creg = ClassicalRegister(3) 
circuit = QuantumCircuit(qreg,creg)

# controlled rotation when the third qubit is |1>
circuit.cu3(2*theta1,0,0,qreg[2],qreg[0])

# controlled rotation when the second qubit is |1>
circuit.cu3(2*theta2,0,0,qreg[1],qreg[0])

# controlled rotation when the third qubit is |0>
circuit.x(qreg[2])
circuit.cu3(2*theta3,0,0,qreg[2],qreg[0])
circuit.x(qreg[2])

# read the corresponding unitary matrix
job = execute(circuit,Aer.get_backend('unitary_simulator'))
unitary_matrix=job.result().get_unitary(circuit,decimals=precision)
for i in range(len(unitary_matrix)):
    s=""
    for j in range(len(unitary_matrix)):
        val = str(unitary_matrix[i][j].real)
        while(len(val)<precision+4): val  = " "+val
        s = s + val
    print(s)<jupyter_output>a1 = theta3 => sin(a1) =  0.52
a2 = theta2+theta3 => sin(a2) =  0.731
a3 = theta1 => sin(a3) =  0.136
a4 = theta1+theta2 => sin(a4) =  0.398

  0.854  -0.52    0.0    0.0    0.0    0.0    0.0    0.0
   0.52  0.854    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0  0.683 -0.731    0.0    0.0    0.0    0.0
    0.0    0.0  0.731  0.683    0.0    0.0    0.0    0.0
    0.0    0.0    0.0    0.0  0.991 -0.136    0.0    0.0
    0.0    0.0    0.0    0.0  0.136  0.991    0.0    0.0
    0.0    0.0    0.0    0.0    0.0    0.0  0.917 -0.398
    0.0    0.0    0.0    0.0    0.0    0.0  0.398  0.917<jupyter_text>click for our solution Task 4Create a circuit for solving problem $ \sf MOD_{31} $ by using the implementation in Task 3.Pick $ \theta_1 $, $ \theta_2 $, and $ \theta_3 $ randomly.At the beginning of the stream and after reading the stream, apply Hadamard operators to each qubit.Execute your quantum program on the streams of lengths from 1 to 31.<jupyter_code>#
# your solution is here
#
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi, sin, cos
from random import randrange

# the angle of rotation
k1 = randrange(1,31)
theta1 = k1*2*pi/31
k2 = randrange(1,31)
theta2 = k2*2*pi/31
k3 = randrange(1,31)
theta3 = k3*2*pi/31

max_percentange = 0
    
# for each stream of length from 1 to 31
for i in range(1,32):    
    # initialize the circuit
    qreg = QuantumRegister(3) 
    creg = ClassicalRegister(3) 
    circuit = QuantumCircuit(qreg,creg)
    
    # Hadamard operators before reading the stream
    for m in range(3):
        circuit.h(qreg[m])   
        
    # read the stream of length i
    print("stream of length",i,"is being read")
    for j in range(i):    
        # controlled rotation when the third qubit is |1>
        circuit.cu3(2*theta1,0,0,qreg[2],qreg[0])

        # controlled rotation when the second qubit is |1>
        circuit.cu3(2*theta2,0,0,qreg[1],qreg[0])

        # controlled rotation when the third qubit is |0>
        circuit.x(qreg[2])
        circuit.cu3(2*theta3,0,0,qreg[2],qreg[0])
        circuit.x(qreg[2])
        
    # Hadamard operators after reading the stream
    for m in range(3):
        circuit.h(qreg[m])  
    # we measure after reading the whole stream
    circuit.measure(qreg,creg)
    # execute the circuit N times
    N = 1000
    job = execute(circuit,Aer.get_backend('qasm_simulator'),shots=N)
    counts = job.result().get_counts(circuit)
    print(counts)
    if '000' in counts.keys():
        c = counts['000']
    else:
        c = 0
    print('000 is observed',c,'times out of',N)
    percentange = round(c/N*100,1)
    if max_percentange < percentange and i != 31: max_percentange = percentange
    print("the ration of 000 is ",percentange,"%")
    print()  
print("maximum percentage of observing unwanted '000' is",max_percentange)<jupyter_output>stream of length 1 is being read
{'001': 27, '010': 24, '110': 272, '100': 99, '111': 83, '101': 342, '000': 80, '011': 73}
000 is observed 80 times out of 1000
the ration of 000 is  8.0 %

stream of length 2 is being read
{'001': 12, '010': 238, '110': 187, '100': 9, '111': 445, '101': 2, '000': 1, '011': 106}
000 is observed 1 times out of 1000
the ration of 000 is  0.1 %

stream of length 3 is being read
{'001': 279, '010': 682, '111': 26, '100': 10, '000': 2, '011': 1}
000 is observed 2 times out of 1000
the ration of 000 is  0.2 %

stream of length 4 is being read
{'001': 53, '010': 6, '110': 11, '100': 661, '111': 84, '101': 168, '000': 16, '011': 1}
000 is observed 16 times out of 1000
the ration of 000 is  1.6 %

stream of length 5 is being read
{'001': 151, '010': 23, '110': 44, '100': 122, '111': 29, '101': 251, '000': 327, '011': 53}
000 is observed 327 times out of 1000
the ration of 000 is  32.7 %

stream of length 6 is being read
{'001': 1, '010': 6, '111': 2, '101': 26, [...]<jupyter_text>click for our solution Task 5 (optional)Based on Task 4, design your own solution for problem $ \sf MOD_{91} $ by using four qubits.Remark that up to 8 different rotations can be implemented by using four qubits.<jupyter_code>#
# your solution is here
#<jupyter_output><empty_output><jupyter_text>Main construction  To implement an operator controlled by two qubits, we use an auxiliary qubit.Depending on the desired values of two qubits, the auxiliary qubit is flipped to $ \ket{1} $ and then the operation is implemented controlled by the auxiliary qubit.Here we describe the case when the control qubits are in state $ \ket{01} $. We also draw the circuit.<jupyter_code>from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi

# initialize the circuit
qreg = QuantumRegister(4)  
circuit = QuantumCircuit(qreg)

# we use the fourth qubit as the auxiliary

# apply a rotation to the first qubit when the third and second qubits are in states |0> and |1>
# change the state of the third qubit to |1>
circuit.x(qreg[2])
# if both the third and second qubits are in states |1>, the state of auxiliary qubit is changed to |1> 
circuit.ccx(qreg[2],qreg[1],qreg[3])
# the rotation is applied to the first qubit if the state of auxiliary qubit is |1>
circuit.cu3(2*pi/6,0,0,qreg[3],qreg[0])
# reverse the effects
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.x(qreg[2])

circuit.draw()<jupyter_output><empty_output><jupyter_text>Based on this idea, different rotation operators are applied to the first qubit when the third and second qubits are in $ \ket{00} $, $ \ket{01} $, $ \ket{10} $, and $ \ket{11} $. We present how to construct $ R(\pi/10,2\pi/10,3\pi/10,4\pi/10) $.<jupyter_code>from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi,sin

# the angles of rotations
theta1 = pi/10
theta2 = 2*pi/10
theta3 = 3*pi/10
theta4 = 4*pi/10

# for verification, print sin(theta)'s
print("sin(theta1) = ",round(sin(theta1),3))
print("sin(theta2) = ",round(sin(theta2),3))
print("sin(theta3) = ",round(sin(theta3),3))
print("sin(theta4) = ",round(sin(theta4),3))
print()

qreg =  QuantumRegister(4) 
circuit = QuantumCircuit(qreg)

# the third qubit is in |0>
# the second qubit is in |0>
circuit.x(qreg[2])
circuit.x(qreg[1])
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.cu3(2*theta1,0,0,qreg[3],qreg[0])
# reverse the effects
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.x(qreg[1])
circuit.x(qreg[2])


# the third qubit is in |0>
# the second qubit is in |1>
circuit.x(qreg[2])
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.cu3(2*theta2,0,0,qreg[3],qreg[0])
# reverse the effects
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.x(qreg[2])

# the third qubit is in |1>
# the second qubit is in |0>
circuit.x(qreg[1])
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.cu3(2*theta3,0,0,qreg[3],qreg[0])
# reverse the effects
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.x(qreg[1])

# the third qubit is in |1>
# the second qubit is in |1>
circuit.ccx(qreg[2],qreg[1],qreg[3])
circuit.cu3(2*theta4,0,0,qreg[3],qreg[0])
# reverse the effects
circuit.ccx(qreg[2],qreg[1],qreg[3])

# read the corresponding unitary matrix
job = execute(circuit,Aer.get_backend('unitary_simulator'))
unitary_matrix=job.result().get_unitary(circuit,decimals=3)
for i in range(len(unitary_matrix)):
    s=""
    for j in range(len(unitary_matrix)):
        val = str(unitary_matrix[i][j].real)
        while(len(val)<7): val  = " "+val
        s = s + val
    print(s)<jupyter_output>sin(theta1) =  0.309
sin(theta2) =  0.588
sin(theta3) =  0.809
sin(theta4) =  0.951

  0.951 -0.309    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
  0.309  0.951    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0  0.809 -0.588    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0  0.588  0.809    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0    0.0    0.0  0.588 -0.809    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0    0.0    0.0  0.809  0.588    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0    0.0    0.0    0.0    0.0  0.309 -0.951    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    0.0    0.0    0.0    0.0    0.0  0.951  0.309    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0
    0.0    [...]<jupyter_text>Remarks: The constructed matrix is bigger than our main matrix because of the auxiliary qubit.Our main matrix appears at the top-left quarter of the constructed matrix.The rest of the constructed matrix does not affect our computation unless the auxiliary qubit is set to state $ \ket{1} $ (except the auxiliary operations). Task 6 (optional)Assume that $\theta_1=\frac{\pi}{11}$, $\theta_2=2\frac{\pi}{11}$, $\theta_3=4\frac{\pi}{11}$, and $\theta_4=8\frac{\pi}{11}$ are the given angles in the above construction.Calculate (by hand or in your mind) the angles of the rotations in the bottom-left quarter of the constructed matrix by following the construction steps. Task 7Create a circuit for solving problem $ \sf MOD_{61} $ by using the above implementation.Pick $ \theta_1 $, $ \theta_2 $, $ \theta_3 $, and $ \theta_4 $ randomly.At the beginning of the stream and after reading the stream, apply Hadamard operators to each qubit.Execute your quantum program on the streams of lengths 1, 11, 21, 31, 41, 51, and 61.<jupyter_code>#
# your solution is here
#
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from math import pi,sin

# the angle of rotation
k1 = randrange(1,61)
theta1 = k1*2*pi/61
k2 = randrange(1,61)
theta2 = k2*2*pi/61
k3 = randrange(1,61)
theta3 = k3*2*pi/61
k4 = randrange(1,61)
theta4 = k4*2*pi/61

max_percentange = 0

# for each stream of length of 1, 11, 21, 31, 41, 51, and 61
for i in [1,11,21,31,41,51,61]: 
#for i in range(1,62): 
    # initialize the circuit
    qreg =  QuantumRegister(4) 
    creg = ClassicalRegister(4)
    circuit = QuantumCircuit(qreg,creg)

    # Hadamard operators before reading the stream
    for m in range(3):
        circuit.h(qreg[m])   
        
    # read the stream of length i
    print("stream of length",i,"is being read")
    for j in range(i):         
        # the third qubit is in |0>
        # the second qubit is in |0>
        circuit.x(qreg[2])
        circuit.x(qreg[1])
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.cu3(2*theta1,0,0,qreg[3],qreg[0])
        # reverse the effects
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.x(qreg[1])
        circuit.x(qreg[2])


        # the third qubit is in |0>
        # the second qubit is in |1>
        circuit.x(qreg[2])
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.cu3(2*theta2,0,0,qreg[3],qreg[0])
        # reverse the effects
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.x(qreg[2])

        # the third qubit is in |1>
        # the second qubit is in |0>
        circuit.x(qreg[1])
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.cu3(2*theta3,0,0,qreg[3],qreg[0])
        # reverse the effects
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.x(qreg[1])

        # the third qubit is in |1>
        # the second qubit is in |1>
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        circuit.cu3(2*theta4,0,0,qreg[3],qreg[0])
        # reverse the effects
        circuit.ccx(qreg[2],qreg[1],qreg[3])
        
    # Hadamard operators after reading the stream
    for m in range(3):
        circuit.h(qreg[m])  
    # we measure after reading the whole stream
    circuit.measure(qreg,creg)
    # execute the circuit N times
    N = 1000
    job = execute(circuit,Aer.get_backend('qasm_simulator'),shots=N)
    counts = job.result().get_counts(circuit)
    print(counts)
    if '0000' in counts.keys():
        c = counts['0000']
    else:
        c = 0
    print('0000 is observed',c,'times out of',N)
    percentange = round(c/N*100,1)
    if max_percentange < percentange and i != 61: max_percentange = percentange
    print("the ration of 0000 is ",percentange,"%")
    print()  
print("maximum percentage of observing unwanted '0000' is",max_percentange)<jupyter_output>stream of length 1 is being read
{'0001': 163, '0010': 14, '0110': 334, '0100': 91, '0111': 36, '0101': 94, '0000': 30, '0011': 238}
0000 is observed 30 times out of 1000
the ration of 0000 is  3.0 %

stream of length 11 is being read
{'0001': 790, '0010': 7, '0110': 1, '0100': 25, '0111': 2, '0101': 9, '0000': 163, '0011': 3}
0000 is observed 163 times out of 1000
the ration of 0000 is  16.3 %

stream of length 21 is being read
{'0001': 93, '0010': 298, '0110': 6, '0100': 59, '0111': 120, '0101': 233, '0000': 14, '0011': 177}
0000 is observed 14 times out of 1000
the ration of 0000 is  1.4 %

stream of length 31 is being read
{'0001': 235, '0010': 543, '0110': 6, '0100': 32, '0111': 120, '0101': 51, '0000': 4, '0011': 9}
0000 is observed 4 times out of 1000
the ration of 0000 is  0.4 %

stream of length 41 is being read
{'0001': 43, '0010': 148, '0111': 11, '0110': 68, '0100': 72, '0000': 277, '0011': 381}
0000 is observed 277 times out of 1000
the ration of 0000 is  27.7 %

stream of[...]
{'fraction_non_alphanumeric': 0.15067689341548263, 'fraction_numerical': 0.08956787794962069, 'mean_word_length': 2.9926372155287817, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 15, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '274836', 'license': 'MIT', 'n_tokens_mistral': 9912, 'n_tokens_neox': 8679, 'n_words': 2782, 'path': 'bronze/B76_Multiple_Rotations.ipynb', 'repo_name': 'zeynepCankara/Introduction-Quantum-Programming', 'size': '23871'}