import numpy as np

ket0 = np.array([1,0])
ket1 = np.array([0,1])

ket0/2 + ket1/2

M1 = np.array([ [1, 1], [0, 0] ])
M2 = np.array([ [1, 1], [1, 0] ])

M1/2 + M2/2

print("product of M1 with ket0: ", np.matmul(M1,ket0))
print("product of M1 and M2: \n",np.matmul(M1,M2))

from qiskit.quantum_info import Statevector

u = Statevector([1/np.sqrt(2), 1/np.sqrt(2)])
v = Statevector([(1+2.j)/3, -2/3])

display(u.draw('latex'))
display(u.draw('text'))

display(v.draw('latex'))

w = Statevector([1/3,2/3])

display(v.is_valid())
display(w.is_valid())

v = Statevector([(1+2.j)/3, -2/3])

v.measure()


from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt

stat = v.sample_counts(10000)
display(stat)
plot_histogram(stat)

from qiskit.quantum_info import Operator

t = np.sqrt(2)

X = Operator([[0,1],[1,0]])
Y = Operator([[0,-1.j],[1.j,0]])
Z = Operator([[1,0],[0,-1]])
H = Operator([[1/t, 1/t],[1/t, -1/t]])
S = Operator([[1,0],[0,1.j]])
T = Operator([[1,0],[0,(1+1.j)/t]])

v = Statevector([1,0])

display(v.evolve(X).draw('latex'))
display(v.evolve(Y).draw('latex'))
display(v.evolve(H).draw('latex'))
display(v.evolve(S).draw('latex'))

from qiskit import QuantumCircuit

# initiate an instance of the class
qc = QuantumCircuit(1) ## A QuantumCircuit with 1 qubits

qc.h(0)
qc.t(0)
qc.h(0)
qc.t(0)
qc.z(0)

qc.draw()

ket0 = Statevector([1,0])
v = ket0.evolve(qc)
v.draw('latex')

stat = v.sample_counts(5000)
plot_histogram(stat)

ket0 = Statevector([1,0])
ket1 = Statevector([0,1])

ket01 = ket0.tensor(ket1)
display(ket01.draw('latex'))

# Another quick way to define the common states

zero = Statevector.from_label('0')
one = Statevector.from_label('1')
plus = Statevector.from_label('+')
minus = Statevector.from_label('-')

i_state = 1/np.sqrt(2) * (zero + 1.j * one)
psi = minus.tensor(i_state)

psi.draw('latex')

X.tensor(Z)

psi_1 = psi.evolve(T^X)

display(psi_1.draw('latex'))

CNOT = Operator([ [1, 0, 0, 0],
                 [0, 1, 0, 0],
                 [0, 0, 0, 1],
                 [0, 0, 1, 0] ])

psi_2 = psi.evolve(CNOT)
display(psi_2.draw('latex'))

# SOLUTION
phi_plus = plus.tensor(zero).evolve(CNOT)
phi_minus = minus.tensor(zero).evolve(CNOT)
psi_plus = plus.tensor(one).evolve(CNOT)
psi_minus = minus.tensor(one).evolve(CNOT)

display(phi_plus.draw('latex'))
display(phi_minus.draw('latex'))
display(psi_plus.draw('latex'))
display(psi_minus.draw('latex'))

W = Statevector([0,1,1,0,1,0,0,0]/np.sqrt(3))
display(W.draw('latex'))

result, new_statevector = W.measure([0])
print(f"Measured: {result} \n New Statevector:")
display(new_statevector.draw('latex'))

result, new_statevector = W.measure([1])
print(f"Measured: {result} \n New Statevector:")
display(new_statevector.draw('latex'))

I = Operator([[1,0],[0,1]])
W1 = W.evolve(I^I^H)

display(W1.draw('latex'))

result, new_statevector = W1.measure([0])
print(f"Measured: {result} \n New Statevector:")
display(new_statevector.draw('latex'))

W1.probabilities([0])

import qiskit.tools.jupyter
%qiskit_version_table

from qiskit import QuantumCircuit
qc = QuantumCircuit(1)
qc.h(0)
qc.s(0)
qc.h(0)
qc.t(0)
qc.draw()

from qiskit import QuantumRegister
u = QuantumRegister(1, "u")
qc = QuantumCircuit(u)
qc.y(0)
qc.s(0)
qc.h(0)
qc.t(0)
qc.x(0)
qc.draw()

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

X = QuantumRegister(1, "x")
Y = QuantumRegister(1, "y")
A = ClassicalRegister(1, "a")
B = ClassicalRegister(1, "b")

qc = QuantumCircuit(Y,X,B,A)
qc.h(Y)
qc.cx(Y,X)

qc.measure(Y,B)
qc.measure(X,A)
qc.draw()

from qiskit import transpile
from qiskit_aer import AerSimulator

simulator = AerSimulator()
qc_simulator = simulator.run(transpile(qc,simulator), shots=1000)
statistics = qc_simulator.result().get_counts()
plot_histogram(statistics)

# Circuit
circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)
circ.measure_all()

from qiskit import Aer
# Transpile for simulator
simulator = Aer.get_backend('aer_simulator')
circ = transpile(circ, simulator)

# Run and get counts
result = simulator.run(circ).result()
counts = result.get_counts(circ)
plot_histogram(counts, title='Bell-State counts')

# Run and get memory
result = simulator.run(circ, shots=10, memory=True).result()
memory = result.get_memory(circ)
memory

Aer.backends()

