import numpy as np

# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, transpile, Aer, IBMQ
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from ibm_quantum_widgets import *
from qiskit.providers.aer import QasmSimulator

# Loading your IBM Quantum account(s)
provider = IBMQ.load_account()

!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 qiskit

# A qubit initialized in the state |0>
qc = qk.QuantumCircuit(1)
qc.initialize([1,0])
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

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.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.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

vout = C.dot(vaHvb); vout

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', group='open', project='main')

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

# 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(i)

# Measuring the three qubits
qc.measure(qr,cr)

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


new_job = qk.execute(qc, 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)

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,0,0,1],
               [0,0,1,0],
               [0,1,0,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.dot(X)

n+n_

X.dot(n_)

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

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


np.kron(n,n)

np.kron(n_,n_)

np.kron(n,n_)

np.kron(n_,n)

np.kron(X,X)

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

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

np.kron(n,n)

np.kron(n_,n_)

np.kron(n_,n)

np.kron(n,n_)

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_))

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

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))

n_n_.dot(nn)

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

D0 = np.array([[1],[0]])
D1 = np.array([[0],[1]])

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

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

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)

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

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)

