import qiskit as q

%matplotlib inline

# Creating a quantum circuit with 3 qbits
circuit = q.QuantumCircuit(2,2)

#Adding a NOT gate to 0th qbit which flips the input
circuit.x(0)

#Adding a 'Controlled NOT' gate between 0th,1st qbits 

#CNOT Gate operation : The second bit is flipped if the first bit is 1

circuit.cx(0,1)

#Mapping the value of qbit to  classical bits (collapse)
circuit.measure([0,1],[0,1])

circuit.draw()

circuit.draw(output="mpl")

from qiskit import IBMQ

IBMQ.save_account("e870e2997e01a21385263381f81495beff826d71a12d646658a7a15ffc5400dbbefa30e9ce0d2e65b872b30170038db21cdf8482e422510d62ef16297ad5c8a2")


IBMQ.load_account()

IBMQ.providers()

provider = IBMQ.get_provider("ibm-q")

# In QC practice,a simulator or a quantum computer is referred to as 'backend'

for backend in provider.backends():
    try:
        qubit_count = len(backend.properties().qubits)
    except :
        qubit_count = "simulated"
    print(backend.name(),"has",backend.status().pending_jobs," queued and ",qubit_count,"qubits")

from qiskit.tools.monitor import job_monitor
backend = provider.get_backend("ibmqx2") #Since it has0 queued
job = q.execute(circuit,backend=backend,shots=500)
job_monitor(job)

# Now our circuit has been successfully run on IBM Cloud's IBMQX2 machine

from qiskit.visualization import plot_histogram

result = job.result()

counts = result.get_counts(circuit)

plot_histogram([counts],legend=['Device'])

circuit = q.QuantumCircuit(2,2)

# Hadamard gate to the first qbit
circuit.h(0)
# The same good old CNOT gate
circuit.cx(0,1)

circuit.measure([0,1],[0,1])



circuit.draw(output="mpl")

# Let's execute this circuit

# This cell isn't much needed yet we'll use it as a revision cell

for backend in provider.backends():
    try:
        qubit_count = len(backend.properties().qubits)
    except:
        qubit_count = "simulated"
    print(backend.name(),"has ",backend.status().pending_jobs,"queued and",qubit_count,"qubits")

# let's choose ibmqx2

backend = provider.get_backend("ibmqx2")

job = q.execute(circuit,backend = backend,shots=500)

job_monitor(job) # Gives the status of our job

result = job.result()
counts = result.get_counts(circuit)

plot_histogram([counts],legend=['Device '])

from qiskit import Aer

for backend in Aer.backends():
    print(backend)

#Let's use qasm_simulator

sim_backend = Aer.get_backend('qasm_simulator')

job = q.execute(circuit,backend=sim_backend,shots=500)

job_monitor(job)

result = job.result()

counts = result.get_counts(circuit)

plot_histogram([counts],legend=['Device'])

import qiskit as q

from qiskit.tools.visualization import plot_bloch_multivector
%matplotlib inline

statevec_simulator = q.Aer.get_backend("statevector_simulator")
qasm_sim = q.Aer.get_backend('qasm_simulator')

def do_job(circuit):
    job = q.execute(circuit,backend=statevec_simulator)
    result = job.result()
    statevec = result.get_statevector()
    
    n_qubits = circuit.n_qubits
    circuit.measure([i for i in range(n_qubits)],[i for i in range(n_qubits)])
    
    qasm_job = q.execute(circuit,backend=qasm_sim,shots=1024).result()
    counts = qasm_job.get_counts()
    
    return statevec,counts
    
    

circuit = q.QuantumCircuit(2,2)

statevec,counts=do_job(circuit)

plot_bloch_multivector(statevec)

# Let's see how superposition looks like in bloch sphere 

circuit = q.QuantumCircuit(2,2)

circuit.h(0)
statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

# The qubit 0 is under superposition . So, it lies between 1 and 0 states in the space

#Let's entangle the qubits

circuit = q.QuantumCircuit(2,2)
circuit.h(0)
circuit.cx(0,1)
statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

from qiskit.visualization import plot_histogram
plot_histogram([counts],legend=['Device'])

#Let's take 3 qubits and control the last qubit by the first two qubits

circuit = q.QuantumCircuit(3,3)
circuit.h(0)
circuit.h(1)
circuit.cx(0,2)
circuit.cx(1,2)
circuit.draw(output="mpl")

statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

plot_histogram([counts],legend=['Device'])

circuit = q.QuantumCircuit(3,3)
circuit.h(0)
circuit.h(1)
circuit.ccx(0,1,2)
circuit.draw(output="mpl")

statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

plot_histogram([counts],legend=['Device'])

circuit = q.QuantumCircuit(3,1)
circuit.h(0)
circuit.h(1)
circuit.ccx(0,1,2)
circuit.measure([2],[0])


result = q.execute(circuit,backend=qasm_sim,shots=1024).result()

counts = result.get_counts()
plot_histogram([counts],legend=['Device'])

import math

circuit = q.QuantumCircuit(3,1)
circuit.h(0)
circuit.h(1)
circuit.ccx(0,1,2)
circuit.rx(math.pi/2,2)
circuit.draw(output="mpl")

circuit.measure([2],[0])
result = q.execute(circuit,backend=qasm_sim,shots=1024).result()
counts = result.get_counts()
plot_histogram([counts],legend=['output'])




#Rotate X by 45 deg

circuit = q.QuantumCircuit(3,3)
circuit.h(0)
circuit.h(1)
circuit.ccx(0,1,2)
circuit.rx(math.pi/4,2)

statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

plot_histogram([counts],legend=['output'])

circuit = q.QuantumCircuit(3,3)  
circuit.h(0)  
circuit.h(1)  
circuit.ccx(0,1,2) 
circuit.rx(math.pi/4, 2)
circuit.rz(math.pi, 2)
circuit.ry(math.pi, 2)
statevec, counts = do_job(circuit)
plot_bloch_multivector(statevec)

circuit = q.QuantumCircuit(3,3)
circuit.h(0)
circuit.h(1)
circuit.x(2)
circuit.crz(math.pi,1,2)
circuit.draw(output="mpl")


statevec,counts = do_job(circuit)
plot_bloch_multivector(statevec)

