Getting Started with qnexus

Here is an example notebook outlining core usage of qnexus, the client Python package for Quantinuum Nexus.

qnexus can be installed with:

pip install qnexus
from datetime import datetime
from pytket import Circuit
import qnexus as qnx

First we’ll call login() to authenticate the client using your web browser.

NB: this step doesn’t need to be done in the Nexus Lab, where authentication is automatic.

qnx.login()

Nexus uses Projects to organise data and jobs. Here we’ll get a project in Nexus, or create it if it doesn’t exist. We can also use ‘properties’ to annotate our jobs and data with labels or scientific parameters.

Learn more about Projects and properties in qnexus.

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

my_project_ref.df()

The thing we get back is a ProjectRef; qnexus uses Refs as ‘references’ to data in the Quantinuum Nexus database.

Next we’ll create a Pytket circuit and upload it to the Nexus database, getting back a CircuitRef for the uploaded circuit. We’ll need to also pass the ProjectRef from earlier to upload the circuit as part of the Project.

circuit = Circuit(2).H(0).CX(0,1).measure_all()

my_circuit_ref = qnx.circuits.upload(
    name=f"My Circuit from {datetime.now()}",
    circuit = circuit,
    project = my_project_ref,
)

We can then get Nexus to compile the circuit (using Quantinuum’s TKET compiler), optimizing and rebasing it for a particular device. This will create a Nexus compile Job, wait for it to complete and fetch the compiled circuit.

Learn more about Jobs in qnexus.

We’ll get back a list containing a single CircuitRef pointing to the compiled circuit stored in Nexus.

compiled_circuits = qnx.compile(
    circuits=[my_circuit_ref],
    name=f"My Compile Job from {datetime.now()}",
    optimisation_level=1,
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)

compiled_circuits.df()

This particular job compiled the circuit for Quantinuum’s H1-1LE device, a noiseless simulator for Quantinuum’s H1-1.

Learn more about how to configure jobs to target specific devices in qnexus.

Learn more about checking the devices you have access to in qnexus.

Next, we’ll submit a request for Nexus to execute this circuit on H1-1LE.

execute_job_ref = qnx.start_execute_job(
    circuits=compiled_circuits,
    name=f"My Execute Job from {datetime.now()}",
    n_shots=[100]* len(compiled_circuits),
    backend_config=qnx.QuantinuumConfig(device_name="H1-1LE"),
    project=my_project_ref,
)

execute_job_ref.df()

This will return an ExecuteJobRef as a reference to the running job in Nexus. If we believe the job will take a long time (hours or days), we can come back to this later either by retrieving the ExecuteJobRef using the API or by saving/loading it to the local filesystem.

Learn more about querying your data/jobs in qnexus.

Learn more about saving and loading Ref objects in qnexus.

We can check the status or wait for completion before retrieving the results.

print(qnx.jobs.status(execute_job_ref))

# Block until the job is complete
qnx.jobs.wait_for(execute_job_ref)

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

# Get a pytket BackendResult for the execution
result = execute_job_result_refs[0].download_result()

result.get_counts()

If we’d like to share our work, we can grant access to team members using collaboration and role-based access control features.

Learn more about Access and Collaboration features in qnexus.

To put all of this together in a real-world example, please see our example of a variational quantum eigensolver workflow in qnexus.

VQE example in qnexus