#Import libraries from qiskit
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np

from qiskit import *
from qiskit.providers.ibmq import least_busy
import math

# Initializing circuit: define as 2 qubits
q = QuantumRegister(2, 'q')
c = ClassicalRegister(2, 'c')

# Create the quantum circuit
qc = QuantumCircuit(q,c)

## Step 1: Apply a Hadarmard gate to all qubits  
qc.h(q)

## Step 2: Implement the Oracle circuit for state |11> + Grover diffusion
qc.cz(q[1],q[0])
qc.barrier(q)

qc.h(q)
qc.x(q)
qc.cz(q[1],q[0])
qc.x(q)
qc.h(q)
qc.barrier(q)

qc.draw(output='mpl')

## Don't forget about the measurement gates!
qc.measure(q[0],c[0])
qc.measure(q[1],c[1])

qc.draw(output='mpl')

## Step 4: Run on backend simulator and print results
simulator = Aer.get_backend('qasm_simulator')
result = execute(qc, backend = simulator, shots = 2048).result()
counts = result.get_counts()

print('RESULT: ',counts,'\n')

from qiskit.tools.visualization import plot_histogram
plot_histogram(counts)

## Step 4: Run on real device from IBM - load account and get least busy backend

provider = IBMQ.load_account()
device = least_busy(provider.backends(simulator=False))
print("Running on current least busy device: ", device)

from qiskit.tools.monitor import job_monitor
job = execute(qc, backend=device, shots=1024, max_credits=10)
job_monitor(job, interval = 2)

## Print results from device from IBM

results = job.result()
answer = results.get_counts(qc)
plot_histogram(answer)

pi = math.pi

# Initializing circuit: define as 3 qubits
q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')

# Create the quantum circuit
qc = QuantumCircuit(q,c)

## Step 1: Apply a Hadarmard gate to all qubits  
qc.h(q)

## Step 2: Implement the Oracle circuit for state |111> + Grover diffusion
qc.cz(q[2],q[0])
qc.barrier(q)

qc.h(q)
qc.x(q)
qc.barrier(q)

qc.cx(q[1],q[0])
qc.z(q[0]),-pi/4
qc.cx(q[2],q[0])
qc.z(q[0]),pi/4
qc.cx(q[1],q[0])
qc.z(q[0]),-pi/4
qc.barrier(q)
qc.cx(q[2],q[0])
qc.z(q[0]),pi/4
qc.z(q[1]),pi/4
qc.barrier(q)
qc.cx(q[2],q[1])
qc.z(q[1]),-pi/4
qc.cx(q[2],q[1])
qc.z(q[2]),pi/4
qc.barrier(q)

qc.x(q)
qc.h(q)
qc.barrier(q)

qc.draw(output='mpl')

## Don't forget about the measurement gates!
qc.measure(q[0],c[0])
qc.measure(q[1],c[1])
qc.measure(q[2],c[2])

qc.draw(output='mpl')

## Step 4: Run on backend simulator and print results
simulator = Aer.get_backend('qasm_simulator')
result = execute(qc, backend = simulator, shots = 2048).result()
counts = result.get_counts()

print('RESULT: ',counts,'\n')

from qiskit.tools.visualization import plot_histogram
plot_histogram(counts)

## Note: accuracy of this implementation is not 100% (may need to run a couple iterations before achieving desired result)

## Step 4: Run on real device from IBM - load account and get least busy backend

provider = IBMQ.load_account()
device = least_busy(provider.backends(simulator=False))
print("Running on current least busy device: ", device)

from qiskit.tools.monitor import job_monitor
job = execute(qc, backend=device, shots=1024, max_credits=10)
job_monitor(job, interval = 2)

## Print results from device from IBM

results = job.result()
answer = results.get_counts(qc)
plot_histogram(answer)

# Initializing circuit: define as 2 qubits
q = QuantumRegister(4, 'q')
c = ClassicalRegister(4, 'c')

# Create the quantum circuit
qc = QuantumCircuit(q,c)

## Step 1: Apply a Hadarmard gate to all qubits  
qc.h(q)

## Step 2: Implement the Oracle circuit for state |111> + Grover diffusion
qc.cz(q[3],q[0])
qc.barrier(q)

qc.h(q)
qc.x(q)
qc.barrier(q)

qc.h(q[1])
qc.cx(q[2],q[1])
qc.tdg(q[1])
qc.cx(q[3],q[1])
qc.t(q[1])
qc.cx(q[2],q[1])
qc.tdg(q[1])
qc.cx(q[3],q[1])
qc.barrier(q)
qc.t(q[1])
qc.tdg(q[2])
qc.h(q[1])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.tdg(q[2])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.s(q[2])
qc.t(q[3])
qc.barrier(q)
qc.cx(q[1],q[0])
qc.t(q[0])
qc.cx(q[1],q[0])
qc.tdg(q[0])
qc.tdg(q[1])
qc.h(q[1])
qc.cx(q[2],q[1])
qc.tdg(q[1])
qc.cx(q[3],q[1])
qc.t(q[1])
qc.cx(q[2],q[1])
qc.tdg(q[1])
qc.cx(q[3],q[1])
qc.t(q[1])
qc.tdg(q[2])
qc.h(q[1])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.tdg(q[2])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.s(q[2])
qc.t(q[3])
qc.barrier(q)
qc.cx(q[1],q[0])
qc.tdg(q[0])
qc.cx(q[1],q[0])
qc.t(q[0])
qc.t(q[1])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.barrier(q)
qc.cx(q[2],q[1])
qc.u1(pi/8,q[1])
qc.cx(q[2],q[1])
qc.u1(-pi/8,q[1])
qc.u1(pi/8,q[2])
qc.barrier(q)
qc.h(q[2])
qc.h(q[3])
qc.cx(q[3],q[2])
qc.h(q[2])
qc.h(q[3])
qc.cx(q[2],q[1])
qc.u1(pi/8,q[1])
qc.cx(q[2],q[1])
qc.u1(pi/8,q[1])
qc.u1(pi/8,q[2])
qc.cx(q[3],q[1])
qc.u1(-pi/8,q[1])
qc.cx(q[3],q[1])
qc.u1(pi/8,q[1])
qc.u1(pi/8,q[3])
qc.barrier(q)
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.cx(q[1],q[0])
qc.h(q[0])
qc.h(q[1])
qc.barrier(q)

qc.x(q)
qc.h(q)
qc.barrier(q)

qc.draw(output='mpl')

## Don't forget about the measurement gates!
qc.measure(q[0],c[0])
qc.measure(q[1],c[1])
qc.measure(q[2],c[2])
qc.measure(q[3],c[3])

qc.draw(output='mpl')

## Step 4: Run on backend simulator and print results
simulator = Aer.get_backend('qasm_simulator')
result = execute(qc, backend = simulator, shots = 2048).result()
counts = result.get_counts()

print('RESULT: ',counts,'\n')

from qiskit.tools.visualization import plot_histogram
plot_histogram(counts)

## Note: accuracy of this implementation not 100% (may need to run a couple iterations before achieving desired result)

## Step 4: Run on real device from IBM - load account and get least busy backend

provider = IBMQ.load_account()
device = least_busy(provider.backends(simulator=False))
print("Running on current least busy device: ", device)

from qiskit.tools.monitor import job_monitor
job = execute(qc, backend=device, shots=1024, max_credits=10)
job_monitor(job, interval = 2)

## Print results from device from IBM

results = job.result()
answer = results.get_counts(qc)
plot_histogram(answer)