import matplotlib.pyplot as plt
import numpy as np
!pip install qiskit
from qiskit import IBMQ, Aer, assemble, transpile, execute
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit.providers.ibmq import least_busy
!pip install qiskit.visualization
from qiskit.visualization import *
from qiskit.tools.jupyter import *
!pip install ibm_quantum_widgets
from ibm_quantum_widgets import *
from qiskit.tools.monitor import job_monitor

def initialize_circuit(qc, qubits):
  for q in qubits:
    qc.h(q)
  return qc

qc = QuantumCircuit(3)
qc.cz(0, 2)
qc.cz(1, 2)
oracle_3 = qc.to_gate()
oracle_3.name = "Uω"

def diffuser(qubits):
  qc = QuantumCircuit(qubits)
  for qubit in range(qubits):
    qc.h(qubit) 
  for qubit in range(qubits):
    qc.x(qubit)
  qc.h(qubits-1)
  qc.mct(list(range(qubits-1)), qubits -1)
  qc.h(qubits-1)
  for qubit in range(qubits):
    qc.x(qubit)
  for qubit in range(qubits):
    qc.h(qubit)
  U_s = qc.to_gate()
  U_s.name = "Us"
  return U_s


n_qubits = 3
grover_circuit = QuantumCircuit(n_qubits)
grover_circuit = initialize_circuit(grover_circuit, [0, 1, 2])
grover_circuit.append(oracle_3, [0, 1, 2])
grover_circuit.append(diffuser(n_qubits), [0, 1, 2])
grover_circuit.measure_all()
grover_circuit.draw()

backend = Aer.get_backend('qasm_simulator')
transpiled_grover_circuit = transpile(grover_circuit, backend)
job = execute(transpiled_grover_circuit, backend)
result = job.result()
counts = result.get_counts()
plot_histogram(counts)

provider = IBMQ.load_account()
device_2 = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= 3 and 
                                   not x.configuration().simulator and x.status().operational==True))
print(device_2)

transpiled_grover_circuit_2 = transpile(grover_circuit, backend_2, optimization_level=3)
job = device_2.run(transpiled_grover_circuit_2)
job_monitor(job, interval=2)

results_2 = job.result()
answer_2 = results_2.get_counts()
plot_histogram(answer_2)

