{ "cells": [ { "cell_type": "markdown", "id": "eb89a144", "metadata": {}, "source": [ "# Compiling and Submitting Circuits onto Sqale via Cirq\n" ] }, { "cell_type": "markdown", "id": "capable-bradley", "metadata": {}, "source": [ "[](https://colab.research.google.com/github/Infleqtion/client-superstaq/blob/main/docs/source/optimizations/sqale/sqale_compile_css.ipynb) [](https://mybinder.org/v2/gh/Infleqtion/client-superstaq/HEAD?labpath=docs/source/optimizations/sqale/sqale_compile_css.ipynb)" ] }, { "cell_type": "markdown", "id": "cd44ef01", "metadata": {}, "source": [ "## Import Requirements" ] }, { "cell_type": "markdown", "id": "188579fc", "metadata": {}, "source": [ "This tutorial will showcase how to compile and submit a circuit onto Infleqtion's hardware, Sqale, using the ```cirq-superstaq``` client. " ] }, { "cell_type": "code", "execution_count": 1, "id": "aff4bd87", "metadata": {}, "outputs": [], "source": [ "# Required imports\n", "try:\n", " import cirq\n", " import cirq_superstaq as css\n", "except ImportError:\n", " print(\"Installing cirq-superstaq...\")\n", " %pip install --quiet 'cirq-superstaq[examples]'\n", " print(\"Installed cirq-superstaq.\")\n", " print(\"You may need to restart the kernel to import newly installed packages.\")\n", " import cirq\n", " import cirq_superstaq as css\n", "\n", "# Optional imports\n", "import os # Used if setting a token as an environment variable" ] }, { "cell_type": "markdown", "id": "ae0dfcb6", "metadata": {}, "source": [ "To interface Superstaq via Cirq, we must first instantiate a service provider in ```cirq-superstaq``` with ```Service()```. We then supply a Superstaq API key (which you can get from https://superstaq.infleqtion.com) by either providing the API key as an argument of Service, i.e., ```css.Service(api_key=\"token\")```, or by setting it as an environment variable. (see more details [here](https://superstaq.readthedocs.io/en/latest/get_started/basics/basics_css.html#Set-up-access-to-Superstaq%E2%80%99s-API))." ] }, { "cell_type": "code", "execution_count": 2, "id": "4464f34f", "metadata": {}, "outputs": [], "source": [ "service = css.Service()" ] }, { "cell_type": "markdown", "id": "415812a3", "metadata": {}, "source": [ "## Create a Circuit" ] }, { "cell_type": "markdown", "id": "f5d5ca21", "metadata": {}, "source": [ "First, we will create an example Cirq circuit that we can then compile and submit to the Sqale QPU" ] }, { "cell_type": "code", "execution_count": 3, "id": "9521d540", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
0: ───H───@───M───\n",
" │ │\n",
"1: ───────X───M───"
],
"text/plain": [
"0: ───H───@───M───\n",
" │ │\n",
"1: ───────X───M───"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qubits = cirq.LineQubit.range(2)\n",
"circuit1 = cirq.Circuit(cirq.H(qubits[0]), cirq.CNOT(qubits[0], qubits[1]), cirq.measure(*qubits))\n",
"circuit1"
]
},
{
"cell_type": "markdown",
"id": "b7812e22",
"metadata": {},
"source": [
"## Single Circuit Compilation"
]
},
{
"cell_type": "markdown",
"id": "eed571b8",
"metadata": {},
"source": [
"We will now compile the above circuit onto Sqale's native gateset and visualize the differences by drawing the compiled circuit"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "b9149284",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"compiler_output = service.cq_compile(circuit1)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "92f3d368",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───\n",
" │ │ │ │ │\n",
"1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───\n",
" │ │ │\n",
"2: ───#3───────────────────────#3─────────────────────────#3────────────────────────\n",
" │ │ │\n",
"3: ───#4───────────────────────#4─────────────────────────#4────────────────────────\n",
" │ │ │\n",
"4: ───#5───────────────────────#5─────────────────────────#5────────────────────────\n",
" │ │ │\n",
"5: ───#6───────────────────────#6─────────────────────────#6────────────────────────"
],
"text/plain": [
"0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───\n",
" │ │ │ │ │\n",
"1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───\n",
" │ │ │\n",
"2: ───#3───────────────────────#3─────────────────────────#3────────────────────────\n",
" │ │ │\n",
"3: ───#4───────────────────────#4─────────────────────────#4────────────────────────\n",
" │ │ │\n",
"4: ───#5───────────────────────#5─────────────────────────#5────────────────────────\n",
" │ │ │\n",
"5: ───#6───────────────────────#6─────────────────────────#6────────────────────────"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"compiler_output.circuit"
]
},
{
"cell_type": "markdown",
"id": "a865f7b3",
"metadata": {},
"source": [
"If you would like to compile (or submit) on a different number of qubits, this can be done via the ```grid_shape``` option. This simply sets the shape of the rectangular qubit grid. However, specifying a grid that is incompatible with Sqale's current capabilities will result in an error when submitting. Anything equal to or smaller than than (6,4) is compatible with Sqale's current capabilities. "
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "2f37e6bd",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"(0, 0): ───RGate(0.5π, -0.5π)───Z───\n",
" │\n",
"(1, 0): ───#2───────────────────Z───\n",
" │\n",
"(2, 0): ───#3───────────────────────\n",
" │\n",
"(3, 0): ───#4───────────────────────"
],
"text/plain": [
"(0, 0): ───RGate(0.5π, -0.5π)───Z───\n",
" │\n",
"(1, 0): ───#2───────────────────Z───\n",
" │\n",
"(2, 0): ───#3───────────────────────\n",
" │\n",
"(3, 0): ───#4───────────────────────"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_circuit = cirq.Circuit(cirq.H.on_each(*qubits))\n",
"new_compiler_output = service.cq_compile(example_circuit, grid_shape=(4, 1))\n",
"new_compiler_output.circuit"
]
},
{
"cell_type": "markdown",
"id": "c6a4b1d3",
"metadata": {},
"source": [
"## Multiple circuit compilation"
]
},
{
"cell_type": "markdown",
"id": "82da705a",
"metadata": {},
"source": [
"If you would like to compile a batch of circuits in one-go, `cirq-superstaq` accepts a list of circuits as well. To illustrate this, let us first create a different example circuit, and compile both circuits we have created so far at the same time. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "32b95bf4",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0: ───H───M───" ], "text/plain": [ "0: ───H───M───" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circuit2 = cirq.Circuit(cirq.H(qubits[0]), cirq.measure(qubits[0]))\n", "circuit2" ] }, { "cell_type": "code", "execution_count": 8, "id": "40fd33d8", "metadata": {}, "outputs": [], "source": [ "compiler_output = service.cq_compile([circuit1, circuit2])" ] }, { "cell_type": "code", "execution_count": 9, "id": "d1961e28", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───\n",
" │ │ │ │ │\n",
"1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───\n",
" │ │ │\n",
"2: ───#3───────────────────────#3─────────────────────────#3────────────────────────\n",
" │ │ │\n",
"3: ───#4───────────────────────#4─────────────────────────#4────────────────────────\n",
" │ │ │\n",
"4: ───#5───────────────────────#5─────────────────────────#5────────────────────────\n",
" │ │ │\n",
"5: ───#6───────────────────────#6─────────────────────────#6────────────────────────"
],
"text/plain": [
"0: ───RGate(0.5π, -0.5π)───@───RGate(-0.25π, -0.5π)───────RGate(0.25π, -0.5π)───M───\n",
" │ │ │ │ │\n",
"1: ───#2───────────────────@───#2─────────────────────Z───#2────────────────────M───\n",
" │ │ │\n",
"2: ───#3───────────────────────#3─────────────────────────#3────────────────────────\n",
" │ │ │\n",
"3: ───#4───────────────────────#4─────────────────────────#4────────────────────────\n",
" │ │ │\n",
"4: ───#5───────────────────────#5─────────────────────────#5────────────────────────\n",
" │ │ │\n",
"5: ───#6───────────────────────#6─────────────────────────#6────────────────────────"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"compiler_output.circuits[0]"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4499aedd",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0: ───RGate(0.5π, -0.5π)───M───\n",
" │\n",
"1: ───#2───────────────────────\n",
" │\n",
"2: ───#3───────────────────────\n",
" │\n",
"3: ───#4───────────────────────\n",
" │\n",
"4: ───#5───────────────────────\n",
" │\n",
"5: ───#6───────────────────────"
],
"text/plain": [
"0: ───RGate(0.5π, -0.5π)───M───\n",
" │\n",
"1: ───#2───────────────────────\n",
" │\n",
"2: ───#3───────────────────────\n",
" │\n",
"3: ───#4───────────────────────\n",
" │\n",
"4: ───#5───────────────────────\n",
" │\n",
"5: ───#6───────────────────────"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"compiler_output.circuits[1]"
]
},
{
"cell_type": "markdown",
"id": "04ad6645",
"metadata": {},
"source": [
"## Circuit Submission"
]
},
{
"cell_type": "markdown",
"id": "ac35a589",
"metadata": {},
"source": [
"All the functionalities we have seen so far can be applied to submit single- or multi-circuit jobs. For example, the code below will submit both the circuits from earlier to the noiseless Sqale simulator. If you would like to run on the Sqale QPU, change the ```target``` argument in ```create_job()``` from ```cq_sqale_simulator``` to ```cq_sqale_qpu```. It is recommended to first submit to the simulator for testing to ensure your code runs before submitting to the Sqale QPU. "
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "dcadf503",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Counts from cirq-superstaq submission for 1st circuit: {'00': 50, '11': 50}\n",
"Counts from cirq-superstaq submission for 2nd circuit: {'0': 44, '1': 56}\n"
]
}
],
"source": [
"job_css = service.create_job([circuit1, circuit2], repetitions=100, target=\"cq_sqale_simulator\")\n",
"result_job_1 = job_css.counts(index=0)\n",
"result_job_2 = job_css.counts(index=1)\n",
"\n",
"print(f\"Counts from cirq-superstaq submission for 1st circuit: {result_job_1}\")\n",
"print(f\"Counts from cirq-superstaq submission for 2nd circuit: {result_job_2}\")"
]
},
{
"cell_type": "markdown",
"id": "d8780e3e",
"metadata": {},
"source": [
"If you would like to submit circuits to a noisy simulator, to see the effects of noise on your simulated measurements without submitting to an actual device, you can additionally pass the argument ```method=noise-sim``` in ```create_job()```. Here's an example code snippet for a single-circuit simulation:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "21ce8024",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Counts from noisy cirq-superstaq submission: {'00': 47, '11': 46, '10': 6, '01': 1}\n"
]
}
],
"source": [
"job_css = service.create_job(\n",
" circuit1, repetitions=100, target=\"cq_sqale_simulator\", method=\"noise-sim\"\n",
")\n",
"result_css = job_css.counts(0)\n",
"print(f\"Counts from noisy cirq-superstaq submission: {result_css}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}