# Set up imports, IBMQ account, and backend
from qiskit import QuantumCircuit, execute, IBMQ
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')

backend = provider.get_backend('ibmq_qasm_simulator')

# Create 2 circuits
circuit_1 = QuantumCircuit(2, 2)
circuit_1.h(0)
circuit_1.cx(0, 1)
circuit_1.measure([0, 1], [0, 1])

circuit_2 = QuantumCircuit(2, 2)
circuit_2.h(1)
circuit_2.cx(1, 0)
circuit_2.measure([0, 1], [0, 1])

# Submit a job for each circuit
job_1 = execute(circuit_1, backend)
job_2 = execute(circuit_2, backend)

print("Job 1: {}".format(job_1.result().get_counts(circuit_1)))
print("Job 2: {}".format(job_2.result().get_counts(circuit_2)))

# Set up imports, IBMQ account, and backend
from qiskit import QuantumCircuit, execute, IBMQ
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')

backend = provider.get_backend('ibmq_qasm_simulator')

circuit_list = []  # This will be what we send with our job

# Create 2 circuits
circuit_1 = QuantumCircuit(2, 2)
circuit_1.h(0)
circuit_1.cx(0, 1)
circuit_1.measure([0, 1], [0, 1])

circuit_2 = QuantumCircuit(2, 2)
circuit_2.h(1)
circuit_2.cx(1, 0)
circuit_2.measure([0, 1], [0, 1])

# Add both circuits to the list
circuit_list.append(circuit_1)
circuit_list.append(circuit_2)

# Submit a single job that contains both circuits
job = execute(circuit_list, backend)

results = job.result()

# Option 1: Use the circuit name
circuit_1_counts = results.get_counts(circuit_1)
circuit_2_counts = results.get_counts(circuit_2)

print("Circuit 1 using circuit name: {}".format(circuit_1_counts))
print("Circuit 2 using circuit name: {}".format(circuit_2_counts))

# Option 2: Use the list index
circuit_1_counts = results.get_counts(circuit_list[0])
circuit_2_counts = results.get_counts(circuit_list[1])

print("Circuit 1 using list index: {}".format(circuit_1_counts))
print("Circuit 2 using list index: {}".format(circuit_2_counts))

import time
circuit_list = []
total_time_taken_individual = 0      # This will be the total runtime for the individual job method
total_execution_time_individual = 0  # This will be the total execution time for the individual job method

for __ in range(5):
    # Create a new circuit
    qc = QuantumCircuit(2, 2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure([0, 1], [0, 1])
    
    # Add the circuit to circuit_list
    circuit_list.append(qc)
    
    # Execute the circuit in its own individual job and get total time taken
    start_time = time.time()
    job_individual = execute(qc, backend)
    if job_individual.result():  # Once job has finished executing get end time
        end_time = time.time()

    total_time_taken_individual += (end_time - start_time)
    
    # Retrieve time_taken executing and add to total time taken
    total_execution_time_individual += job_individual.result().time_taken
    
# Create single job and execute, and get total time taken
start_time = time.time()
job_bundled = execute(circuit_list, backend)
if job_bundled.result():  # Once job has finished executing get end time
    end_time = time.time()

total_time_taken_bundled = (end_time - start_time)
total_execution_time_bundled = job_bundled.result().time_taken

# Compare execution time and total time taken between the two methods. Round to 5 decimal places.
print("Total execution time with individual jobs: {} seconds".format(round(total_execution_time_individual, 5)))
print("Total execution time with a single job:    {} seconds".format(round(total_execution_time_bundled, 5)))
print("Total time taken with individual jobs:     {} seconds".format(round(total_time_taken_individual, 5)))
print("Total time taken with a single job:        {} seconds".format(round(total_time_taken_bundled, 5)))

