Skip to content

Commit f7284c5

Browse files
authored
[DOC] Organizing the tutorial, splitting it across low-level and high-level (#39)
1 parent 9455daa commit f7284c5

6 files changed

Lines changed: 525 additions & 42 deletions

.github/workflows/test.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
if-no-files-found: ignore
4444

4545
test_notebook:
46-
name: Run the Jupyter notebook tutorial (ubuntu)
46+
name: Run the Jupyter notebook tutorials (ubuntu)
4747
runs-on: ubuntu-latest
4848
strategy:
4949
matrix:
@@ -64,8 +64,9 @@ jobs:
6464
- name: Run notebook
6565
run: |
6666
hatch run pip install jupyter
67-
hatch run jupyter execute examples/tutorial.ipynb
68-
hatch run jupyter execute examples/ml_tutorial.ipynb
67+
for tutorial in examples/tutorial*.ipynb; do
68+
hatch run jupyter execute "$tutorial";
69+
done
6970
7071
publish:
7172
name: Publish to PyPI

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ $ pipx install quantum-evolution-kernel
4444

4545
## Usage
4646

47-
For the time being, the easiest way to learn how to use this package is to look
48-
at the [example notebook](examples/tutorial.ipynb).
47+
We have a two parts tutorial:
48+
49+
1. [Using a Quantum Device to extract machine-learning features](examples/tutorial%201%20-%20Using%20a%20Quantum%20Device%20to%20Extract%20Machine-Learning%20Features.ipynb);
50+
2. [Machine Learning with the Quantum Evolution Kernel](examples/tutorial%202%20-%20Machine-Learning%20with%20the%20Quantum%20EvolutionKernel.ipynb)
4951

5052
See also the [full API documentation](https://pqs.pages.pasqal.com/quantum-evolution-kernel/).
5153

examples/tutorial.ipynb renamed to examples/tutorial 1 - Using a Quantum Device to Extract Machine-Learning Features.ipynb

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,19 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# QEK from A to Z\n",
7+
"# Tutorial 1: using a Quantum Device to extract machine-learning features\n",
88
"\n",
9-
"This notebook reproduces the results of the [QEK paper](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.107.042615).\n",
9+
"This notebook reproduces the first part of the [QEK paper](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.107.042615) using the library's high-level API, dedicated to features extraction using a Quantum Device.\n",
1010
"\n",
11-
"At the end, you will be able to:\n",
12-
"1. Extract the embeddings of a molecular dataset\n",
13-
"2. Compile these embeddings into Pulse sequences for use on a Quantum Device or an amulator.\n",
14-
"3. Run the Pulse sequences on a Quantum Device or an emulator.\n",
11+
"By the end of this notebook, you will know how to:\n",
1512
"\n",
13+
"1. Setup import for a molecular dataset (the library supports other type of graphs, of course).\n",
14+
"2. Setup compilation and execution of these graphs for execution on a Quantum Device (either an emulator or a physical QPU).\n",
15+
"3. Launch the execution and extract the relevant machine-learning features.\n",
1616
"\n",
17-
"We also provide a another [machine learning tutorial](ml_tutorial.ipynb) to train an SVM with the QEK (Quantum Evolution Kernel) kernel and benchmark the performance reported in the paper."
18-
]
19-
},
20-
{
21-
"cell_type": "code",
22-
"execution_count": null,
23-
"metadata": {},
24-
"outputs": [],
25-
"source": [
17+
"A [companion notebook](./tutorial%202%20-%20Machine-Learning%20with%20the%20Quantum%20EvolutionKernel.ipynb) will guide you through machine-learning with QEK.\n",
2618
"\n",
27-
"import torch_geometric.datasets as pyg_dataset"
19+
"If, instead of using the library's high-level API, you prefer digging a bit closer to the qubits, you may prefer the companion [low-level notebook](./tutorial%201a%20-%20Using%20a%20Quantum%20Device%20to%20Extract%20Machine-Learning%20Features%20-%20low-level.ipynb) that mirrors this notebook, but using a lower-level API that will let you experiment with different quantum pulses."
2820
]
2921
},
3022
{
@@ -42,8 +34,10 @@
4234
"metadata": {},
4335
"outputs": [],
4436
"source": [
37+
"import torch_geometric.datasets as pyg_dataset\n",
38+
"\n",
4539
"# Load the original PTC-FM dataset\n",
46-
"og_ptcfm = [data for data in pyg_dataset.TUDataset(root=\"dataset\", name=\"PTC_FM\")]\n",
40+
"og_ptcfm = pyg_dataset.TUDataset(root=\"dataset\", name=\"PTC_FM\")\n",
4741
"\n",
4842
"display(\"Loaded %s samples\" % (len(og_ptcfm), ))"
4943
]
@@ -54,7 +48,7 @@
5448
"source": [
5549
"To extract machine-learning features from our dataset, we will need to configure a feature extractor. This library provides several feature extractors to either make use of a physical quantum device (QPU), or a variety of emulators.\n",
5650
"\n",
57-
"To configure a feature extractor, we will need to give it a _compiler_, whose task is to take a list of graphs, extract embeddings and compile these embeddings to _sequences of pulses_, the format that can be executed by either a QPU or an emulator. For this tutorial, our dataset is composed of molecule graphs encoded with the PTC-FM conventions, so we will use the `PTCFMGraphCompiler`:"
51+
"To configure a feature extractor, we will need to provide a _compiler_, whose task is to take a list of graphs, extract embeddings and compile these embeddings to _sequences of pulses_, the format that can be executed by either a QPU or an emulator. For this tutorial, our dataset is composed of molecule graphs following the PTCFM conventions, so we will use the `PTCFMCompiler`:"
5852
]
5953
},
6054
{
@@ -72,7 +66,7 @@
7266
"cell_type": "markdown",
7367
"metadata": {},
7468
"source": [
75-
"This library provides other compilers from other formats of graphs, including the `MoleculeGraphCompiler` and general-purpose graph compilers for pytorch_geometric or networkx graphs."
69+
"This library also provides other compilers from a variety of graph formats."
7670
]
7771
},
7872
{
@@ -111,7 +105,7 @@
111105
"cell_type": "markdown",
112106
"metadata": {},
113107
"source": [
114-
"As you can see, the number of sequences compiled is lower than the number of samples loaded. Some of this is due to limitations within the algorithm (not all graphs can be efficiently laid out for execution on a Quantum Device), while others are due to the limitations of the emulator we target (which at the time of this writing is limited to 50 qubits).\n",
108+
"As you can see, the number of sequences compiled is lower than the number of samples loaded. Some of this is due to limitations within the algorithm (not all graphs can be efficiently laid out for execution on a Quantum Device), while others are due to the limitations of the emulator we target (which at the time of this writing is limited to ~50 qubits).\n",
115109
"\n",
116110
"We may now run the extraction on the emulator:"
117111
]
@@ -125,6 +119,8 @@
125119
"# Limit the number of qubits for this run, for performance reasons.\n",
126120
"# You can increase this value to higher number of qubits, but this\n",
127121
"# notebook will take longer to execute and may run out of memory.\n",
122+
"#\n",
123+
"# On our test computer, the practical limit is around 10 qubits.\n",
128124
"max_qubits = 5\n",
129125
"processed_dataset = extractor.run(max_qubits=max_qubits)\n",
130126
"display(\"Extracted features from %s samples\"% (len(processed_dataset.states), ))"
@@ -134,7 +130,7 @@
134130
"cell_type": "markdown",
135131
"metadata": {},
136132
"source": [
137-
"If you wish to extract features from more samples, feel free to increase the value of `max_qubits` above. However, you will soon run into limitations of a quantum emulator, and possibly crash this notebook. At this point, you have other options, such as using `EmuMPSExtractor` instead of `QutipExtractor`, a more recent emulator that features much better performance in most cases, or you can run the extraction on a physical QPU."
133+
"If you wish to extract features from more samples, feel free to increase the value of `MAX_QUBITS` above. However, you will soon run into limitations of a quantum emulator, and possibly crash this notebook. At this point, you have other options, such as using `EmuMPSExtractor` instead of `QutipExtractor`, a more recent emulator that features much better performance in most cases, or you can run the extraction on a physical QPU."
138134
]
139135
},
140136
{
@@ -178,11 +174,11 @@
178174
"\n",
179175
" # Launch the execution.\n",
180176
" processed_dataset = extractor.run()\n",
181-
" display(\"Work enqueued with ids %s\" % (processed_dataset.batch_ids, ))\n",
177+
" display(\"Work enqueued with ids %s\" % (extractor.batch_ids, ))\n",
182178
"\n",
183179
" # ...and wait for the results.\n",
184180
" await processed_dataset\n",
185-
" display(\"Extracted states from %s samples\"% (len(processed_dataset.states), ))"
181+
" display(\"Extracted features from %s samples\"% (len(processed_dataset.states), ))"
186182
]
187183
},
188184
{
@@ -219,8 +215,7 @@
219215
"outputs": [],
220216
"source": [
221217
"import qek.data.dataset as qek_dataset\n",
222-
"from qek.data.dataset import ProcessedData\n",
223-
"processed_dataset: list[ProcessedData] = qek_dataset.load_dataset(file_path=\"ptcfm_processed_dataset.json\")\n",
218+
"processed_dataset = qek_dataset.load_dataset(file_path=\"ptcfm_processed_dataset.json\")\n",
224219
"print(f\"Size of the quantum compatible dataset = {len(processed_dataset)}\")"
225220
]
226221
},
@@ -283,7 +278,38 @@
283278
"- each of the keys represents one possible state for the register (which represents the graph), with each qubit (which represents a single node) being in state `0` or `1`;\n",
284279
"- the corresponding value is the number of samples observed with this specific state of the register.\n",
285280
"\n",
286-
"In this example, for instance, we can see that the state observed most frequently is `10000001010`, with 43/1000 samples.\n"
281+
"In this example, for instance, we can see that the state observed most frequently is `10000001010`, with 43/1000 samples.\n",
282+
"\n",
283+
"Note: Since Quantum Devices are inherently non-deterministic, you will probably obtained different samples if you run this on a Quantum Device instead of loading the dataset.\n"
284+
]
285+
},
286+
{
287+
"cell_type": "markdown",
288+
"metadata": {},
289+
"source": [
290+
"## Machine learning-features\n",
291+
"\n",
292+
"From the state dictionary, we derive as machine-learning feature the _distribution of excitation_. We'll use this in a second to define our kernel."
293+
]
294+
},
295+
{
296+
"cell_type": "code",
297+
"execution_count": null,
298+
"metadata": {},
299+
"outputs": [],
300+
"source": [
301+
"dataset_example.draw_excitation()"
302+
]
303+
},
304+
{
305+
"cell_type": "markdown",
306+
"metadata": {},
307+
"source": [
308+
"# What now?\n",
309+
"\n",
310+
"What we have seen so far covers the use of a Quantum Device to extract machine-learning features.\n",
311+
"\n",
312+
"For the next step, we'll see [how to use these features for machine learning](./tutorial%202%20-%20Machine-Learning%20with%20the%20Quantum%20EvolutionKernel.ipynb)."
287313
]
288314
}
289315
],
@@ -303,7 +329,7 @@
303329
"name": "python",
304330
"nbconvert_exporter": "python",
305331
"pygments_lexer": "ipython3",
306-
"version": "3.10.15"
332+
"version": "3.12.3"
307333
}
308334
},
309335
"nbformat": 4,

0 commit comments

Comments
 (0)