|
107 | 107 | "\n",
|
108 | 108 | "Basis encoding encodes a classical $P$-bit string into a computational basis state of a $P$-qubit system. Take for example $\\vec{x}^{(1)}_3 = 5 = 0(2^3)+1(2^2)+0(2^1)+1(2^0).$ This can be represented as a $4$-bit string as $(0101)$, and by a $4$-qubit system as the quantum state $|0101\\rangle$. More generally, for a $P$-bit string: $\\vec{x}^{(j)}_k = (b_1, b_2, ... , b_P)$, the corresponding $P$-qubit state is $|x^{(j)}_k\\rangle = | b_1, b_2, ... , b_P \\rangle$ with $b_n \\in \\{0,1\\}$ for $n = 1 , \\dots , P$. Note that this is just for a single feature.\n",
|
109 | 109 | "\n",
|
110 |
| - "If each feature of this data vector is mapped to a quantum state $|x^{(j)}_k\\rangle$, then we can describe a data vector from our set as a superposition of all the computational basis states describing the features of that vector:\n", |
| 110 | + "Basis encoding in quantum computing represents each classical bit as a separate qubit, mapping the binary representation of data directly onto quantum states in the computational basis. When multiple features need to be encoded, each feature is first converted to its binary form and then assigned to a distinct group of qubits — one group per feature — where each qubit reflects a bit in the binary representation of that feature.\n", |
111 | 111 | "\n",
|
112 |
| - "$$\n", |
113 |
| - "|x^{(j)} \\rangle = \\frac{1}{\\sqrt{N}}\\sum_{k=1}^{N}|x^{(j)}_k \\rangle\n", |
114 |
| - "$$\n", |
| 112 | + "As an example, let us encode the vector (5, 7, 0).\n", |
| 113 | + "\n", |
| 114 | + "Suppose all features are stored in four bits (more than we need, but enough to represent any integer that is single-digit in base 10):\n", |
115 | 115 | "\n",
|
116 |
| - "In Qiskit, once we calculate what state will encode our data point, we can use the `initialize` function to prepare it. Consider the 4th data vector in our dataset $\\vec{x}^{(4)} = (5,7,0)$. We have $x^{(4)}_1=101, x^{(4)}_2=111$, and $x^{(4)}_3 = 000$. This is encoded as the state $|x^{(4)}\\rangle= \\frac{1}{\\sqrt{3}}(|101\\rangle+|111\\rangle+|000\\rangle)$.\n", |
| 116 | + " 5 → binary 0101\n", |
117 | 117 | "\n",
|
118 |
| - "We can generate a circuit that will prepare this state using `initialize`. For this specific case, we will use three qubits. The space of all $2^3$ measurable states of these three qubits is spanned by\n", |
| 118 | + " 7 → binary 0111\n", |
119 | 119 | "\n",
|
| 120 | + " 0 → binary 0000\n", |
| 121 | + "\n", |
| 122 | + "These bit strings are assigned to three sets of four qubits, so the overall 12-qubit basis state is:\n", |
120 | 123 | "$$\n",
|
121 |
| - "\\vert 000\\rangle, \\vert 001\\rangle, \\vert 010\\rangle, \\vert 011\\rangle, \\vert 100\\rangle, \\vert 101\\rangle, \\vert 110\\rangle, \\vert 111\\rangle\n", |
| 124 | + "∣0101 0111 0000⟩\n", |
122 | 125 | "$$\n",
|
123 | 126 | "\n",
|
124 |
| - "When specifying the desired state of our 3-qubit system, we specify the amplitude of each of these $2^3$ basis states, in this order. Thus, our desired state will have $1 /\\sqrt{3}$ in the $1^\\text{st}$, $6^\\text{th}$, and $8^\\text{th}$ entries, and zeros everywhere else." |
| 127 | + "Here, the first four qubits represent the first feature, the next four qubits the second feature, and the last four qubits the third feature. The code below converts the data vector (5,7,0) to a quantum state, and is generalized to do so for other single-digit features." |
125 | 128 | ]
|
126 | 129 | },
|
127 | 130 | {
|
128 | 131 | "cell_type": "code",
|
129 |
| - "execution_count": 31, |
| 132 | + "execution_count": 1, |
130 | 133 | "id": "85ee995f-1e50-4860-a24c-16bbc8b5c8b0",
|
131 | 134 | "metadata": {},
|
132 | 135 | "outputs": [
|
|
136 | 139 | "<Image src=\"/learning/images/courses/quantum-machine-learning/data-encoding/extracted-outputs/85ee995f-1e50-4860-a24c-16bbc8b5c8b0-0.avif\" alt=\"Output of the previous code cell\" />"
|
137 | 140 | ]
|
138 | 141 | },
|
139 |
| - "execution_count": 31, |
| 142 | + "execution_count": 1, |
140 | 143 | "metadata": {},
|
141 | 144 | "output_type": "execute_result"
|
142 | 145 | }
|
143 | 146 | ],
|
144 | 147 | "source": [
|
145 |
| - "import math\n", |
146 |
| - "import numpy as np\n", |
147 | 148 | "from qiskit import QuantumCircuit\n",
|
148 | 149 | "\n",
|
149 |
| - "desired_state = [1 / math.sqrt(3), 0, 0, 0, 0, 1 / math.sqrt(3), 0, 1 / math.sqrt(3)]\n", |
| 150 | + "# Data point to encode\n", |
| 151 | + "x = 5 # binary: 0101\n", |
| 152 | + "y = 7 # binary: 0111\n", |
| 153 | + "z = 0 # binary: 0000\n", |
150 | 154 | "\n",
|
151 |
| - "qc = QuantumCircuit(3)\n", |
152 |
| - "qc.initialize(desired_state, [0, 1, 2])\n", |
153 |
| - "qc.decompose(reps=8).draw(output=\"mpl\")" |
154 |
| - ] |
155 |
| - }, |
156 |
| - { |
157 |
| - "cell_type": "markdown", |
158 |
| - "id": "b96f0bfc-a892-4f68-84a6-1859381f099d", |
159 |
| - "metadata": {}, |
160 |
| - "source": [ |
161 |
| - "This example illustrates a couple of disadvantages of basis encoding. While it is simple to understand, the state vectors can become quite sparse, and schemes to implement it are usually not efficient." |
| 155 | + "# Convert each to 4-bit binary list\n", |
| 156 | + "x_bits = [int(b) for b in format(x, \"04b\")] # [0,1,0,1]\n", |
| 157 | + "y_bits = [int(b) for b in format(y, \"04b\")] # [0,1,1,1]\n", |
| 158 | + "z_bits = [int(b) for b in format(z, \"04b\")] # [0,0,0,0]\n", |
| 159 | + "\n", |
| 160 | + "# Combine all bits\n", |
| 161 | + "all_bits = x_bits + y_bits + z_bits # [0,1,0,1,0,1,1,1,0,0,0,0]\n", |
| 162 | + "\n", |
| 163 | + "# Initialize a 12-qubit quantum circuit\n", |
| 164 | + "qc = QuantumCircuit(12)\n", |
| 165 | + "\n", |
| 166 | + "# Apply x-gates where the bit is 1\n", |
| 167 | + "for idx, bit in enumerate(all_bits):\n", |
| 168 | + " if bit == 1:\n", |
| 169 | + " qc.x(idx)\n", |
| 170 | + "\n", |
| 171 | + "qc.draw(\"mpl\")" |
162 | 172 | ]
|
163 | 173 | },
|
164 | 174 | {
|
|
187 | 197 | "import math\n",
|
188 | 198 | "from qiskit import QuantumCircuit\n",
|
189 | 199 | "\n",
|
190 |
| - "desired_state = [\n", |
191 |
| - " 0,\n", |
192 |
| - " 0,\n", |
193 |
| - " 0,\n", |
194 |
| - " 0,\n", |
195 |
| - " 1 / math.sqrt(3),\n", |
196 |
| - " 1 / math.sqrt(3),\n", |
197 |
| - " 0,\n", |
198 |
| - " 0,\n", |
199 |
| - " 1 / math.sqrt(3),\n", |
200 |
| - " 0,\n", |
201 |
| - " 0,\n", |
202 |
| - " 0,\n", |
203 |
| - " 0,\n", |
204 |
| - " 0,\n", |
205 |
| - " 0,\n", |
206 |
| - " 0,\n", |
207 |
| - "]\n", |
| 200 | + "# Data point to encode\n", |
| 201 | + "x = 4 # binary: 0100\n", |
| 202 | + "y = 8 # binary: 1000\n", |
| 203 | + "z = 5 # binary: 0101\n", |
208 | 204 | "\n",
|
209 |
| - "print(desired_state)\n", |
| 205 | + "# Convert each to 4-bit binary list\n", |
| 206 | + "x_bits = [int(b) for b in format(x, '04b')] # [0,1,0,0]\n", |
| 207 | + "y_bits = [int(b) for b in format(y, '04b')] # [1,0,0,0]\n", |
| 208 | + "z_bits = [int(b) for b in format(z, '04b')] # [0,1,0,1]\n", |
210 | 209 | "\n",
|
211 |
| - "qc = QuantumCircuit(4)\n", |
212 |
| - "qc.initialize(desired_state, [0, 1, 2, 3])\n", |
213 |
| - "qc.decompose(reps=7).draw(output=\"mpl\")\n", |
214 |
| - "```\n", |
| 210 | + "# Combine all bits\n", |
| 211 | + "all_bits = x_bits + y_bits + z_bits # [0,1,0,0,1,0,0,0,0,1,0,1]\n", |
215 | 212 | "\n",
|
216 |
| - "[0, 0, 0, 0, 0.5773502691896258, 0.5773502691896258, 0, 0, 0.5773502691896258, 0, 0, 0, 0, 0, 0, 0]\n", |
| 213 | + "# Initialize a 12-qubit quantum circuit\n", |
| 214 | + "qc = QuantumCircuit(12)\n", |
217 | 215 | "\n",
|
218 |
| - "\n", |
| 216 | + "# Apply x-gates where the bit is 1\n", |
| 217 | + "for idx, bit in enumerate(all_bits):\n", |
| 218 | + " if bit == 1:\n", |
| 219 | + " qc.x(idx)\n", |
| 220 | + "\n", |
| 221 | + "qc.draw('mpl')\n", |
| 222 | + "```\n", |
219 | 223 | "\n",
|
220 | 224 | "</details>"
|
221 | 225 | ]
|
|
269 | 273 | },
|
270 | 274 | {
|
271 | 275 | "cell_type": "code",
|
272 |
| - "execution_count": 33, |
| 276 | + "execution_count": null, |
273 | 277 | "id": "19810c6d-8d60-49ee-bd6f-6f6fbd5e7363",
|
274 | 278 | "metadata": {},
|
275 | 279 | "outputs": [
|
|
285 | 289 | }
|
286 | 290 | ],
|
287 | 291 | "source": [
|
| 292 | + "import math\n", |
| 293 | + "\n", |
288 | 294 | "desired_state = [\n",
|
289 | 295 | " 1 / math.sqrt(105) * 4,\n",
|
290 | 296 | " 1 / math.sqrt(105) * 8,\n",
|
|
521 | 527 | },
|
522 | 528 | {
|
523 | 529 | "cell_type": "code",
|
524 |
| - "execution_count": 39, |
| 530 | + "execution_count": null, |
525 | 531 | "id": "666700f7-7798-43ce-a8ca-d91e48adda4f",
|
526 | 532 | "metadata": {},
|
527 | 533 | "outputs": [
|
|
536 | 542 | }
|
537 | 543 | ],
|
538 | 544 | "source": [
|
| 545 | + "import numpy as np\n", |
539 | 546 | "from qiskit.visualization.bloch import Bloch\n",
|
540 | 547 | "from qiskit.visualization.state_visualization import _bloch_multivector_data\n",
|
541 | 548 | "\n",
|
|
0 commit comments