import qiskit
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from qiskit.quantum_info import Operator

import numpy as np

from qiskit import execute, Aer

simulator = Aer.get_backend('qasm_simulator')

import matplotlib.pyplot as plt

import warnings
warnings.filterwarnings('ignore')

def createYouneInitCircuit():
    circuit = QuantumCircuit(3, 2)
    
    circuit.h(0)
    circuit.h(1)
    circuit.barrier()
    
    return circuit

youneInitCircuit = createYouneInitCircuit()
youneInitCircuit.draw(output='mpl')

def createYouneOracle():
    circuit = QuantumCircuit(3, 2)
    
    circuit.x(0)
    circuit.x(1)
    circuit.ccx(0, 1, 2)
    circuit.x(0)
    circuit.x(1)
    circuit.barrier()
    
    circuit.x(0)
    circuit.ccx(0, 1, 2)
    circuit.x(0)
    circuit.barrier()
    
    return circuit

youneOracle = createYouneOracle()
youneOracle.draw(output='mpl')

def createYouneDiffuser():
    circuit = QuantumCircuit(3, 2)
    
    circuit.h(0)
    circuit.h(1)
    circuit.barrier(2)
    
    circuit.x(2)
    circuit.x(0)
    circuit.x(1)
    circuit.h(2)
    circuit.ccx(0, 1, 2)
    circuit.barrier(0)
    circuit.barrier(1)
    circuit.h(2)
    circuit.x(2)
    circuit.x(0)
    circuit.x(1)
    
    circuit.h(0)
    circuit.h(1)
#     circuit.h(2)
    circuit.barrier()
    
    return circuit

youneDiffuser = createYouneDiffuser()
youneDiffuser.draw(output='mpl')

youneGroverIteration = createYouneOracle().compose(createYouneDiffuser())

grover_youne = createYouneInitCircuit().compose(youneGroverIteration.copy())
grover_youne.draw(output='mpl')

grover_youne.measure([0, 1], [0, 1])

job = execute(grover_youne, simulator, shots = 10000)
results = job.result()
counts = results.get_counts(grover_youne)
print(counts)

plot_histogram(counts, figsize=(4, 5), color="#0099CC", title="youne grover - find evens")

def createYouneOracle2():
    circuit = QuantumCircuit(3, 2)
    
    circuit.x(0)
    circuit.cx(0, 2)
    circuit.x(0)
    circuit.barrier()
    
    return circuit

youneOracle2 = createYouneOracle2()
youneOracle2.draw(output='mpl')

# 0 => 4 2 => 6
Operator(youneOracle2).data

youneGroverIteration2 = createYouneOracle2().compose(createYouneDiffuser())

grover_youne2 = createYouneInitCircuit().compose(youneGroverIteration2.copy())
grover_youne2.draw(output='mpl')

grover_youne2.measure([0, 1], [0, 1])

job = execute(grover_youne2, simulator, shots = 10000)
results = job.result()
counts = results.get_counts(grover_youne2)
print(counts)

plot_histogram(counts, figsize=(4, 5), color="#66CCFF", title="youne grover(using another Oracle) - find evens")

