# Expand the Width of the Cells to a ratio of 100%
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

# Update, the Conda's version, if necessary
!conda update -n base conda --yes

# Install other useful Libraries for Quantum Information Science,
# the QuTiP Framework, in this case, based on Python Programming Language
!conda install qutip --yes

# Import the matplotlib Library
import matplotlib.pyplot as plt
%matplotlib inline

# Import the NumPy and Math Libraries,
# based on Python Programming Language
import numpy as np
import math

# Import some basic Modules from Qiskit Library and configuring account
from qiskit import IBMQ, BasicAer
from qiskit import QuantumCircuit, execute, Aer, IBMQ, QuantumRegister, ClassicalRegister
from qiskit.compiler import transpile, assemble
from qiskit.providers.ibmq import least_busy
from qiskit.tools.jupyter import *
from qiskit.visualization import *

# Import some basic Visualization/Plot Modules/Tools from Qiskit Library
from qiskit.tools.visualization import plot_histogram

# In Jupyter Notebooks we can display this nicely using Latex.
# If not using Jupyter Notebooks you may need to remove the 
# array_to_latex function and use print() instead.
from qiskit_textbook.tools import array_to_latex

# Import Operator Module from Qiskit Library, for Custom Operators
from qiskit.quantum_info.operators import Operator



def cz(circuit, qr):
    
    circuit.h(qr[1])
    
    circuit.cx(qr[0],qr[1])
    
    circuit.h(qr[1])

# Create a Classical Register for 2 Bits (Classical Bits), with a Total of 2 Possible Processed States
qr2 = QuantumRegister(2)

czCircuit = QuantumCircuit(qr2)

cz(czCircuit,qr2)

czCircuit.draw(output="mpl")

def ccz(circuit,qr):
    
    circuit.h(qr[2])
    
    # CCX is the Toffoli gate 
    circuit.ccx(qr[0], qr[1], qr[2])
    
    circuit.h(qr[2])

qr3 = QuantumRegister(3)

cczCircuit = QuantumCircuit(qr3)

ccz(cczCircuit,qr3)

cczCircuit.draw(output="mpl")

def cccz(circuit,qr):
    pi = math.pi
    
    circuit.cu1(pi/4,qr[0],qr[3])
    circuit.cx(qr[0], qr[1])
    circuit.cu1(-pi/4, qr[1],qr[3])
    circuit.cx(qr[0], qr[1])
    circuit.cu1(pi/4, qr[1],qr[3])
    circuit.cx(qr[1], qr[2])
    circuit.cu1(-pi/4, qr[2],qr[3])
    circuit.cx(qr[0], qr[2])
    circuit.cu1(pi/4, qr[2],qr[3])
    circuit.cx(qr[1], qr[2])
    circuit.cu1(-pi/4, qr[2],qr[3])
    circuit.cx(qr[0], qr[2])
    circuit.cu1(pi/4, qr[2],qr[3])

qr4 = QuantumRegister(4)

ccczCircuit = QuantumCircuit(qr4)

cccz(ccczCircuit,qr4)

ccczCircuit.draw(output="mpl")

def ccccz(circuit, qr):

    unitaryMatrixCCCCZ = Operator([
        [1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, 1, 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, -1] 
    ])
    
    circuit.unitary(unitaryMatrixCCCCZ, qr, label='CCCCZ')

qr5 = QuantumRegister(5)

cccczCircuit = QuantumCircuit(qr5)

ccccz(cccczCircuit,qr5)

cccczCircuit.draw(output="mpl")

def n_controlled_Z(circuit, qr):
    
    # Implement a Z-Gate with multiple controls
    if (len(qr) > 5):
        raise ValueError('The Controlled-Z with more than 4 Control-Qubits is not implemented!!!')
        
    # This is the case n = 2 (1 control + 1 target Qubit)
    elif (len(qr) == 2):
        cz(circuit,qr)
        
    # This is the case n = 3 (2 control + 1 target Qubit)
    elif (len(qr) == 3):
        ccz(circuit,qr)
        
    # This is the case n = 4 (3 control + 1 target Qubit)
    elif (len(qr) == 4):
        cccz(circuit,qr)
    
    # Extra Exercise (Made by Rúben André Barreiro)
    # This is the case n = 5 (4 control + 1 target Qubit)
    elif (len(qr) == 5):
        cccz(circuit,qr)

# Getting the Backend for the Unitary Representation of the Controlled-Z Gate
# (i.e., the Quantum State represented as an Unitary Matrix)
backend = Aer.get_backend('unitary_simulator')
unitaryCZ = execute(czCircuit,backend).result().get_unitary()
unitaryCCZ = execute(cczCircuit,backend).result().get_unitary()
unitaryCCCZ = execute(ccczCircuit,backend).result().get_unitary()
unitaryCCCCZ = execute(cccczCircuit,backend).result().get_unitary()

array_to_latex(unitaryCZ, pretext="\\text{CZ (Controlled-Z) = }\n")
array_to_latex(unitaryCCZ, pretext="\\text{CCZ (Controlled-Controlled-Z) = }\n")
array_to_latex(unitaryCCCZ, pretext="\\text{CCCZ (Controlled-Controlled-Controlled-Z) = }\n")

# Extra Exercise (not asked by the Professors):
# - Multi Controlled-Z Gate for 5 Qubits (Made by Rúben André Barreiro)
array_to_latex(unitaryCCCCZ, pretext="\\text{CCCZ (Controlled-Controlled-Controlled-Controlled-Z) = }\n")

def phase_oracle(circuit,qr,element):
    
    # Element is an Array that defines the searched Element,
    # for example, Element = [0,1,0,1]
    
    for j,x in enumerate(element):
        if (x == 0):
            circuit.x(qr[j])
    
    circuit.barrier()
    
    n_controlled_Z(circuit,qr) 
    
    circuit.barrier()
    
    for j,x in enumerate(element):
        if (x == 0):
            circuit.x(qr[j])

def mark_state(element_test_state, testCircuit):
    
    for qubit_index, element in enumerate(element_test_state):
        if element == 1:
            testCircuit.x(qubit_index)
    
    testCircuit.barrier()

# Defining some tests, for the Phase Oracle, with n = 2

#element_test_2_states = [0,0]

element_test_2_states = [0,1]

#element_test_2_states = [1,0]

#element_test_2_states = [1,1]

qr2 = QuantumRegister(2)

testFunctionCircuit2 = QuantumCircuit(qr2)

element_test_2_states_binary = ''.join(map(str,element_test_2_states))

print("The Marked State is: |{}⟩".format(element_test_2_states_binary))

element_test_2_states.reverse()

mark_state(element_test_2_states, testFunctionCircuit2)

phase_oracle(testFunctionCircuit2,qr2,element_test_2_states)

testFunctionCircuit2.draw(output="mpl")

# Getting the Backend for the Statevector Representation
# (i.e., the Quantum State represented as State Vector)
statevector_backend = Aer.get_backend('statevector_simulator')
final_state = execute(testFunctionCircuit2,statevector_backend).result().get_statevector()

array_to_latex(final_state, pretext="\\text{Final State for Marked State (Statevector) = }\n", precision = 1)

# Defining some tests, for the Phase Oracle, with n = 3

#element_test_3_states = [0,0,0]

#element_test_3_states = [0,0,1]

#element_test_3_states = [0,1,0]

element_test_3_states = [0,1,1]

#element_test_3_states = [1,0,0]

#element_test_3_states = [1,0,1]

#element_test_3_states = [1,1,0]

#element_test_3_states = [1,1,1]

qr3 = QuantumRegister(3)

testFunctionCircuit3 = QuantumCircuit(qr3)

element_test_3_states_binary = ''.join(map(str,element_test_3_states))

print("The Marked State is: |{}⟩".format(element_test_3_states_binary))

element_test_3_states.reverse()

mark_state(element_test_3_states, testFunctionCircuit3)

phase_oracle(testFunctionCircuit3,qr3,element_test_3_states)

testFunctionCircuit3.draw(output="mpl")

# Getting the Backend for the Statevector Representation
# (i.e., the Quantum State represented as State Vector)
statevector_backend = Aer.get_backend('statevector_simulator')
final_state = execute(testFunctionCircuit3,statevector_backend).result().get_statevector()

array_to_latex(final_state, pretext="\\text{Final State for Marked State (Statevector) = }\n", precision = 1)

# Defining some tests, for the Phase Oracle, with n = 4

#element_test_4_states = [0,0,0,0]

#element_test_4_states = [0,0,0,1]

#element_test_4_states = [0,0,1,0]

#element_test_4_states = [0,0,1,1]

#element_test_4_states = [0,1,0,0]

#element_test_4_states = [0,1,0,1]

#element_test_4_states = [0,1,1,0]

#element_test_4_states = [0,1,1,1]

#element_test_4_states = [1,0,0,0]

#element_test_4_states = [1,0,0,1]

element_test_4_states = [1,0,1,0]

#element_test_4_states = [1,0,1,1]

#element_test_4_states = [1,1,0,0]

#element_test_4_states = [1,1,0,1]

#element_test_4_states = [1,1,1,0]

#element_test_4_states = [1,1,1,1]

qr4 = QuantumRegister(4)

testFunctionCircuit4 = QuantumCircuit(qr4)

element_test_4_states_binary = ''.join(map(str,element_test_4_states))

print("The Marked State is: |{}⟩".format(element_test_4_states_binary))

element_test_4_states.reverse()

mark_state(element_test_4_states, testFunctionCircuit4)

phase_oracle(testFunctionCircuit4,qr4,element_test_4_states)

testFunctionCircuit4.draw(output="mpl")

# Getting the Backend for the Statevector Representation
# (i.e., the Quantum State represented as State Vector)
statevector_backend = Aer.get_backend('statevector_simulator')
final_state = execute(testFunctionCircuit4,statevector_backend).result().get_statevector()

array_to_latex(final_state, pretext="\\text{Final State for Marked State (Statevector) = }\n", precision = 1)



def inversion_about_average(circuit, qr):
    
    # Apply Inversion Operator about the Average step of Grover's Algorithm
    
    circuit.h(qr)
    circuit.x(qr)
    
    n_controlled_Z(circuit, qr)
    
    circuit.x(qr)
    circuit.h(qr)

# Now, let's plot the Quantum Circuit for the Quantum Average
qr = QuantumRegister(4)

qAverage = QuantumCircuit(qr)

inversion_about_average(qAverage, qr)

qAverage.draw(output='mpl')

def putAllQubitsInQuantumSuperposition(n, quantumCircuit):
    
    for qubit_index in range(n):
        quantumCircuit.h(qubit_index)

def measureAllQubits(n, quantumCircuit, quantumRegister, classicalRegister):
    
    for qubit_index in range(n):
        quantumCircuit.measure(quantumRegister[qubit_index], classicalRegister[qubit_index])

def grover_algorithm(quantumCircuit,quantumRegister,classicalRegister,element,n):
    
    putAllQubitsInQuantumSuperposition(n,quantumCircuit)
    
    # Experimental Constant Factor,
    # for incrementing the number of Steps of the Grover's Algorithm
    additional_steps = 0
    #additional_steps = 1
    #additional_steps = 2
    #additional_steps = 3
    #additional_steps = 4
    
    for step in range(1, ( n + additional_steps )):
        phase_oracle(quantumCircuit,quantumRegister, element)
        inversion_about_average(quantumCircuit, quantumRegister)
        
    measureAllQubits(n, quantumCircuit, quantumRegister, classicalRegister)

qr2 = QuantumRegister(2)
cr2 = ClassicalRegister(2)

groverCircuit = QuantumCircuit(qr2,cr2)

#element_2_states = [0,0]
element_2_states = [0,1]
#element_2_states = [1,0]
#element_2_states = [1,1]

element_2_states_binary = ''.join(map(str,element_2_states))

print("The Marked State, we're looking for, is: |{}⟩".format(element_2_states_binary))

element_2_states.reverse()

grover_algorithm(groverCircuit,qr2,cr2,element_2_states,2)

groverCircuit.draw("mpl")

# Now, let's execute the Quantum Circuit in the QASM Simulator of the Aer Module,
# of the IBM Qiskit Library
backend = Aer.get_backend('qasm_simulator')
counts = execute(groverCircuit,backend,shots=2048).result().get_counts()

# Print the Counts of the Frequencies, resulting from this Experiment
print(counts)

# Plot the Counts of the Frequencies, resulting from this Experiment, through a Histogram
# (i.e., a Distribution of the Probabilities)
plot_histogram(counts)

qr3 = QuantumRegister(3)
cr3 = ClassicalRegister(3)

groverCircuit = QuantumCircuit(qr3,cr3)

#element_3_states = [0,0,0]
#element_3_states = [0,0,1]
#element_3_states = [0,1,0]
#element_3_states = [0,1,1]
#element_3_states = [1,0,0]
#element_3_states = [1,0,1]
element_3_states = [1,1,0]
#element_3_states = [1,1,1]

element_3_states_binary = ''.join(map(str,element_3_states))

print("The Marked State, we're looking for, is: |{}⟩".format(element_3_states_binary))

element_3_states.reverse()

grover_algorithm(groverCircuit,qr3,cr3,element_3_states,3)

groverCircuit.draw("mpl")

# Now, let's execute the Quantum Circuit in the QASM Simulator of the Aer Module,
# of the IBM Qiskit Library
backend = Aer.get_backend('qasm_simulator')
counts = execute(groverCircuit,backend,shots=2048).result().get_counts()

# Print the Counts of the Frequencies, resulting from this Experiment
print(counts)

# Plot the Counts of the Frequencies, resulting from this Experiment, through a Histogram
# (i.e., a Distribution of the Probabilities)
plot_histogram(counts)

qr4 = QuantumRegister(4)
cr4 = ClassicalRegister(4)

groverCircuit = QuantumCircuit(qr4,cr4)

#element_4_states = [0,0,0,0]
#element_4_states = [0,0,0,1]
#element_4_states = [0,0,1,0]
#element_4_states = [0,0,1,1]
#element_4_states = [0,1,0,0]
#element_4_states = [0,1,0,1]
#element_4_states = [0,1,1,0]
#element_4_states = [0,1,1,1]
#element_4_states = [1,0,0,0]
#element_4_states = [1,0,0,1]
#element_4_states = [1,0,1,0]
element_4_states = [1,0,1,1]
#element_4_states = [1,1,0,0]
#element_4_states = [1,1,0,1]
#element_4_states = [1,1,1,0]
#element_4_states = [1,1,1,1]

element_4_states_binary = ''.join(map(str,element_4_states))

print("The Marked State, we're looking for, is: |{}⟩".format(element_4_states_binary))

element_4_states.reverse()

grover_algorithm(groverCircuit,qr4,cr4,element_4_states,4)

groverCircuit.draw("mpl")

# Now, let's execute the Quantum Circuit in the QASM Simulator of the Aer Module,
# of the IBM Qiskit Library
backend = Aer.get_backend('qasm_simulator')
counts = execute(groverCircuit,backend,shots=2048).result().get_counts()

# Print the Counts of the Frequencies, resulting from this Experiment
print(counts)

# Plot the Counts of the Frequencies, resulting from this Experiment, through a Histogram
# (i.e., a Distribution of the Probabilities)
plot_histogram(counts)

qr5 = QuantumRegister(5)
cr5 = ClassicalRegister(5)

groverCircuit = QuantumCircuit(qr5,cr5)

#element_5_states = [0,0,0,0,0]
#element_5_states = [0,0,0,0,1]
element_5_states = [0,0,0,1,0]
#element_5_states = [0,0,0,1,1]
#element_5_states = [0,0,1,0,0]
#element_5_states = [0,0,1,0,1]
#element_5_states = [0,0,1,1,0]
#element_5_states = [0,0,1,1,1]
#element_5_states = [0,1,0,0,0]
#element_5_states = [0,1,0,0,1]
#element_5_states = [0,1,0,1,0]
#element_5_states = [0,1,0,1,1]
#element_5_states = [0,1,1,0,0]
#element_5_states = [0,1,1,0,1]
#element_5_states = [0,1,1,1,0]
#element_5_states = [0,1,1,1,1]
#element_5_states = [1,0,0,0,0]
#element_5_states = [1,0,0,0,1]
#element_5_states = [1,0,0,1,0]
#element_5_states = [1,0,0,1,1]
#element_5_states = [1,0,1,0,0]
#element_5_states = [1,0,1,0,1]
#element_5_states = [1,0,1,1,0]
#element_5_states = [1,0,1,1,1]
#element_5_states = [1,1,0,0,0]
#element_5_states = [1,1,0,0,1]
#element_5_states = [1,1,0,1,0]
#element_5_states = [1,1,0,1,1]
#element_5_states = [1,1,1,0,0]
#element_5_states = [1,1,1,0,1]
#element_5_states = [1,1,1,1,0]
#element_5_states = [1,1,1,1,1]

element_5_states_binary = ''.join(map(str,element_5_states))

print("The Marked State, we're looking for, is: |{}⟩".format(element_5_states_binary))

element_5_states.reverse()

grover_algorithm(groverCircuit,qr5,cr5,element_5_states,5)

groverCircuit.draw("mpl")

# Now, let's execute the Quantum Circuit in the QASM Simulator of the Aer Module,
# of the IBM Qiskit Library
backend = Aer.get_backend('qasm_simulator')
counts = execute(groverCircuit,backend,shots=2048).result().get_counts()

# Print the Counts of the Frequencies, resulting from this Experiment
print(counts)

# Plot the Counts of the Frequencies, resulting from this Experiment, through a Histogram
# (i.e., a Distribution of the Probabilities)
plot_histogram(counts)

# Print the current Qiskit's Modules' Version
import qiskit
qiskit.__qiskit_version__