from qiskit import *
from qiskit.tools.jupyter import *
from qiskit.visualization import *
import matplotlib.pyplot as plotter
import numpy as np
from IPython.display import display, Math, Latex
%matplotlib inline
# Loading your IBM Q account(s)
provider = IBMQ.load_account()

# The '0' state
plot_bloch_vector([0,0,1])

# The '1' state
plot_bloch_vector([0,0,-1])

qc1 = QuantumCircuit(2,2) # Initializing a quantum ciruit (2 qubits, 2 classical bits) 
# All initialized to '0' by default.
qc1.draw(output='mpl') # Draws the circuit diagram

qc1.x(0) # Applying X gate to the first qubit
qc1.draw(output='mpl')


qc1.x(1) # Applying X gate to the second qubit
qc1.draw(output='mpl')

# The '+' state
plot_bloch_vector([1,0,0])

# The '-' state
plot_bloch_vector([-1,0,0])

qc2 = QuantumCircuit(2,2) # A new quantum circuit with 2 qubits and 2 classical bits 
qc2.h(0) # Applying the Hadamard gate on first qubit
qc2.draw(output='mpl')

qc2.cx(0,1) # Applying CX gate ('control','target')
qc2.draw(output='mpl')

qc2.measure(0,0) # Measure first qubit and store it in first classical bit 
qc2.measure(1,1) # Measure second qubit and store it in second classical bit
# The code below plots a histogram of the measurement result. You can copy it for further use.
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(qc2)
print(counts)
plot_histogram(counts)

qc1.h(0)
qc1.cx(0, 1)
qc1.draw(output='mpl')

qc1.measure(0,0)
qc1.measure(1,1)

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator')
    result = execute(qc, backend, shots = 2000).result()
    counts = result.get_counts()
    return counts

counts = run_circuit(qc1)
print(counts)
plot_histogram(counts)

qc3 = QuantumCircuit(3,3)
qc3.x(range(3)) # Setting the all qubits to '1'
qc3.toffoli(0,1,2) # (control,control,target)
qc3.measure(0,0)
qc3.measure(1,1)
qc3.measure(2,2)
def run_circuit(qc3): 
    backend = Aer.get_backend('qasm_simulator') # we choose the simulator as our backend
    result = execute(qc3, backend, shots = 2000).result() # we run the simulation
    counts = result.get_counts() # we get the counts
    return counts

counts = run_circuit(qc3)
print(counts)
plot_histogram(counts)
# The output should be '011' as the highest (q2) is flipped because the other two qubits were set to '1'

qc4 = QuantumCircuit(2,2)

#Applying the Pauli-X gate to quantum bit 0, we turn it into 1 so that the swap outcome is observable.
qc4.x(0)

qc4.cx(0, 1)
qc4.cx(1, 0)
qc4.cx(0, 1)
qc4.draw(output='mpl')

qc4.measure(0,0)
qc4.measure(1,1)

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator')
    result = execute(qc, backend, shots = 2000).result()
    counts = result.get_counts()
    return counts

counts = run_circuit(qc4)
print(counts)
plot_histogram(counts)

qc5 = QuantumCircuit(2,2)

#We turn quantum bit 1 into 1 so that we can observe the results of HZH on both 0 (from q0) and 1 (from q1).
qc5.x(1)

qc5.h((0, 1))
qc5.z((0, 1))
qc5.h((0, 1))
qc5.draw(output='mpl')

qc5.measure(0,0)
qc5.measure(1,1)

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator')
    result = execute(qc, backend, shots = 2000).result()
    counts = result.get_counts()
    return counts

counts = run_circuit(qc5)
print(counts)
plot_histogram(counts)

qc6 = QuantumCircuit(3,3)

#Initializing quantum bits using gates:
#q0 is initialized to 0.
#q1 is initialized to 1.
qc6.x(1)
#q2 is initialized to the state given above.
qc6.x(2)
qc6.h(2)
qc6.t(2)

#We change q2 for the controlled swap now; we'll bring it back to the same state afterwards.
qc6.tdg(2)
qc6.h(2)

#Controlled swap.
qc6.toffoli(0, 2, 1)
qc6.toffoli(1, 2, 0)
qc6.toffoli(0, 2, 1)

#We convert q2 back to whatever it was.
qc6.h(2)
qc6.t(2)

qc6.draw(output='mpl')

qc6.measure(0, 0)
qc6.measure(1, 1)
qc6.measure(2, 2)

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator')
    result = execute(qc, backend, shots = 2000).result()
    counts = result.get_counts()
    return counts

counts = run_circuit(qc6)
print(counts)
plot_histogram(counts)