# Fyi in a code cell use a hash symbol or more coloquially known as a 
# 'hashtag' to make a line comment, comments do not get interpreted 
# by the editor and are great for leaving notes and things
# and mostly are used to express clarity so other programmers like me 
# and yur classmates can read what you did and why you did it

"""

You can make block comments that spam multiple lines
using triple quotes above and below your block. Please use these, take 
notes when you copy examples and are writing your own code
I will try to do my best to leave these for your guys when I write code

"""

print('I love Quantum Computing')
# when I run this cell it doesnt read the rest, only prints

# At the top of every Notebook we use for this course we need to import
# all the Qiskit functionality, this is done using Import 

from qiskit import * # this means that from the qiskit package
                     # import ALL functionality(*)
    
# we also want to see our results in insightful ways through graphs! 
from qiskit.visualization import * # bloch sphere graphs, bar graphs for measurements 

# We also need to import the simulators that we will use to make measurements

S_simulator=Aer.backends(name='statevector_simulator')[0] # allows you to simulate statevectors
M_simulator=Aer.backends(name='qasm_simulator')[0] # allows you to simulate measurements 
    
# You should be able to run this import with NO ERRORS, if you do get an 
# error please contact me so we can trouble shoot this together

# In qiskit we can make a quantum circut by using the QuantumCircuit 
# class, and specifying our number of Quantum bits and Classical bits

# example make a Quantum Circuit with 1 qubit and 1 classical bit

our_first_quantum_circuit = QuantumCircuit(1,1) 

# Note that you can call the circuit whatever you want, most of the time
# you want to be as specific as possible

#NOTE: Unless programmed otherwise ALL qubits start in the |0> state. 


# qiskit makes it really easy to use gates, we just need to know which
# gate and which qubit(s) we want to use it on

#use the hadammard gate on the first qubit in our circuit

our_first_quantum_circuit.h(0)

# Lets explain what we did! 

# I used the name of my circuit, then a '.' followed by the gate
# h for hadammard, and the in paranthesis I will specify the qubit I am
# using the gate on, Python counts starting at 0, so the first qubit 
# will always be coded as the zeroth! 


# Now we made a circuit, and used a gate, how do we know if it worked?
# we Measure it! 

our_first_quantum_circuit.measure(0,0) # this measures our first qubit

# Notice how I have two inputs for measurement, the first input 
# is the qubit we want to measure and the second is the classical bit
# we want to store the measurement in

# execute our measurement 1000 times
job=execute(our_first_quantum_circuit, M_simulator, shots=1000)

#get the results
counts=job.result().get_counts()

#plot them in a pretty histogram
plot_histogram(counts)


# we can also measure the statevector using the S_simulator! 
# lets make a new ciruit and try it out to get the state vector

#make a new circuit 
state_circuit= QuantumCircuit(1,1) 

state_circuit.h(0)

#NOTE: to find out state in a superposition of state we do NOT measure! 

# execute our measurement of the statevector 
job=execute(state_circuit, S_simulator)

#get the results
state_vector=job.result().get_statevector()

#plot them in a pretty histogram
print('This should be the |+> state: ', state_vector)


our_first_quantum_circuit.draw() # the draw method draws your circuit

# if you use pip install matplotlib in command line you use 
# the matplotlib drawer to get really pretty circuits
our_first_quantum_circuit.draw(output='mpl') 