{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Labelling workflow data in Nexus using Properties\n", "\n", "In this example, we'll submit a few different circuits on a few different simulators and use Nexus Properties to label our data.\n", "\n", "These properties can then be used to filter our results when we make queries to Nexus." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "from datetime import datetime\n", "from pytket import Circuit\n", "from pytket.pauli import Pauli\n", "from pytket.circuit import PauliExpBox, QControlBox\n", "\n", "import qnexus as qnx\n", "\n", "from qiskit_aer import noise" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "my_project = qnx.projects.get_or_create(name=\"My Properties Example Project\")\n", "\n", "qnx.context.set_active_project(my_project)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "# Add some properties to the project\n", "\n", "qnx.projects.add_property(\n", " name=\"name_qpu\",\n", " description=\"The name of the device used for a job\",\n", " property_type=\"string\",\n", ")\n", "\n", "qnx.projects.add_property(\n", " name=\"circuit_type\",\n", " description=\"The type of circuit ran, either 'pauli_gadget' or 'bell_state'\",\n", " property_type=\"string\",\n", ")\n", "\n", "qnx.projects.add_property(\n", " name=\"noisy\",\n", " description=\"Was the circuit run with noise?\",\n", " property_type=\"bool\",\n", ")\n", "\n", "qnx.projects.add_property(\n", " name=\"num_shots\",\n", " description=\"Shots run when executing the circuit\",\n", " property_type=\"int\",\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create our circuits\n", "\n", "Here we'll create two simple 'types' of circuit." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "bell_circuit = Circuit(2, 2).H(0).CX(0, 1).measure_all()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "bell_circuit_ref = qnx.circuits.upload(\n", " circuit=bell_circuit,\n", " name=\"Bell State Circuit\",\n", " properties={\"circuit_type\": \"bell_state\"},\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pauli_gadget_circuit = Circuit(5,5)\n", "\n", "zzyx_box = PauliExpBox([Pauli.Z, Pauli.Z, Pauli.Y, Pauli.X], 0.7)\n", "\n", "# Controlled Pauli gadget with a single control.\n", "controlled_pauli = QControlBox(zzyx_box, 1)\n", "\n", "pauli_gadget_circuit.H(0).add_gate(controlled_pauli, [0,1,2,3,4]).measure_all()" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "pauli_circuit_ref =qnx.circuits.upload(\n", " circuit=pauli_gadget_circuit,\n", " name=\"Pauli Gadget Circuit\",\n", " properties={\"circuit_type\": \"pauli_gadget\"},\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define a simple workflow to run on Nexus-hosted simulators" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Double check the properties defined on the project (currently set in the context)\n", "qnx.projects.get_properties().df()" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "def run_workflow(\n", " config: qnx.BackendConfig,\n", " num_shots: int,\n", "):\n", " \n", " device_name = qnx.context.get_active_properties().get(\"name_qpu\")\n", "\n", " compiled_pauli_refs = qnx.compile(\n", " circuits=[pauli_circuit_ref],\n", " name=f\"Pauli Gadget Circuit Compilation for {device_name} on {datetime.now()}\",\n", " properties={\"circuit_type\": \"pauli_gadget\"},\n", " backend_config=config\n", " )\n", "\n", " compiled_reg_refs = qnx.compile(\n", " circuits=[bell_circuit_ref],\n", " name=f\"Bell Circuit Compilation for {device_name} on {datetime.now()}\",\n", " properties={\"circuit_type\": \"bell_state\"},\n", " backend_config=config\n", " )\n", "\n", " with qnx.context.using_properties(\n", " num_shots=num_shots, \n", " ):\n", " \n", " qnx.start_execute_job(\n", " circuits=compiled_pauli_refs,\n", " n_shots=[num_shots],\n", " name=f\"Pauli Gadget Circuit Execution for {device_name} on {datetime.now()}\",\n", " properties={\"circuit_type\": \"pauli_gadget\"},\n", " backend_config=config,\n", " )\n", " qnx.start_execute_job(\n", " circuits=compiled_reg_refs,\n", " n_shots=[num_shots],\n", " name=f\"Bell State Circuit Execution for {device_name} on {datetime.now()}\",\n", " properties={\"circuit_type\": \"bell_state\"},\n", " backend_config=config,\n", " )" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "# Run on H1-Emulator\n", "with qnx.context.using_properties(name_qpu=\"H1-Emulator\"):\n", "\n", " with qnx.context.using_properties(noisy=True):\n", " run_workflow(\n", " config = qnx.QuantinuumConfig(device_name=\"H1-Emulator\"),\n", " num_shots=100,\n", " )\n", "\n", " with qnx.context.using_properties(noisy=False):\n", " run_workflow(\n", " config = qnx.QuantinuumConfig(device_name=\"H1-Emulator\", noisy_simulation=False),\n", " num_shots=100,\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "qnx.projects.summarize(my_project)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "# Simple qiskit aer noise model\n", "prob_ro = 1e-3\n", "n_qubits = 5\n", "\n", "noise_model = noise.NoiseModel()\n", "probabilities = [[1 - prob_ro, prob_ro], [prob_ro, 1 - prob_ro]]\n", "\n", "error_ro = noise.ReadoutError(probabilities)\n", "for i in range(n_qubits):\n", " noise_model.add_readout_error(error_ro, [i])" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "# Run on the Aer simulator\n", "with qnx.context.using_properties(name_qpu=\"Aer\"):\n", " \n", " with qnx.context.using_properties(noisy=True):\n", "\n", " run_workflow(\n", " config = qnx.AerConfig(noise_model=noise_model),\n", " num_shots=100,\n", " )\n", "\n", " with qnx.context.using_properties(noisy=False):\n", "\n", " run_workflow(\n", " config = qnx.AerConfig(),\n", " num_shots=100,\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "qnx.projects.summarize(my_project)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use properties to filter and compare our results\n", "\n", "Using the 'properties' filter when retrieving jobs, we can obtain the results we want to compare." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "jobs_query = qnx.jobs.get_all(\n", " job_type=[\"execute\"],\n", " properties={\n", " \"circuit_type\": \"bell_state\",\n", " # Uncomment the below line to filter by the name of the QPU\n", " #\"name_qpu\": \"H1-Emulator\", \n", " \"noisy\": False,\n", " }\n", ")\n", "\n", "jobs_query.df()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Download the results and print the counts side by side for comparison\n", "\n", "results = []\n", "labels = []\n", "\n", "\n", "for job in jobs_query.list():\n", "\n", " results.append(qnx.jobs.results(job)[0].download_result())\n", "\n", " qpu_name = job.annotations.properties.get(\"name_qpu\")\n", " noisy = job.annotations.properties.get(\"noisy\")\n", " labels.append(f\"{qpu_name} {'noisy' if noisy else 'noiseless'}\")\n", "\n", "\n", "\n", "\n", "for result, label in zip(results, labels):\n", " print(f\"{label}\")\n", " print(result.get_counts())\n" ] } ], "metadata": { "kernelspec": { "display_name": "qnexus-Rou6F43i-py3.11", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.5" } }, "nbformat": 4, "nbformat_minor": 2 }