InQuanto-Nexus

The inquanto-nexus extension enables the use of Quantinuum Nexus, Quantinuum’s platform for circuit management, compilation, and execution through the qnexus API. The qnexus API is the default way to interact with Quantinuum Nexus- for more information, please refer to the documentation.

This extension automatically stores experimental results performed with InQuanto to a user’s Quantinuum Nexus account. A user can connect ot a project and specify which backend device to run experiments on when instantiating an InQuanto Protocol.

Setting up Projects and Protocols with QNexus

In order to store circuits in your Quantinuum Nexus account, the user must authenticate and select a project that will hold results using the qnexus API. Projects may be annotated with custom properties that may be of interest to the user. Below, we can optionally annotate circuits belonging to this project by number of qubits.

from qnexus.client import auth, project

auth.login()

project_ref = project.create(
    name=f"qNexus Demo {datetime.now()}", description="a demo project", properties={}
)

project.add_property(
    project_ref=project_ref,
    name="Number of Qubits",
    property_type="int",
    description="Number of qubits in my InQuanto algorithm",
    required=False,
)

We set up an experiment on a 3-qubit state where we will calculate the probability of measuring strings (000) or (001) using the ProjectiveMeasurements protocol. We connect our Nexus project to this Protocol along with the qnexus backend configuration. Protocol instantiation is the only place where we can connect to our Nexus project.

import math

from qnexus import AerConfig

from inquanto.ansatzes import MultiConfigurationStateBox
from inquanto.states import QubitState, QubitStateString
from inquanto.protocols import ProjectiveMeasurements

lc_qs = (
    QubitState(QubitStateString((0, 0, 0)), -math.sqrt(0.5))
    + QubitState(QubitStateString((0, 0, 1)), math.sqrt(0.5))
)

lc_ansatz = MultiConfigurationStateBox(lc_qs)

protocol = ProjectiveMeasurements(
    backend=AerConfig(),
    shots_per_circuit=2,
    project_ref=project_ref,
)

Annotations

From this point on, we can use the standard InQuanto notation for building, compiling and running protocols. A user may opt to create annotations for circuits that we are interested in and also compilation and execution jobs. This allows for easier searching in the Nexus projects database.

Annotations are entirely optional, but a user has the ability to mark circuits or jobs with a name, description and properties corresponding to the project properties.

import math
from datetime import datetime

from qnexus import AerConfig

from inquanto.ansatzes import MultiConfigurationStateBox
from inquanto.protocols import ProjectiveMeasurements
from inquanto.states import QubitState, QubitStateString

from inquanto.extensions.nexus import ProtocolAnnotations


protocol.build({}, lc_ansatz)

circuit_annotations = ProtocolAnnotations(
name="My Circuit",
description="Description of my circuit",
properties={"Number of Qubits": 3},
)

compile_job_annotations = ProtocolAnnotations(name=f"Compile Job {datetime.now()}")

protocol.compile_circuits(
    circuit_annotations=circuit_annotations, compile_job_annotations=compile_job_annotations
)

execute_job_annotations = ProtocolAnnotations(name=f"Execute Job {datetime.now()}")

protocol.run(seed=0, execute_job_annotations=execute_job_annotations)

dominant_states = protocol.get_dominant_basis_states(n=2)
print(dominant_states)