microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-circuit-panel-error-message

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

samples/notebooks/parallel_teleport.ipynb

210lines · modecode

1{
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "id": "f94615ed",
6 "metadata": {},
7 "source": [
8 "# Experimenting with Parallel Teleport on Neutral Atom Device\n",
9 "\n",
10 "This notebook shows how you can use the `NeutralAtomDevice` class to visualize and simulate a scaled, parallel teleport sample program.\n",
11 "\n",
12 "First, set up the environment."
13 ]
14 },
15 {
16 "cell_type": "code",
17 "execution_count": null,
18 "id": "ae94a027",
19 "metadata": {},
20 "outputs": [],
21 "source": [
22 "from qdk import init, TargetProfile, code, Result\n",
23 "from qdk.qsharp import compile, circuit\n",
24 "from qdk.simulation import NeutralAtomDevice, NoiseConfig\n",
25 "from qdk.widgets import Circuit, Histogram\n",
26 "\n",
27 "init(target_profile=TargetProfile.Base)"
28 ]
29 },
30 {
31 "cell_type": "markdown",
32 "id": "df5d6387",
33 "metadata": {},
34 "source": [
35 "Next, we use Q# to define a `ParalellTeleport` that uses distinct sets of qubits to perform a measurement deferred teleportation. Using different qubits rather than the same qubits should allow later device-specific compilation steps to identify parallelism and run those teleports across the qubits at the same time."
36 ]
37 },
38 {
39 "cell_type": "code",
40 "execution_count": null,
41 "id": "0d435592",
42 "metadata": {
43 "vscode": {
44 "languageId": "qsharp"
45 }
46 },
47 "outputs": [],
48 "source": [
49 "%%qsharp\n",
50 "\n",
51 "operation ParallelTeleport(instances : Int) : Result[] {\n",
52 " // Partitions the teleport instances across rows and columns on the machine\n",
53 " let cols = if instances >= 12 { 36 } else { instances * 3 };\n",
54 " let rows = (instances + 11) / 12; // 1 to 12 = 1, 13 to 24 = 2, etc.\n",
55 "\n",
56 " use qubits = Qubit[instances * 3];\n",
57 " mutable results : Result[] = [];\n",
58 "\n",
59 " for i in 0..instances-1 {\n",
60 " let rowId = i / 12;\n",
61 " let colId = (i % 12) * 3;\n",
62 " let idx = colId + (rowId * 36);\n",
63 "\n",
64 " // Prep state on msg qubit\n",
65 " if i % 4 == 1 {\n",
66 " X(qubits[idx]);\n",
67 " } elif i % 4 == 2 {\n",
68 " H(qubits[idx]);\n",
69 " } elif i % 4 == 3 {\n",
70 " SX(qubits[idx]);\n",
71 " }\n",
72 "\n",
73 " Teleport(qubits[idx], qubits[idx + 1], qubits[idx + 2]);\n",
74 "\n",
75 " // Reverse state prep on Bob's qubit\n",
76 " if i % 4 == 1 {\n",
77 " X(qubits[idx + 2]);\n",
78 " } elif i % 4 == 2 {\n",
79 " H(qubits[idx + 2]);\n",
80 " } elif i % 4 == 3 {\n",
81 " X(qubits[idx + 2]);\n",
82 " SX(qubits[idx + 2]);\n",
83 " }\n",
84 " results += [MResetZ(qubits[idx + 2])];\n",
85 " ResetAll([qubits[idx], qubits[idx + 1]]);\n",
86 " }\n",
87 "\n",
88 " return results;\n",
89 "}\n",
90 "\n",
91 "operation Teleport(msg : Qubit, alice : Qubit, bob : Qubit) : Unit {\n",
92 " // Create some entanglement that we can use to send our message.\n",
93 " H(alice);\n",
94 " CNOT(alice, bob);\n",
95 "\n",
96 " // Encode the message into the entangled pair.\n",
97 " CNOT(msg, alice);\n",
98 " H(msg);\n",
99 "\n",
100 " CNOT(alice, bob);\n",
101 " Controlled Z([msg], bob);\n",
102 "}"
103 ]
104 },
105 {
106 "cell_type": "markdown",
107 "id": "d86e19f4",
108 "metadata": {},
109 "source": [
110 "You can verify the circuit for two parallel teleports using the `Circuit` widget."
111 ]
112 },
113 {
114 "cell_type": "code",
115 "execution_count": null,
116 "id": "b815acd4",
117 "metadata": {},
118 "outputs": [],
119 "source": [
120 "Circuit(circuit(code.ParallelTeleport, 2))"
121 ]
122 },
123 {
124 "cell_type": "markdown",
125 "id": "c342d7e9",
126 "metadata": {},
127 "source": [
128 "Now, let's visualize 120 instances of teleportation in parallel on the `NeutralAtomDevice`. This will decompose the program to the device's native gate set and schedule the operations with movement, showing how it might execute on such a device."
129 ]
130 },
131 {
132 "cell_type": "code",
133 "execution_count": null,
134 "id": "e2422917",
135 "metadata": {},
136 "outputs": [],
137 "source": [
138 "# Compile the code into a high-level program\n",
139 "program = compile(code.ParallelTeleport, 120)\n",
140 "\n",
141 "# Visualize a trace of running the program on the target machine,\n",
142 "# decomposing into native gates and scheduling parallel operations\n",
143 "device = NeutralAtomDevice()\n",
144 "device.show_trace(program)"
145 ]
146 },
147 {
148 "cell_type": "markdown",
149 "id": "87b8e819",
150 "metadata": {},
151 "source": [
152 "Because the teleport algorithm uses only gates from the Clifford group, we can efficiently simulate a large number of shots of the same program with the Clifford simulator. We'll use a small helper function to interpret the results, which we expect to be all zeros. Without noise, \"Correct\" should be the only bar in the resulting Histogram."
153 ]
154 },
155 {
156 "cell_type": "code",
157 "execution_count": null,
158 "id": "698849c0",
159 "metadata": {},
160 "outputs": [],
161 "source": [
162 "results = device.simulate(program, shots=1000, type=\"clifford\")\n",
163 "Histogram([\"Loss\" if any(r == Result.Loss for r in shot) else \"Flip\" if any(r == Result.One for r in shot) else \"Correct\" for shot in results])"
164 ]
165 },
166 {
167 "cell_type": "markdown",
168 "id": "ce124bf0",
169 "metadata": {},
170 "source": [
171 "You can also perform this simulation with noise, shown here by configuring a 0.1% chance of loss on the SX gate. Now we'll see a mix of correct and incorrect results in the output of the simulation."
172 ]
173 },
174 {
175 "cell_type": "code",
176 "execution_count": null,
177 "id": "774df3a7",
178 "metadata": {},
179 "outputs": [],
180 "source": [
181 "# Now with noise.\n",
182 "noise = NoiseConfig()\n",
183 "noise.sx.loss = 0.001\n",
184 "results = device.simulate(program, shots=1000, noise=noise, type=\"clifford\")\n",
185 "Histogram([\"Loss\" if any(r == Result.Loss for r in shot) else \"Flip\" if any(r == Result.One for r in shot) else \"Correct\" for shot in results])"
186 ]
187 }
188 ],
189 "metadata": {
190 "kernelspec": {
191 "display_name": "Python 3",
192 "language": "python",
193 "name": "python3"
194 },
195 "language_info": {
196 "codemirror_mode": {
197 "name": "ipython",
198 "version": 3
199 },
200 "file_extension": ".py",
201 "mimetype": "text/x-python",
202 "name": "python",
203 "nbconvert_exporter": "python",
204 "pygments_lexer": "ipython3",
205 "version": "3.11.14"
206 }
207 },
208 "nbformat": 4,
209 "nbformat_minor": 5
210}
211