microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
samples/python_interop/qir_circuit_submission_to_azure.ipynb
289lines · modecode
| 1 | { |
| 2 | "cells": [ |
| 3 | { |
| 4 | "cell_type": "markdown", |
| 5 | "id": "b1c8553d", |
| 6 | "metadata": {}, |
| 7 | "source": [ |
| 8 | "# Manual QIR Circuit Submission to Azure Quantum\n", |
| 9 | "\n", |
| 10 | "This notebook demonstrates how to submit quantum circuits to Azure Quantum via an explicit **OpenQASM 3 → QIR** compilation path, covering both **Qiskit** and **Cirq** circuits.\n", |
| 11 | "\n", |
| 12 | "This approach gives full visibility and control over intermediate compilation artifacts. It is useful when you need to inspect or modify OpenQASM or QIR before submission, target backends that require raw QIR, or share a single submission pipeline across frameworks.\n", |
| 13 | "\n", |
| 14 | "For the recommended getting-started experience for each framework, see:\n", |
| 15 | "- `qiskit_submission_to_azure.ipynb`\n", |
| 16 | "- `cirq_submission_to_azure.ipynb`" |
| 17 | ] |
| 18 | }, |
| 19 | { |
| 20 | "cell_type": "markdown", |
| 21 | "id": "906a9b09", |
| 22 | "metadata": {}, |
| 23 | "source": [ |
| 24 | "The same compilation pipeline works for both Qiskit and Cirq circuits:\n", |
| 25 | "\n", |
| 26 | "1. Build a circuit in Qiskit or Cirq.\n", |
| 27 | "2. Export it to **OpenQASM 3** text — this intermediate representation can be inspected or modified.\n", |
| 28 | "3. Compile the OpenQASM 3 source to **QIR** with `qdk.openqasm.compile` (choose a `TargetProfile`).\n", |
| 29 | "4. Connect to an Azure Quantum workspace with `qdk.azure.Workspace`.\n", |
| 30 | "5. Select a target (e.g. a simulator such as `rigetti.sim.qvm`).\n", |
| 31 | "6. Submit the QIR payload (`target.submit(qir, job_name, shots)`) and retrieve results (`job.get_results()`)." |
| 32 | ] |
| 33 | }, |
| 34 | { |
| 35 | "cell_type": "markdown", |
| 36 | "id": "243e083e", |
| 37 | "metadata": {}, |
| 38 | "source": [ |
| 39 | "## Prerequisites\n", |
| 40 | "\n", |
| 41 | "Install the `qdk` package with `azure` and whichever framework extras you need. Install both if you plan to run both sections of this notebook:" |
| 42 | ] |
| 43 | }, |
| 44 | { |
| 45 | "cell_type": "code", |
| 46 | "execution_count": null, |
| 47 | "id": "afb12537", |
| 48 | "metadata": {}, |
| 49 | "outputs": [], |
| 50 | "source": [ |
| 51 | "%pip install \"qdk[azure,cirq,qiskit]\"" |
| 52 | ] |
| 53 | }, |
| 54 | { |
| 55 | "cell_type": "markdown", |
| 56 | "id": "83d2907f", |
| 57 | "metadata": {}, |
| 58 | "source": [ |
| 59 | "After installing, restart the notebook kernel if it was already running. Verify installation:" |
| 60 | ] |
| 61 | }, |
| 62 | { |
| 63 | "cell_type": "code", |
| 64 | "execution_count": null, |
| 65 | "id": "3e3b8778", |
| 66 | "metadata": {}, |
| 67 | "outputs": [], |
| 68 | "source": [ |
| 69 | "import cirq, qiskit, qdk, qdk.azure # should import without errors" |
| 70 | ] |
| 71 | }, |
| 72 | { |
| 73 | "cell_type": "markdown", |
| 74 | "id": "4c503ee7", |
| 75 | "metadata": {}, |
| 76 | "source": [ |
| 77 | "## Configure Azure Quantum workspace connection\n", |
| 78 | "\n", |
| 79 | "Replace the placeholder values with your own workspace details. These are shared across both the Qiskit and Cirq examples below." |
| 80 | ] |
| 81 | }, |
| 82 | { |
| 83 | "cell_type": "code", |
| 84 | "execution_count": null, |
| 85 | "id": "20dc0946", |
| 86 | "metadata": {}, |
| 87 | "outputs": [], |
| 88 | "source": [ |
| 89 | "subscription_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n", |
| 90 | "resource_group = 'myresourcegroup'\n", |
| 91 | "workspace_name = 'myworkspace'\n", |
| 92 | "location = 'westus'\n", |
| 93 | "\n", |
| 94 | "# Replace with any QIR-capable target name from your workspace\n", |
| 95 | "target_name = \"rigetti.sim.qvm\"" |
| 96 | ] |
| 97 | }, |
| 98 | { |
| 99 | "cell_type": "markdown", |
| 100 | "id": "bbee43f6", |
| 101 | "metadata": {}, |
| 102 | "source": [ |
| 103 | "---\n", |
| 104 | "## Part A: Submitting a Qiskit circuit\n", |
| 105 | "\n", |
| 106 | "### Build a Qiskit circuit\n", |
| 107 | "\n", |
| 108 | "We use a Bell-state circuit — two entangled qubits — to demonstrate the Qiskit path.\n" |
| 109 | ] |
| 110 | }, |
| 111 | { |
| 112 | "cell_type": "code", |
| 113 | "execution_count": null, |
| 114 | "id": "0d0e8013", |
| 115 | "metadata": {}, |
| 116 | "outputs": [], |
| 117 | "source": [ |
| 118 | "from qiskit import QuantumCircuit\n", |
| 119 | "\n", |
| 120 | "qiskit_circuit = QuantumCircuit(2, 2)\n", |
| 121 | "qiskit_circuit.h(0)\n", |
| 122 | "qiskit_circuit.cx(0, 1)\n", |
| 123 | "qiskit_circuit.measure([0, 1], [0, 1])\n", |
| 124 | "\n", |
| 125 | "qiskit_circuit.draw(output=\"text\")\n" |
| 126 | ] |
| 127 | }, |
| 128 | { |
| 129 | "cell_type": "markdown", |
| 130 | "id": "f5848792", |
| 131 | "metadata": {}, |
| 132 | "source": [ |
| 133 | "### Export to OpenQASM 3\n", |
| 134 | "\n", |
| 135 | "`qiskit.qasm3.dumps` converts a Qiskit circuit to an OpenQASM 3 string. This intermediate text can be inspected or modified before compilation." |
| 136 | ] |
| 137 | }, |
| 138 | { |
| 139 | "cell_type": "code", |
| 140 | "execution_count": null, |
| 141 | "id": "85413498", |
| 142 | "metadata": {}, |
| 143 | "outputs": [], |
| 144 | "source": [ |
| 145 | "from qiskit import qasm3\n", |
| 146 | "\n", |
| 147 | "qasm3_str_qiskit = qasm3.dumps(qiskit_circuit)\n", |
| 148 | "print(qasm3_str_qiskit)" |
| 149 | ] |
| 150 | }, |
| 151 | { |
| 152 | "cell_type": "markdown", |
| 153 | "id": "43904206", |
| 154 | "metadata": {}, |
| 155 | "source": [ |
| 156 | "### Compile to QIR and submit\n", |
| 157 | "\n", |
| 158 | "Compile the OpenQASM 3 source to QIR, then connect to the workspace and submit the payload." |
| 159 | ] |
| 160 | }, |
| 161 | { |
| 162 | "cell_type": "code", |
| 163 | "execution_count": null, |
| 164 | "id": "f6f32b4c", |
| 165 | "metadata": {}, |
| 166 | "outputs": [], |
| 167 | "source": [ |
| 168 | "from qdk.openqasm import compile\n", |
| 169 | "from qdk import TargetProfile\n", |
| 170 | "from qdk.azure import Workspace\n", |
| 171 | "\n", |
| 172 | "qir_qiskit = compile(qasm3_str_qiskit, target_profile=TargetProfile.Base)\n", |
| 173 | "\n", |
| 174 | "workspace = Workspace(\n", |
| 175 | " subscription_id=subscription_id,\n", |
| 176 | " resource_group=resource_group,\n", |
| 177 | " name=workspace_name,\n", |
| 178 | " location=location,\n", |
| 179 | ")\n", |
| 180 | "\n", |
| 181 | "target = workspace.get_targets(target_name)\n", |
| 182 | "job = target.submit(qir_qiskit, \"qiskit-manual-job\", shots=100)\n", |
| 183 | "print(\"Job submitted. Waiting for results...\")\n", |
| 184 | "\n", |
| 185 | "results = job.get_results()\n", |
| 186 | "print(results)" |
| 187 | ] |
| 188 | }, |
| 189 | { |
| 190 | "cell_type": "markdown", |
| 191 | "id": "c580ff95", |
| 192 | "metadata": {}, |
| 193 | "source": [ |
| 194 | "---\n", |
| 195 | "## Part B: Submitting a Cirq circuit\n", |
| 196 | "\n", |
| 197 | "### Build a Cirq circuit\n", |
| 198 | "\n", |
| 199 | "We create a simple Bell-state circuit with two named measurement keys." |
| 200 | ] |
| 201 | }, |
| 202 | { |
| 203 | "cell_type": "code", |
| 204 | "execution_count": null, |
| 205 | "id": "6d3e980e", |
| 206 | "metadata": {}, |
| 207 | "outputs": [], |
| 208 | "source": [ |
| 209 | "import cirq\n", |
| 210 | "\n", |
| 211 | "q0, q1 = cirq.LineQubit.range(2)\n", |
| 212 | "cirq_circuit = cirq.Circuit(\n", |
| 213 | " cirq.H(q0),\n", |
| 214 | " cirq.CNOT(q0, q1),\n", |
| 215 | " cirq.measure(q0, key=\"q0\"),\n", |
| 216 | " cirq.measure(q1, key=\"q1\"),\n", |
| 217 | ")\n", |
| 218 | "print(cirq_circuit)" |
| 219 | ] |
| 220 | }, |
| 221 | { |
| 222 | "cell_type": "markdown", |
| 223 | "id": "7978d457", |
| 224 | "metadata": {}, |
| 225 | "source": [ |
| 226 | "### Export to OpenQASM 3\n", |
| 227 | "\n", |
| 228 | "`circuit.to_qasm(version=\"3.0\")` converts a Cirq circuit to an OpenQASM 3 string. This intermediate text can be inspected or modified before compilation." |
| 229 | ] |
| 230 | }, |
| 231 | { |
| 232 | "cell_type": "code", |
| 233 | "execution_count": null, |
| 234 | "id": "d8aead8b", |
| 235 | "metadata": {}, |
| 236 | "outputs": [], |
| 237 | "source": [ |
| 238 | "qasm3_str_cirq = cirq_circuit.to_qasm(version=\"3.0\")\n", |
| 239 | "print(qasm3_str_cirq)" |
| 240 | ] |
| 241 | }, |
| 242 | { |
| 243 | "cell_type": "markdown", |
| 244 | "id": "ba3547ee", |
| 245 | "metadata": {}, |
| 246 | "source": [ |
| 247 | "### Compile to QIR and submit\n", |
| 248 | "\n", |
| 249 | "The compile and submission steps are identical to Part A — `compile` and `workspace` are already available from the cells above." |
| 250 | ] |
| 251 | }, |
| 252 | { |
| 253 | "cell_type": "code", |
| 254 | "execution_count": null, |
| 255 | "id": "f00236c7", |
| 256 | "metadata": {}, |
| 257 | "outputs": [], |
| 258 | "source": [ |
| 259 | "qir_cirq = compile(qasm3_str_cirq, target_profile=TargetProfile.Base)\n", |
| 260 | "\n", |
| 261 | "target = workspace.get_targets(target_name)\n", |
| 262 | "job = target.submit(qir_cirq, \"cirq-manual-job\", shots=100)\n", |
| 263 | "print(\"Job submitted. Waiting for results...\")\n", |
| 264 | "\n", |
| 265 | "results = job.get_results()\n", |
| 266 | "print(results)" |
| 267 | ] |
| 268 | }, |
| 269 | { |
| 270 | "cell_type": "markdown", |
| 271 | "id": "0270d310", |
| 272 | "metadata": {}, |
| 273 | "source": [ |
| 274 | "## Notes\n", |
| 275 | "\n", |
| 276 | "- **TargetProfile**: Use `TargetProfile.Base` for most simulators and hardware targets. Use `TargetProfile.Adaptive_RI` for targets that support adaptive circuits with classical branching.\n", |
| 277 | "- **Shared compilation step**: The `compile → submit` pipeline is identical for both frameworks — the only difference is how the OpenQASM 3 string is produced.\n", |
| 278 | "- **QIR inspection**: The `qir` object is LLVM bitcode. You can write it to a `.bc` file for offline inspection with LLVM tools.\n" |
| 279 | ] |
| 280 | } |
| 281 | ], |
| 282 | "metadata": { |
| 283 | "language_info": { |
| 284 | "name": "python" |
| 285 | } |
| 286 | }, |
| 287 | "nbformat": 4, |
| 288 | "nbformat_minor": 5 |
| 289 | } |