!pip install qutip -q
!pip install qiskit -q
!pip install qiskit[visualization] -q
!pip install git+https://github.com/qiskit-community/qiskit-textbook.git#subdirectory=qiskit-textbook-src -q

import numpy as np
np.set_printoptions(precision=3, suppress=True)
import qutip as qt
from matplotlib import pyplot as plt
%matplotlib inline

import pandas as pd
import sklearn as sk
import qiskit as qk

# Remember that qiskit has to be already installed in the Python environment.
# Otherwise the import command will fail
import qiskit as qk

# A circuit composed of just one qubit
qc = qk.QuantumCircuit(1)
qc.draw('mpl')

import qiskit as qiskit

# A qubit initialized in the state |0>
qc = qk.QuantumCircuit(1)
qc.initialize([1,0])
qc.draw('mpl')

import qiskit as qk

# A qubit initialized in |0> and a measurement
qc = qk.QuantumCircuit(1)
qc.initialize([1,0])
qc.measure_all()
qc.draw('mpl')

import qiskit as qk

# A list of possible measurements. The results of measurements are obtained
#  by executing an object called backend
a = [print(i) for i in qk.Aer.backends()]

import qiskit as qk

qc = qk.QuantumCircuit(1)
qc.initialize([1,0],0)
qc.measure_all()

# Let's choose the statevector simulator from the Aer backend
backend = qk.Aer.get_backend('statevector_simulator')

# And execute the circuit qc in the simulator backend
#  getting as final result the counts from 1.000 measures
#  of the qubit state
result = qk.execute(qc, backend, shots=1000).result().get_counts()
result

import qiskit as qk

qc = qk.QuantumCircuit(1)
qc.initialize([1,0],0)
qc.measure_all()
backend = qk.Aer.get_backend('statevector_simulator')
result = qk.execute(qc, backend, shots=1000).result().get_counts()

qk.visualization.plot_histogram(result)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([1,0],0)
qc.measure(0,0)
qc.draw('mpl')

backend = qk.Aer.get_backend('statevector_simulator')
result = qk.execute(qc, backend, shots=1000).result().get_counts()

qk.visualization.plot_histogram(result)

import numpy as np
v0 = np.array([[1],[0]]);v0

v1 = np.array([[0],[1]]); v1

X = np.array([[0,1],[1,0]]); X

X.dot(v0)

X.dot(v1)

import qiskit as qk
qr = qk.QuantumRegister(1,"q0")
cr = qk.ClassicalRegister(1,"c0")
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([1,0],0)
qc.x(0)
qc.measure(qr[0], cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=1000).result().get_counts()
results

qk.visualization.plot_histogram(results)

import numpy as np
# Notice that we are creating the v0 matrix using the transpose operation
v0 = np.array([[1,0]]).T; v0

# Here it is created again de X matrix
X = np.array([[0,1],[1,0]]); X

# Multiplying v0 by the X matrix twice you get again v0
X.dot(X).dot(v0)

# Multiplying the X matrix by itself you get the Identity matrix
X.dot(X)

import qiskit as qk
qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([1,0],0)
qc.x(0)
qc.x(0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

# The result of 1000 measures of the qubit above gives the |0> state as result
#  in all measures
simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=1000).result().get_counts()
results

qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([2**-0.5,2**-0.5],0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
v0 = np.array([[1,0]]).T; v0

H = np.array([[1,1],[1,-1]])/np.sqrt(2); H

H.dot(v0)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.h(qr[0])
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([2**-0.5,-(2**-0.5)],0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([2**-0.5,-(2**-0.5)],0)
qc.h(0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(1,'q0')
cr = qk.ClassicalRegister(1,'c0')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([0,1],0)
qc.h(0)
qc.h(0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np

# First let's start with the qubit in the state |psi> = (|0> - |1>)/sqrt(2)
psi = np.array([[1,-1]]).T/(2**0.5); psi

H = np.array([[1,1],[1,-1]])/2**0.5; H

# Now let's pass the qubit Psi through an Hadamard gate.
# The result is a qubit in the state |1>
H.dot(psi)

# Let's start with a qubit in the state |1>, pass it through a
#  a hadamard gate twice and check the result
v0 = np.array([[0,1]]).T; v0

H.dot(H).dot(v0)

# This means that if we multiply the H gate by itself the result
#  will be an Identity matrix. Let's check it.
H.dot(H)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
psi1 = np.array([[1,0]]).T; psi1

psi2 = np.array([[1,0]]).T; psi2

# In numpy the tensor product is calculated with the function kron
np.kron(psi1,psi2)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.h(1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
psi1 = np.array([[1,0]]).T;psi1

psi2 = np.array([[1,0]]).T;psi2

H = np.array([[1,1],[1,-1]])/2**0.5;H

# When we want to combine two vector states or gate matrices we tensor product them.
psi3 = np.kron(psi1,psi2);psi3

H2 = np.kron(H,H);H2

# When we want to pass a vetor through a gate we calculate the dot product
#  of the total gate matrix with the total vector.
# As we have predicted, the resulting vector state has a=b=c=d=1/2
psi4 = H2.dot(psi3); psi4

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([0,1],0)
qc.initialize([0,1],1)
qc.h(0)
qc.h(1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
psi1 = np.array([[0,1]]).T;psi1

psi2 = np.array([[0,1]]).T;psi2

H = np.array([[1,1],[1,-1]])/2**0.5;H

# When we want to combine two vector states or gate matrices we tensor product them.
psi3 = np.kron(psi1,psi2);psi3

H2 = np.kron(H,H);H2

# When we want to pass a vetor through a gate we calculate the dot product
#  of the total gate matrix with the total vector.
# As we have predicted, the resulting vector state has a=b=c=d=1/2
psi4 = H2.dot(psi3); psi4

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.cnot(0,1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

v00 = np.array([[1,0,0,0]]).T;v00

# C.v00 = v00
C.dot(v00)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([0,1],1)
qc.cnot(0,1)
qc.measure(qr,cr)
qc.draw('mpl')

# Please notice that Qiskit's qubits presentation order is reversed.
#  Therefore 10 in the histogram's x axis should be read as 01 (from
#  inside out or right to left).
simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

v01 = np.array([[0,1,0,0]]).T;v01

# C.v01 = v01
C.dot(v01)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([0,1],0)
qc.initialize([1,0],1)
qc.cnot(0,1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

v10 = np.array([[0,0,1,0]]).T; v10

# C.v10 = v11
C.dot(v10)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([0,1],0)
qc.initialize([0,1],1)
qc.cnot(0,1)
qc.measure(qr,cr)
qc.draw('mpl')

# Again remember to read qiskit qubits state presentation order
#  from right to left. Therefore 01 in the x axis is in fact 10
simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc, simulator, shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

v11 = np.array([[0,0,0,1]]).T; v11

# C.v11 = v10
C.dot(v11)

import qiskit as qk
qr = qk.QuantumRegister(2, 'q')
cr = qk.ClassicalRegister(2, 'c')
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(qr[0])
qc.cx(qr[0],qr[1])
qc.measure(qr, cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
va = np.array([[1,0]]).T; va

vb = np.array([[1,0]]).T; vb

H = np.array([[1,1],[1,-1]])/2**0.5;H

vaH = H.dot(va); vaH

vaHvb = np.kron(vaH,vb); vaHvb

C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

vout = C.dot(vaHvb); vout

import qiskit as qk
qr = qk.QuantumRegister(2, 'q')
cr = qk.ClassicalRegister(2, 'c')
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([0,1],0)
qc.initialize([1,0],1)
qc.h(qr[0])
qc.cx(qr[0],qr[1])
qc.measure(qr, cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
va = np.array([[0,1]]).T; va

vb = np.array([[1,0]]).T; vb

H = np.array([[1,1],[1,-1]])/2**0.5;H

vaH = H.dot(va); vaH

vaHvb = np.kron(vaH,vb); vaHvb

C = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]); C

vout = C.dot(vaHvb); vout

# Get the IBM API key in: https://quantum-computing.ibm.com
# chave = 'My key is already saved in this environment'
# qk.IBMQ.save_account(chave)

# Load the account in the active session
qk.IBMQ.load_account()

# The default provider is é hub='ibm-q', group='open, project='main'
# The code below is executed as an example
provider_1 = qk.IBMQ.get_provider(hub='ibm-q', group='open', project='main')

# In the public provider we will use a cloud simulator.
backend_1 = provider_1.get_backend('ibmq_qasm_simulator')

# The provider listed below has unlimited jobs
provider_2 = qk.IBMQ.get_provider(hub='ibm-q-education', group='fgv-1', project='ml-business-app')

# For this provider we will use the ibmq_jakarta machine
backend_2 = provider_2.get_backend('ibmq_jakarta')

# With n Qubits we can generate a random number from 0 to 2^n - 1
n = 3

qr = qk.QuantumRegister(n,'q')
cr = qk.ClassicalRegister(n,'c')
qc = qk.QuantumCircuit(qr, cr)

# Applying a Hadamard to each of the three qubits
for i in range(n):
  qc.h(q[i])

# Measuring the three qubits
qc.measure(q,c)

# Visualizing the circuit
qc.draw('mpl')

# qk.execute envia para o backend. Conferindo no iqmq explorer aparece o job
new_job = qk.execute(circ, backend_2, shots=1)

# this result is stored on the local machine. However, it will only be available
# after the job has been executed. It returns a python dictionary.
new_job.result().get_counts()

int(list(new_job.result().get_counts().keys())[0],2)

from qiskit import QuantumCircuit
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0,1)
circuit.measure([0,1], [0,1])
display(circuit.draw('mpl'))

from qiskit.providers.aer import AerSimulator
print(AerSimulator().run(circuit, shots=1000).result().get_counts())
print(AerSimulator().run(circuit, shots=1000).result().get_counts())

from qiskit import QuantumCircuit
circuito = QuantumCircuit(3,3)
for i in range(3):
  circuito.h(i)
  circuito.measure(i,i)
display(circuito.draw('mpl'))

from qiskit.providers.aer import AerSimulator
AerSimulator().run(circuito, shots = 1000).result().get_counts()

from qiskit import QuantumCircuit
qc = QuantumCircuit(4,4)
qc.x([0,1])
qc.cx([0,1],[2,2])
qc.ccx(0,1,3)
qc.measure([0,1,2,3],[0,1,2,3])
display(qc.draw(output='mpl'))

from qiskit.providers.aer import AerSimulator
AerSimulator().run(qc, shots = 10000).result().get_counts()

import qiskit as qk
qr = qk.QuantumRegister(1,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr, cr)
qc.initialize([1,0],0)

print("Circuit 1 - Registers Only")
display(qc.draw('mpl'))
qc.x(qr)

print("Circuit 1 - Quantum Register with a Gate X ")
display(qc.draw('mpl'))

job = qk.execute(experiments = qc,
                 backend = qk.Aer.get_backend('statevector_simulator'))
result1 = job.result().get_statevector()

print("Quantum Register Vector State")
from qiskit.tools.visualization import plot_bloch_multivector
display(plot_bloch_multivector(result1))

job = qk.execute(experiments = qc,
                 backend = qk.Aer.get_backend('unitary_simulator'))

print("Transformation Matrix (up to this stage)")
print(job.result().get_unitary())

qc.measure(qr, cr)
print()
print("Circuit 1 - Registers, Gate X and Quantum Register Measure")
display(qc.draw('mpl'))

print("Quantum Register Thousand Measures")
job = qk.execute(experiments = qc,
                 backend = qk.Aer.get_backend('statevector_simulator'),
                 shots = 1000)
print(job.result().get_counts())

print()
print("Result's Histogram")
from qiskit.tools.visualization import plot_histogram
plot_histogram(data = job.result().get_counts(), figsize=(4,3))

import qiskit as qk
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
qr = qk.QuantumRegister(3,'q')
cr = qk.ClassicalRegister(3,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([1,0],2)
display(qc.draw('mpl'))

sv = Statevector.from_label('000')
state_data = lambda qc,sv: np.round(np.asarray(sv.evolve(qc).data),4)
state_bloch = lambda qc,sv: plot_bloch_multivector(sv.evolve(qc).data, reverse_bits=True)

print(state_data(qc,sv))
state_bloch(qc,sv)

qc.x(0)
qc.barrier()
display(qc.draw('mpl'))

print(state_data(qc,sv))
display(state_bloch(qc,sv))

qc.h(1)
display(qc.draw('mpl'))

print(state_data(qc,sv))
state_bloch(qc,sv)

qc.cnot(1,2)
display(qc.draw("mpl"))

state_data(qc,sv)
state_bloch(qc,sv)

qc.cnot(0,1)
display(qc.draw('mpl'))
state_data(qc,sv)

qc.h(0)
qc.barrier()
display(qc.draw('mpl'))
state_data(qc,sv)

qc.measure(0,0)
qc.measure(1,1)
qc.barrier()
qc.cnot(1,2)
qc.cz(0,2)
qc.measure(2,2)
display(qc.draw('mpl'))

simulador = qk.Aer.get_backend('statevector_simulator')
resultado = qk.execute(qc, simulador, shots=10000).result()
qk.visualization.plot_histogram(resultado.get_counts())

import numpy as np

V = np.array([[3+2j],[4-2j]])
modV = np.real(V.T.conjugate().dot(V)[0,0])**0.5
Vn = V/modV; Vn

v0 = np.array([[1,0]]).T
v1 = np.array([[0,1]]).T
Vn[0,0]*v0 + Vn[1,0]*v1

import qiskit as qk

qr = qk.QuantumRegister(1,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([Vn[0,0],Vn[1,0]],0)
qc.measure(qr[0],cr[0])
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

Vn[0,0].conjugate()*Vn[0,0]

Vn[1,0].conjugate()*Vn[1,0]

import numpy as np
CNOT = np.array([[1,0,0,0],
                 [0,1,0,0],
                 [0,0,0,1],
                 [0,0,1,0]])
CNOT.dot(CNOT)

import numpy as np
H = np.array([[1,1],[1,-1]])/2**0.5
H.dot(H)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.cnot(qr[0],qr[1])
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.cnot(qr[0],qr[1])
qc.cnot(qr[0],qr[1])
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(2,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.cnot(qr[0],qr[1])
qc.cnot(qr[0],qr[1])
qc.h(0)
qc.measure(qr,cr)
qc.draw('mpl')

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
X = np.array([[0,1],
              [1,0]])
X

X.conj().T.dot(X)

Y = np.array([[0,-1j],
              [1j,0]])
Y

Y.conj().T.dot(Y)

Z = np.array([[1,0],
              [0,-1]])
Z

Z.conj().T.dot(Z)

H = (X+Z)/np.sqrt(2); H

H.dot(Z).dot(H)

H.dot(X).dot(H)

-H.dot(Y).dot(H)

import numpy as np
S = np.array([[1,0],
              [0,1j]])
S

S.conj().T.dot(S)

T = np.array([[1,0],
              [0,np.exp(1j*np.pi/4)]])
T

T.conj().T.dot(T)

S = np.array([[1,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,1]]); S

S.dot(v00)

S.dot(v01)

S.dot(v10)

S.dot(v11)

C = np.array([[1,0,0,0],
              [0,1,0,0],
              [0,0,0,1],
              [0,0,1,0]]);C

C_ = np.array([[1,0,0,0],
               [0,0,0,1],
               [0,0,1,0],
               [0,1,0,0]]);C_

C.dot(C_).dot(C)

v = v0 + v1; v

n = np.array([[0,0],[0,1]]); n

n.dot(v)

n_ = np.array([[1,0],[0,0]]);n_

I2 = np.identity(2); I2

I2 - n

n_.dot(v)

n.dot(n)

n_.dot(n_)

n.dot(n_)

n_.dot(n)

n+n_

n.dot(X)

X.dot(n_)

import numpy as np
n = np.array([[0,0],[0,1]]); n

n_ = np.array([[1,0],[0,0]]);n_

# ni nj operam em bits distintos. Como cada operador n atua em um vetor de
#  2 dimensões, ni nj é um operador de 4 dimensões. Sendo assim, fica implícito
#  pelos subscritos que ni nj é um produto tensorial.
np.kron(n,n)

# O mesmo vale para n'i n'j
np.kron(n_,n_)

# Para ni n'j
np.kron(n,n_)

# E para n'i nj
np.kron(n_,n)

# Xi Xj são dois operadores 2x2 de inversão, cada um atuando em um bit
#  distinto. Sendo assim, fazemos o produto tensorial entre ambos
#  para obter XiXj
np.kron(X,X)

# No caso da expressão XiXj(ninj' + ni'nj) temos entre parênteses duas
#  matrizes 4x4 (ninj'+ni'nj) e fora dos parênteses uma matriz 4x4 (XiXj)
#  Sendo assim fazemos neste caso o produto matricial normal para
#  calcular esta expressão.
np.kron(X,X).dot(np.kron(n,n_)+np.kron(n_,n))

# E por último somamos com o resultado inicial de ninj + ni'nj'
#  Como pode-se ver, esta expressão gera o operador de SWAP
np.kron(n,n) + np.kron(n_,n_) + np.kron(X,X).dot(np.kron(n,n_)+np.kron(n_,n))

# É importante observar que ninj forma um operador que projeta um vetor de
#  4 dimensões (00, 01, 10, 11) em sua componente 11
np.kron(n,n)

# De maneira similar ni'nj' projeta um vetor de 4 dimensões em sua componente 00
np.kron(n_,n_)

# ni'nj projeta em 01
np.kron(n_,n)

# Assim como ninj' projeta em 10
np.kron(n,n_)

# E por último vemos que ni'nj' + ni'nj + ninj' + ninj = I
nn = np.kron(n,n)
nn_ = np.kron(n,n_)
n_n = np.kron(n_,n)
n_n_ = np.kron(n_,n_)
nn + nn_ + n_n + n_n_

import numpy as np
n = np.array([[0,0],[0,1]]); n

n_ = np.array([[1,0],[0,0]]);n_

# (n x n).(n_ x n_)
np.kron(n,n).dot(np.kron(n_,n_))

# Faz sentido que (ni x nj).(ni_ x nj_) seja o vetor nulo pois:
#   ni_ x nj_ é um operador que recebe um vetor de 4 dimensões e
#   produz como resultado apenas sua componente |00>. Por sua
#   vez ni x nj é um operador que recebe um vetor de 4 dimensões
#   e produz como resultado apenas sua componente |11>. Esta
#   componente foi zerada pelo primeiro operador, logo o resultado
#   será nulo. Isto vai acontecer sempre que a componente não
#   zerada do primeiro operador for diferente da do segundo em
#   outras palavras sempre que ij do primeiro for diferente de ij
#   do segundo.

np.kron(n,n).dot(np.kron(n_,n_))

# Outra forma de entender é transformar (n x n).(n_ x n_) em
#  (n.n_) x (n.n_). Como n é ortogonal a n_, a projeção de n
#  em n_ dará zero também.

np.kron(n.dot(n_),n.dot(n_))

nn.dot(n_n_)

# (n_ x n).(n x n_)
np.kron(n_,n).dot(np.kron(n,n_))

n_n.dot(nn_)

# (n x n_).(n_ x n)
np.kron(n, n_).dot(np.kron(n_,n))

nn_.dot(n_n)

# (n_ x n_).(n x n)
np.kron(n_, n_).dot(np.kron(n, n))

n_n_.dot(nn)

NOT = np.array([[0,1],[1,0]]); NOT

NOT.dot(D0)

NOT.dot(D1)

AND = np.array([[1,1,1,0],[0,0,0,1]]); AND

AND.dot(np.kron(D0,D0))

AND.dot(np.kron(D0,D1))

AND.dot(np.kron(D1,D0))

AND.dot(np.kron(D1,D1))

OR = np.array([[1,0,0,0],[0,1,1,1]]); OR

OR.dot(np.kron(D0,D0))

OR.dot(np.kron(D0,D1))

OR.dot(np.kron(D1,D0))

OR.dot(np.kron(D1,D1))

NAND = np.array([[0,0,0,1],[1,1,1,0]]); NAND

NOT.dot(AND)

NOR = np.array([[0,1,1,1],[1,0,0,0]]);NOR

NOT.dot(OR)

np.kron(NOT,AND)

OR.dot(np.kron(NOT,AND))

NOT.dot(AND).dot(np.kron(NOT,NOT))

OR

NOT.dot(OR).dot(np.kron(NOT,NOT))

AND

import numpy as np
k = np.kron
XOR = np.array([[1,0,0,1],
                [0,1,1,0]])
AND = np.array(([1,1,1,0],
                [0,0,0,1]))
k(XOR,AND)

def criaCompat(nbits,nvezes):
  nlins = 2**(nbits*nvezes)
  ncols = 2**nbits
  compat = np.zeros(nlins*ncols).reshape(nlins,ncols)
  for i in range(ncols):
   formato = "0" + str(nbits) + "b"
   binario = format(i,formato)*nvezes
   decimal = int(binario,2)
   compat[decimal,i] = 1
  return(compat)

criaCompat(2,2)

k(XOR,AND).dot(criaCompat(2,2))

import numpy as np
k = np.kron

def criaCompat(nbits,nvezes):
  nlins = 2**(nbits*nvezes)
  ncols = 2**nbits
  compat = np.zeros(nlins*ncols).reshape(nlins,ncols)
  for i in range(ncols):
   formato = "0" + str(nbits) + "b"
   binario = format(i,formato)*nvezes
   decimal = int(binario,2)
   compat[decimal,i] = 1
  return(compat)

criaCompat(2,2)

NOT = np.array([[0,1],
                [1,0]])

AND3 = np.array([[1,1,1,1,1,1,1,0],
                 [0,0,0,0,0,0,0,1]])

OR4 = np.array([[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]])

I2 = np.array([[1,0],
               [0,1]])

t1z = k(NOT,k(NOT,I2))
t2z = k(NOT,k(I2,NOT))
t3z = k(I2,k(NOT,NOT))
t4z = k(I2,k(I2,I2))
ORz = k(AND3,k(AND3,k(AND3,AND3)))
ORz = OR4.dot(ORz).dot(k(t1z,k(t2z,k(t3z,t4z))))

t1c = k(NOT,k(I2,I2))
t2c = k(I2,k(NOT,I2))
t3c = k(I2,k(I2,NOT))
t4c = k(I2,k(I2,I2))
ORc = k(AND3,k(AND3,k(AND3,AND3)))
ORc = OR4.dot(ORc).dot(k(t1c,k(t2c,k(t3c,t4c))))

compat = criaCompat(3,8)
k(ORz,ORc).dot(compat)

import numpy as np
TOFFOLI = np.array([[1,0,0,0,0,0,0,0],
                    [0,1,0,0,0,0,0,0],
                    [0,0,1,0,0,0,0,0],
                    [0,0,0,1,0,0,0,0],
                    [0,0,0,0,1,0,0,0],
                    [0,0,0,0,0,1,0,0],
                    [0,0,0,0,0,0,0,1],
                    [0,0,0,0,0,0,1,0]])
TOFFOLI.dot(TOFFOLI)

Z1 = np.array([[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,1,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,1]])
Z1

Z1I4 = np.array([[0,0,0,0],
                 [1,0,0,0],
                 [0,0,0,0],
                 [0,1,0,0],
                 [0,0,0,0],
                 [0,0,1,0],
                 [0,0,0,0],
                 [0,0,0,1]])
TOFFOLI.dot(ZpY).dot(TOFFOLI).dot(Z1I4)

ZpY = np.zeros([8,8])
ZpY[0,0] = 1; ZpY[1,2] = 1; ZpY[2,1] = 1; ZpY[3,3] = 1
ZpY[4,4] = 1; ZpY[5,6] = 1; ZpY[6,5] = 1; ZpY[7,7] = 1
ZpY

Zfim = np.array([[1,0,1,0,1,0,1,0],
                 [0,1,0,1,0,1,0,1]])

Zfim.dot(TOFFOLI).dot(ZpY).dot(TOFFOLI).dot(Z1I4)

import numpy as np
fred = np.identity(8)
fred[5,5] = 0; fred[5,6] = 1
fred[6,5] = 1; fred[6,6] = 0
fred

fred.dot(fred)

import numpy as np
Fy0 = np.zeros([8,4])
Fy0[0,0] = 1; Fy0[1,1] = 1; Fy0[4,2] = 1; Fy0[5,3] = 1
Fy0

xYz = np.array([[1,1,0,0,1,1,0,0],
                [0,0,1,1,0,0,1,1]])

xYz.dot(fred).dot(Fy0)

import numpy as np
q0 = np.array([[1,0]]).T; q0

q1 = np.array([[0,1]]).T; q1

q01 = np.kron(q0,q1); q01

H = np.array([[1,1],[1,-1]])/np.sqrt(2); H

H2 = np.kron(H,H); H2

H2.dot(q01)

I4 = np.eye(4); I4

I4.dot(H2).dot(q01)

I2 = np.eye(2); I2

HI2 = np.kron(H,I2); HI2

HI2.dot(I4).dot(H2).dot(q01)

X = np.array([[0,1],[1,0]]); X

I2 = np.eye(2); I2

I2X = np.kron(I2,X); I2X

HI2.dot(I2X).dot(H2).dot(q01)

CNOT = np.array([[1,0,0,0],
                 [0,1,0,0],
                 [0,0,0,1],
                 [0,0,1,0]])
CNOT

HI2.dot(CNOT).dot(H2).dot(q01)

X = np.array([[0,1],[1,0]]); X

I2 = np.eye(2); I2

XI2 = np.kron(X,I2); XI2

CNOT = np.array([[1,0,0,0],
                 [0,1,0,0],
                 [0,0,0,1],
                 [0,0,1,0]])
CNOT

CNOT.dot(XI2)

HI2.dot(CNOT).dot(XI2).dot(H2).dot(q01)

import qiskit as qk
import numpy as np

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([0,1],1)
qc.h(0)
qc.h(1)

qc.barrier()

qc.barrier()

qc.h(0)
qc.measure(qr[0],cr[0])

qc.draw('mpl')

simulator = qk.Aer.get_backend("statevector_simulator")
results = qk.execute(qc, simulator).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk
import numpy as np

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([0,1],1)
qc.h(0)
qc.h(1)

qc.barrier()
qc.x(1)
qc.barrier()

qc.h(0)
qc.measure(qr[0],cr[0])

qc.draw('mpl')

simulator = qk.Aer.get_backend("statevector_simulator")
results = qk.execute(qc, simulator).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk
import numpy as np

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([0,1],1)
qc.h(0)
qc.h(1)

qc.barrier()
qc.cx(0,1)
qc.barrier()

qc.h(0)
qc.measure(qr[0],cr[0])

qc.draw('mpl')

simulator = qk.Aer.get_backend("statevector_simulator")
results = qk.execute(qc, simulator).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk
import numpy as np

qr = qk.QuantumRegister(2,'q')
cr = qk.ClassicalRegister(1,'c')
qc = qk.QuantumCircuit(qr,cr)
qc.initialize([1,0],0)
qc.initialize([0,1],1)
qc.h(0)
qc.h(1)

qc.barrier()
qc.x(0)
qc.cx(0,1)
qc.barrier()

qc.h(0)
qc.measure(qr[0],cr[0])

qc.draw('mpl')

simulator = qk.Aer.get_backend("statevector_simulator")
results = qk.execute(qc, simulator).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk

qc = qk.QuantumCircuit(3,3)
qc.barrier()
qc.cnot(1,2)
qc.barrier()
qc.draw('mpl')

import qiskit as qk

qc = qk.QuantumCircuit(3,3)
qc.initialize([0,0,0,0,1,0,0,0],[0,1,2])

qc.h([0,1,2])

qc.barrier()
qc.cnot(1,2)
qc.barrier()

qc.h([0,1])

qc.measure([0,1],[0,1])
qc.draw('mpl')

def histograma(qc):
  import qiskit as qk
  from qiskit.visualization import plot_histogram
  simulador = qk.Aer.get_backend('statevector_simulator')
  results = qk.execute(qc,simulador,shots=10000).result().get_counts()
  grafico = plot_histogram(results)
  return(grafico)

histograma(qc)

import numpy as np
x1 = np.array([[1,0]]).T
x0 = np.array([[1,0]]).T
y  = np.array([[0,1]]).T
psi0 = np.kron(y,np.kron(x1,x0)); psi0.T

import numpy as np
H = np.array([[1, 1],
              [1,-1]])/np.sqrt(2)
H3 = np.kron(H,np.kron(H,H)); np.round(H3,3)

psi0 = np.array([[0,0,0,0,1,0,0,0]]).T
psi1 = H3.dot(psi0); psi1.T

CNOTsm = np.array([[1,0,0,0],
                   [0,0,0,1],
                   [0,0,1,0],
                   [0,1,0,0]])

I2 = np.array([[1,0],
               [0,1]])

CNOTsm_I2 = np.kron(CNOTsm,I2)

psi0 = np.array([[0,0,0,0,1,0,0,0]]).T
CNOTsm_I2.dot(H3).dot(psi0).T

psi = np.array([[1,1,-1,-1]]).T/2
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H2.dot(psi)

import qiskit as qk
qc = qk.QuantumCircuit(3,3)

qc.initialize([0,0,0,0,1,0,0,0],[0,1,2])
qc.h([0,1,2])

qc.barrier()
qc.cnot(0,2)
qc.barrier()

qc.h([0,1])

qc.measure([0,1],[0,1])
display(qc.draw('mpl'))
histograma(qc)

import numpy as np
v0 = np.array([[0,0,0,0,1,0,0,0]]).T; v0.T

H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H); H3 = np.kron(H2,H)
H3.dot(v0).T

CNOTs_I_m = np.array([[1,0,0,0,0,0,0,0],
                      [0,0,0,0,0,1,0,0],
                      [0,0,1,0,0,0,0,0],
                      [0,0,0,0,0,0,0,1],
                      [0,0,0,0,1,0,0,0],
                      [0,1,0,0,0,0,0,0],
                      [0,0,0,0,0,0,1,0],
                      [0,0,0,1,0,0,0,0]])

v0 = np.array([[0,0,0,0,1,0,0,0]]).T
CNOTs_I_m.dot(H3).dot(v0).T

psi = np.array([[+1,-1,+1,-1]]).T/2
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H2.dot(psi)

import qiskit as qk
qc = qk.QuantumCircuit(3,3)
qc.initialize([0,0,0,0,1,0,0,0],[0,1,2])
qc.h([0,1,2])

qc.barrier()
qc.cnot(0,1)
qc.cnot(1,2)
qc.cnot(0,1)
qc.barrier()

qc.h([0,1])

qc.measure([0,1],[0,1])
display(qc.draw('mpl'))
histograma(qc)

v0 = np.array([[0,0,0,0,1,0,0,0]]).T
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H); H3 = np.kron(H2,H)
H3.dot(v0).T

CNOT_CNOT = np.array([[1,0,0,0,0,0,0,0],
                      [0,0,0,0,0,1,0,0],
                      [0,0,0,0,0,0,1,0],
                      [0,0,0,1,0,0,0,0],
                      [0,0,0,0,1,0,0,0],
                      [0,1,0,0,0,0,0,0],
                      [0,0,1,0,0,0,0,0],
                      [0,0,0,0,0,0,0,1]])

v0 = np.array([[0,0,0,0,1,0,0,0]]).T
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H); H3 = np.kron(H2,H)
CNOT_CNOT.dot(H3).dot(v0).T

psi = np.array([[+1,-1,-1,+1]]).T/2
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H2.dot(psi)

import numpy as np
CNOTsm = np.array([[1,0,0,0],
                   [0,0,0,1],
                   [0,0,1,0],
                   [0,1,0,0]])

I = np.array([[1,0],
              [0,1]])

ISM = np.kron(I,CNOTsm)
SMI = np.kron(CNOTsm,I)

H = np.array([[1, 1],
              [1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H3 = np.kron(H2,H)

IH2 = np.kron(I,H2)

v0 = np.array([[0,0,0,0,1,0,0,0]]).T
IH2.dot(ISM).dot(SMI).dot(ISM).dot(H3).dot(v0).round(3)

CNOT_CNOT = np.array([[1,0,0,0,0,0,0,0],
                      [0,0,0,0,0,1,0,0],
                      [0,0,0,0,0,0,1,0],
                      [0,0,0,1,0,0,0,0],
                      [0,0,0,0,1,0,0,0],
                      [0,1,0,0,0,0,0,0],
                      [0,0,1,0,0,0,0,0],
                      [0,0,0,0,0,0,0,1]])

ISM.dot(SMI).dot(ISM)

import qiskit as qk
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_histogram

qr = qk.QuantumRegister(3,'q')
cr = qk.ClassicalRegister(3,'c')
qc = qk.QuantumCircuit(qr,cr)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([0,1],2)

qc.h(0)
qc.h(1)
qc.h(2)

qc.barrier()
qc.barrier()

qc.h(0)
qc.h(1)

qc.measure(0,0)
qc.measure(1,1)
display(qc.draw('mpl'))
histograma(qc)

psi = np.array([[1,1,1,1]]).T/2
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H2.dot(psi)

import qiskit as qk
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_histogram

qr = qk.QuantumRegister(3,'q')
cr = qk.ClassicalRegister(3,'c')
qc = qk.QuantumCircuit(qr,cr)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([0,1],2)

qc.h(0)
qc.h(1)
qc.h(2)

qc.barrier()
qc.x(2)
qc.barrier()

qc.h(0)
qc.h(1)

qc.measure(0,0)
qc.measure(1,1)
display(qc.draw('mpl'))
histograma(qc)

psi = np.array([[1,1,1,1]]).T/2
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H2.dot(psi)

import qiskit as qk
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_histogram

qr = qk.QuantumRegister(3,'q')
cr = qk.ClassicalRegister(3,'c')
qc = qk.QuantumCircuit(qr,cr)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([0,1],2)

qc.h(0)
qc.h(1)
qc.h(2)

qc.barrier()
qc.ccx(0,1,2)
qc.barrier()

qc.h(0)
qc.h(1)

qc.measure(0,0)
qc.measure(1,1)
display(qc.draw('mpl'))
histograma(qc)

import qiskit as qk

qrx = qk.QuantumRegister(2,'x')
qry = qk.QuantumRegister(2,'y')
qc = qk.QuantumCircuit(qrx,qry)

qc.barrier()
qc.cx(0,2)
qc.cx(0,3)
qc.cx(1,2)
qc.cx(1,3)
qc.barrier()

qc.draw('mpl')

def histograma(qc):
  simulador = qk.Aer.get_backend('statevector_simulator')
  resultado = qk.execute(qc,simulador,shots=10000).result()
  contagens = resultado.get_counts()
  grafico = qk.visualization.plot_histogram(contagens)
  return(grafico)

def simon(initial_y, initial_x):
  import qiskit as qk
  qrx = qk.QuantumRegister(2,'x')
  crx = qk.ClassicalRegister(4,'c')
  qry = qk.QuantumRegister(2,'y')

  qc = qk.QuantumCircuit(qrx,qry,crx)

  qc.initialize(initial_x,qrx)
  qc.initialize(initial_y,qry)

  qc.barrier()
  qc.cx(0,2)
  qc.cx(0,3)
  qc.cx(1,2)
  qc.cx(1,3)
  qc.barrier()

  qc.measure([0,1,2,3],[0,1,2,3])

  display(qc.draw('mpl'))
  grafico = histograma(qc)
  return(grafico)

simon([1,0,0,0],[1,0,0,0])

simon([1,0,0,0],[0,0,0,1])

simon([1,0,0,0],[0,1,0,0])

simon([1,0,0,0],[0,0,1,0])

import qiskit as qk
qrx = qk.QuantumRegister(2,'x')
crx = qk.ClassicalRegister(2,'c')
qry = qk.QuantumRegister(2,'y')

qc = qk.QuantumCircuit(qrx,qry,crx)

qc.initialize([1,0,0,0],qrx)
qc.initialize([1,0,0,0],qry)
qc.h([0,1])

qc.barrier()
qc.cx(0,2)
qc.cx(0,3)
qc.cx(1,2)
qc.cx(1,3)
qc.barrier()

qc.h([0,1])
qc.measure([0,1],[0,1])

display(qc.draw('mpl'))
histograma(qc)

import numpy as np
x0 = np.array([[1,0]]).T
x1 = np.array([[1,0]]).T
x1x0 = np.kron(x1,x0)

y0 = np.array([[1,0]]).T
y1 = np.array([[1,0]]).T
y1y0 = np.kron(y1,y0)

psi0 = np.kron(y1y0,x1x0)
psi0.T

H = np.array([[1,1],[1,-1]],dtype='int')
H2 = np.kron(H,H)
I2 = np.eye(4)
I2H2 = np.kron(I2,H2)
psi1 = I2H2.dot(psi0)/(np.sqrt(2)*np.sqrt(2))
I2H2.dot(psi0).T

Tf1_2 = np.eye(16)
Tf1_2 = Tf1_2[:,[0,5,2,7,4,1,6,3,8,9,10,11,12,13,14,15]]
psi2 = Tf1_2.dot(psi1); psi2.T*2

Tf2_3 = np.eye(16)
Tf2_3 = Tf2_3[:,[0,1,2,3,4,13,6,15,8,9,10,11,12,5,14,7]]
psi3 = Tf2_3.dot(psi2); psi3.T*2

Tf3_4 = np.eye(16)
Tf3_4 = Tf3_4[:,[0,1,6,3,4,5,2,7,8,9,10,15,12,13,14,11]]
psi4 = Tf3_4.dot(psi3); psi4.T*2

Tf4_5 = np.eye(16)
Tf4_5 = Tf4_5[:,[0,1,2,11,4,5,14,7,8,9,10,3,12,13,6,15]]
psi5 = Tf4_5.dot(psi4); psi5.T*2

I2 = np.eye(4)
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
I2H2 = np.kron(I2,H2)
psi6 = I2H2.dot(psi5)
print(psi6.T*2)

import numpy as np
I2 = np.eye(4, dtype='int');
H2 = np.array([[1, 1, 1, 1],
               [1,-1, 1,-1],
               [1, 1,-1,-1],
               [1,-1,-1, 1]])/2;
I2H2 = np.kron(I2,H2);
print(I2H2*2)

import numpy as np
x0 = np.array([[1,0]]).T
x1 = np.array([[1,0]]).T
x2 = np.array([[1,0]]).T
x2x1x0 = np.kron(x2,np.kron(x1,x0))
x2x1x0.T

y0 = np.array([[1,0]]).T
y1 = np.array([[1,0]]).T
y2 = np.array([[1,0]]).T
y2y1y0 = np.kron(y2,np.kron(y1,y0))
y2y1y0.T

psi0 = np.kron(y2y1y0,x2x1x0)
psi0.T

I3 = np.eye(2**3)
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H3 = np.kron(H,H2)
I3H3 = np.kron(I3,H3)
psi1 = I3H3.dot(psi0)
psi1.T.round(2)

n = 2*3 # 2 números de 3 digitos cada
Uf = np.eye(2**n) # 2^6 = 64 posições
Uf = Uf[:,[ 0, 9,18,27,12, 5,30,23,
            8, 1,10,11, 4,13,14,15,
           16,17, 2,19,20,21,22, 7,
           24,25,26, 3,28,29, 6,31,
           32,33,34,35,36,37,38,39,
           40,41,42,43,44,45,46,47,
           48,49,50,51,52,53,54,55,
           56,57,58,59,60,61,62,63]]

psi5 = Uf.dot(psi1)
psi5.T.round(2)

psi6 = I3H3.dot(psi5)
psi6.T

np.where(psi6 > 0)[0]

[format(i,'#08b')[2:] for i in np.where(psi6 > 0)[0]]

import numpy as np
CCNOT = np.eye(8)
CCNOT = CCNOT[:,[0,1,2,7,4,5,6,3]]
CCNOT.dot(CCNOT)

import qiskit as qk

def qNAND(y0,x0):
  x = qk.QuantumRegister(1,"x")
  y = qk.QuantumRegister(1,"y")
  z = qk.QuantumRegister(1,"z")
  u = qk.QuantumRegister(1,"u")
  c = qk.ClassicalRegister(3,'c')
  qc = qk.QuantumCircuit(x,y,z,u,c)

  # Put qubits u and z in state |0>
  qc.initialize([1,0],z)
  qc.initialize([1,0],u)
  qc.initialize(y0,y)
  qc.initialize(x0,x)

  # Perform computation
  qc.barrier()
  qc.ccx(x,y,z)
  qc.x(z)
  # Copy CLASSICALY state of z to u
  qc.cx(z,u)
  qc.barrier()

  # Reverse computation
  qc.x(z)
  qc.ccx(x,y,z)
  qc.barrier()

  # Measure results
  qc.measure(x,c[0])
  qc.measure(y,c[1])
  qc.measure(u,c[2])
  display(qc.draw('mpl'))

  simulator = qk.Aer.get_backend("statevector_simulator")
  results = qk.execute(qc, simulator, shots=10000).result().get_counts()
  grafico = qk.visualization.plot_histogram(results)
  return(grafico)

print("0 NAND 0 = 1")
qNAND([1,0],[1,0])

print("0 NAND 1 = 1")
qNAND([1,0],[0,1])

print("1 NAND 0 = 1")
qNAND([0,1],[1,0])

print("1 NAND 1 = 0")
qNAND([0,1],[0,1])

import qiskit as qk

def qOR(y0,x0):
  x = qk.QuantumRegister(1,"x")
  y = qk.QuantumRegister(1,"y")
  z = qk.QuantumRegister(1,"z")
  u = qk.QuantumRegister(1,"u")
  c = qk.ClassicalRegister(3,'c')

  # Initialize qubits
  qc = qk.QuantumCircuit(x,y,z,u,c)
  qc.initialize(x0,x)
  qc.initialize(y0,y)
  qc.initialize([1,0],z)
  qc.initialize([1,0],u)

  # Compute function
  qc.barrier()
  qc.x(x)
  qc.x(y)
  qc.ccx(x,y,z)
  qc.x(z)
  qc.cx(z,u)
  qc.barrier()

  # Reverse computation
  qc.x(z)
  qc.ccx(x,y,z)
  qc.x(y)
  qc.x(x)
  qc.barrier()

  # Measure results
  qc.measure(x,c[0])
  qc.measure(y,c[1])
  qc.measure(u,c[2])
  display(qc.draw('mpl'))

  # Simulate circuit
  simulator = qk.Aer.get_backend('statevector_simulator')
  results = qk.execute(qc,simulator,shots=10000).result().get_counts()
  grafico = qk.visualization.plot_histogram(results)
  return(grafico)

qOR([1,0],[1,0])

qOR([1,0],[0,1])

qOR([0,1],[1,0])

qOR([0,1],[0,1])

import qiskit as qk

def qNXOR(y0,x0,calc=True,show=False):
  ##################################################
  # Create registers                               #
  ##################################################
  # Base registers
  x = qk.QuantumRegister(1,"x")
  y = qk.QuantumRegister(1,"y")

  # Auxiliary register (for x and y)
  z = qk.QuantumRegister(1,"z")

  # Auxiliary register (to store x AND y)
  a1 = qk.QuantumRegister(1,"a1")

  # Auxiliary register (to store NOT(x) AND NOT(y))
  a2 = qk.QuantumRegister(1,"a2")

  # Auxiliary register (for a1 and a2)
  b1 = qk.QuantumRegister(1,"b1")

  # Auxiliary register (to store a1 OR a2)
  b2 = qk.QuantumRegister(1,"b2")

  # Classical Registers to store x,y and final measurement
  c = qk.ClassicalRegister(3,"c")
  ##################################################
  # Create Circuit                                 #
  ##################################################
  qc = qk.QuantumCircuit(x,y,z,a1,a2,b1,b2,c)

  ##################################################
  # Initialize registers                           #
  ##################################################
  qc.initialize(x0,x)
  qc.initialize(y0,y)
  qc.initialize([1,0],z)
  qc.initialize([1,0],a1)
  qc.initialize([1,0],a2)
  qc.initialize([1,0],b1)
  qc.initialize([1,0],b2)

  ###################################################
  # Calculate x AND y. Copy result to a1. Reverse z #
  ###################################################
  qc.barrier()
  qc.ccx(x,y,z)
  qc.cx(z,a1)
  qc.ccx(x,y,z)
  qc.barrier()

  #########################################################
  # Calc. NOT(x) AND NOT(y). Copy result to a2. Reverse z #
  #########################################################
  qc.barrier()
  qc.x(x)
  qc.x(y)
  qc.ccx(x,y,z)
  qc.cx(z,a2)
  qc.ccx(x,y,z)
  qc.x(y)
  qc.x(x)
  qc.barrier()

  #################################################
  # Calc. a1 OR a2. Copy result to b2. Reverse b1 #
  #################################################
  qc.barrier()
  qc.x(a1)
  qc.x(a2)
  qc.ccx(a1,a2,b1)
  qc.x(b1)
  qc.cx(b1,b2)
  qc.x(b1)
  qc.ccx(a1,a2,b1)
  qc.barrier()

  #################################################
  # Measure b2                                    #
  #################################################
  qc.measure(x,c[0])
  qc.measure(y,c[1])
  qc.measure(b2,c[2])

  #################################################
  # Draw circuit                                  #
  #################################################
  if show:
    display(qc.draw("mpl"))

  #################################################
  # Run circuit. Collect results                  #
  #################################################
  if calc:
    simulator = qk.Aer.get_backend("statevector_simulator")
    results = qk.execute(qc,simulator,shots=10000).result().get_counts()
    grafico = qk.visualization.plot_histogram(results)
    return(grafico)
  else:
    return()


qNXOR([1,0],[1,0],False,True)

qNXOR([1,0],[1,0])

qNXOR([1,0],[0,1])

qNXOR([0,1],[1,0])

qNXOR([0,1],[0,1])

x0 = np.array([1,1])/np.sqrt(2)
y0 = np.array([1,1])/np.sqrt(2)
qNXOR(y0,x0)

import qiskit as qk
from qiskit.quantum_info.operators import Operator

qr = qk.QuantumRegister(6,"q")
cr = qk.ClassicalRegister(6,"c")
qc = qk.QuantumCircuit(qr,cr)

for i in range(6):
  qc.initialize([1,0],i)

for i in range(3):
  qc.h(i)

oracle = np.eye(2**6)
oracle[:,[ 0,  0]] = oracle[:,[  0, 0]]
oracle[:,[ 1,  9]] = oracle[:,[  9, 1]]
oracle[:,[ 2, 18]] = oracle[:,[ 18, 2]]
oracle[:,[ 3, 27]] = oracle[:,[ 27, 3]]
oracle[:,[ 4, 12]] = oracle[:,[ 12, 4]]
oracle[:,[ 5,  5]] = oracle[:,[  5, 5]]
oracle[:,[ 6, 30]] = oracle[:,[ 30, 6]]
oracle[:,[ 7, 23]] = oracle[:,[ 23, 7]]
oracle = Operator(oracle)

qc.append(oracle,qr)

for i in range(3):
  qc.h(i)

qc.barrier()

for i in range(3):
  qc.measure(i,i)

display(qc.draw("mpl"))

simulator = qk.Aer.get_backend("statevector_simulator")
results = qk.execute(qc,simulator,shots=10000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
oracle = np.eye(8)
oracle[:,[2,6]] = oracle[:,[6,2]]
oracle

import numpy as np
x0 = np.array([[1,0]]).T
x1 = np.array([[1,0]]).T
psi0 = np.kron(x1,x0)

H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
psi1 = H2.dot(psi0)
psi1.T

# Initialize a qubit y in state |1>
y  = np.array([[0,1]]).T

# Pass it through a Hadamard gate and obtain state psi2a
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
psi2a = H.dot(y)
psi2a.T

psi2 = np.kron(psi2a,psi1)
psi2.T

oracle = np.eye(8)
oracle[:,[2,6]] = oracle[:,[6,2]]
oracle

psi3 = oracle.dot(psi2)
psi3.T

v0 = np.array([[10,20,-30,40,50]]).T
mu = np.mean(v0)
v0.T, mu

D = v0 - mu
D.T

v1 = 2*np.mean(v0)-v0
v1.T

import numpy as np
A = np.ones(5**2).reshape(5,5)
A = A/5
I = np.eye(5)
R = 2*A-I
R

R.dot(R)

n = 4
I = np.eye(n)
A = np.ones(n**2).reshape(n,n)/n
R = 2*A-I
R

I2 = np.eye(2)
I2R = np.kron(I2,R)
I2R

psi4 = I2R.dot(psi3)
psi4.T

import qiskit as qk
import numpy as np

from qiskit.quantum_info.operators import Operator

q = qk.QuantumRegister(3,'q')
c = qk.ClassicalRegister(3,'c')
qc = qk.QuantumCircuit(q,c)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.h(0)
qc.h(1)

qc.initialize([0,1],2)
qc.h(2)

qc.barrier()
oracle = np.eye(8)
oracle[:,[2,6]] = oracle[:,[6,2]]
oracle = Operator(oracle)
qc.append(oracle,q)

# n = 2 (two digits number to look for)
A = np.ones(4*4).reshape(4,4)/4
I4 = np.eye(4)
R = 2*A - I4
I2 = np.eye(2)
boost = np.kron(I2,R)
boost = Operator(boost)
qc.append(boost,q)

qc.barrier()
qc.measure(q[:2],c[:2])

display(qc.draw('mpl'))

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=1000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
x0 = np.array([[1,0]]).T
x1 = np.array([[1,0]]).T
x2 = np.array([[1,0]]).T
x2x1x0 = np.kron(x2,np.kron(x1,x0))
x2x1x0.T

H = np.array([[1,1],[1,-1]])/np.sqrt(2)
H2 = np.kron(H,H)
H3 = np.kron(H,H2)
x = H3.dot(x2x1x0)
x.T

y0 = np.array([[0,1]]).T
y0.T

H = np.array([[1,1],[1,-1]])/np.sqrt(2)
y = H.dot(y0)
y.T

psi0 = np.kron(y,x)
psi0.T

oracle = np.eye(16)
oracle[:,[5,13]] = oracle[:,[13,5]]
psi1 = oracle.dot(psi0)
psi1.T

# n = 8
A = np.ones(8*8).reshape(8,8)/8
I8 = np.eye(8)
R = 2*A-I8
R

I2 = np.eye(2)
I2R = np.kron(I2,R)
psi2 = I2R.dot(psi1)
psi2.T

0.625**2 + 0.625**2

psi3 = I2R.dot(oracle).dot(psi2)
psi3.T

0.687**2 + 0.687**2

I2R.dot(oracle).dot(psi3).T

T = I2R.dot(oracle)

psi = psi1
prob = []
for i in range(25):
  prob.append(psi[5,0]**2 + psi[13,0]**2)
  psi = T.dot(psi)

from matplotlib import pyplot as plt
plt.plot(list(range(25)), prob);

import qiskit as qk
import numpy as np

from qiskit.quantum_info.operators import Operator

q = qk.QuantumRegister(4,'q')
c = qk.ClassicalRegister(4,'c')
qc = qk.QuantumCircuit(q,c)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([1,0],2)
qc.h(0)
qc.h(1)
qc.h(2)

qc.initialize([0,1],3)
qc.h(3)

qc.barrier()

# Create oracle matrix
oracle = np.eye(16)
oracle[:,[5,13]] = oracle[:,[13,5]]

# Create rotation about the mean matrix
# n = 3 (three digits number to look for)
A = np.ones(8*8).reshape(8,8)/8
I8 = np.eye(8)
R = 2*A - I8

# Identity matrix to leave fourth qubit undisturbed
I2 = np.eye(2)

# Create second transformation matrix
boost = np.kron(I2,R)

# Combine oracle with second transformation matrix in
#  an unique operator
T = boost.dot(oracle)
T = Operator(T)

# Apply operator twice (2 phase inversions and
#  rotations about the mean)
qc.append(T,q)
qc.append(T,q)

qc.barrier()
qc.measure(q[:3],c[:3])

display(qc.draw('mpl'))

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=1000).result().get_counts()
qk.visualization.plot_histogram(results)

import qiskit as qk
import numpy as np

from qiskit.quantum_info.operators import Operator

q = qk.QuantumRegister(5,'q')
c = qk.ClassicalRegister(5,'c')
qc = qk.QuantumCircuit(q,c)

qc.initialize([1,0],0)
qc.initialize([1,0],1)
qc.initialize([1,0],2)
qc.initialize([1,0],3)
qc.h(0)
qc.h(1)
qc.h(2)
qc.h(3)

qc.initialize([0,1],4)
qc.h(4)

qc.barrier()

# Create oracle matrix
oracle = np.eye(32)
oracle[:,[13,29]] = oracle[:,[29,13]]

# Create rotation about the mean matrix
# n = 4 (four digits number to look for)
A = np.ones(16*16).reshape(16,16)/16
I16 = np.eye(16)
R = 2*A - I16

# Identity matrix to leave fifth qubit undisturbed
I2 = np.eye(2)

# Create second transformation matrix
boost = np.kron(I2,R)

# Combine oracle with second transformation matrix in
#  an unique operator
T = boost.dot(oracle)

# n = 4. Therefore it will be necessary 4 T operations
#  to get maximum probability.
Tn = T.dot(T).dot(T)
Tn = Operator(Tn)

# Apply operator Tn once (n phase inversions and
#  rotations about the mean)
qc.append(Tn,q)

qc.barrier()
qc.measure(q[:4],c[:4])

display(qc.draw('mpl'))

simulator = qk.Aer.get_backend('statevector_simulator')
results = qk.execute(qc,simulator,shots=1000).result().get_counts()
qk.visualization.plot_histogram(results)

import numpy as np
import pandas as pd
N = 35; a = 6

GCD = pd.DataFrame({'N':[N], 'a':[a], 'N-a':[N-a]})

while GCD.iloc[-1,2] != 0:
  temp = GCD.iloc[-1].values
  temp = np.sort(temp); temp[-1] = temp[-2] - temp[-3]
  temp = pd.DataFrame(data = temp.reshape(-1,3), columns = ['N','a','N-a'])
  GCD = GCD.append(temp, ignore_index=True)

GCD

import numpy as np
import pandas as pd
N = 15; a = 9

GCD = pd.DataFrame({'N':[N], 'a':[a], 'N-a':[N-a]})

while GCD.iloc[-1,2] != 0:
  temp = GCD.iloc[-1].values
  temp = np.sort(temp); temp[-1] = temp[-2] - temp[-3]
  temp = pd.DataFrame(data = temp.reshape(-1,3), columns = ['N','a','N-a'])
  GCD = GCD.append(temp, ignore_index=True)

GCD

import numpy as np
np.gcd(6,35), np.gcd(9,15)

import numpy as np
np.gcd(215,35), np.gcd(217,35)

20 % 7

import numpy as np
f = lambda x,a,N: a**x % N

[f(x,2,15) for x in range(10)]

import numpy as np
(13*35)%11, ((2%11)*(24%11))%11

import numpy as np

def f(x,a,N):
  a0 = 1
  for i in range(x):
    a0 = ((a%N)*(a0))%N
  return(a0)

[f(x,2,371) for x in range(8)]

[f(x,2,371) for x in range(154,159)]

[f(x,24,371) for x in range(77,81)]

import numpy as np

def fr(a,N):
  ax = ((a%N)*(1))%N
  x = 1
  while ax != 1:
    ax = ((a%N)*(ax))%N
    x = x+1
  return(x)

fr(2,371), fr(6,371), fr(24,371)

import numpy as np

def fr(a,N):
  a0 = 1
  a0 = ((a%N)*a0)%N
  x = 2
  find = False
  while find==False:
    a0 = ((a%N)*(a0))%N
    if a0 == 1:
      find = True
    x = x+1
  return(x-1)

N = 35
a = 2
fr(a,N)

2**(12/2)-1, 2**(12/2)+1

np.gcd(63,35), np.gcd(65,35)

import numpy as np
# Function to calculate the period of f(x) = a^x MOD N
def fr(a,N):
  a1 = ((a%N)*(1))%N
  x = 1
  while a1 != 1:
    a1 = ((a%N)*a1)%N
    x = x+1
  return(x)

# Function to factor N based on a
def factor(N, a=2):
  r = fr(a,N)
  g1 = a**(int(r/2)) - 1
  g2 = a**(int(r/2)) + 1
  f1 = np.gcd(g1,N)
  f2 = np.gcd(g2,N)
  return(f1,f2, f1*f2)

factor(247)

factor(1045)

import numpy as np
N = 15 # number to be factored
n = 4  # number of bits necessary to represent N
m = 8  # number of bits necessary to represent N^2
x = np.zeros(2**m).reshape(-1,1)
x[0,0] = 1
x.shape # since x is a 2^8 = 256 positions vector it will not be showed here

y = np.zeros(2**n).reshape(-1,1)
y[0,0] = 1; y.T # y is a 2^4 = 16 positions vector shown below

psi0 = np.kron(y,x)
psi0.shape # psi0 is a 256 x 16 = 4.096 positions vector

In = np.eye(2**n); In.shape

H = np.array([[1,1],[1,-1]])/np.sqrt(2)
Hm = H.copy()
for i in range(1,m):
  Hm = np.kron(Hm,H)

Hm.shape

psi1 = np.kron(In,Hm).dot(psi0); psi1.shape