from qiskit import *

%matplotlib inline

circuit = QuantumCircuit(2,2)

#quantum_register = QuantumRegister(2)
#classical_register = ClassicalRegister(2)
#circuit = QuantumCircuit(quantum_register,classical_register)

circuit.draw()

circuit.h(0)
circuit.draw()

circuit.cx(0,1) # 0-> control qubit, 1-> target qubit
circuit.measure([0,1],[0,1])
circuit.draw()

simulator = Aer.get_backend('qasm_simulator')

result = execute(circuit,backend=simulator).result()

from qiskit.visualization import plot_histogram

plot_histogram(result.get_counts(circuit))

from qiskit.tools.visualization import plot_bloch_multivector
from qiskit.visualization import plot_histogram

import math


# identification of simulators

qasm_simulator = Aer.get_backend('qasm_simulator')
statevector_simulator = Aer.get_backend('statevector_simulator')

# We run our circuit in the simulators we define using a single function.

def run_on_simulators(circuit):
    statevec_job = execute(circuit, backend=statevector_simulator)
    result = statevec_job.result()
    statevec = result.get_statevector()
    
    num_qubits = circuit.num_qubits
    circuit.measure([i for i in range(num_qubits)], [i for i in range(num_qubits)])
    
    qasm_job = execute(circuit, backend=qasm_simulator, shots=1024).result()
    counts = qasm_job.get_counts()
    
    return statevec, counts

circuit = QuantumCircuit(2,2)
statevec, counts = run_on_simulators(circuit)

plot_bloch_multivector(statevec)

# Qubit 0 enters superposition state with hadamard

circuit.h(0)
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

circuit = QuantumCircuit(2,2)
circuit.h(0)
circuit.cx(0,1)  # Controlled-X (CX)
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

plot_histogram([counts])

circuit = QuantumCircuit(2,2)
circuit.rx(math.pi/4, 0)     # rx() , performs rotation on the X axis.
circuit.rx(math.pi / 2, 1)   # rx() , performs rotation on the X axis.
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

circuit = QuantumCircuit(2,2)
circuit.ry(math.pi/4, 0)     # ry() , performs rotation on the Y axis.
circuit.ry(math.pi / 2, 1)   # ry() , performs rotation on the Y axis.
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

circuit = QuantumCircuit(1,1)
circuit.h(0)
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

circuit = QuantumCircuit(1,1)
circuit.h(0)
circuit.z(0)  # Z Gate
statevec, counts = run_on_simulators(circuit)
plot_bloch_multivector(statevec)

plot_histogram([counts])

circuit = QuantumCircuit(3,3)

circuit.x(0) # optional, we want to transfer state 1 in this example

circuit.barrier()

circuit.h(1)
circuit.cx(1,2)

circuit.barrier()

circuit.draw()

circuit.cx(0,1)
circuit.h(0)

circuit.barrier()
circuit.draw()

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

circuit.barrier()
circuit.draw()

circuit.cx(1, 2)
circuit.cz(0, 2)  # Controlled-Z (CZ) Gate
circuit.measure([2], [2])
circuit.draw()

simulator = Aer.get_backend('qasm_simulator')
result = execute(circuit, backend=simulator, shots=1024).result()
from qiskit.visualization import plot_histogram
plot_histogram(result.get_counts(circuit))

secretNumber = '10101010100'

circuit = QuantumCircuit(len(secretNumber)+1,len(secretNumber))

circuit.h(range(len(secretNumber)))
circuit.x(len(secretNumber))
circuit.h(len(secretNumber))

circuit.barrier()

for index, one in enumerate(reversed(secretNumber)):
    print(f"index{index} is {one}")
    if one == "1":
        circuit.cx(index,len(secretNumber))

circuit.barrier()

circuit.h(range(len(secretNumber)))

circuit.barrier()

circuit.measure(range(len(secretNumber)),range(len(secretNumber)))

circuit.draw()

simulator = Aer.get_backend('qasm_simulator')
result = execute(circuit, backend=simulator, shots=1).result()
counts = result.get_counts()
print(counts)

plot_histogram([counts])

circuit = QuantumCircuit(2,1)

circuit.h(0)
circuit.x(1)
circuit.h(1)
circuit.barrier()
circuit.draw()

circuit.cx(0,1)
circuit.barrier()
circuit.h(0)
circuit.barrier()
circuit.draw()

circuit.measure(0,0)

circuit.draw()

backend = Aer.get_backend('qasm_simulator')
result = execute(circuit, backend=backend, shots=1024).result()
counts = result.get_counts(circuit)

plot_histogram([counts])

myList = [5,4,6,9,1,2,3,7,8,0]

def oracle(number):
    winningNumber = 8
    if number == winningNumber:
        response = True
    else:
        response = False
    return response

for index, number in enumerate(myList):
    if oracle(number) is True:
        print(f"winning number index: {index}")
        print(f"execution count: {index+1}")
        break

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

mainCircuit = QuantumCircuit(2,2)
mainCircuit.h([0,1])
mainCircuit.append(oracleCircuit,[0,1])
mainCircuit.draw(output='mpl')


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

mainCircuit.append(reflectionCircuit,[0,1])
mainCircuit.measure([0,1],[0,1])
mainCircuit.draw()

backend = Aer.get_backend('qasm_simulator')
result = execute(mainCircuit,backend=backend,shots=1).result()
counts = result.get_counts(mainCircuit)
plot_histogram([counts])