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