Jobs & Results

Quantinuum Nexus offers different types of Job that represent a component of your workflow that is running in Nexus, Quantinuum Systems or a third-party.

  • CompileJobs represent the TKET compilation of circuits for a particular target device.

  • ExecuteJobs represent the execution of circuits on a quantum computer or simulator.

Nexus manages the storage of Job outputs such as BackendResults, BackendInfo or compiled Circuits.

from datetime import datetime

import qnexus as qnx

from pytket import Circuit
my_job_name_prefix = datetime.now()

my_project_ref = qnx.projects.get_or_create(name="My Project")

my_circuit_ref = qnx.circuits.upload(
    name=f"My Circuit from {datetime.now()}",
    circuit = Circuit(2).H(0).CX(0,1).measure_all(),
    project = my_project_ref,
)

Compile Jobs

These jobs represent the TKET compilation of one or more circuit(s) in Nexus for a particular target backend.

BackendConfigs define the target, in this case we are targetting the H1-1LE noiseless simulator.

# Compile the circuit (blocking), to receive a list of compiled CircuitRefs

compiled_circuits = qnx.compile(
    circuits=[my_circuit_ref],
    name=f"{my_job_name_prefix}_compile",
    optimisation_level=1,
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)

compiled_circuits.df()
# Run in an asyncronous manner to receieve a JobRef

compile_job_ref = qnx.start_compile_job(
    circuits=[my_circuit_ref],
    name=f"{my_job_name_prefix}_compile_async",
    optimisation_level=1,
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref
)

# Block until the job is complete (or perform other tasks while we wait)
qnx.jobs.wait_for(compile_job_ref)

# Retrieve a CompilationResultRef for every Circuit that was compiled
compile_job_result_refs = qnx.jobs.results(compile_job_ref)

compile_job_result_refs.df()
# Retrieve the compiled CircuitRef for the first Circuit
compile_job_result_refs[0].get_output()
# View the compilation passes that we applied when compiling the circuit
compile_job_result_refs[0].get_passes().df()

Execute Jobs

These jobs represent the execution of one or more circuit(s) on a quantum computer or simulator.

# Execute the circuit (blocking), to receive a list of pytket BackendResults

results = qnx.execute(
    circuits=compiled_circuits,
    name=f"{my_job_name_prefix}_execute",
    n_shots=[100]* len(compiled_circuits),
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)

results[0].get_counts()
# Run in an asyncronous manner to receieve a JobRef

execute_job_ref = qnx.start_execute_job(
    circuits=compiled_circuits,
    name=f"{my_job_name_prefix}_execute_async",
    n_shots=[100]* len(compiled_circuits),
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)

# Block until the job is complete (or perform other tasks while we wait)
qnx.jobs.wait_for(execute_job_ref)

# Retrieve a ExecutionResultRef for every Circuit that was run
execute_job_result_refs = qnx.jobs.results(execute_job_ref)

execute_job_result_refs.df()
# Get the input CircuitRef
execute_job_result_refs[0].get_input()
# Get the results of the execution
result = execute_job_result_refs[0].download_result()

result.get_counts()
# Get the pytket BackendInfo to see the state of the device
execute_job_result_refs[0].download_backend_info()

Getting results for unfinished or incomplete jobs

By default, you can only retrieve results for jobs with the COMPLETED status (meaning that all items in the Job have successfully completed).

In some contexts you may want to retrieve results for the completed items in an otherwise pending or errored job. For example, maybe you have submitted 10 circuits to be executed on quantum hardware, but only 6 of them have completed before you ran out of credit quota for that device. In this case you can still get the results from the completed items.

# Fetch the completed results for an otherwise incomplete job
execute_job_result_refs = qnx.jobs.results(
    job=execute_job_ref,
    allow_incomplete=True
)

Managing Jobs

You can use the API to check on jobs, but also perform operations like cancelling or retrying.

# View your current jobs that are in the SUBMITTED state
qnx.jobs.get_all(job_status=[qnx.jobs.JobStatusEnum.SUBMITTED])
other_execute_job_ref = qnx.start_execute_job(
    circuits=compiled_circuits,
    name=f"{my_job_name_prefix}_execute_other",
    n_shots=[100]* len(compiled_circuits),
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)
# Cancel the job
qnx.jobs.cancel(other_execute_job_ref)
# Retry the job
qnx.jobs.retry_submission(
    other_execute_job_ref,
    retry_status=[qnx.jobs.StatusEnum.CANCELLED],
    remote_retry_strategy=qnx.jobs.RemoteRetryStrategy.FULL_RESTART)