import numpy as np
import matplotlib.pyplot as plt

# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, transpile, Aer, IBMQ, execute
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from ibm_quantum_widgets import *
from qiskit.providers.aer import QasmSimulator

# Loading your IBM Quantum account(s)
provider = IBMQ.load_account()

y_target = 3

def f(x):
    return x # can be any function!

def oracle(x):
    return f(x) == y_target # logic to determine this oracle can be anything ! This is just the simplest example ... but hopefully only ONE satisfying value or answers are inconsistent

N = 10

for i in range(N):
    if oracle(i):
        print("%i satisfies f(x)" % i)


oracle = QuantumCircuit(2,name='oracle')
oracle.cz(0,1)
oracle.to_gate()
oracle.draw()

grover = QuantumCircuit(2,2)
grover.h([0,1])
grover.append(oracle,[0,1])
grover.draw()

backend = Aer.get_backend('statevector_simulator')
job = execute(grover,backend)
result = job.result()
sv = result.get_statevector()
np.around(sv,2)

reflection = QuantumCircuit(2,name='reflection')
reflection.h([0,1])
reflection.z([0,1])
reflection.cz(0,1)
reflection.h([0,1])
reflection.to_gate()
reflection.draw()

backend = Aer.get_backend('qasm_simulator')
grover = QuantumCircuit(2,2)
grover.h([0,1])
grover.append(oracle,[0,1])
grover.append(reflection,[0,1]) # repeat sqrt(N) times...
grover.measure([0,1],[0,1])
grover.draw()

job = execute(grover,backend,shots=1)
job.result().get_counts()

