|
52 | 52 | "metadata": {}, |
53 | 53 | "outputs": [], |
54 | 54 | "source": [ |
55 | | - "## Classiq imports\n", |
56 | | - "\n", |
57 | 55 | "import matplotlib.pyplot as plt\n", |
58 | 56 | "import numpy as np\n", |
59 | | - "\n", |
60 | | - "## svm imports for train and validate\n", |
61 | 57 | "from sklearn.svm import SVC\n", |
62 | 58 | "\n", |
63 | 59 | "from classiq import *" |
|
199 | 195 | "\n", |
200 | 196 | "A feature map is a way to encode classical data into quantum.\n", |
201 | 197 | "Here, we chose to encode the data onto the surface of the bloch sphere.\n", |
202 | | - "Behind the scenes, this can be translated to:\n", |
| 198 | + "This can be defined as:\n", |
203 | 199 | "```\n", |
204 | 200 | "R_X(x[0] / 2)\n", |
205 | 201 | "R_Z(x[1])\n", |
206 | 202 | "```\n", |
207 | | - "Where `x` is the 2D input vector, and the circuit takes a single qubit per data-point. We define a quantum function that generalizes the Bloch sphere mapping to input vector of any dimension (also known as \"dense angle encoding\" in the field of Quantum Nueral Networks)." |
| 203 | + "Where `x` is the 2D input vector, and the circuit takes a single qubit per data-point. This creates a state which is: $\\cos(x[0]/4)|0\\rangle + e^{x[1]/4}\\sin(x[0]/4)|1\\rangle$ (up to a global phase). We define a quantum function that generalizes the Bloch sphere mapping to input vector of any dimension (also known as \"dense angle encoding\" in the field of Quantum Nueral Networks): each pair of entries in the vector is mapped to a Bloch sphere, in the case of odd size we apply a single RX gate on an extra qubit." |
208 | 204 | ] |
209 | 205 | }, |
210 | 206 | { |
|
218 | 214 | "\n", |
219 | 215 | "\n", |
220 | 216 | "@qfunc\n", |
221 | | - "def my_bloch_feature_map(data: CArray[CReal], qba: QArray[QBit]):\n", |
| 217 | + "def bloch_feature_map(data: CArray[CReal], qba: QArray[QBit]):\n", |
222 | 218 | " repeat(ceiling(data.len / 2), lambda i: RX(data[2 * i] / 2, qba[i]))\n", |
223 | 219 | " repeat(floor(data.len / 2), lambda i: RZ(data[(2 * i) + 1], qba[i]))" |
224 | 220 | ] |
|
256 | 252 | "metadata": {}, |
257 | 253 | "source": [ |
258 | 254 | "### Construct a model\n", |
259 | | - "We can now construct the QSVM model using the `my_bloch_feature_map` function, and its inverse:" |
| 255 | + "We can now construct the QSVM model using the `bloch_feature_map` function, and its inverse:" |
260 | 256 | ] |
261 | 257 | }, |
262 | 258 | { |
|
277 | 273 | "):\n", |
278 | 274 | "\n", |
279 | 275 | " allocate(ceiling(data1.len / 2), qba)\n", |
280 | | - " my_bloch_feature_map(data1, qba)\n", |
281 | | - " invert(lambda: my_bloch_feature_map(data2, qba))\n", |
| 276 | + " bloch_feature_map(data1, qba)\n", |
| 277 | + " invert(lambda: bloch_feature_map(data2, qba))\n", |
282 | 278 | "\n", |
283 | 279 | "\n", |
284 | | - "QSVM_BLOCH_SHPERE = create_model(main, out_file=\"qsvm\")" |
285 | | - ] |
286 | | - }, |
287 | | - { |
288 | | - "cell_type": "code", |
289 | | - "execution_count": 8, |
290 | | - "id": "d9497b62-577d-4d27-bcdb-1be89bad4546", |
291 | | - "metadata": {}, |
292 | | - "outputs": [], |
293 | | - "source": [ |
294 | | - "write_qmod(QSVM_BLOCH_SHPERE, \"qsvm\")" |
| 280 | + "QSVM_BLOCH_SHPERE_qmod = create_model(main, out_file=\"qsvm\")" |
295 | 281 | ] |
296 | 282 | }, |
297 | 283 | { |
|
306 | 292 | }, |
307 | 293 | { |
308 | 294 | "cell_type": "code", |
309 | | - "execution_count": 9, |
| 295 | + "execution_count": 8, |
310 | 296 | "id": "c9cdefbe", |
311 | 297 | "metadata": {}, |
312 | 298 | "outputs": [ |
313 | 299 | { |
314 | 300 | "name": "stdout", |
315 | 301 | "output_type": "stream", |
316 | 302 | "text": [ |
317 | | - "Opening: https://platform.classiq.io/circuit/2rJdx2JxqcGgCHGbmSKSaxKLZg2?version=0.64.0\n" |
| 303 | + "Opening: https://platform.classiq.io/circuit/2rMZUsGqPxLANP3DjFBG3cYMIq7?version=0.65.1\n" |
318 | 304 | ] |
319 | 305 | } |
320 | 306 | ], |
321 | 307 | "source": [ |
322 | | - "qprog = synthesize(QSVM_BLOCH_SHPERE)\n", |
| 308 | + "qprog = synthesize(QSVM_BLOCH_SHPERE_qmod)\n", |
323 | 309 | "show(qprog)" |
324 | 310 | ] |
325 | 311 | }, |
|
338 | 324 | }, |
339 | 325 | { |
340 | 326 | "cell_type": "code", |
341 | | - "execution_count": 10, |
| 327 | + "execution_count": 9, |
342 | 328 | "id": "48f3a4bd", |
343 | 329 | "metadata": {}, |
344 | 330 | "outputs": [], |
345 | 331 | "source": [ |
346 | | - "def set_execution_params(data1, data2=None, train=False):\n", |
| 332 | + "def get_execution_params(data1, data2=None):\n", |
347 | 333 | " \"\"\"\n", |
348 | 334 | " Generate execution parameters based on the mode (train or validate).\n", |
349 | 335 | "\n", |
350 | 336 | " Parameters:\n", |
351 | 337 | " - data1: First dataset (used for both training and validation).\n", |
352 | | - " - data2: Second dataset (only required for validation when train=False).\n", |
353 | | - " - train: Boolean flag. If True, generates symmetric pairs for training.\n", |
| 338 | + " - data2: Second dataset (only required for validation).\n", |
354 | 339 | "\n", |
355 | 340 | " Returns:\n", |
356 | 341 | " - A list of dictionaries with execution parameters.\n", |
357 | 342 | " \"\"\"\n", |
358 | | - " if train:\n", |
359 | | - " # Training mode (symmetric pairs, data2 is ignored)\n", |
| 343 | + " if data2 is None:\n", |
| 344 | + " # Training mode (symmetric pairs of data1)\n", |
360 | 345 | " return [\n", |
361 | 346 | " {\"data1\": data1[k], \"data2\": data1[j]}\n", |
362 | 347 | " for k in range(len(data1))\n", |
363 | 348 | " for j in range(k, len(data1)) # Avoid symmetric pairs\n", |
364 | 349 | " ]\n", |
365 | 350 | " else:\n", |
366 | | - " # Validation mode\n", |
367 | | - " assert (\n", |
368 | | - " data2 is not None\n", |
369 | | - " ), \"For validation, data2 must be provided explicitly or set equal to data1.\"\n", |
| 351 | + " # Prediction mode\n", |
370 | 352 | " return [\n", |
371 | 353 | " {\"data1\": data1[k], \"data2\": data2[j]}\n", |
372 | 354 | " for k in range(len(data1))\n", |
|
376 | 358 | "\n", |
377 | 359 | "def construct_kernel_matrix(matrix_size, res_batch, train=False):\n", |
378 | 360 | " \"\"\"\n", |
379 | | - " Construct a kernel matrix from `res_batch`, depending on whether it's for training or validation.\n", |
| 361 | + " Construct a kernel matrix from `res_batch`, depending on whether it's for training or predicting.\n", |
380 | 362 | "\n", |
381 | 363 | " Parameters:\n", |
382 | 364 | " - matrix_size: Tuple of (number of rows, number of columns) for the matrix.\n", |
|
387 | 369 | " - A kernel matrix as a NumPy array.\n", |
388 | 370 | " \"\"\"\n", |
389 | 371 | " rows, cols = matrix_size\n", |
390 | | - " my_kernel_matrix = np.zeros((rows, cols))\n", |
| 372 | + " kernel_matrix = np.zeros((rows, cols))\n", |
391 | 373 | "\n", |
392 | 374 | " num_shots = res_batch[0].num_shots\n", |
393 | 375 | " num_output_qubits = len(next(iter(res_batch[0].counts)))\n", |
|
400 | 382 | " value = (\n", |
401 | 383 | " res_batch[count].counts.get(\"0\" * num_output_qubits, 0) / num_shots\n", |
402 | 384 | " )\n", |
403 | | - " my_kernel_matrix[k, j] = value\n", |
404 | | - " my_kernel_matrix[j, k] = value # Use symmetry\n", |
| 385 | + " kernel_matrix[k, j] = value\n", |
| 386 | + " kernel_matrix[j, k] = value # Use symmetry\n", |
405 | 387 | " count += 1\n", |
406 | 388 | " else:\n", |
407 | 389 | " # Non-symmetric matrix (validation)\n", |
408 | 390 | " for k in range(rows):\n", |
409 | 391 | " for j in range(cols):\n", |
410 | | - " my_kernel_matrix[k, j] = (\n", |
| 392 | + " kernel_matrix[k, j] = (\n", |
411 | 393 | " res_batch[count].counts.get(\"0\" * num_output_qubits, 0) / num_shots\n", |
412 | 394 | " )\n", |
413 | 395 | " count += 1\n", |
414 | 396 | "\n", |
415 | | - " return my_kernel_matrix\n", |
| 397 | + " return kernel_matrix\n", |
416 | 398 | "\n", |
417 | 399 | "\n", |
418 | 400 | "def train_svm(es, train_data, train_labels):\n", |
|
422 | 404 | " Parameters:\n", |
423 | 405 | " - es: ExecutionSession object to process batch execution for kernel computation.\n", |
424 | 406 | " - train_data: List of data points for training.\n", |
425 | | - " - train_labels: List of labels corresponding to the training data.\n", |
| 407 | + " - train_labels: List of binary labels corresponding to the training data.\n", |
426 | 408 | "\n", |
427 | 409 | " Returns:\n", |
428 | 410 | " - svm_model: A trained SVM model using the precomputed kernel.\n", |
429 | 411 | " \"\"\"\n", |
430 | 412 | " train_size = len(train_data)\n", |
431 | | - " train_execution_params = set_execution_params(train_data, train=True)\n", |
| 413 | + " train_execution_params = get_execution_params(train_data)\n", |
432 | 414 | " res_train_batch = es.batch_sample(train_execution_params) # execute batch\n", |
433 | 415 | " # generate kernel matrix for train\n", |
434 | 416 | " kernel_train = construct_kernel_matrix(\n", |
|
457 | 439 | " \"\"\"\n", |
458 | 440 | " predict_size = len(data)\n", |
459 | 441 | " train_size = len(train_data)\n", |
460 | | - " predict_execution_params = set_execution_params(data, train_data, train=False)\n", |
| 442 | + " predict_execution_params = get_execution_params(data, train_data)\n", |
461 | 443 | " res_predict_batch = es.batch_sample(predict_execution_params) # execute batch\n", |
462 | 444 | " kernel_predict = construct_kernel_matrix(\n", |
463 | 445 | " matrix_size=(predict_size, train_size), res_batch=res_predict_batch, train=False\n", |
|
479 | 461 | }, |
480 | 462 | { |
481 | 463 | "cell_type": "code", |
482 | | - "execution_count": 11, |
| 464 | + "execution_count": 10, |
483 | 465 | "id": "2a05189f-5875-45f2-9aef-63e2e65a621c", |
484 | 466 | "metadata": {}, |
485 | 467 | "outputs": [], |
|
510 | 492 | }, |
511 | 493 | { |
512 | 494 | "cell_type": "code", |
513 | | - "execution_count": 12, |
| 495 | + "execution_count": 11, |
514 | 496 | "id": "6d4b68fc", |
515 | 497 | "metadata": {}, |
516 | 498 | "outputs": [ |
|
536 | 518 | }, |
537 | 519 | { |
538 | 520 | "cell_type": "code", |
539 | | - "execution_count": 13, |
| 521 | + "execution_count": 12, |
540 | 522 | "id": "a0c29c77-fa68-4d74-87ae-10a40af9af31", |
541 | 523 | "metadata": {}, |
542 | 524 | "outputs": [ |
|
566 | 548 | }, |
567 | 549 | { |
568 | 550 | "cell_type": "code", |
569 | | - "execution_count": 14, |
| 551 | + "execution_count": 13, |
570 | 552 | "id": "00db178e-4d49-4e55-8144-ba424b3fe833", |
571 | 553 | "metadata": {}, |
572 | 554 | "outputs": [ |
|
0 commit comments