Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 112 additions & 56 deletions qiskit/utils/run_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,70 +418,126 @@ def run_circuits(circuits: Union[QuantumCircuit, List[QuantumCircuit]],
run_config = run_config or {}
with_autorecover = not is_simulator_backend(backend)

job, job_id = _safe_submit_circuits(circuits,
backend,
qjob_config=qjob_config,
backend_options=backend_options,
noise_config=noise_config,
run_config=run_config)
result = None
if MAX_CIRCUITS_PER_JOB is not None:
max_circuits_per_job = int(MAX_CIRCUITS_PER_JOB)
else:
if is_local_backend(backend):
max_circuits_per_job = sys.maxsize
else:
max_circuits_per_job = backend.configuration().max_experiments

if len(circuits) > max_circuits_per_job:
jobs = []
job_ids = []
split_circuits = []
count = 0
while count < len(circuits):
some_circuits = circuits[count: count + max_circuits_per_job]
split_circuits.append(some_circuits)
job, job_id = _safe_submit_circuits(
some_circuits,
backend,
qjob_config=qjob_config,
backend_options=backend_options,
noise_config=noise_config,
run_config=run_config,
)
jobs.append(job)
job_ids.append(job_id)
count += max_circuits_per_job
else:
job, job_id = _safe_submit_circuits(
circuits,
backend,
qjob_config=qjob_config,
backend_options=backend_options,
noise_config=noise_config,
run_config=run_config,
)
jobs = [job]
job_ids = [job_id]
split_circuits = [circuits]
results = []
if with_autorecover:
logger.info("Backend status: %s", backend.status())
logger.info("There is one jobs are submitted: id: %s", job_id)
while True:
logger.info("Running job id: %s", job_id)
# try to get result if possible
logger.info("There are %s jobs are submitted.", len(jobs))
logger.info("All job ids:\n%s", job_ids)
for idx, _ in enumerate(jobs):
result = None
logger.info("Backend status: %s", backend.status())
logger.info("There is one jobs are submitted: id: %s", job_id)
job = jobs[idx]
job_id = job_ids[idx]
while True:
job_status = _safe_get_job_status(job, job_id)
queue_position = 0
if job_status in JOB_FINAL_STATES:
# do callback again after the job is in the final states
logger.info("Running job id: %s", job_id)
# try to get result if possible
while True:
job_status = _safe_get_job_status(job, job_id)
queue_position = 0
if job_status in JOB_FINAL_STATES:
# do callback again after the job is in the final states
if job_callback is not None:
job_callback(job_id, job_status, queue_position, job)
break
if job_status == JobStatus.QUEUED and hasattr(job, "queue_position"):
queue_position = job.queue_position()
logger.info("Job id: %s is queued at position %s", job_id, queue_position)
else:
logger.info("Job id: %s, status: %s", job_id, job_status)
if job_callback is not None:
job_callback(job_id, job_status, queue_position, job)
break
if job_status == JobStatus.QUEUED and hasattr(job, queue_position):
queue_position = job.queue_position()
logger.info("Job id: %s is queued at position %s", job_id, queue_position)
else:
logger.info("Job id: %s, status: %s", job_id, job_status)
if job_callback is not None:
job_callback(job_id, job_status, queue_position, job)
time.sleep(qjob_config['wait'])
time.sleep(qjob_config["wait"])

# get result after the status is DONE
if job_status == JobStatus.DONE:
while True:
result = job.result()
if result.success:
logger.info("COMPLETED: job id: %s", job_id)
break
# get result after the status is DONE
if job_status == JobStatus.DONE:
while True:
result = job.result()
if result.success:
results.append(result)
logger.info("COMPLETED the %s-th job, job id: %s", idx, job_id)
break

logger.warning("FAILURE: Job id: %s", job_id)
logger.warning("Job (%s) is completed anyway, retrieve result "
"from backend again.", job_id)
job = backend.retrieve_job(job_id)
break
# for other cases, resubmit the circuit until the result is available.
# since if there is no result returned, there is no way algorithm can do any process
if job_status == JobStatus.CANCELLED:
logger.warning("FAILURE: Job id: %s is cancelled. Re-submit the circuits.",
job_id)
elif job_status == JobStatus.ERROR:
logger.warning("FAILURE: Job id: %s encounters the error. "
"Error is : %s. Re-submit the circuits.",
job_id, job.error_message())
else:
logging.warning("FAILURE: Job id: %s. Unknown status: %s. "
"Re-submit the circuits.", job_id, job_status)

job, job_id = _safe_submit_circuits(circuits,
backend,
qjob_config=qjob_config,
backend_options=backend_options,
noise_config=noise_config,
run_config=run_config)
logger.warning("FAILURE: Job id: %s", job_id)
logger.warning(
"Job (%s) is completed anyway, retrieve result " "from backend again.",
job_id,
)
job = backend.retrieve_job(job_id)
break
# for other cases, resubmit the circuit until the result is available.
# since if there is no result returned, there is no way algorithm can do any process
if job_status == JobStatus.CANCELLED:
logger.warning(
"FAILURE: Job id: %s is cancelled. Re-submit the circuits.", job_id
)
elif job_status == JobStatus.ERROR:
logger.warning(
"FAILURE: Job id: %s encounters the error. "
"Error is : %s. Re-submit the circuits.",
job_id,
job.error_message(),
)
else:
logging.warning(
"FAILURE: Job id: %s. Unknown status: %s. " "Re-submit the circuits.",
job_id,
job_status,
)

job, job_id = _safe_submit_circuits(
split_circuits[idx],
backend,
qjob_config=qjob_config,
backend_options=backend_options,
noise_config=noise_config,
run_config=run_config,
)
else:
result = job.result()
results = []
for job in jobs:
results.append(job.result())

result = _combine_result_objects(results) if results else None

# If result was not successful then raise an exception with either the status msg or
# extra information if this was an Aer partial result return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
fixes:
- |
Fixed an issue with the :class:`~qiskit.utils.QuantumInstance` with
:class:`~qiskit.providers.BackendV1` backends with the
:attr:`~qiskit.providers.models.BackendConfiguration.`max_experiments`
attribute set to a value less than the number of circuits to run. Previously
the :class:`~qiskit.utils.QuantumInstance` would not correctly split the
circuits to run into separate jobs, which has been corrected.