# Import the Qiskit SDK
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import available_backends, execute, Aer
from qiskit.tools.visualization import plot_histogram, circuit_drawer, plot_state

# Create a Quantum Register with 2 qubits.
q = QuantumRegister(2)
# Create a Classical Register with 2 bits.
c = ClassicalRegister(2)
# Create a Quantum Circuit
qc = QuantumCircuit(q, c)

# Add a H gate on qubit 0, putting this qubit in superposition.
qc.h(q[0])
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
qc.cx(q[0], q[1])
# Add a Measure gate to see the state.
qc.measure(q, c)

# See a list of available local simulators
print("Aer backends: ", Aer.backends())
backend_sim = Aer.get_backend('qasm_simulator')

# Compile and run the Quantum circuit on a simulator backend
sim_result1 = execute(qc, backend_sim, shots=2).result()
sim_result2 = execute(qc, backend_sim, shots=1000).result()
counts1 = sim_result1.get_counts(qc)
counts2 = sim_result2.get_counts(qc)

# Show the results as text and plot
print("First simulation: ", sim_result1)
print("Output: ", counts1)
print("Second simulation: ", sim_result2)
print("Output: ", counts2)
legend = ['First execution', 'Second execution']
plot_histogram([counts1,counts2], legend=legend)
circuit_drawer(qc)

# Import the Qiskit
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, QISKitError
from qiskit import execute, IBMQ, Aer
from qiskit.backends.ibmq import least_busy
from qiskit.tools.visualization import plot_histogram, circuit_drawer, plot_state

# Authenticate for access to remote backends
try:
    import Qconfig
    IBMQ.load_accounts()
except:
    print("""WARNING: There's no connection with the API for remote backends.
             Have you initialized a file with your personal token?
             For now, there's only access to local simulator backends...""")

try:
    # Create a Quantum Register with 2 qubits.
    q = QuantumRegister(2)
    # Create a Classical Register with 2 bits.
    c = ClassicalRegister(2)
    # Create a Quantum Circuit
    qc = QuantumCircuit(q, c)

    # Add a H gate on qubit 0, putting this qubit in superposition.
    qc.h(q[0])
    # Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
    # the qubits in a Bell state.
    qc.cx(q[0], q[1])
    # Add a Measure gate to see the state.
    qc.measure(q, c)

    # see a list of available remote backends
    ibmq_backends = IBMQ.backends()

    print("Remote backends: ", ibmq_backends)
    # Compile and run the Quantum Program on a real device backend
    try:
        least_busy_device = least_busy(IBMQ.backends(simulator=False))
        print("Running on current least busy device: ", least_busy_device)

        #running the job twice and get counts
        result_exp1 = execute(qc, least_busy_device, shots=1024, max_credits=10).result()
        result_exp2 = execute(qc, least_busy_device, shots=1024, max_credits=10).result()
        counts01 = result_exp1.get_counts(qc)
        counts02 = result_exp2.get_counts(qc)

        # Show the results
        print("First experiment: ", result_exp1)
        print("Output: ", counts01)
        print("Second experiment: ", result_exp2)
        print("Output: ", counts02)
        legend = ['First experiment', 'Second experiment']
        plot_histogram([counts01,counts02],  legend=legend)
    except:
        print("All devices are currently unavailable. Try again later.")

except QISKitError as ex:
    print('There was an error in the circuit!. Error = {}'.format(ex))

# Import the Qiskit SDK.
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import available_backends, execute, Aer
from qiskit.tools.visualization import plot_histogram, circuit_drawer, plot_state
# Define the number of n-qbits.
n = 2
# Create a Quantum Register with n-qbits.
q = QuantumRegister(n)
# Create a Classical Register with n-bits.
c = ClassicalRegister(n)
# Create a Quantum Circuit
qc = QuantumCircuit(q, c)
# Add H-gate to get superposition.
qc.h(q[0])
qc.h(q[1])

# Apply the oracle 11.
qc.x(q[0])
qc.h(q[1])
qc.cx(q[0],q[1])
qc.x(q[0])
qc.h(q[1])

for x in range(0, 1):
    
    # Apply the grover-algorithm 11
    qc.h(q[0])
    qc.h(q[1])
    qc.x(q[0])
    qc.x(q[1])
    qc.h(q[1])
    qc.cx(q[0],q[1])
    qc.h(q[1])
    qc.x(q[0])
    qc.x(q[1])
    qc.h(q[0])
    qc.h(q[1])

# Measure qubit to bit. .
qc.measure(q, c)
# Get Aer backend.
backend_sim = Aer.get_backend('qasm_simulator')
# Compile and run the Quantum circuit on a simulator backend.
sim_result1 = execute(qc, backend_sim, shots=1000).result()
counts1 = sim_result1.get_counts(qc)
# Show the results as text and plot.
print("Simulation: ", sim_result1)
print("Output: ", counts1)
plot_histogram(counts1)
circuit_drawer(qc)

from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import available_backends, execute, Aer, backends
from qiskit.tools.visualization import plot_histogram, circuit_drawer, plot_state
import math

# Authenticate for access to remote backends
try:
    import Qconfig
    IBMQ.load_accounts()
except:
    print("""WARNING: There's no connection with the API for remote backends.
             Have you initialized a file with your personal token?
             For now, there's only access to local simulator backends...""")

# decide, on which backend you want to run the grover algorithmus
backendIBMQ = True

# define the number n-Qbits
n = 4
N = 2^n
O = math.sqrt(N)
pi = math.pi

try:
    # Create a Quantum-Register with n-Qbits.
    qr = QuantumRegister(n)
    cr = ClassicalRegister(n)
    qc = QuantumCircuit(qr, cr)

    # initialize n-Qbits
    qc.h(qr[0])
    qc.h(qr[1])
    qc.h(qr[2])
    qc.h(qr[3])

    # Create oracle for 0010
    qc.x(qr[0])
    qc.x(qr[2])
    qc.x(qr[3])
    qc.cu1(pi/4, qr[0], qr[3])
    qc.cx(qr[0], qr[1])
    qc.cu1(-pi/4, qr[1], qr[3])
    qc.cx(qr[0], qr[1])
    qc.cu1(pi/4, qr[1], qr[3])
    qc.cx(qr[1], qr[2])
    qc.cu1(-pi/4, qr[2], qr[3])
    qc.cx(qr[0], qr[2])
    qc.cu1(pi/4, qr[2], qr[3])
    qc.cx(qr[1], qr[2])
    qc.cu1(-pi/4, qr[2], qr[3])
    qc.cx(qr[0], qr[2])
    qc.cu1(pi/4, qr[2], qr[3])
    qc.x(qr[0])
    qc.x(qr[2])
    qc.x(qr[3])
    
    # avarage of O(sqrt(N)) repititions
    for x in range(0, 1):
        # Amplification
        qc.h(qr[0])
        qc.h(qr[1])
        qc.h(qr[2])
        qc.h(qr[3])
        qc.x(qr[0])
        qc.x(qr[1])
        qc.x(qr[2])
        qc.x(qr[3])
            ######## cccZ #########
        qc.cu1(pi/4, qr[0], qr[3])
        qc.cx(qr[0], qr[1])
        qc.cu1(-pi/4, qr[1], qr[3])
        qc.cx(qr[0], qr[1])
        qc.cu1(pi/4, qr[1], qr[3])
        qc.cx(qr[1], qr[2])
        qc.cu1(-pi/4, qr[2], qr[3])
        qc.cx(qr[0], qr[2])
        qc.cu1(pi/4, qr[2], qr[3])
        qc.cx(qr[1], qr[2])
        qc.cu1(-pi/4, qr[2], qr[3])
        qc.cx(qr[0], qr[2])
        qc.cu1(pi/4, qr[2], qr[3])
           ####### end cccZ #######
        qc.x(qr[0])
        qc.x(qr[1])
        qc.x(qr[2])
        qc.x(qr[3])
        qc.h(qr[0])
        qc.h(qr[1])
        qc.h(qr[2])
        qc.h(qr[3])
        
    # Measure: take state from Qbit to Cbit
    qc.barrier(qr)
    qc.measure(qr[0], cr[0])
    qc.measure(qr[1], cr[1])
    qc.measure(qr[2], cr[2])
    qc.measure(qr[3], cr[3])
    
except QISKitError as ex:
        print('There was an error in the circuit!. Error = {}'.format(ex))

# run the code on a real quantumcomputer from IBM
if backendIBMQ: 
    try:
        # See a list of available local simulators
        least_busy_device = least_busy(IBMQ.backends(simulator=False))   # IBMQ.get_backend('ibmq_16_melbourne')
        print("Running on current least busy device: ", least_busy_device)

        #running the job twice and get counts
        result_exp1 = execute(qc, least_busy_device, shots = 500, max_credits = 10).result()
        result_exp2 = execute(qc, least_busy_device, shots = 500, max_credits = 10).result()
        counts01 = result_exp1.get_counts(qc)
        counts02 = result_exp2.get_counts(qc)

        # Show the results
        print("First experiment: ", result_exp1)
        print("Output: ", counts01)
        print("Second experiment: ", result_exp2)
        print("Output: ", counts02)
        legend = ['First experiment', 'Second experiment']
        plot_histogram([counts01, counts02], legend=legend)
        circuit_drawer(qc)
    except:
        print("All devices are currently unavailable. Try again later.")
        
# or run the code on your own system with the simulation backend Aer
else:
    # See a list of available local simulators
    print("Aer backends: ", Aer.backends())
    backend_sim = Aer.get_backend('qasm_simulator')

    # Compile and run the Quantum circuit on a simulator backend
    sim_result1 = execute(qc, backend_sim, shots=1000).result()
    sim_result2 = execute(qc, backend_sim, shots=1000).result()
    counts1 = sim_result1.get_counts(qc)
    counts2 = sim_result2.get_counts(qc)

    # Show the results as text and plot
    print("First simulation: ", sim_result1)
    print("Output: ", counts1)
    print("Second simulation: ", sim_result2)
    print("Output: ", counts2)
    legend = ['First execution', 'Second execution']
    plot_histogram([counts1,counts2], legend=legend)
    circuit_drawer(qc)

