import numpy as np
from qiskit import *
%matplotlib inline

circ = QuantumCircuit(2)
circ.h(0)
circ.x(1)
circ.h(1)
circ.cx(0,1) #oracle here for f(x)=x
circ.h(0)
circ.draw('mpl')

meas = QuantumCircuit(2, 2)
meas.barrier(range(2))
meas.measure(range(2), range(2)) # map the quantum measurement to the classical bits

qc = circ + meas
qc.draw()

# Use Aer's qasm_simulator
backend_sim = Aer.get_backend('qasm_simulator')

# Execute the circuit on the qasm simulator. We've set the number of repeats of the circuit to be 1024, which is the default.
job_sim = execute(qc, backend_sim, shots=1024)
result_sim = job_sim.result()

counts = result_sim.get_counts(qc)
print("Counts for QASM:", counts)

from qiskit.visualization import plot_histogram
plot_histogram(counts)

from qiskit.providers.ibmq import least_busy
provider = IBMQ.load_account()
backend = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= (3) and
                                   not x.configuration().simulator and x.status().operational==True))
print("least busy backend: ", backend)

from qiskit.tools.monitor import job_monitor

shots = 1024
job = execute(qc, backend=backend, shots=shots, optimization_level=3)

job_monitor(job, interval = 2)

from qiskit.visualization import plot_histogram
results = job.result()
answer = results.get_counts()
print("Counts for IBM machine:", answer)

plot_histogram((counts, answer), legend=['QASM simulation','IBM machine']) # ibm machine

n = 2
grover = QuantumCircuit(n)
grover.h([0,1])
grover.cz(0,1) # Oracle

# Diffusion operator (U_s)
grover.h([0,1])
grover.z([0,1])
grover.cz(0,1)
grover.h([0,1])
grover.draw()

meas = QuantumCircuit(2, 2)
meas.barrier(range(2))
meas.measure(range(2), range(2)) # map the quantum measurement to the classical bits

qc3 = grover + meas
qc3.draw()

#Simulator
from qiskit.visualization import plot_histogram

backend = Aer.get_backend('statevector_simulator')
shots = 1024
results = execute(qc3, backend=backend, shots=shots).result()
counts = results.get_counts()
plot_histogram(counts)

from qiskit.providers.ibmq import least_busy
provider = IBMQ.load_account()
backend = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= (3) and
                                   not x.configuration().simulator and x.status().operational==True))
print("least busy backend: ", backend)

from qiskit.tools.monitor import job_monitor

shots = 1024
job = execute(qc3, backend=backend, shots=shots, optimization_level=3)

job_monitor(job, interval = 2)

from qiskit.visualization import plot_histogram
results = job.result()
answer = results.get_counts()
print("Counts for IBM machine:", answer)

plot_histogram((counts, answer), legend=['QASM simulation','IBM machine']) # ibm machine

circ2 = QuantumCircuit(3)
for i in range(2):
    circ2.h(i)
    circ2.x(i)

circ2.h(2)
circ2.x(2)
circ2.h(2)

# Toffoli gate = oracle
circ2.ccx(0,1,2)

for i in range(2):
    circ2.h(i)
    circ2.x(i)

circ2.h(2)
circ2.x(2)
circ2.h(2)

circ2.draw('mpl')

meas2 = QuantumCircuit(3, 3)
meas2.barrier(range(3))
meas2.measure(range(3), range(3)) # map the quantum measurement to the classical bits

qc2 = circ2 + meas2
qc2.draw()

# Use Aer's qasm_simulator
backend_sim = Aer.get_backend('qasm_simulator')

# Execute the circuit on the qasm simulator. We've set the number of repeats of the circuit to be 1024, which is the default.
job_sim = execute(qc2, backend_sim, shots=1024)
result_sim = job_sim.result()

counts = result_sim.get_counts(qc2)
print("Counts for QASM:", counts)

from qiskit.visualization import plot_histogram
plot_histogram(counts)

from qiskit.providers.ibmq import least_busy
provider = IBMQ.load_account()
backend = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= (3) and
                                   not x.configuration().simulator and x.status().operational==True))
print("least busy backend: ", backend)

from qiskit.tools.monitor import job_monitor

shots = 1024
job = execute(qc2, backend=backend, shots=shots, optimization_level=3)

job_monitor(job, interval = 2)

from qiskit.visualization import plot_histogram
results = job.result()
answer = results.get_counts()
print("Counts for IBM machine:", answer)

plot_histogram((counts, answer), legend=['QASM simulation','IBM machine']) # ibm machine

# The groover algorithm needs 3 work qubits to execute the algorithm, therefore 8 qubits needed here
circ2 = QuantumCircuit(8)
for i in range(4):
    circ2.h(i)
    circ2.x(i)

circ2.h(7)
circ2.x(7)
circ2.h(7)

# Toffoli gate = oracle
circ2.ccx(0,1,4)
circ2.ccx(4,2,5)
circ2.ccx(5,3,6)

circ2.cx(6,7)


circ2.ccx(5,3,6)
circ2.ccx(4,2,5)
circ2.ccx(0,1,4)


for i in range(4):
    circ2.h(i)
    circ2.x(i)

circ2.h(7)
circ2.x(7)
circ2.h(7)

circ2.draw('mpl')

meas2 = QuantumCircuit(8, 8)
meas2.barrier([0,1,2,3,7])
meas2.measure([0,1,2,3,7], [0,1,2,3,7]) # map the quantum measurement to the classical bits

qc2 = circ2 + meas2
qc2.draw()

# Use Aer's qasm_simulator
backend_sim = Aer.get_backend('qasm_simulator')

# Execute the circuit on the qasm simulator. We've set the number of repeats of the circuit to be 1024, which is the default.
job_sim = execute(qc2, backend_sim, shots=1024)
result_sim = job_sim.result()

counts = result_sim.get_counts(qc2)
print("Counts for QASM:", counts)

from qiskit.visualization import plot_histogram
plot_histogram(counts)

from qiskit.providers.ibmq import least_busy
provider = IBMQ.load_account()
backend = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= (3) and
                                   not x.configuration().simulator and x.status().operational==True))
print("least busy backend: ", backend)

from qiskit.tools.monitor import job_monitor

shots = 1024
job = execute(qc2, backend=backend, shots=shots, optimization_level=3)

job_monitor(job, interval = 2)

