# Cell 1
import numpy as np

from qiskit import Aer, QuantumCircuit, execute
from qiskit.visualization import plot_histogram
from IPython.display import display, Math, Latex

from may4_challenge import plot_state_qsphere
from may4_challenge.ex1 import minicomposer
from may4_challenge.ex1 import check1, check2, check3, check4, check5, check6, check7, check8
from may4_challenge.ex1 import return_state, vec_in_braket, statevec

# Cell 2
# press shift + return to run this code cell
# then, click on the gate that you want to apply to your qubit
# next, you have to choose the qubit that you want to apply it to (choose '0' here)
# click on clear to restart
minicomposer(1, dirac=True, qsphere=True)

# Cell 3
def create_circuit():
    qc = QuantumCircuit(1)
    qc.x(0)
    return qc

# check solution
qc = create_circuit()
state = statevec(qc)
check1(state)
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True) 

# Cell 4
def create_circuit2():
    qc = QuantumCircuit(1)
    qc.h(0)
    return qc

qc = create_circuit2()
state = statevec(qc)
check2(state)
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True) 

# Cell 5
def create_circuit3():
    qc = QuantumCircuit(1)
    qc.x(0)
    qc.h(0)
    return qc

qc = create_circuit3()
state = statevec(qc)
check3(state)
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True) 

# Cell 6
def create_circuit4():
    qc = QuantumCircuit(1)
    qc.h(0)
    qc.sdg(0)
    return qc

qc = create_circuit4()
state = statevec(qc)
check4(state)
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True) 

# Cell 7
# press shift + return to run this code cell
# then, click on the gate that you want to apply followed by the qubit(s) that you want it to apply to
# for controlled gates, the first qubit you choose is the control qubit and the second one the target qubit
# click on clear to restart

minicomposer(2, dirac = True, qsphere = True)

# Cell 8
def create_circuit():
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    return qc

qc = create_circuit()
state = statevec(qc) # determine final state after running the circuit
display(Math(vec_in_braket(state.data)))
check5(state)
qc.draw(output='mpl') # we draw the circuit

# Cell 9
def create_circuit6():
    qc = QuantumCircuit(2,2) # this time, we not only want two qubits, but also 
                             # two classical bits for the measurement later
    qc.h(0)
    qc.x(1)
    qc.cx(0, 1)
    qc.z(0)
    return qc

qc = create_circuit6()
state = statevec(qc) # determine final state after running the circuit
display(Math(vec_in_braket(state.data)))
check6(state)
qc.measure(0, 0) # we perform a measurement on qubit q_0 and store the information on the classical bit c_0
qc.measure(1, 1) # we perform a measurement on qubit q_1 and store the information on the classical bit c_1
qc.draw(output='mpl') # we draw the circuit

# Cell 10
def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator') # we choose the simulator as our backend
    result = execute(qc, backend, shots = 1000).result() # we run the simulation
    counts = result.get_counts() # we get the counts
    return counts

counts = run_circuit(qc)
print(counts)
plot_histogram(counts) # let us plot a histogram to see the possible outcomes and corresponding probabilities

# Cell 11
def create_circuit7():
    qc = QuantumCircuit(2)
    qc.rx(np.pi/3,0)
    qc.x(1)
    qc.swap(0, 1)
    return qc

qc = create_circuit7()
def create_circuit():
  
    qc.x(0)
    qc.h(1)
    qc.sdg(1)
    qc.swap(0, 1)
 
state = statevec(qc) # determine final state after running the circuit
display(Math(vec_in_braket(state.data)))
check7(state)
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True) 

# Cell 12
#
#
# FILL YOUR CODE IN HERE
def create_circuit8():
    qc = QuantumCircuit(3,3) # this time, we not only want two qubits, but also 
                             # two classical bits for the measurement later
    def create_circuit():
        qc = QuantumCircuit(3)
    qc.h(2)
    qc.cx(2, 1)
    qc.cx(1, 0)
    return qc

qc = create_circuit8()
state = statevec(qc) # determine final state after running the circuit
display(Math(vec_in_braket(state.data)))

qc.measure(0, 0) # we perform a measurement on qubit q_0 and store the information on the classical bit c_0
qc.measure(1, 1) # we perform a measurement on qubit q_1 and store the information on the classical bit c_1
qc.measure(2, 2)
qc.draw(output='mpl') # we draw the circuit
plot_state_qsphere(state.data, show_state_labels=True, show_state_angles=True)





#

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator') # we choose the simulator as our backend
    result = execute(qc, backend, shots = 2000).result() # we run the simulation
    counts = result.get_counts() # we get the counts
    return counts

counts = run_circuit(qc)



#
print(counts)
check8(counts)
plot_histogram(counts)



