]"
402 | ]
403 | },
404 | "execution_count": 15,
405 | "metadata": {},
406 | "output_type": "execute_result"
407 | }
408 | ],
409 | "source": [
410 | "from qbraid.runtime import OQCProvider\n",
411 | "\n",
412 | "token = os.getenv(\"OQC_AUTH_TOKEN\")\n",
413 | "\n",
414 | "provider = OQCProvider(token=token)\n",
415 | "\n",
416 | "provider.get_devices()"
417 | ]
418 | },
419 | {
420 | "cell_type": "code",
421 | "execution_count": null,
422 | "id": "f632294e",
423 | "metadata": {},
424 | "outputs": [],
425 | "source": []
426 | }
427 | ],
428 | "metadata": {
429 | "kernelspec": {
430 | "display_name": "sdk311",
431 | "language": "python",
432 | "name": "python3"
433 | },
434 | "language_info": {
435 | "codemirror_mode": {
436 | "name": "ipython",
437 | "version": 3
438 | },
439 | "file_extension": ".py",
440 | "mimetype": "text/x-python",
441 | "name": "python",
442 | "nbconvert_exporter": "python",
443 | "pygments_lexer": "ipython3",
444 | "version": "3.11.9"
445 | }
446 | },
447 | "nbformat": 4,
448 | "nbformat_minor": 5
449 | }
450 |
--------------------------------------------------------------------------------
/qbraid_sdk/qbraid_sdk_transpiler.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "98528633",
6 | "metadata": {},
7 | "source": [
8 | "# qBraid-SDK: Transpiler"
9 | ]
10 | },
11 | {
12 | "cell_type": "code",
13 | "execution_count": 1,
14 | "id": "331a496f",
15 | "metadata": {},
16 | "outputs": [],
17 | "source": [
18 | "import numpy as np\n",
19 | "\n",
20 | "from qbraid.programs import QPROGRAM_REGISTRY\n",
21 | "from qbraid.interface import (\n",
22 | " circuits_allclose,\n",
23 | " assert_allclose_up_to_global_phase,\n",
24 | " random_circuit,\n",
25 | ")\n",
26 | "from qbraid.transpiler import transpile"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "id": "f8360d49",
32 | "metadata": {},
33 | "source": [
34 | "The qBraid transpiler supports all-to-all connectivity between the following quantum program types:"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 2,
40 | "id": "0c41ae38",
41 | "metadata": {},
42 | "outputs": [
43 | {
44 | "data": {
45 | "text/plain": [
46 | "{'cirq': cirq.circuits.circuit.Circuit,\n",
47 | " 'qiskit': qiskit.circuit.quantumcircuit.QuantumCircuit,\n",
48 | " 'pennylane': pennylane.tape.tape.QuantumTape,\n",
49 | " 'pyquil': pyquil.quil.Program,\n",
50 | " 'pytket': pytket._tket.circuit.Circuit,\n",
51 | " 'braket': braket.circuits.circuit.Circuit,\n",
52 | " 'braket_ahs': braket.ahs.analog_hamiltonian_simulation.AnalogHamiltonianSimulation,\n",
53 | " 'openqasm3': openqasm3.ast.Program,\n",
54 | " 'pyqir': Module,\n",
55 | " 'cpp_pyqubo': cpp_pyqubo.Model,\n",
56 | " 'qasm2': str,\n",
57 | " 'qasm3': str,\n",
58 | " 'ionq': ~IonQDict,\n",
59 | " 'bloqade': bloqade.builder.assign.BatchAssign}"
60 | ]
61 | },
62 | "execution_count": 2,
63 | "metadata": {},
64 | "output_type": "execute_result"
65 | }
66 | ],
67 | "source": [
68 | "QPROGRAM_REGISTRY"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "id": "ac83d0b6",
74 | "metadata": {},
75 | "source": [
76 | "## Basic usage example: Qiskit $\\leftrightarrow$ Amazon Braket $\\leftrightarrow$ Cirq"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": 3,
82 | "id": "da3079f7",
83 | "metadata": {},
84 | "outputs": [],
85 | "source": [
86 | "from qiskit import QuantumCircuit\n",
87 | "\n",
88 | "\n",
89 | "def test_circuit():\n",
90 | " circuit = QuantumCircuit(4)\n",
91 | "\n",
92 | " circuit.h([0, 1, 2, 3])\n",
93 | " circuit.x([0, 1])\n",
94 | " circuit.y(2)\n",
95 | " circuit.z(3)\n",
96 | " circuit.s(0)\n",
97 | " circuit.sdg(1)\n",
98 | " circuit.t(2)\n",
99 | " circuit.tdg(3)\n",
100 | " circuit.rx(np.pi / 4, 0)\n",
101 | " circuit.ry(np.pi / 2, 1)\n",
102 | " circuit.rz(3 * np.pi / 4, 2)\n",
103 | " circuit.p(np.pi / 8, 3)\n",
104 | " circuit.sx(0)\n",
105 | " circuit.sxdg(1)\n",
106 | " circuit.iswap(2, 3)\n",
107 | " circuit.swap([0, 1], [2, 3])\n",
108 | " circuit.cx(0, 1)\n",
109 | " circuit.cp(np.pi / 4, 2, 3)\n",
110 | "\n",
111 | " return circuit"
112 | ]
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "id": "a55cf255",
117 | "metadata": {},
118 | "source": [
119 | "We'll start with a 4-qubit qiskit circuit that uses 15 unique gates"
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "execution_count": 4,
125 | "id": "8710a671",
126 | "metadata": {},
127 | "outputs": [
128 | {
129 | "data": {
130 | "text/html": [
131 | " ┌───┐┌───┐ ┌───┐ ┌─────────┐ ┌────┐ \n",
132 | "q_0: ┤ H ├┤ X ├─┤ S ├─┤ Rx(π/4) ├───┤ √X ├───X────────■────\n",
133 | " ├───┤├───┤┌┴───┴┐├─────────┤ ┌┴────┴┐ │ ┌─┴─┐ \n",
134 | "q_1: ┤ H ├┤ X ├┤ Sdg ├┤ Ry(π/2) ├──┤ √Xdg ├──┼──X───┤ X ├──\n",
135 | " ├───┤├───┤└┬───┬┘├─────────┴┐┌┴──────┴┐ │ │ └───┘ \n",
136 | "q_2: ┤ H ├┤ Y ├─┤ T ├─┤ Rz(3π/4) ├┤0 ├─X──┼──■───────\n",
137 | " ├───┤├───┤┌┴───┴┐└┬────────┬┘│ Iswap │ │ │P(π/4) \n",
138 | "q_3: ┤ H ├┤ Z ├┤ Tdg ├─┤ P(π/8) ├─┤1 ├────X──■───────\n",
139 | " └───┘└───┘└─────┘ └────────┘ └────────┘
"
140 | ],
141 | "text/plain": [
142 | " ┌───┐┌───┐ ┌───┐ ┌─────────┐ ┌────┐ \n",
143 | "q_0: ┤ H ├┤ X ├─┤ S ├─┤ Rx(π/4) ├───┤ √X ├───X────────■────\n",
144 | " ├───┤├───┤┌┴───┴┐├─────────┤ ┌┴────┴┐ │ ┌─┴─┐ \n",
145 | "q_1: ┤ H ├┤ X ├┤ Sdg ├┤ Ry(π/2) ├──┤ √Xdg ├──┼──X───┤ X ├──\n",
146 | " ├───┤├───┤└┬───┬┘├─────────┴┐┌┴──────┴┐ │ │ └───┘ \n",
147 | "q_2: ┤ H ├┤ Y ├─┤ T ├─┤ Rz(3π/4) ├┤0 ├─X──┼──■───────\n",
148 | " ├───┤├───┤┌┴───┴┐└┬────────┬┘│ Iswap │ │ │P(π/4) \n",
149 | "q_3: ┤ H ├┤ Z ├┤ Tdg ├─┤ P(π/8) ├─┤1 ├────X──■───────\n",
150 | " └───┘└───┘└─────┘ └────────┘ └────────┘ "
151 | ]
152 | },
153 | "execution_count": 4,
154 | "metadata": {},
155 | "output_type": "execute_result"
156 | }
157 | ],
158 | "source": [
159 | "qiskit_circuit = test_circuit()\n",
160 | "qiskit_circuit.draw()"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": 5,
166 | "id": "7f1ef479",
167 | "metadata": {},
168 | "outputs": [
169 | {
170 | "name": "stdout",
171 | "output_type": "stream",
172 | "text": [
173 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │\n",
174 | " ┌───┐ ┌───┐ ┌───┐ ┌──────────┐ ┌───┐ \n",
175 | "q0 : ─┤ H ├─┤ X ├─┤ S ├───┤ Rx(0.79) ├─────┤ V ├──────x─────────────────────●────────\n",
176 | " └───┘ └───┘ └───┘ └──────────┘ └───┘ │ │ \n",
177 | " ┌───┐ ┌───┐ ┌────┐ ┌──────────┐ ┌────┐ │ ┌─┴─┐ \n",
178 | "q1 : ─┤ H ├─┤ X ├─┤ Si ├──┤ Ry(1.57) ├────┤ Vi ├──────┼────────x──────────┤ X ├──────\n",
179 | " └───┘ └───┘ └────┘ └──────────┘ └────┘ │ │ └───┘ \n",
180 | " ┌───┐ ┌───┐ ┌───┐ ┌──────────┐ ┌───────┐ │ │ \n",
181 | "q2 : ─┤ H ├─┤ Y ├─┤ T ├───┤ Rz(2.36) ├───┤ ISWAP ├────x────────┼────────────●────────\n",
182 | " └───┘ └───┘ └───┘ └──────────┘ └───┬───┘ │ │ \n",
183 | " ┌───┐ ┌───┐ ┌────┐ ┌─────────────┐ ┌───┴───┐ │ ┌──────┴──────┐ \n",
184 | "q3 : ─┤ H ├─┤ Z ├─┤ Ti ├─┤ PHASE(0.39) ├─┤ ISWAP ├─────────────x─────┤ PHASE(0.79) ├─\n",
185 | " └───┘ └───┘ └────┘ └─────────────┘ └───────┘ └─────────────┘ \n",
186 | "T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │\n"
187 | ]
188 | }
189 | ],
190 | "source": [
191 | "braket_circuit = transpile(qiskit_circuit, \"braket\")\n",
192 | "print(braket_circuit)"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": 6,
198 | "id": "2a6eb7e7",
199 | "metadata": {},
200 | "outputs": [
201 | {
202 | "name": "stdout",
203 | "output_type": "stream",
204 | "text": [
205 | "q_0: ───H───X───S──────Rx(0.25π)───X^0.5────────────────×───────@────────\n",
206 | " │ │\n",
207 | "q_1: ───H───X───S^-1───Ry(0.5π)────X^-0.5───────────────┼───×───X────────\n",
208 | " │ │\n",
209 | "q_2: ───H───Y───T──────Rz(0.75π)───S────────H───@───X───×───┼───@────────\n",
210 | " │ │ │ │\n",
211 | "q_3: ───H───Z───T^-1───Z^(1/8)─────S────────────X───@───H───×───@^0.25───\n"
212 | ]
213 | }
214 | ],
215 | "source": [
216 | "cirq_circuit = transpile(qiskit_circuit, \"cirq\")\n",
217 | "print(cirq_circuit)"
218 | ]
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "id": "0963d29d",
223 | "metadata": {},
224 | "source": [
225 | "Qubit indexing varies between packages, so some circuit diagrams appear flipped, but the matrix representations are equivalent.\n",
226 | "\n",
227 | "To verify, we'll use the sdk's `circuits_allclose` function, which applies the agnostic `qbraid.interface.to_unitary` function to each of two input circuits, checks the matricies against `np.allclose`, and returns the result."
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": 7,
233 | "id": "665c6c0b",
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "data": {
238 | "text/plain": [
239 | "True"
240 | ]
241 | },
242 | "execution_count": 7,
243 | "metadata": {},
244 | "output_type": "execute_result"
245 | }
246 | ],
247 | "source": [
248 | "circuits_allclose(qiskit_circuit, braket_circuit) and circuits_allclose(\n",
249 | " braket_circuit, cirq_circuit\n",
250 | ")"
251 | ]
252 | },
253 | {
254 | "cell_type": "markdown",
255 | "id": "5359d22b",
256 | "metadata": {},
257 | "source": [
258 | "## Stress-testing against randomly generated circuits"
259 | ]
260 | },
261 | {
262 | "cell_type": "markdown",
263 | "id": "31a3cbc8",
264 | "metadata": {},
265 | "source": [
266 | "For a second example, we'll generate some even larger circuits, and do so randomly, to test the limits of the transpiler.\n",
267 | "\n",
268 | "The qBraid-SDK has its own `random_circuit` function that takes in any supported package as an argument, but to show that there's no pre-processing or filtering going on behind the scenes, we'll use functions from cirq's testing module to generate circuits and to check equivalance after transpiling."
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "execution_count": 8,
274 | "id": "afe95c34",
275 | "metadata": {},
276 | "outputs": [
277 | {
278 | "name": "stdout",
279 | "output_type": "stream",
280 | "text": [
281 | "num_qubits: 10\n",
282 | "depth: 10\n",
283 | "op_density: 0.85\n",
284 | "matrix dimension: (1024, 1024)\n",
285 | "\n",
286 | " ┌──┐ ┌──┐ ┌──────────┐ ┌────┐ ┌───────┐ ┌───┐ ┌───┐ ┌────┐ ┌────────┐\n",
287 | "0: ─────×─────Z──────@─────────────@───────@───────────────────@──────@───────@───────────────────\n",
288 | " │ │ │ │ │ │ │\n",
289 | "1: ────Y┼─────T──────┼────iSwap────┼─────×─┼──────×────────────┼──────┼───────┼X───────×──────────\n",
290 | " │ │ │ │ │ │ │ │ │ ││ │\n",
291 | "2: ────Z┼────────────┼────iSwap────X─────┼×┼─────X┼────────────┼──────┼@─────×┼┼───────┼iSwap─────\n",
292 | " │ │ │││ ││ │ ││ │││ ││\n",
293 | "3: ────T┼─────@──────X─────────────S────S┼┼┼─────┼┼iSwap──────×┼─────Z┼┼─────┼┼┼T──────┼┼─────────\n",
294 | " │ │ │││ │││ ││ ││ │││ ││\n",
295 | "4: ────Z┼─────┼@─────iSwap─────────Y────Z┼┼┼─────@┼┼─────────Z┼┼─────X┼┼─────┼@┼───────┼┼────×────\n",
296 | " │ ││ │ │││ ││ ││ ││ │ │ ││ │\n",
297 | "5: ────T┼─────┼X─────┼────X────────Y────H┼┼┼──────┼iSwap──────┼@─────H┼┼─────┼─┼──────Y┼┼────┼────\n",
298 | " │ │ │ │ │││ │ │ ││ │ │ ││ │\n",
299 | "6: ─────┼─────@──────┼────┼────────X─────×┼┼──────┼───────────┼───────┼@─────×─┼───────┼┼────×────\n",
300 | " │ │ │ ││ │ │ │ │ ││\n",
301 | "7: ─────×────────────┼────@────────Z──────┼X─────T┼───────────×──────@┼──────Y─┼───────┼iSwap─────\n",
302 | " │ │ │ ││ │ │\n",
303 | "8: ────Y──────T──────┼────T────────X────T─┼───────┼──────────X───────X┼────────┼───────×──────────\n",
304 | " │ │ │ │ │ │ │\n",
305 | "9: ───────────Z──────iSwap─────────@──────×───────×──────────@────────@────────@──────H───────────\n",
306 | " └──┘ └──┘ └──────────┘ └────┘ └───────┘ └───┘ └───┘ └────┘ └────────┘\n"
307 | ]
308 | }
309 | ],
310 | "source": [
311 | "import cirq\n",
312 | "\n",
313 | "kwargs = {\n",
314 | " \"num_qubits\": np.random.randint(8, 11),\n",
315 | " \"depth\": np.random.randint(8, 11),\n",
316 | " \"op_density\": np.random.randint(80, 100) / 100,\n",
317 | " \"random_state\": np.random.randint(1, 11),\n",
318 | "}\n",
319 | "\n",
320 | "circuit_start = random_circuit(\"cirq\", **kwargs)\n",
321 | "start_u = circuit_start.unitary()\n",
322 | "print(\"num_qubits:\", len(circuit_start.all_qubits()))\n",
323 | "print(\"depth:\", len(circuit_start))\n",
324 | "print(\"op_density:\", kwargs[\"op_density\"])\n",
325 | "print(f\"matrix dimension: {start_u.shape}\\n\")\n",
326 | "print(circuit_start)"
327 | ]
328 | },
329 | {
330 | "cell_type": "markdown",
331 | "id": "5818071d",
332 | "metadata": {},
333 | "source": [
334 | "Starting with this randomly generated circuit, we'll repeatedly apply the qbraid circuit wrapper and transpile from one supported package to the next until we arrive all the way back at a cirq circuit."
335 | ]
336 | },
337 | {
338 | "cell_type": "code",
339 | "execution_count": 9,
340 | "id": "bbe4be5f",
341 | "metadata": {},
342 | "outputs": [
343 | {
344 | "name": "stdout",
345 | "output_type": "stream",
346 | "text": [
347 | "\n"
348 | ]
349 | }
350 | ],
351 | "source": [
352 | "braket_circuit = transpile(circuit_start, \"braket\")\n",
353 | "print(type(braket_circuit))"
354 | ]
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": 10,
359 | "id": "d2813ee0",
360 | "metadata": {},
361 | "outputs": [
362 | {
363 | "name": "stdout",
364 | "output_type": "stream",
365 | "text": [
366 | "\n"
367 | ]
368 | }
369 | ],
370 | "source": [
371 | "pyquil_circuit = transpile(braket_circuit, \"pyquil\")\n",
372 | "print(type(pyquil_circuit))"
373 | ]
374 | },
375 | {
376 | "cell_type": "code",
377 | "execution_count": 11,
378 | "id": "fbb476fb",
379 | "metadata": {},
380 | "outputs": [
381 | {
382 | "name": "stdout",
383 | "output_type": "stream",
384 | "text": [
385 | "\n"
386 | ]
387 | }
388 | ],
389 | "source": [
390 | "qiskit_circuit = transpile(pyquil_circuit, \"qiskit\")\n",
391 | "print(type(qiskit_circuit))"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": 12,
397 | "id": "fc405e6e",
398 | "metadata": {},
399 | "outputs": [
400 | {
401 | "name": "stdout",
402 | "output_type": "stream",
403 | "text": [
404 | "\n"
405 | ]
406 | }
407 | ],
408 | "source": [
409 | "pytket_circuit = transpile(qiskit_circuit, \"pytket\")\n",
410 | "print(type(pytket_circuit))"
411 | ]
412 | },
413 | {
414 | "cell_type": "code",
415 | "execution_count": 13,
416 | "id": "072f6aeb",
417 | "metadata": {},
418 | "outputs": [
419 | {
420 | "name": "stdout",
421 | "output_type": "stream",
422 | "text": [
423 | "\n"
424 | ]
425 | }
426 | ],
427 | "source": [
428 | "circuit_finish = transpile(pytket_circuit, \"cirq\")\n",
429 | "print(type(circuit_finish))"
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "id": "b621daed",
435 | "metadata": {},
436 | "source": [
437 | "Computing the final unitary and checking its shape"
438 | ]
439 | },
440 | {
441 | "cell_type": "code",
442 | "execution_count": 14,
443 | "id": "5f6f3633",
444 | "metadata": {},
445 | "outputs": [
446 | {
447 | "name": "stdout",
448 | "output_type": "stream",
449 | "text": [
450 | "(1024, 1024)\n"
451 | ]
452 | }
453 | ],
454 | "source": [
455 | "finish_u = circuit_finish.unitary()\n",
456 | "print(finish_u.shape)"
457 | ]
458 | },
459 | {
460 | "cell_type": "code",
461 | "execution_count": 15,
462 | "id": "9f461918",
463 | "metadata": {},
464 | "outputs": [
465 | {
466 | "name": "stdout",
467 | "output_type": "stream",
468 | "text": [
469 | "Test passed!\n"
470 | ]
471 | }
472 | ],
473 | "source": [
474 | "try:\n",
475 | " assert_allclose_up_to_global_phase(start_u, finish_u, atol=1e-7)\n",
476 | " print(\"Test passed!\")\n",
477 | "except AssertionError:\n",
478 | " print(\"Test failed\")"
479 | ]
480 | },
481 | {
482 | "cell_type": "code",
483 | "execution_count": null,
484 | "id": "5d7dd657-c7ec-425e-9036-7109aa4c07e2",
485 | "metadata": {},
486 | "outputs": [],
487 | "source": []
488 | }
489 | ],
490 | "metadata": {
491 | "kernelspec": {
492 | "display_name": "Python 3 [qBraid]",
493 | "language": "python",
494 | "name": "python3_qbraid_sdk_9j9sjy"
495 | },
496 | "language_info": {
497 | "codemirror_mode": {
498 | "name": "ipython",
499 | "version": 3
500 | },
501 | "file_extension": ".py",
502 | "mimetype": "text/x-python",
503 | "name": "python",
504 | "nbconvert_exporter": "python",
505 | "pygments_lexer": "ipython3",
506 | "version": "3.11.9"
507 | }
508 | },
509 | "nbformat": 4,
510 | "nbformat_minor": 5
511 | }
512 |
--------------------------------------------------------------------------------