%matplotlib inline
# Importing standard Qiskit libraries and configuring account
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.compiler import transpile, assemble
from qiskit.tools.jupyter import *
from qiskit.visualization import *
import numpy as np
from fractions import Fraction as frac 
import qiskit.quantum_info as qi
# Loading your IBM Q account(s)
provider = IBMQ.load_account()

qc=QuantumCircuit(4)

#In this particular oracle, the last qubit is storing the value of the function

qc.cx(0,3)
qc.cx(1,3)
qc.cx(2,3)
#The last qubit is 1 if there are odd no. of 1s in the other 3 qubits
#and 0 otherwise
#Hence it is a balanced function

qc.draw('mpl')

qc1=QuantumCircuit(3)
qc1.x(2)
qc1.h(0)
qc1.h(1)
qc1.h(2)

qc1.barrier(range(3))
qc1.cx(0,2)
qc1.cx(1,2)
qc1.barrier(range(3))
qc1.h(0)
qc1.h(1)

meas = QuantumCircuit(3, 2)
meas.measure(range(2),range(2))

# The Qiskit circuit object supports composition using
# the addition operator.
circ = qc1+meas

circ.draw('mpl')

backend_sim = Aer.get_backend('qasm_simulator')

job_sim = execute(circ, backend_sim, shots=1000)

result_sim = job_sim.result()
counts = result_sim.get_counts(circ)
print(counts)
plot_histogram(counts)

qc2=QuantumCircuit(5)
qc2.x(4)
qc2.h(0)
qc2.h(1)
qc2.h(2)
qc2.h(3)
qc2.h(4)

qc2.barrier(range(5))
#The oracle:
qc2.x(0)
qc2.x(1)
qc2.x(3)

qc2.cx(0,4)
qc2.cx(1,4)
qc2.cx(2,4)
qc2.cx(3,4)

qc2.x(0)
qc2.x(1)
qc2.x(3)
#oracle ends here
qc2.barrier(range(5))
qc2.h(0)
qc2.h(1)
qc2.h(2)
qc2.h(3)

meas2 = QuantumCircuit(5, 4)
meas2.measure(range(4),range(4))

circ2 = qc2+meas2
circ2.draw('mpl')


#verification cell, reinitialising the circuit so that it's easier for you to copy-paste the oracle
qc2=QuantumCircuit(5)
#Add X gates HERE as required to change the input state
#Let's check for |1001>
qc2.x(0)
qc2.x(3)

qc2.barrier(range(5))

#Copy and paste your code for the oracle from the above cell here
qc2.x(0)
qc2.x(1)
qc2.x(3)

qc2.cx(0,4)
qc2.cx(1,4)
qc2.cx(2,4)
qc2.cx(3,4)

qc2.x(0)
qc2.x(1)
qc2.x(3)



qc2.barrier(range(5))

measv = QuantumCircuit(5, 1)
measv.measure(4,0)

circv = qc2+measv
circv.draw('mpl')



#DO NOT RUN THIS CELL WITHOUT EDITING THE ABOVE ONE AS DESIRED
#The following code will give you f(x) for the value of x you chose in the above cell
backend_sim2 = Aer.get_backend('qasm_simulator')

job_sim2 = execute(circv, backend_sim2, shots=1000)

result_sim2 = job_sim2.result()
counts2 = result_sim2.get_counts(circv)
print(counts2)
plot_histogram(counts2)

#Similarly you can check f(x) for different values of x