import cirq

## Data qubit and target qubit
q0, q1 = cirq.LineQubit.range(2)

## Dictionary of oracles
oracles = {'0' : [], '1' : [cirq.X(q1)], 'x' : [cirq.CNOT(q0, q1)], 'notx' : [cirq.CNOT(q0, q1), cirq.X(q1)]}

def deutsch_algorithm(oracle):
    ## Yield a circuit for Deustch algorithm given operations implementing
    
    yield cirq.X(q1)
    yield cirq.H(q0), cirq.H(q1)
    yield oracle
    yield cirq.H(q0)
    yield cirq.measure(q0)


for key, oracle in oracles.items():
    print('Circuit for {} :'. format(key))
    print(cirq.Circuit.from_ops(deutsch_algorithm(oracle)), end = "\n\n")
    


simulator = cirq.Simulator()

for key, oracle in oracles.items():
    result = simulator.run(cirq.Circuit.from_ops(deutsch_algorithm(oracle)), repetitions=20)
    print('Oracle : {:<4}   results: {}'. format(key, result))

import cirq

q0, q1, q2 = cirq.LineQubit.range(3)

## Oracles for constant functions
constant = ([], [cirq.X(q2)])

## Oracles for balanced functions
balanced = ([cirq.CNOT(q0, q2)],
           [cirq.CNOT(q1, q2)],
            [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2)],
            [cirq.CNOT(q0, q2), cirq.X(q2)],
            [cirq.CNOT(q1, q2), cirq.X(q2)],
            [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2), cirq.X(q2)]
           )

def your_circuit(oracle):

    ## Phase kickback trick
    yield cirq.X(q2), cirq.H(q2)
    
    ## Equal Superposition over input bits
    yield cirq.H(q0), cirq.H(q1)
    
    ## Query the function
    yield oracle
    
    ## interface to get result, put last qubit into |1>
    yield cirq.H(q0),  cirq.H(q1), cirq.H(q2)
    
    ## a final OR gate to put result in final qubit
    yield cirq.X(q0), cirq.X(q1), cirq.CCX(q0, q1, q2)
    yield cirq.measure(q2)

simulator = cirq.Simulator()

print("your result on constant functions:")
for oracle in constant:
    result = simulator.run(cirq.Circuit.from_ops(your_circuit(oracle)), repetitions=10)
    print(result)
    

print("your result on balanced functions:")
for oracle in balanced:
    result = simulator.run(cirq.Circuit.from_ops(your_circuit(oracle)), repetitions=10)
    print(result)
    

