|
a |
|
b/Code/All Qiskit, PennyLane QML Nov 23/14a Time Series RY 70% RM1 kkawchak.ipynb |
|
|
1 |
{ |
|
|
2 |
"cells": [ |
|
|
3 |
{ |
|
|
4 |
"cell_type": "code", |
|
|
5 |
"execution_count": 3, |
|
|
6 |
"metadata": { |
|
|
7 |
"id": "0GKevPuPa5L_" |
|
|
8 |
}, |
|
|
9 |
"outputs": [], |
|
|
10 |
"source": [ |
|
|
11 |
"# This cell is added by sphinx-gallery\n", |
|
|
12 |
"# It can be customized to whatever you like\n", |
|
|
13 |
"%matplotlib inline\n", |
|
|
14 |
"# !pip install pennylane\n", |
|
|
15 |
"# !pip install covalent" |
|
|
16 |
] |
|
|
17 |
}, |
|
|
18 |
{ |
|
|
19 |
"cell_type": "markdown", |
|
|
20 |
"metadata": { |
|
|
21 |
"id": "2OVQzmEGa5MA" |
|
|
22 |
}, |
|
|
23 |
"source": [ |
|
|
24 |
"Quantum detection of time series anomalies\n", |
|
|
25 |
"==========================================\n", |
|
|
26 |
"\n", |
|
|
27 |
"::: {.meta}\n", |
|
|
28 |
":property=\\\"og:description\\\": Learn how to quantumly detect anomalous\n", |
|
|
29 |
"behaviour in time series data with the help of Covalent.\n", |
|
|
30 |
":property=\\\"og:image\\\":\n", |
|
|
31 |
"<https://pennylane.ai/qml/_images/thumbnail_tutorial_univariate_qvr.jpg>\n", |
|
|
32 |
":::\n", |
|
|
33 |
"\n", |
|
|
34 |
"::: {.related}\n", |
|
|
35 |
"tutorial\\_qaoa\\_intro Intro to QAOA\n", |
|
|
36 |
":::\n", |
|
|
37 |
"\n", |
|
|
38 |
"*Authors: Jack Stephen Baker, Santosh Kumar Radha --- Posted: 7 February\n", |
|
|
39 |
"2023.*\n", |
|
|
40 |
"\n", |
|
|
41 |
"Systems producing observable characteristics which evolve with time are\n", |
|
|
42 |
"almost everywhere we look. The temperature changes as day turns to\n", |
|
|
43 |
"night, stock markets fluctuate and the bacteria colony living in the\n", |
|
|
44 |
"coffee cup to your right, which you *promised* you would clean\n", |
|
|
45 |
"yesterday, is slowly growing (seriously, clean it). In many situations,\n", |
|
|
46 |
"it is important to know when these systems start behaving abnormally.\n", |
|
|
47 |
"For example, if the pressure inside a nuclear fission reactor starts\n", |
|
|
48 |
"violently fluctuating, you may wish to be alerted of that. The task of\n", |
|
|
49 |
"identifying such temporally abnormal behaviour is known as time series\n", |
|
|
50 |
"anomaly detection and is well known in machine learning circles.\n", |
|
|
51 |
"\n", |
|
|
52 |
"In this tutorial, we take a stab at time series anomaly detection using\n", |
|
|
53 |
"the *Quantum Variational Rewinding* algorithm, or QVR, proposed by\n", |
|
|
54 |
"[Baker, Horowitz, Radha et. al (2022)](https://arxiv.org/abs/2210.16438)\n", |
|
|
55 |
"--- a quantum machine learning algorithm for gate model quantum\n", |
|
|
56 |
"computers. QVR leverages the power of unitary time evolution/devolution\n", |
|
|
57 |
"operators to learn a model of *normal* behaviour for time series data.\n", |
|
|
58 |
"Given a new (i.e., unseen in training) time series, the normal model\n", |
|
|
59 |
"produces a value that, beyond a threshold, defines anomalous behaviour.\n", |
|
|
60 |
"In this tutorial, we'll be showing you how all of this works, combining\n", |
|
|
61 |
"elements from [Covalent](https://www.covalent.xyz/),\n", |
|
|
62 |
"[Pennylane](https://pennylane.ai/) and [PyTorch](https://pytorch.org/).\n", |
|
|
63 |
"\n", |
|
|
64 |
"Before getting into the technical details of the algorithm, let\\'s get a\n", |
|
|
65 |
"high-level overview with the help of the cartoon below.\n" |
|
|
66 |
] |
|
|
67 |
}, |
|
|
68 |
{ |
|
|
69 |
"cell_type": "markdown", |
|
|
70 |
"metadata": { |
|
|
71 |
"id": "fAi-GyNpa5MB" |
|
|
72 |
}, |
|
|
73 |
"source": [ |
|
|
74 |
"{.align-center\n", |
|
|
75 |
"width=\"70.0%\"}\n", |
|
|
76 |
"\n", |
|
|
77 |
"Going left-to-right, a time series is sampled at three points in time,\n", |
|
|
78 |
"corresponding to different stages in the life cycle of a butterfly: a\n", |
|
|
79 |
"catepillar, a chrysalis and a butterfly. This information is then\n", |
|
|
80 |
"encoded into quantum states and passed to a time machine which time\n", |
|
|
81 |
"devolves the states as generated by a learnt Hamiltonian operator (in\n", |
|
|
82 |
"practice, there is a distribution of such operators). After the devolved\n", |
|
|
83 |
"state is measured, the time series is recognized as normal if the\n", |
|
|
84 |
"average measurement is smaller than a given threshold and anomalous if\n", |
|
|
85 |
"the threshold is exceeded. In the first case, the time series is\n", |
|
|
86 |
"considered rewindable, correctly recovering the initial condition for\n", |
|
|
87 |
"the life cycle of a butterfly: eggs on a leaf. In the second case, the\n", |
|
|
88 |
"output is unrecognizable.\n", |
|
|
89 |
"\n", |
|
|
90 |
"This will all make more sense once we delve into the math a little.\n", |
|
|
91 |
"Let\\'s do it!\n" |
|
|
92 |
] |
|
|
93 |
}, |
|
|
94 |
{ |
|
|
95 |
"cell_type": "markdown", |
|
|
96 |
"metadata": { |
|
|
97 |
"id": "q6D1SN3Ga5MB" |
|
|
98 |
}, |
|
|
99 |
"source": [ |
|
|
100 |
"Background\n", |
|
|
101 |
"==========\n", |
|
|
102 |
"\n", |
|
|
103 |
"To begin, let's quickly recount the data that QVR handles: time series.\n", |
|
|
104 |
"A general time series $\\boldsymbol{y}$ can be described as a sequence of\n", |
|
|
105 |
"$p$-many observations of a process/system arranged in chronological\n", |
|
|
106 |
"order, where $p$ is a positive integer:\n", |
|
|
107 |
"\n", |
|
|
108 |
"$$\\boldsymbol{y} := (\\boldsymbol{y}_t: t \\in T), \\quad T := (t_l: l \\in \\mathbb{Z}^{+}_{\\leq p}).$$\n", |
|
|
109 |
"\n", |
|
|
110 |
"In the simple and didactic case treated in this tutorial,\n", |
|
|
111 |
"$\\boldsymbol{y}$ is univariate (i.e, is a one-dimensional time series),\n", |
|
|
112 |
"so bold-face for $\\boldsymbol{y}$ is dropped from this point onwards.\n", |
|
|
113 |
"Also, we take $y_t \\in \\mathbb{R}$ and $t_l \\in \\mathbb{R}_{>0}$.\n", |
|
|
114 |
"\n", |
|
|
115 |
"The goal of QVR and many other (classical) machine learning algorithms\n", |
|
|
116 |
"for time series anomaly detection is to determine a suitable *anomaly\n", |
|
|
117 |
"score* function $a_{X}$, where $X$ is a training dataset of *normal*\n", |
|
|
118 |
"time series instances $x \\in X$ ($x$ is defined analogously to $y$ in\n", |
|
|
119 |
"the above), from which the anomaly score function was learnt. When\n", |
|
|
120 |
"passed a general time series $y$, this function produces a real number:\n", |
|
|
121 |
"$a_X(y) \\in \\mathbb{R}$. The goal is to have $a_X(x) \\approx 0$, for all\n", |
|
|
122 |
"$x \\in X$. Then, for an unseen time series $y$ and a threshold\n", |
|
|
123 |
"$\\zeta \\in \\mathbb{R}$, the series is said to be anomalous should\n", |
|
|
124 |
"$a_X(y) > \\zeta,$ and normal otherwise. We show a strategy for setting\n", |
|
|
125 |
"$\\zeta$ later in this tutorial.\n", |
|
|
126 |
"\n", |
|
|
127 |
"The first step for doing all of this *quantumly* is to generate a\n", |
|
|
128 |
"sequence $\\mathcal{S} := (|x_{t} \\rangle: t \\in T)$ of $n$-qubit quantum\n", |
|
|
129 |
"states corresponding to a classical time series instance in the training\n", |
|
|
130 |
"set. Now, we suppose that each $|x_t \\rangle$ is a quantum state evolved\n", |
|
|
131 |
"to a time $t$, as generated by an *unknown embedding Hamiltonian* $H_E$.\n", |
|
|
132 |
"That is, each element of $\\mathcal{S}$ is defined by\n", |
|
|
133 |
"$|x_t \\rangle = e^{-iH_E(x_t)}|0\\rangle^{\\otimes n} = U(x_t)|0\\rangle^{\\otimes n}$\n", |
|
|
134 |
"for an embedding unitary operator $U(x_t)$ implementing a quantum\n", |
|
|
135 |
"feature map (see the [Pennylane embedding\n", |
|
|
136 |
"templates](https://docs.pennylane.ai/en/stable/introduction/templates.html#embedding-templates)\n", |
|
|
137 |
"for efficient quantum circuits for doing so). Next, we operate on each\n", |
|
|
138 |
"$|x_t\\rangle$ with a parameterized\n", |
|
|
139 |
"$e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}$ operator to prepare\n", |
|
|
140 |
"the states\n", |
|
|
141 |
"\n", |
|
|
142 |
"$$|x_t, \\boldsymbol{\\alpha}, \\boldsymbol{\\gamma}\\rangle := e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}|x_t\\rangle,$$\n", |
|
|
143 |
"\n", |
|
|
144 |
"where we write $e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}$ as\n", |
|
|
145 |
"an eigendecomposition\n", |
|
|
146 |
"\n", |
|
|
147 |
"$$V_t(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma}) := W^{\\dagger}(\\boldsymbol{\\alpha})D(\\boldsymbol{\\gamma}, t)W(\\boldsymbol{\\alpha}) = e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}.$$\n", |
|
|
148 |
"\n", |
|
|
149 |
"Here, the unitary matrix of eigenvectors $W(\\boldsymbol{\\alpha})$ is\n", |
|
|
150 |
"parametrized by $\\boldsymbol{\\alpha}$ and the unitary diagonalization\n", |
|
|
151 |
"$D(\\boldsymbol{\\gamma}, t)$ is parametrized by $\\boldsymbol{\\gamma}.$\n", |
|
|
152 |
"Both can be implemented efficiently using parameterized quantum\n", |
|
|
153 |
"circuits. The above equality with\n", |
|
|
154 |
"$e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}$ is a consequence of\n", |
|
|
155 |
"Stone's theorem for strongly continuous one-parameter unitary groups.\n", |
|
|
156 |
"\n", |
|
|
157 |
"We now ask the question: *What condition is required for*\n", |
|
|
158 |
"$|x_t, \\boldsymbol{\\alpha}, \\boldsymbol{\\gamma} \\rangle = |0 \\rangle^{\\otimes n}$\n", |
|
|
159 |
"*for all time?* To answer this, we impose\n", |
|
|
160 |
"$P(|0\\rangle^{\\otimes n}) = |\\langle 0|^{\\otimes n}|x_t, \\boldsymbol{\\alpha}, \\boldsymbol{\\gamma} \\rangle|^2 = 1.$\n", |
|
|
161 |
"Playing with the algebra a little, we find that the following condition\n", |
|
|
162 |
"must be satisfied for all $t$:\n", |
|
|
163 |
"\n", |
|
|
164 |
"$$\\langle 0|^{\\otimes n}e^{-iH(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t}e^{-iH_E(x_t)}|0\\rangle^{\\otimes n} = 1 \\iff H(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})t = -H_E(x_t).$$\n", |
|
|
165 |
"\n", |
|
|
166 |
"In other words, for the above to be true, the parameterized unitary\n", |
|
|
167 |
"operator $V_t(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma})$ should be able\n", |
|
|
168 |
"to reverse or *rewind* $|x_t\\rangle$ to its initial state\n", |
|
|
169 |
"$|0\\rangle^{\\otimes n}$ before the embedding unitary operator $U(x_t)$\n", |
|
|
170 |
"was applied.\n", |
|
|
171 |
"\n", |
|
|
172 |
"We are nearly there! Because it is reasonable to expect that a single\n", |
|
|
173 |
"Hamiltonian will not be able to successfully rewind every $x \\in X$ (in\n", |
|
|
174 |
"fact, this is impossible to do if each $x$ is unique, which is usually\n", |
|
|
175 |
"true), we consider the average effect of many Hamiltonians generated by\n", |
|
|
176 |
"drawing $\\boldsymbol{\\gamma}$ from a normal distribution\n", |
|
|
177 |
"$\\mathcal{N}(\\mu, \\sigma)$ with mean $\\mu$ and standard deviation\n", |
|
|
178 |
"$\\sigma$:\n", |
|
|
179 |
"\n", |
|
|
180 |
"$$F(\\boldsymbol{\\phi}, x_t) := \\mathop{\\mathbb{E}_{\\boldsymbol{\\gamma} \\sim \\mathcal{N}(\\mu, \\sigma)}}\\left[\\langle 0|^{\\otimes n} |x_t, \\boldsymbol{\\alpha}, \\boldsymbol{\\gamma}\\rangle \\right], \\quad \\boldsymbol{\\phi} = [\\boldsymbol{\\alpha}, \\mu, \\sigma].$$\n", |
|
|
181 |
"\n", |
|
|
182 |
"The goal is for the function $F$ defined above to be as close to $1$ as\n", |
|
|
183 |
"possible, for all $x \\in X$ and $t \\in T.$ With this in mind, we can\n", |
|
|
184 |
"define the loss function to minimize as the mean square error\n", |
|
|
185 |
"regularized by a penalty function $P_{\\tau}(\\sigma)$ with a single\n", |
|
|
186 |
"hyperparameter $\\tau$:\n", |
|
|
187 |
"\n", |
|
|
188 |
"$$\\mathcal{L(\\boldsymbol{\\phi})} = \\frac{1}{2|X||T|}\\sum_{x \\in X} \\sum_{t \\in T}[1 - F(\\boldsymbol{\\phi}, x_t)]^2 + P_{\\tau}(\\sigma).$$\n", |
|
|
189 |
"\n", |
|
|
190 |
"We will show the exact form of $P_{\\tau}(\\sigma)$ later. The general\n", |
|
|
191 |
"purpose of the penalty function is to penalize large values of $\\sigma$\n", |
|
|
192 |
"(justification for this is given in the Supplement of). After\n", |
|
|
193 |
"approximately finding the argument $\\boldsymbol{\\phi}^{\\star}$ that\n", |
|
|
194 |
"minimizes the loss function (found using a classical optimization\n", |
|
|
195 |
"routine), we finally arrive at a definition for our anomaly score\n", |
|
|
196 |
"function $a_X(y)$\n", |
|
|
197 |
"\n", |
|
|
198 |
"$$a_X(y) = \\frac{1}{|T|}\\sum_{t \\in T}[1 - F(\\boldsymbol{\\phi}^{\\star}, y_t)]^2.$$\n", |
|
|
199 |
"\n", |
|
|
200 |
"It may now be apparent that we have implemented a clustering algorithm!\n", |
|
|
201 |
"That is, our model $F$ was trained such that normal time series\n", |
|
|
202 |
"$x \\in X$ produce $F(\\boldsymbol{\\phi}^{\\star}, x_t)$ clustered about a\n", |
|
|
203 |
"center at $1$. Given a new time series $y$, should\n", |
|
|
204 |
"$F(\\boldsymbol{\\phi}^{\\star}, y_t)$ venture far from the normal center\n", |
|
|
205 |
"at $1$, we are observing anomalous behaviour!\n", |
|
|
206 |
"\n", |
|
|
207 |
"Take the time now to have another look at the cartoon at the start of\n", |
|
|
208 |
"this tutorial. Hopefully things should start making sense now.\n", |
|
|
209 |
"\n", |
|
|
210 |
"Now with our algorithm defined, let's stitch this all together: enter\n", |
|
|
211 |
"[Covalent](https://www.covalent.xyz/).\n" |
|
|
212 |
] |
|
|
213 |
}, |
|
|
214 |
{ |
|
|
215 |
"cell_type": "markdown", |
|
|
216 |
"metadata": { |
|
|
217 |
"id": "0Ecv2jQ7a5MB" |
|
|
218 |
}, |
|
|
219 |
"source": [ |
|
|
220 |
"Covalent: heterogeneous workflow orchestration\n", |
|
|
221 |
"==============================================\n", |
|
|
222 |
"\n", |
|
|
223 |
"Presently, many QML algorithms are *heterogeneous* in nature. This means\n", |
|
|
224 |
"that they require computational resources from both classical and\n", |
|
|
225 |
"quantum computing. Covalent is a tool that can be used to manage their\n", |
|
|
226 |
"interaction by sending different tasks to different computational\n", |
|
|
227 |
"resources and stitching them together as a workflow. While you will be\n", |
|
|
228 |
"introduced to other concepts in Covalent throughout this tutorial, we\n", |
|
|
229 |
"define two key components to begin with.\n", |
|
|
230 |
"\n", |
|
|
231 |
"1. **Electrons**. Decorate regular Python functions with `@ct.electron`\n", |
|
|
232 |
" to desginate a *task*. These are the atoms of a computation.\n", |
|
|
233 |
"\n", |
|
|
234 |
"2. **Lattices**. Decorate a regular Python function with `@ct.lattice`\n", |
|
|
235 |
" to designate a *workflow*. These contain electrons stitched together\n", |
|
|
236 |
" to do something useful.\n", |
|
|
237 |
"\n", |
|
|
238 |
" Different electrons can be run remotely on different hardware and\n", |
|
|
239 |
" multiple computational paridigms (classical, quantum, etc.: see the\n", |
|
|
240 |
" [Covalent\n", |
|
|
241 |
" executors](https://covalent.readthedocs.io/en/stable/plugins.html)).\n", |
|
|
242 |
" In this tutorial, however, to keep things simple, tasks are run on a\n", |
|
|
243 |
" local Dask cluster, which provides (among other things)\n", |
|
|
244 |
" auto-parallelization.\n", |
|
|
245 |
"\n", |
|
|
246 |
"{.align-center\n", |
|
|
249 |
"width=\"70.0%\"}\n", |
|
|
250 |
"\n", |
|
|
251 |
"Now is a good time to import Covalent and launch the Covalent server!\n" |
|
|
252 |
] |
|
|
253 |
}, |
|
|
254 |
{ |
|
|
255 |
"cell_type": "code", |
|
|
256 |
"execution_count": 4, |
|
|
257 |
"metadata": { |
|
|
258 |
"id": "HxukqHJ4a5MC" |
|
|
259 |
}, |
|
|
260 |
"outputs": [], |
|
|
261 |
"source": [ |
|
|
262 |
"import covalent as ct\n", |
|
|
263 |
"import os\n", |
|
|
264 |
"import time\n", |
|
|
265 |
"\n", |
|
|
266 |
"# Set up Covalent server\n", |
|
|
267 |
"os.environ[\"COVALENT_SERVER_IFACE_ANY\"] = \"1\"\n", |
|
|
268 |
"os.system(\"covalent start\")\n", |
|
|
269 |
"# If you run into any out-of-memory issues with Dask when running this notebook,\n", |
|
|
270 |
"# Try reducing the number of workers and making a specific memory request. I.e.:\n", |
|
|
271 |
"# os.system(\"covalent start -m \"2GiB\" -n 2\")\n", |
|
|
272 |
"# try covalent –help for more info\n", |
|
|
273 |
"time.sleep(2) # give the Dask cluster some time to launch" |
|
|
274 |
] |
|
|
275 |
}, |
|
|
276 |
{ |
|
|
277 |
"cell_type": "markdown", |
|
|
278 |
"metadata": { |
|
|
279 |
"id": "hWn7V9Cba5MC" |
|
|
280 |
}, |
|
|
281 |
"source": [ |
|
|
282 |
"Generating univariate synthetic time series\n", |
|
|
283 |
"===========================================\n", |
|
|
284 |
"\n", |
|
|
285 |
"In this tutorial, we shall deal with a simple and didactic example.\n", |
|
|
286 |
"Normal time series instances are chosen to be noisy low-amplitude\n", |
|
|
287 |
"signals normally distributed about the origin. In our case,\n", |
|
|
288 |
"$x_t \\sim \\mathcal{N}(0, 0.1)$. Series we deem to be anomalous are the\n", |
|
|
289 |
"same but with randomly inserted spikes with random durations and\n", |
|
|
290 |
"amplitudes.\n", |
|
|
291 |
"\n", |
|
|
292 |
"Let's make a `@ct.electron` to generate each of these synthetic time\n", |
|
|
293 |
"series sets. For this, we\\'ll need to import Torch. We\\'ll also set the\n", |
|
|
294 |
"default tensor type and pick a random seed for the whole tutorial for\n", |
|
|
295 |
"reproducibility.\n" |
|
|
296 |
] |
|
|
297 |
}, |
|
|
298 |
{ |
|
|
299 |
"cell_type": "code", |
|
|
300 |
"execution_count": 5, |
|
|
301 |
"metadata": { |
|
|
302 |
"id": "EMKwGXA8a5MC", |
|
|
303 |
"colab": { |
|
|
304 |
"base_uri": "https://localhost:8080/", |
|
|
305 |
"height": 0 |
|
|
306 |
}, |
|
|
307 |
"outputId": "e24f79a4-d37b-48c1-bdbf-6ee154ec33e8" |
|
|
308 |
}, |
|
|
309 |
"outputs": [ |
|
|
310 |
{ |
|
|
311 |
"output_type": "stream", |
|
|
312 |
"name": "stderr", |
|
|
313 |
"text": [ |
|
|
314 |
"/usr/local/lib/python3.10/dist-packages/torch/__init__.py:614: UserWarning: torch.set_default_tensor_type() is deprecated as of PyTorch 2.1, please use torch.set_default_dtype() and torch.set_default_device() as alternatives. (Triggered internally at ../torch/csrc/tensor/python_tensor.cpp:451.)\n", |
|
|
315 |
" _C._set_default_tensor_type(t)\n" |
|
|
316 |
] |
|
|
317 |
} |
|
|
318 |
], |
|
|
319 |
"source": [ |
|
|
320 |
"import torch\n", |
|
|
321 |
"\n", |
|
|
322 |
"# Seed Torch for reproducibility and set default tensor type\n", |
|
|
323 |
"GLOBAL_SEED = 1989\n", |
|
|
324 |
"torch.manual_seed(GLOBAL_SEED)\n", |
|
|
325 |
"torch.set_default_tensor_type(torch.DoubleTensor)\n", |
|
|
326 |
"\n", |
|
|
327 |
"\n", |
|
|
328 |
"@ct.electron\n", |
|
|
329 |
"def generate_normal_time_series_set(\n", |
|
|
330 |
" p: int, num_series: int, noise_amp: float, t_init: float, t_end: float, seed: int = GLOBAL_SEED\n", |
|
|
331 |
") -> tuple:\n", |
|
|
332 |
" \"\"\"Generate a normal time series data set where each of the p elements\n", |
|
|
333 |
" is drawn from a normal distribution x_t ~ N(0, noise_amp).\n", |
|
|
334 |
" \"\"\"\n", |
|
|
335 |
" torch.manual_seed(seed)\n", |
|
|
336 |
" X = torch.normal(0, noise_amp, (num_series, p))\n", |
|
|
337 |
" T = torch.linspace(t_init, t_end, p)\n", |
|
|
338 |
" return X, T\n", |
|
|
339 |
"\n", |
|
|
340 |
"\n", |
|
|
341 |
"@ct.electron\n", |
|
|
342 |
"def generate_anomalous_time_series_set(\n", |
|
|
343 |
" p: int,\n", |
|
|
344 |
" num_series: int,\n", |
|
|
345 |
" noise_amp: float,\n", |
|
|
346 |
" spike_amp: float,\n", |
|
|
347 |
" max_duration: int,\n", |
|
|
348 |
" t_init: float,\n", |
|
|
349 |
" t_end: float,\n", |
|
|
350 |
" seed: int = GLOBAL_SEED,\n", |
|
|
351 |
") -> tuple:\n", |
|
|
352 |
" \"\"\"Generate an anomalous time series data set where the p elements of each sequence are\n", |
|
|
353 |
" from a normal distribution x_t ~ N(0, noise_amp). Then,\n", |
|
|
354 |
" anomalous spikes of random amplitudes and durations are inserted.\n", |
|
|
355 |
" \"\"\"\n", |
|
|
356 |
" torch.manual_seed(seed)\n", |
|
|
357 |
" Y = torch.normal(0, noise_amp, (num_series, p))\n", |
|
|
358 |
" for y in Y:\n", |
|
|
359 |
" # 5–10 spikes allowed\n", |
|
|
360 |
" spike_num = torch.randint(low=5, high=10, size=())\n", |
|
|
361 |
" durations = torch.randint(low=1, high=max_duration, size=(spike_num,))\n", |
|
|
362 |
" spike_start_idxs = torch.randperm(p - max_duration)[:spike_num]\n", |
|
|
363 |
" for start_idx, duration in zip(spike_start_idxs, durations):\n", |
|
|
364 |
" y[start_idx : start_idx + duration] += torch.normal(0.0, spike_amp, (duration,))\n", |
|
|
365 |
" T = torch.linspace(t_init, t_end, p)\n", |
|
|
366 |
" return Y, T" |
|
|
367 |
] |
|
|
368 |
}, |
|
|
369 |
{ |
|
|
370 |
"cell_type": "markdown", |
|
|
371 |
"metadata": { |
|
|
372 |
"id": "Ag9HApCFa5MC" |
|
|
373 |
}, |
|
|
374 |
"source": [ |
|
|
375 |
"Let\\'s do a quick sanity check and plot a couple of these series.\n", |
|
|
376 |
"Despite the above function\\'s `@ct.electron` decorators, these can still\n", |
|
|
377 |
"be used as normal Python functions without using the Covalent server.\n", |
|
|
378 |
"This is useful for quick checks like this:\n" |
|
|
379 |
] |
|
|
380 |
}, |
|
|
381 |
{ |
|
|
382 |
"cell_type": "code", |
|
|
383 |
"execution_count": 6, |
|
|
384 |
"metadata": { |
|
|
385 |
"colab": { |
|
|
386 |
"base_uri": "https://localhost:8080/", |
|
|
387 |
"height": 449 |
|
|
388 |
}, |
|
|
389 |
"id": "JMcxr3jga5MC", |
|
|
390 |
"outputId": "018c3ace-18d5-4690-b21d-21e939646dd0" |
|
|
391 |
}, |
|
|
392 |
"outputs": [ |
|
|
393 |
{ |
|
|
394 |
"output_type": "display_data", |
|
|
395 |
"data": { |
|
|
396 |
"text/plain": [ |
|
|
397 |
"<Figure size 640x480 with 1 Axes>" |
|
|
398 |
], |
|
|
399 |
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkYAAAGwCAYAAABM/qr1AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACZbElEQVR4nOzdd3iUVfbA8e+09EZIQgIEQif0XgWRXsTeUQSxiw3dVfa3KqzrYsGuqy6KvaNYUJEIUqT33ltoSQjpfTIzvz/emUlC2tRMyfk8D08mU965eZlkztx7zrkqk8lkQgghhBBCoPb0AIQQQgghvIUERkIIIYQQZhIYCSGEEEKYSWAkhBBCCGEmgZEQQgghhJkERkIIIYQQZhIYCSGEEEKYaT09AF9jNBo5e/Ys4eHhqFQqTw9HCCGEEDYwmUzk5+fTvHlz1Ora54UkMLLT2bNnSUxM9PQwhBBCCOGAU6dO0bJly1pvl8DITuHh4YByYiMiIlx2XL1ez7Jlyxg7diw6nc5lx/UXcn7qJuenbnJ+6ibnp3ZyburmS+cnLy+PxMRE6/t4bSQwspNl+SwiIsLlgVFISAgRERFe/+LyBDk/dZPzUzc5P3WT81M7OTd188XzU18ajCRfCyGEEEKYSWAkhBBCCGEmgZEQQgghhJnkGAkhhPBbBoMBvV7v8OP1ej1arZaSkhIMBoMLR+YfvOn86HQ6NBqN08eRwEgIIYTfMZlMpKWlkZOT4/Rx4uPjOXXqlPSuq4G3nZ+oqCji4+OdGosERkIIIfyOJSiKi4sjJCTE4TdKo9FIQUEBYWFhdTYFbKy85fyYTCaKiorIyMgAICEhweFjSWAkhBDCrxgMBmtQ1LRpU6eOZTQaKSsrIygoSAKjGnjT+QkODgYgIyODuLg4h5fV5H9ZCCGEX7HkFIWEhHh4JKKhWf7Pnckrk8BICCGEX/KGnBfRsFzxfy6BkRBCCCGEmQRGQgghhBBmEhgJIYQQwmF//fUXGo3G6dYI3kICIyFcxWQCfbGnRyGE8GHTpk1DpVLx/PPPV7n+hx9+kJypBiKBkRCu8s1UmN8JCs57eiRCCB8WFBTECy+8QHZ2tsuOWVZW5rJj+TsJjIRwleOroTQX0vd4eiRCiEpMJhNFZeUO/ysuMzj8WJPJZPd4R48eTXx8PPPmzav1Pt999x1du3YlMDCQpKQkXn755Sq3JyUl8eyzzzJ16lQiIiK4++67+eijj4iKimLJkiV06tSJkJAQrrvuOoqKivj4449JSkqiSZMmPPTQQ1W29/j000/p168f4eHhxMfHc8stt1gbKfojafAohCvoS6AkR7lcnOXRoQghqirWG+jy9O8eee59/xpHSIB9b7UajYb//Oc/3HLLLTz00EO0bNmyyu1bt27lhhtuYM6cOdx4442sW7eO+++/n6ZNmzJt2jTr/ebPn8/TTz/NM888A8CaNWsoKirijTfe4KuvviI/P59rrrmGq6++mqioKH799VeOHTvGtddey9ChQ7nxxhsBpSfQs88+S6dOncjIyGDWrFlMmzaNX3/91bmT46UkMBLCFQrSKy4XSWAkhHDO1VdfTa9evXjmmWf44IMPqtz2yiuvMGrUKJ566ikAOnbsyL59+3jppZeqBEYjR47kscces36/Zs0a9Ho977zzDu3atQPguuuu49NPPyU9PZ2wsDC6dOnCZZddxp9//mkNjO644w7rMdq2bcsbb7xB//79KSgo8MsmmhIYCeEKBZWmlSUwEsKrBOs07PvXOIceazQayc/LJzwi3KEtL4J1ju/2/sILLzBy5Egef/zxKtfv37+fK6+8ssp1Q4cO5bXXXsNgMFi3wujXr1+1Y4aEhFiDIoBmzZqRlJREWFhYlesqL5Vt3bqVOXPmsHPnTrKzszEajQCkpqbSuXNnh38+byWBkRCuUJBWcVmW0oTwKiqVyu7lLAuj0Uh5gIaQAG2D7wU2fPhwxo0bx+zZs6vMBNkqNDS02nU6na7K9yqVqsbrLMFPYWEh48aNY9y4cXz++efExsaSmprKuHHj/DahWwIjIVyhylLaBc+NQwjhV55//nl69epFp06drNclJyezdu3aKvdbu3YtHTt2dHjj1NocOHCACxcu8Pzzz5OYmAjAli1bXPoc3kaq0oRwhXzJMRJCuF737t2ZMmUKb7zxhvW6xx57jOXLl/Pss89y6NAhPv74Y956661qS26u0KpVKwICAnjzzTc5duwYP/30E88++6zLn8ebSGAkhCvIjJEQwk3+9a9/WZe2APr06cM333zDV199Rbdu3Xj66af517/+5dByW31iY2P56KOP+Pbbb+nSpQvPP/888+fPd/nzeBNZShPCFSoHRpJjJIRw0EcffVTtuqSkJEpLS6tcd+2113LttdfW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ZYunh+U0CYy8wNdff82sWbN45pln2LZtGz179mTcuHFkZGR4emgeV1hYSM+ePXn77bc9PRSvtGrVKh544AE2bNhASkoKer2esWPHUlhY6OmheVzLli15/vnn2bp1K1u2bGHkyJFceeWV7N2719ND8zqbN2/mvffeo0ePHp4eilfp2rUr586ds/7766+/PD0kr5Gdnc3QoUPR6XT89ttv7Nu3j5dffpkmTZp4emhOk3J9LzBw4ED69+/PW2+9BSj7sSUmJvLggw/y5JNPenh03kOlUrF48WKuuuoqTw/Fa50/f564uDhWrVrF8OHDPT0crxMdHc1LL73EjBkzPD0Ur1FQUECfPn3473//y7///W969erFa6+95ulhedycOXP44Ycf2LFjh6eH4pWefPJJ1q5dy5o1azw9FJeTGSMPKysrY+vWrYwePdp6nVqtZvTo0axfv96DIxO+KDc3F1ACAFHBYDDw1VdfUVhYyODBgz09HK/ywAMPMGnSpCp/g4Ti8OHDNG/enLZt2zJlyhRSU1M9PSSv8dNPP9GvXz+uv/564uLi6N27NwsWLPD0sFxCAiMPy8zMxGAw0KxZsyrXN2vWjLS0NA+NSvgio9HII488wtChQ+nWrZunh+MVdu/eTVhYGIGBgdx7770sXryYLl26eHpYXuOrr75i27ZtzJs3z9ND8ToDBw7ko48+YunSpbzzzjscP36cYcOGkZ+f7+mheYVjx47xzjvv0KFDB37//Xfuu+8+HnroIT7++GNPD81pWk8PQAjhGg888AB79uyRPIhKOnXqxI4dO8jNzWXRokXcfvvtrFq1SoIj4NSpUzz88MOkpKQQFBTk6eF4nQkTJlgv9+jRg4EDB9K6dWu++eYbWYpF+SDWr18//vOf/wDQu3dv9uzZw7vvvsvtt9/u4dE5R2aMPCwmJgaNRkN6enqV69PT04mPj/fQqISvmTlzJkuWLOHPP/+kZcuWnh6O1wgICKB9+/b07duXefPm0bNnT15//XVPD8srbN26lYyMDPr06YNWq0Wr1bJq1SreeOMNtFotBoPB00P0KlFRUXTs2JEjR454eiheISEhodoHjOTkZL9YbpTAyMMCAgLo27cvy5cvt15nNBpZvny55EKIeplMJmbOnMnixYtZsWIFbdq08fSQvJrRaKS0tNTTw/AKo0aNYvfu3ezYseP/27tfkNbCOA7jXziXIypjoBxwCOcsiiyOBQ0KpgWrQwxTq8E/rJgEg1mwnSKWdTFp0aimZVEmBpNFnFHfW34IF2+7F38nPB84ZenL0rOzd2dfV71e18rKinq9nqIo8p5YKIPBQA8PD6pUKt5TCmF2dvbbo0Hu7u6UZZnTov+Hr9IKYGdnR+12W/V6XY1GQ4eHh3p/f9fa2pr3NHeDweCPT2j9fl+9Xk9jY2NK09RxWTFsbGyo2+3q9PRUpVLp61xauVzW8PCw8zpfu7u7ajabStNUb29v6na7urq60vn5ufe0QiiVSt/Ooo2Ojmp8fJwzapI6nY4WFxeVZZmen5+1t7enKIq0vLzsPa0Qtre3NTMzo4ODAy0tLen29lZ5nivPc+9p/y6gEI6OjkKapiGO49BoNML19bX3pEK4vLwMkr5d7Xbbe1oh/O29kRSOj4+9p7lbX18PWZaFOI5DkiRhYWEhXFxceM8qtLm5ubC5uek9oxBarVaoVCohjuMwOTkZWq1WuL+/955VKGdnZ6FWq4WhoaEwNTUV8jz3nvRf8BwjAAAAwxkjAAAAQxgBAAAYwggAAMAQRgAAAIYwAgAAMIQRAACAIYwAAAAMYQQAAGAIIwAAAEMYAYCZn5/X1taW9wwAjggjAAAAw3+lAYCk1dVVnZyc/PFav99XtVr1GQTABWEEAJJeX1/VbDZVq9W0v78vSUqSRFEUOS8D8JN+eQ8AgCIol8uK41gjIyOamJjwngPACWeMAAAADGEEAABgCCMAMHEc6+Pjw3sGAEeEEQCYarWqm5sbPT4+6uXlRZ+fn96TAPwwwggATKfTURRFmp6eVpIkenp68p4E4Ifxc30AAADDHSMAAABDGAEAABjCCAAAwBBGAAAAhjACAAAwhBEAAIAhjAAAAAxhBAAAYAgjAAAAQxgBAAAYwggAAMD8BgKNCRAb0OZrAAAAAElFTkSuQmCC\n" |
|
|
400 |
}, |
|
|
401 |
"metadata": {} |
|
|
402 |
} |
|
|
403 |
], |
|
|
404 |
"source": [ |
|
|
405 |
"import matplotlib.pyplot as plt\n", |
|
|
406 |
"\n", |
|
|
407 |
"X_norm, T_norm = generate_normal_time_series_set(25, 25, 0.1, 0.1, 2 * torch.pi)\n", |
|
|
408 |
"Y_anom, T_anom = generate_anomalous_time_series_set(25, 25, 0.1, 0.4, 5, 0, 2 * torch.pi)\n", |
|
|
409 |
"\n", |
|
|
410 |
"plt.figure()\n", |
|
|
411 |
"plt.plot(T_norm, X_norm[0], label=\"Normal\")\n", |
|
|
412 |
"plt.plot(T_anom, Y_anom[1], label=\"Anomalous\")\n", |
|
|
413 |
"plt.ylabel(\"$y(t)$\")\n", |
|
|
414 |
"plt.xlabel(\"t\")\n", |
|
|
415 |
"plt.grid()\n", |
|
|
416 |
"leg = plt.legend()" |
|
|
417 |
] |
|
|
418 |
}, |
|
|
419 |
{ |
|
|
420 |
"cell_type": "markdown", |
|
|
421 |
"metadata": { |
|
|
422 |
"id": "y_u4k0J1a5MC" |
|
|
423 |
}, |
|
|
424 |
"source": [ |
|
|
425 |
"Taking a look at the above, the generated series are what we wanted. We\n", |
|
|
426 |
"have a simple human-parsable notion of what it is for a time series to\n", |
|
|
427 |
"be anomalous (big spikes). Of course, we don\\'t need a complicated\n", |
|
|
428 |
"algorithm to be able to detect such anomalies but this is just a\n", |
|
|
429 |
"didactic example remember!\n", |
|
|
430 |
"\n", |
|
|
431 |
"Like many machine learning algorithms, training is done in mini-batches.\n", |
|
|
432 |
"Examining the form of the loss function\n", |
|
|
433 |
"$\\mathcal{L}(\\boldsymbol{\\phi})$, we can see that time series are\n", |
|
|
434 |
"atomized. In other words, each term in the mean square error is for a\n", |
|
|
435 |
"given $x_t$ and not measured against the entire series $x$. This allows\n", |
|
|
436 |
"us to break down the training set $X$ into time-series-independent\n", |
|
|
437 |
"chunks. Here's an electron to do that:\n" |
|
|
438 |
] |
|
|
439 |
}, |
|
|
440 |
{ |
|
|
441 |
"cell_type": "code", |
|
|
442 |
"execution_count": 7, |
|
|
443 |
"metadata": { |
|
|
444 |
"id": "uAho8PSLa5MC" |
|
|
445 |
}, |
|
|
446 |
"outputs": [], |
|
|
447 |
"source": [ |
|
|
448 |
"@ct.electron\n", |
|
|
449 |
"def make_atomized_training_set(X: torch.Tensor, T: torch.Tensor) -> list:\n", |
|
|
450 |
" \"\"\"Convert input time series data provided in a two-dimensional tensor format\n", |
|
|
451 |
" to atomized tuple chunks: (xt, t).\n", |
|
|
452 |
" \"\"\"\n", |
|
|
453 |
" X_flat = torch.flatten(X)\n", |
|
|
454 |
" T_flat = T.repeat(X.size()[0])\n", |
|
|
455 |
" atomized = [(xt, t) for xt, t in zip(X_flat, T_flat)]\n", |
|
|
456 |
" return atomized" |
|
|
457 |
] |
|
|
458 |
}, |
|
|
459 |
{ |
|
|
460 |
"cell_type": "markdown", |
|
|
461 |
"metadata": { |
|
|
462 |
"id": "yaG5czXla5MD" |
|
|
463 |
}, |
|
|
464 |
"source": [ |
|
|
465 |
"We now wish to pass this to a cycled `torch.utils.data.DataLoader`.\n", |
|
|
466 |
"However, this object is not\n", |
|
|
467 |
"[pickleable](https://docs.python.org/3/library/pickle.html#:~:text=%E2%80%9CPickling%E2%80%9D%20is%20the%20process%20whereby,back%20into%20an%20object%20hierarchy.),\n", |
|
|
468 |
"which is a requirement of electrons in Covalent. We therefore use the\n", |
|
|
469 |
"below helper class to create a pickleable version.\n" |
|
|
470 |
] |
|
|
471 |
}, |
|
|
472 |
{ |
|
|
473 |
"cell_type": "code", |
|
|
474 |
"execution_count": 8, |
|
|
475 |
"metadata": { |
|
|
476 |
"id": "aN270Z0pa5MD" |
|
|
477 |
}, |
|
|
478 |
"outputs": [], |
|
|
479 |
"source": [ |
|
|
480 |
"from collections.abc import Iterator\n", |
|
|
481 |
"\n", |
|
|
482 |
"\n", |
|
|
483 |
"class DataGetter:\n", |
|
|
484 |
" \"\"\"A pickleable mock-up of a Python iterator on a torch.utils.Dataloader.\n", |
|
|
485 |
" Provide a dataset X and the resulting object O will allow you to use next(O).\n", |
|
|
486 |
" \"\"\"\n", |
|
|
487 |
"\n", |
|
|
488 |
" def __init__(self, X: torch.Tensor, batch_size: int, seed: int = GLOBAL_SEED) -> None:\n", |
|
|
489 |
" \"\"\"Calls the _init_data method on intialization of a DataGetter object.\"\"\"\n", |
|
|
490 |
" torch.manual_seed(seed)\n", |
|
|
491 |
" self.X = X\n", |
|
|
492 |
" self.batch_size = batch_size\n", |
|
|
493 |
" self.data = []\n", |
|
|
494 |
" self._init_data(\n", |
|
|
495 |
" iter(torch.utils.data.DataLoader(self.X, batch_size=self.batch_size, shuffle=True))\n", |
|
|
496 |
" )\n", |
|
|
497 |
"\n", |
|
|
498 |
" def _init_data(self, iterator: Iterator) -> None:\n", |
|
|
499 |
" \"\"\"Load all of the iterator into a list.\"\"\"\n", |
|
|
500 |
" x = next(iterator, None)\n", |
|
|
501 |
" while x is not None:\n", |
|
|
502 |
" self.data.append(x)\n", |
|
|
503 |
" x = next(iterator, None)\n", |
|
|
504 |
"\n", |
|
|
505 |
" def __next__(self) -> tuple:\n", |
|
|
506 |
" \"\"\"Analogous behaviour to the native Python next() but calling the\n", |
|
|
507 |
" .pop() of the data attribute.\n", |
|
|
508 |
" \"\"\"\n", |
|
|
509 |
" try:\n", |
|
|
510 |
" return self.data.pop()\n", |
|
|
511 |
" except IndexError: # Caught when the data set runs out of elements\n", |
|
|
512 |
" self._init_data(\n", |
|
|
513 |
" iter(torch.utils.data.DataLoader(self.X, batch_size=self.batch_size, shuffle=True))\n", |
|
|
514 |
" )\n", |
|
|
515 |
" return self.data.pop()" |
|
|
516 |
] |
|
|
517 |
}, |
|
|
518 |
{ |
|
|
519 |
"cell_type": "markdown", |
|
|
520 |
"metadata": { |
|
|
521 |
"id": "tP_VGMbLa5MD" |
|
|
522 |
}, |
|
|
523 |
"source": [ |
|
|
524 |
"We call an instance of the above in an electron\n" |
|
|
525 |
] |
|
|
526 |
}, |
|
|
527 |
{ |
|
|
528 |
"cell_type": "code", |
|
|
529 |
"execution_count": 9, |
|
|
530 |
"metadata": { |
|
|
531 |
"id": "ORHpMJ-qa5MD" |
|
|
532 |
}, |
|
|
533 |
"outputs": [], |
|
|
534 |
"source": [ |
|
|
535 |
"@ct.electron\n", |
|
|
536 |
"def get_training_cycler(Xtr: torch.Tensor, batch_size: int, seed: int = GLOBAL_SEED) -> DataGetter:\n", |
|
|
537 |
" \"\"\"Get an instance of the DataGetter class defined above, which behaves analogously to\n", |
|
|
538 |
" next(iterator) but is pickleable.\n", |
|
|
539 |
" \"\"\"\n", |
|
|
540 |
" return DataGetter(Xtr, batch_size, seed)" |
|
|
541 |
] |
|
|
542 |
}, |
|
|
543 |
{ |
|
|
544 |
"cell_type": "markdown", |
|
|
545 |
"metadata": { |
|
|
546 |
"id": "c67taJ9ba5MD" |
|
|
547 |
}, |
|
|
548 |
"source": [ |
|
|
549 |
"We now have the means to create synthetic data and cycle through a\n", |
|
|
550 |
"training set. Next, we need to build our loss function\n", |
|
|
551 |
"$\\mathcal{L}(\\boldsymbol{\\phi})$ from electrons with the help of\n", |
|
|
552 |
"`PennyLane`.\n" |
|
|
553 |
] |
|
|
554 |
}, |
|
|
555 |
{ |
|
|
556 |
"cell_type": "markdown", |
|
|
557 |
"metadata": { |
|
|
558 |
"id": "hov7fVBZa5MD" |
|
|
559 |
}, |
|
|
560 |
"source": [ |
|
|
561 |
"Building the loss function\n", |
|
|
562 |
"==========================\n", |
|
|
563 |
"\n", |
|
|
564 |
"Core to building the loss function is the quantum circuit implementing\n", |
|
|
565 |
"$V_t(\\boldsymbol{\\alpha}, \\boldsymbol{\\gamma}) := W^{\\dagger}(\\boldsymbol{\\alpha})D(\\boldsymbol{\\gamma}, t)W(\\boldsymbol{\\alpha})$.\n", |
|
|
566 |
"While there are existing templates in `PennyLane` for implementing\n", |
|
|
567 |
"$W(\\boldsymbol{\\alpha})$, we use a custom circuit to implement\n", |
|
|
568 |
"$D(\\boldsymbol{\\gamma}, t)$. Following the approach taken in (also\n", |
|
|
569 |
"explained in and the appendix of), we create the electron:\n" |
|
|
570 |
] |
|
|
571 |
}, |
|
|
572 |
{ |
|
|
573 |
"cell_type": "code", |
|
|
574 |
"execution_count": 10, |
|
|
575 |
"metadata": { |
|
|
576 |
"id": "PtRU27Jca5MD" |
|
|
577 |
}, |
|
|
578 |
"outputs": [], |
|
|
579 |
"source": [ |
|
|
580 |
"import pennylane as qml\n", |
|
|
581 |
"from itertools import combinations\n", |
|
|
582 |
"\n", |
|
|
583 |
"\n", |
|
|
584 |
"@ct.electron\n", |
|
|
585 |
"def D(gamma: torch.Tensor, n_qubits: int, k: int = None, get_probs: bool = False) -> None:\n", |
|
|
586 |
" \"\"\"Generates an n_qubit quantum circuit according to a k-local Walsh operator\n", |
|
|
587 |
" expansion. Here, k-local means that 1 <= k <= n of the n qubits can interact.\n", |
|
|
588 |
" See <https://doi.org/10.1088/1367-2630/16/3/033040> for more\n", |
|
|
589 |
" details. Optionally return probabilities of bit strings.\n", |
|
|
590 |
" \"\"\"\n", |
|
|
591 |
" if k is None:\n", |
|
|
592 |
" k = n_qubits\n", |
|
|
593 |
" cnt = 0\n", |
|
|
594 |
" for i in range(1, k + 1):\n", |
|
|
595 |
" for comb in combinations(range(n_qubits), i):\n", |
|
|
596 |
" if len(comb) == 1:\n", |
|
|
597 |
" qml.RZ(gamma[cnt], wires=[comb[0]])\n", |
|
|
598 |
" cnt += 1\n", |
|
|
599 |
" elif len(comb) > 1:\n", |
|
|
600 |
" cnots = [comb[i : i + 2] for i in range(len(comb) - 1)]\n", |
|
|
601 |
" for j in cnots:\n", |
|
|
602 |
" qml.CNOT(wires=j)\n", |
|
|
603 |
" qml.RZ(gamma[cnt], wires=[comb[-1]])\n", |
|
|
604 |
" cnt += 1\n", |
|
|
605 |
" for j in cnots[::-1]:\n", |
|
|
606 |
" qml.CNOT(wires=j)\n", |
|
|
607 |
" if get_probs:\n", |
|
|
608 |
" return qml.probs(wires=range(n_qubits))" |
|
|
609 |
] |
|
|
610 |
}, |
|
|
611 |
{ |
|
|
612 |
"cell_type": "markdown", |
|
|
613 |
"metadata": { |
|
|
614 |
"id": "tkaI_FJra5MD" |
|
|
615 |
}, |
|
|
616 |
"source": [ |
|
|
617 |
"While the above may seem a little complicated, since we only use a\n", |
|
|
618 |
"single qubit in this tutorial, the resulting circuit is merely a single\n", |
|
|
619 |
"$R_z(\\theta)$ gate.\n" |
|
|
620 |
] |
|
|
621 |
}, |
|
|
622 |
{ |
|
|
623 |
"cell_type": "code", |
|
|
624 |
"execution_count": 11, |
|
|
625 |
"metadata": { |
|
|
626 |
"colab": { |
|
|
627 |
"base_uri": "https://localhost:8080/", |
|
|
628 |
"height": 237 |
|
|
629 |
}, |
|
|
630 |
"id": "uUbcEi6Wa5MD", |
|
|
631 |
"outputId": "0e967bcd-0874-494e-a1cd-1eb540a6f499" |
|
|
632 |
}, |
|
|
633 |
"outputs": [ |
|
|
634 |
{ |
|
|
635 |
"output_type": "display_data", |
|
|
636 |
"data": { |
|
|
637 |
"text/plain": [ |
|
|
638 |
"<Figure size 400x200 with 1 Axes>" |
|
|
639 |
], |
|
|
640 |
"image/png": "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YCBV+9vf/oaEhATU1tY6fHzo0KGYPn06Jk6ciIiICNXNZVdeXo6ioiJkZ2cjPT3d7rqVBjqdDh9++GGLbjXhCazHA75SDzVhGJHqHThwAK+++ipKSkqaXbd3796IiIhAv3790LFjR+j1ep8Z9VVfX4+qqipYLBZcv34dRUVFdpNsOmIwGLB582ZMmjTJC71sHuvhW/VQDblvzIjcw2KxiGXLlgm9Xm/3cYm//uj1erFs2TKf/HKc9aCW4jsj8ivFxcVITU1FRkYGvvnmG9nd8YjevXtj2rRpWLRokc8PF2Y9yFkMI/JLtbW1yM3NRXp6OrKyslBSUgK1/qprNBoYDAbExsZi+vTpiImJUd2V/KwHNYdhRG1CVVUVrl69iqKiIhQVFeHOnTu4f/8+7t+/L7trCh06dECHDh0QFBSEiIgIREREIDQ01O9uO8B6kC2GERERSecbw1aIiKhNYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISDqGERERSccwIiIi6RhGREQkHcOIiIikYxgREZF0DCMiIpKOYURERNIxjIiISLr/BxCn8tHBLwreAAAAAElFTkSuQmCC\n" |
|
|
641 |
}, |
|
|
642 |
"metadata": {} |
|
|
643 |
} |
|
|
644 |
], |
|
|
645 |
"source": [ |
|
|
646 |
"n_qubits = 2\n", |
|
|
647 |
"dev = qml.device(\"default.qubit\", wires=n_qubits, shots=None)\n", |
|
|
648 |
"D_one_qubit = qml.qnode(dev)(D)\n", |
|
|
649 |
"_ = qml.draw_mpl(D_one_qubit, decimals=2)(torch.tensor([1, 0]), 1, 1, True)" |
|
|
650 |
] |
|
|
651 |
}, |
|
|
652 |
{ |
|
|
653 |
"cell_type": "markdown", |
|
|
654 |
"metadata": { |
|
|
655 |
"id": "IDWWmn_7a5MD" |
|
|
656 |
}, |
|
|
657 |
"source": [ |
|
|
658 |
"You may find the general function for $D$\\` useful in case you want to\n", |
|
|
659 |
"experiment with more qubits and your own (possibly multi-dimensional)\n", |
|
|
660 |
"data after this tutorial.\n", |
|
|
661 |
"\n", |
|
|
662 |
"Next, we define a circuit to calculate the probability of certain bit\n", |
|
|
663 |
"strings being measured in the computational basis. In our simple\n", |
|
|
664 |
"example, we work only with one qubit and use the `default.qubit` local\n", |
|
|
665 |
"quantum circuit simulator.\n" |
|
|
666 |
] |
|
|
667 |
}, |
|
|
668 |
{ |
|
|
669 |
"cell_type": "code", |
|
|
670 |
"execution_count": 12, |
|
|
671 |
"metadata": { |
|
|
672 |
"id": "IbWRykxxa5MD" |
|
|
673 |
}, |
|
|
674 |
"outputs": [], |
|
|
675 |
"source": [ |
|
|
676 |
"@ct.electron\n", |
|
|
677 |
"@qml.qnode(dev, interface=\"torch\", diff_method=\"backprop\")\n", |
|
|
678 |
"def get_probs(\n", |
|
|
679 |
" xt: torch.Tensor,\n", |
|
|
680 |
" t: float,\n", |
|
|
681 |
" alpha: torch.Tensor,\n", |
|
|
682 |
" gamma: torch.Tensor,\n", |
|
|
683 |
" k: int,\n", |
|
|
684 |
" U: callable,\n", |
|
|
685 |
" W: callable,\n", |
|
|
686 |
" D: callable,\n", |
|
|
687 |
" n_qubits: int,\n", |
|
|
688 |
") -> torch.Tensor:\n", |
|
|
689 |
" \"\"\"Measure the probabilities for measuring each bitstring after applying a\n", |
|
|
690 |
" circuit of the form W†DWU to the |0⟩^(⊗n) state. This\n", |
|
|
691 |
" function is defined for individual sequence elements xt.\n", |
|
|
692 |
" \"\"\"\n", |
|
|
693 |
" U(xt, wires=range(n_qubits))\n", |
|
|
694 |
" W(alpha, wires=range(n_qubits))\n", |
|
|
695 |
" D(gamma * t, n_qubits, k)\n", |
|
|
696 |
" qml.adjoint(W)(alpha, wires=range(n_qubits))\n", |
|
|
697 |
" return qml.probs(range(n_qubits))" |
|
|
698 |
] |
|
|
699 |
}, |
|
|
700 |
{ |
|
|
701 |
"cell_type": "markdown", |
|
|
702 |
"metadata": { |
|
|
703 |
"id": "8UEO-z-Qa5MD" |
|
|
704 |
}, |
|
|
705 |
"source": [ |
|
|
706 |
"To take the projector $|0\\rangle^{\\otimes n} \\langle 0 |^{\\otimes n}$,\n", |
|
|
707 |
"we consider only the probability of measuring the bit string of all\n", |
|
|
708 |
"zeroes, which is the 0th element of the probabilities (bit strings are\n", |
|
|
709 |
"returned in lexicographic order).\n" |
|
|
710 |
] |
|
|
711 |
}, |
|
|
712 |
{ |
|
|
713 |
"cell_type": "code", |
|
|
714 |
"execution_count": 13, |
|
|
715 |
"metadata": { |
|
|
716 |
"id": "1u3xoE3Sa5MD" |
|
|
717 |
}, |
|
|
718 |
"outputs": [], |
|
|
719 |
"source": [ |
|
|
720 |
"@ct.electron\n", |
|
|
721 |
"def get_callable_projector_func(\n", |
|
|
722 |
" k: int, U: callable, W: callable, D: callable, n_qubits: int, probs_func: callable\n", |
|
|
723 |
") -> callable:\n", |
|
|
724 |
" \"\"\"Using get_probs() above, take only the probability of measuring the\n", |
|
|
725 |
" bitstring of all zeroes (i.e, take the projector\n", |
|
|
726 |
" |0⟩^(⊗n)⟨0|^(⊗n)) on the time devolved state.\n", |
|
|
727 |
" \"\"\"\n", |
|
|
728 |
" callable_proj = lambda xt, t, alpha, gamma: probs_func(\n", |
|
|
729 |
" xt, t, alpha, gamma, k, U, W, D, n_qubits\n", |
|
|
730 |
" )[0]\n", |
|
|
731 |
" return callable_proj" |
|
|
732 |
] |
|
|
733 |
}, |
|
|
734 |
{ |
|
|
735 |
"cell_type": "markdown", |
|
|
736 |
"metadata": { |
|
|
737 |
"id": "7CASnQNva5MD" |
|
|
738 |
}, |
|
|
739 |
"source": [ |
|
|
740 |
"We now have the necessary ingredients to build\n", |
|
|
741 |
"$F(\\boldsymbol{\\phi}, x_t)$.\n" |
|
|
742 |
] |
|
|
743 |
}, |
|
|
744 |
{ |
|
|
745 |
"cell_type": "code", |
|
|
746 |
"execution_count": 14, |
|
|
747 |
"metadata": { |
|
|
748 |
"id": "Un_xjqcxa5MD" |
|
|
749 |
}, |
|
|
750 |
"outputs": [], |
|
|
751 |
"source": [ |
|
|
752 |
"@ct.electron\n", |
|
|
753 |
"def F(\n", |
|
|
754 |
" callable_proj: callable,\n", |
|
|
755 |
" xt: torch.Tensor,\n", |
|
|
756 |
" t: float,\n", |
|
|
757 |
" alpha: torch.Tensor,\n", |
|
|
758 |
" mu: torch.Tensor,\n", |
|
|
759 |
" sigma: torch.Tensor,\n", |
|
|
760 |
" gamma_length: int,\n", |
|
|
761 |
" n_samples: int,\n", |
|
|
762 |
") -> torch.Tensor:\n", |
|
|
763 |
" \"\"\"Take the classical expecation value of of the projector on zero sampling\n", |
|
|
764 |
" the parameters of D from normal distributions. The expecation value is estimated\n", |
|
|
765 |
" with an average over n_samples.\n", |
|
|
766 |
" \"\"\"\n", |
|
|
767 |
" # length of gamma should not exceed 2^n - 1\n", |
|
|
768 |
" gammas = sigma.abs() * torch.randn((n_samples, gamma_length)) + mu\n", |
|
|
769 |
" expectation = torch.empty(n_samples)\n", |
|
|
770 |
" for i, gamma in enumerate(gammas):\n", |
|
|
771 |
" expectation[i] = callable_proj(xt, t, alpha, gamma)\n", |
|
|
772 |
" return expectation.mean()" |
|
|
773 |
] |
|
|
774 |
}, |
|
|
775 |
{ |
|
|
776 |
"cell_type": "markdown", |
|
|
777 |
"metadata": { |
|
|
778 |
"id": "KkaRe8d9a5MD" |
|
|
779 |
}, |
|
|
780 |
"source": [ |
|
|
781 |
"We now return to the matter of the penalty function $P_{\\tau}$. We\n", |
|
|
782 |
"choose\n", |
|
|
783 |
"\n", |
|
|
784 |
"$$P_{\\tau}(\\sigma) := \\frac{1}{\\pi} \\arctan(2 \\pi \\tau |\\sigma|).$$\n", |
|
|
785 |
"\n", |
|
|
786 |
"As an electron, we have\n" |
|
|
787 |
] |
|
|
788 |
}, |
|
|
789 |
{ |
|
|
790 |
"cell_type": "code", |
|
|
791 |
"execution_count": 15, |
|
|
792 |
"metadata": { |
|
|
793 |
"id": "MijWXiBLa5ME" |
|
|
794 |
}, |
|
|
795 |
"outputs": [], |
|
|
796 |
"source": [ |
|
|
797 |
"@ct.electron\n", |
|
|
798 |
"def callable_arctan_penalty(tau: float) -> callable:\n", |
|
|
799 |
" \"\"\"Create a callable arctan function with a single hyperparameter\n", |
|
|
800 |
" tau to penalize large entries of sigma.\n", |
|
|
801 |
" \"\"\"\n", |
|
|
802 |
" prefac = 1 / (torch.pi)\n", |
|
|
803 |
" callable_pen = lambda sigma: prefac * torch.arctan(2 * torch.pi * tau * sigma.abs()).mean()\n", |
|
|
804 |
" return callable_pen" |
|
|
805 |
] |
|
|
806 |
}, |
|
|
807 |
{ |
|
|
808 |
"cell_type": "markdown", |
|
|
809 |
"metadata": { |
|
|
810 |
"id": "Mrh5wkIRa5ME" |
|
|
811 |
}, |
|
|
812 |
"source": [ |
|
|
813 |
"The above is a sigmoidal function chosen because it comes with the\n", |
|
|
814 |
"useful property of being bounded. The prefactor of $1/\\pi$ is chosen\n", |
|
|
815 |
"such that the final loss $\\mathcal{L}(\\boldsymbol{\\phi})$ is defined in\n", |
|
|
816 |
"the range (0, 1), as defined in the below electron.\n" |
|
|
817 |
] |
|
|
818 |
}, |
|
|
819 |
{ |
|
|
820 |
"cell_type": "code", |
|
|
821 |
"execution_count": 16, |
|
|
822 |
"metadata": { |
|
|
823 |
"id": "veCMIMuwa5ME" |
|
|
824 |
}, |
|
|
825 |
"outputs": [], |
|
|
826 |
"source": [ |
|
|
827 |
"@ct.electron\n", |
|
|
828 |
"def get_loss(\n", |
|
|
829 |
" callable_proj: callable,\n", |
|
|
830 |
" batch: torch.Tensor,\n", |
|
|
831 |
" alpha: torch.Tensor,\n", |
|
|
832 |
" mu: torch.Tensor,\n", |
|
|
833 |
" sigma: torch.Tensor,\n", |
|
|
834 |
" gamma_length: int,\n", |
|
|
835 |
" n_samples: int,\n", |
|
|
836 |
" callable_penalty: callable,\n", |
|
|
837 |
") -> torch.Tensor:\n", |
|
|
838 |
" \"\"\"Evaluate the loss function ℒ, defined in the background section\n", |
|
|
839 |
" for a certain set of parameters.\n", |
|
|
840 |
" \"\"\"\n", |
|
|
841 |
" X_batch, T_batch = batch\n", |
|
|
842 |
" loss = torch.empty(X_batch.size()[0])\n", |
|
|
843 |
" for i in range(X_batch.size()[0]):\n", |
|
|
844 |
" # unsqueeze required for tensor to have the correct dimension for PennyLane templates\n", |
|
|
845 |
" loss[i] = (\n", |
|
|
846 |
" 1\n", |
|
|
847 |
" - F(\n", |
|
|
848 |
" callable_proj,\n", |
|
|
849 |
" X_batch[i].unsqueeze(0),\n", |
|
|
850 |
" T_batch[i].unsqueeze(0),\n", |
|
|
851 |
" alpha,\n", |
|
|
852 |
" mu,\n", |
|
|
853 |
" sigma,\n", |
|
|
854 |
" gamma_length,\n", |
|
|
855 |
" n_samples,\n", |
|
|
856 |
" )\n", |
|
|
857 |
" ).square()\n", |
|
|
858 |
" return 0.5 * loss.mean() + callable_penalty(sigma)" |
|
|
859 |
] |
|
|
860 |
}, |
|
|
861 |
{ |
|
|
862 |
"cell_type": "markdown", |
|
|
863 |
"metadata": { |
|
|
864 |
"id": "ZxOb7d5ga5ME" |
|
|
865 |
}, |
|
|
866 |
"source": [ |
|
|
867 |
"Training the normal model\n", |
|
|
868 |
"=========================\n", |
|
|
869 |
"\n", |
|
|
870 |
"Now equipped with a loss function, we need to minimize it with a\n", |
|
|
871 |
"classical optimization routine. To start this optimization, however, we\n", |
|
|
872 |
"need some initial parameters. We can generate them with the below\n", |
|
|
873 |
"electron.\n" |
|
|
874 |
] |
|
|
875 |
}, |
|
|
876 |
{ |
|
|
877 |
"cell_type": "code", |
|
|
878 |
"execution_count": 17, |
|
|
879 |
"metadata": { |
|
|
880 |
"id": "ZiirtuMva5ME" |
|
|
881 |
}, |
|
|
882 |
"outputs": [], |
|
|
883 |
"source": [ |
|
|
884 |
"@ct.electron\n", |
|
|
885 |
"def get_initial_parameters(\n", |
|
|
886 |
" W: callable, W_layers: int, n_qubits: int, seed: int = GLOBAL_SEED\n", |
|
|
887 |
") -> dict:\n", |
|
|
888 |
" \"\"\"Randomly generate initial parameters. We need initial parameters for the\n", |
|
|
889 |
" variational circuit ansatz implementing W(alpha) and the standard deviation\n", |
|
|
890 |
" and mean (sigma and mu) for the normal distribution we sample gamma from.\n", |
|
|
891 |
" \"\"\"\n", |
|
|
892 |
" torch.manual_seed(seed)\n", |
|
|
893 |
" init_alpha = torch.rand(W.shape(W_layers, n_qubits))\n", |
|
|
894 |
" init_mu = torch.rand(1)\n", |
|
|
895 |
" # Best to start sigma small and expand if needed\n", |
|
|
896 |
" init_sigma = torch.rand(1)\n", |
|
|
897 |
" init_params = {\n", |
|
|
898 |
" \"alpha\": (2 * torch.pi * init_alpha).clone().detach().requires_grad_(True),\n", |
|
|
899 |
" \"mu\": (2 * torch.pi * init_mu).clone().detach().requires_grad_(True),\n", |
|
|
900 |
" \"sigma\": (0.1 * init_sigma + 0.05).clone().detach().requires_grad_(True),\n", |
|
|
901 |
" }\n", |
|
|
902 |
" return init_params" |
|
|
903 |
] |
|
|
904 |
}, |
|
|
905 |
{ |
|
|
906 |
"cell_type": "markdown", |
|
|
907 |
"metadata": { |
|
|
908 |
"id": "wfYxh6Fja5ME" |
|
|
909 |
}, |
|
|
910 |
"source": [ |
|
|
911 |
"Using the `PyTorch` interface to `PennyLane`, we define our final\n", |
|
|
912 |
"electron before running the training workflow.\n" |
|
|
913 |
] |
|
|
914 |
}, |
|
|
915 |
{ |
|
|
916 |
"cell_type": "code", |
|
|
917 |
"execution_count": 18, |
|
|
918 |
"metadata": { |
|
|
919 |
"id": "zt2IVHlWa5ME" |
|
|
920 |
}, |
|
|
921 |
"outputs": [], |
|
|
922 |
"source": [ |
|
|
923 |
"@ct.electron\n", |
|
|
924 |
"def train_model_gradients(\n", |
|
|
925 |
" lr: float,\n", |
|
|
926 |
" init_params: dict,\n", |
|
|
927 |
" pytorch_optimizer: callable,\n", |
|
|
928 |
" cycler: DataGetter,\n", |
|
|
929 |
" n_samples: int,\n", |
|
|
930 |
" callable_penalty: callable,\n", |
|
|
931 |
" batch_iterations: int,\n", |
|
|
932 |
" callable_proj: callable,\n", |
|
|
933 |
" gamma_length: int,\n", |
|
|
934 |
" seed=GLOBAL_SEED,\n", |
|
|
935 |
" print_intermediate=False,\n", |
|
|
936 |
") -> dict:\n", |
|
|
937 |
" \"\"\"Train the QVR model (minimize the loss function) with respect to the\n", |
|
|
938 |
" variational parameters using gradient-based training. You need to pass a\n", |
|
|
939 |
" PyTorch optimizer and a learning rate (lr).\n", |
|
|
940 |
" \"\"\"\n", |
|
|
941 |
" torch.manual_seed(seed)\n", |
|
|
942 |
" opt = pytorch_optimizer(init_params.values(), lr=lr)\n", |
|
|
943 |
" alpha = init_params[\"alpha\"]\n", |
|
|
944 |
" mu = init_params[\"mu\"]\n", |
|
|
945 |
" sigma = init_params[\"sigma\"]\n", |
|
|
946 |
"\n", |
|
|
947 |
" def closure():\n", |
|
|
948 |
" opt.zero_grad()\n", |
|
|
949 |
" loss = get_loss(\n", |
|
|
950 |
" callable_proj, next(cycler), alpha, mu, sigma, gamma_length, n_samples, callable_penalty\n", |
|
|
951 |
" )\n", |
|
|
952 |
" loss.backward()\n", |
|
|
953 |
" return loss\n", |
|
|
954 |
"\n", |
|
|
955 |
" loss_history = []\n", |
|
|
956 |
" for i in range(batch_iterations):\n", |
|
|
957 |
" loss = opt.step(closure)\n", |
|
|
958 |
" loss_history.append(loss.item())\n", |
|
|
959 |
" if batch_iterations % 10 == 0 and print_intermediate:\n", |
|
|
960 |
" print(f\"Iteration number {i}\\n Current loss {loss.item()}\\n\")\n", |
|
|
961 |
"\n", |
|
|
962 |
" results_dict = {\n", |
|
|
963 |
" \"opt_params\": {\n", |
|
|
964 |
" \"alpha\": opt.param_groups[0][\"params\"][0],\n", |
|
|
965 |
" \"mu\": opt.param_groups[0][\"params\"][1],\n", |
|
|
966 |
" \"sigma\": opt.param_groups[0][\"params\"][2],\n", |
|
|
967 |
" },\n", |
|
|
968 |
" \"loss_history\": loss_history,\n", |
|
|
969 |
" }\n", |
|
|
970 |
" return results_dict" |
|
|
971 |
] |
|
|
972 |
}, |
|
|
973 |
{ |
|
|
974 |
"cell_type": "markdown", |
|
|
975 |
"metadata": { |
|
|
976 |
"id": "Nio1PhXga5ME" |
|
|
977 |
}, |
|
|
978 |
"source": [ |
|
|
979 |
"Now, enter our first `@ct.lattice`. This combines the above electrons,\n", |
|
|
980 |
"eventually returning the optimal parameters $\\boldsymbol{\\phi}^{\\star}$\n", |
|
|
981 |
"and the loss with batch iterations.\n" |
|
|
982 |
] |
|
|
983 |
}, |
|
|
984 |
{ |
|
|
985 |
"cell_type": "code", |
|
|
986 |
"execution_count": 19, |
|
|
987 |
"metadata": { |
|
|
988 |
"id": "K95eoEaLa5ME" |
|
|
989 |
}, |
|
|
990 |
"outputs": [], |
|
|
991 |
"source": [ |
|
|
992 |
"@ct.lattice\n", |
|
|
993 |
"def training_workflow(\n", |
|
|
994 |
" U: callable,\n", |
|
|
995 |
" W: callable,\n", |
|
|
996 |
" D: callable,\n", |
|
|
997 |
" n_qubits: int,\n", |
|
|
998 |
" k: int,\n", |
|
|
999 |
" probs_func: callable,\n", |
|
|
1000 |
" W_layers: int,\n", |
|
|
1001 |
" gamma_length: int,\n", |
|
|
1002 |
" n_samples: int,\n", |
|
|
1003 |
" p: int,\n", |
|
|
1004 |
" num_series: int,\n", |
|
|
1005 |
" noise_amp: float,\n", |
|
|
1006 |
" t_init: float,\n", |
|
|
1007 |
" t_end: float,\n", |
|
|
1008 |
" batch_size: int,\n", |
|
|
1009 |
" tau: float,\n", |
|
|
1010 |
" pytorch_optimizer: callable,\n", |
|
|
1011 |
" lr: float,\n", |
|
|
1012 |
" batch_iterations: int,\n", |
|
|
1013 |
"):\n", |
|
|
1014 |
" \"\"\"\n", |
|
|
1015 |
" Combine all of the previously defined electrons to do an entire training workflow,\n", |
|
|
1016 |
" including (1) generating synthetic data, (2) packaging it into training cyclers\n", |
|
|
1017 |
" (3) preparing the quantum functions and (4) optimizing the loss function with\n", |
|
|
1018 |
" gradient based optimization. You can find definitions for all of the arguments\n", |
|
|
1019 |
" by looking at the electrons and text cells above.\n", |
|
|
1020 |
" \"\"\"\n", |
|
|
1021 |
"\n", |
|
|
1022 |
" X, T = generate_normal_time_series_set(p, num_series, noise_amp, t_init, t_end)\n", |
|
|
1023 |
" Xtr = make_atomized_training_set(X, T)\n", |
|
|
1024 |
" cycler = get_training_cycler(Xtr, batch_size)\n", |
|
|
1025 |
" init_params = get_initial_parameters(W, W_layers, n_qubits)\n", |
|
|
1026 |
" callable_penalty = callable_arctan_penalty(tau)\n", |
|
|
1027 |
" callable_proj = get_callable_projector_func(k, U, W, D, n_qubits, probs_func)\n", |
|
|
1028 |
" results_dict = train_model_gradients(\n", |
|
|
1029 |
" lr,\n", |
|
|
1030 |
" init_params,\n", |
|
|
1031 |
" pytorch_optimizer,\n", |
|
|
1032 |
" cycler,\n", |
|
|
1033 |
" n_samples,\n", |
|
|
1034 |
" callable_penalty,\n", |
|
|
1035 |
" batch_iterations,\n", |
|
|
1036 |
" callable_proj,\n", |
|
|
1037 |
" gamma_length,\n", |
|
|
1038 |
" print_intermediate=False,\n", |
|
|
1039 |
" )\n", |
|
|
1040 |
" return results_dict" |
|
|
1041 |
] |
|
|
1042 |
}, |
|
|
1043 |
{ |
|
|
1044 |
"cell_type": "markdown", |
|
|
1045 |
"metadata": { |
|
|
1046 |
"id": "_cVnbMBQa5ME" |
|
|
1047 |
}, |
|
|
1048 |
"source": [ |
|
|
1049 |
"Before running this workflow, we define all of the input parameters.\n" |
|
|
1050 |
] |
|
|
1051 |
}, |
|
|
1052 |
{ |
|
|
1053 |
"cell_type": "code", |
|
|
1054 |
"execution_count": 20, |
|
|
1055 |
"metadata": { |
|
|
1056 |
"id": "zrgDBKbCa5ME" |
|
|
1057 |
}, |
|
|
1058 |
"outputs": [], |
|
|
1059 |
"source": [ |
|
|
1060 |
"general_options = {\n", |
|
|
1061 |
" \"U\": qml.AngleEmbedding,\n", |
|
|
1062 |
" \"W\": qml.StronglyEntanglingLayers,\n", |
|
|
1063 |
" \"D\": D,\n", |
|
|
1064 |
" \"n_qubits\": 1,\n", |
|
|
1065 |
" \"probs_func\": get_probs,\n", |
|
|
1066 |
" \"gamma_length\": 1,\n", |
|
|
1067 |
" \"n_samples\": 10,\n", |
|
|
1068 |
" \"p\": 25,\n", |
|
|
1069 |
" \"num_series\": 25,\n", |
|
|
1070 |
" \"noise_amp\": 0.1,\n", |
|
|
1071 |
" \"t_init\": 0.1,\n", |
|
|
1072 |
" \"t_end\": 2 * torch.pi,\n", |
|
|
1073 |
" \"k\": 1,\n", |
|
|
1074 |
"}\n", |
|
|
1075 |
"\n", |
|
|
1076 |
"training_options = {\n", |
|
|
1077 |
" \"batch_size\": 10,\n", |
|
|
1078 |
" \"tau\": 5,\n", |
|
|
1079 |
" \"pytorch_optimizer\": torch.optim.Adam,\n", |
|
|
1080 |
" \"lr\": 0.01,\n", |
|
|
1081 |
" \"batch_iterations\": 100,\n", |
|
|
1082 |
" \"W_layers\": 2,\n", |
|
|
1083 |
"}\n", |
|
|
1084 |
"\n", |
|
|
1085 |
"training_options.update(general_options)" |
|
|
1086 |
] |
|
|
1087 |
}, |
|
|
1088 |
{ |
|
|
1089 |
"cell_type": "markdown", |
|
|
1090 |
"metadata": { |
|
|
1091 |
"id": "lOYhgeYRa5MF" |
|
|
1092 |
}, |
|
|
1093 |
"source": [ |
|
|
1094 |
"We can now dispatch the lattice to the Covalent server.\n" |
|
|
1095 |
] |
|
|
1096 |
}, |
|
|
1097 |
{ |
|
|
1098 |
"cell_type": "code", |
|
|
1099 |
"execution_count": 21, |
|
|
1100 |
"metadata": { |
|
|
1101 |
"id": "-QCVzIZya5MF" |
|
|
1102 |
}, |
|
|
1103 |
"outputs": [], |
|
|
1104 |
"source": [ |
|
|
1105 |
"tr_dispatch_id = ct.dispatch(training_workflow)(**training_options)" |
|
|
1106 |
] |
|
|
1107 |
}, |
|
|
1108 |
{ |
|
|
1109 |
"cell_type": "markdown", |
|
|
1110 |
"metadata": { |
|
|
1111 |
"id": "BRxajqpva5MF" |
|
|
1112 |
}, |
|
|
1113 |
"source": [ |
|
|
1114 |
"If you are running the notebook version of this tutorial, if you\n", |
|
|
1115 |
"navigate to <http://localhost:48008/> you can view the workflow on the\n", |
|
|
1116 |
"Covalent GUI. It will look like the screenshot below, showing nicely how\n", |
|
|
1117 |
"all of the electrons defined above interact with each other in the\n", |
|
|
1118 |
"workflow. You can also track the progress of the calculation here.\n", |
|
|
1119 |
"\n", |
|
|
1120 |
"{.align-center\n", |
|
|
1122 |
"width=\"85.0%\"}\n" |
|
|
1123 |
] |
|
|
1124 |
}, |
|
|
1125 |
{ |
|
|
1126 |
"cell_type": "markdown", |
|
|
1127 |
"metadata": { |
|
|
1128 |
"id": "zakSI7tla5MF" |
|
|
1129 |
}, |
|
|
1130 |
"source": [ |
|
|
1131 |
"We now pull the results back from the Covalent server:\n" |
|
|
1132 |
] |
|
|
1133 |
}, |
|
|
1134 |
{ |
|
|
1135 |
"cell_type": "code", |
|
|
1136 |
"execution_count": 22, |
|
|
1137 |
"metadata": { |
|
|
1138 |
"id": "KeMi_bN8a5MF" |
|
|
1139 |
}, |
|
|
1140 |
"outputs": [], |
|
|
1141 |
"source": [ |
|
|
1142 |
"ct_tr_results = ct.get_result(dispatch_id=tr_dispatch_id, wait=True)\n", |
|
|
1143 |
"results_dict = ct_tr_results.result" |
|
|
1144 |
] |
|
|
1145 |
}, |
|
|
1146 |
{ |
|
|
1147 |
"cell_type": "markdown", |
|
|
1148 |
"metadata": { |
|
|
1149 |
"id": "bHd9avMWa5MF" |
|
|
1150 |
}, |
|
|
1151 |
"source": [ |
|
|
1152 |
"and take a look at the training loss history:\n" |
|
|
1153 |
] |
|
|
1154 |
}, |
|
|
1155 |
{ |
|
|
1156 |
"cell_type": "code", |
|
|
1157 |
"execution_count": 23, |
|
|
1158 |
"metadata": { |
|
|
1159 |
"colab": { |
|
|
1160 |
"base_uri": "https://localhost:8080/", |
|
|
1161 |
"height": 472 |
|
|
1162 |
}, |
|
|
1163 |
"id": "z8PVX7W0a5MF", |
|
|
1164 |
"outputId": "0016a872-f7d9-46d2-b5eb-35a06b8d0d36" |
|
|
1165 |
}, |
|
|
1166 |
"outputs": [ |
|
|
1167 |
{ |
|
|
1168 |
"output_type": "display_data", |
|
|
1169 |
"data": { |
|
|
1170 |
"text/plain": [ |
|
|
1171 |
"<Figure size 640x480 with 1 Axes>" |
|
|
1172 |
], |
|
|
1173 |
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjkAAAHHCAYAAABdm0mZAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABzoElEQVR4nO3dd3yT1f4H8M+TdKZ70QEtLaXsDQXZIFNwIFyt4pXK74oDcFxcIFeGVwUHXLwqeEVBLw5ABXFdoBQQ2VvZMkpboYOW7t3k/P5I89A0SZu2aZKmn/frxUvz5HmenJznafLNOd9zjiSEECAiIiJyMApbF4CIiIioKTDIISIiIofEIIeIiIgcEoMcIiIickgMcoiIiMghMcghIiIih8Qgh4iIiBwSgxwiIiJySAxyiIiIyCExyCGb2Lp1K3r16gU3NzdIkoTc3FxbF8koSZKwaNEiWxfD4X366aeQJAlHjx61dVEAAFevXoUkSXjnnXcadPzu3bshSRJ2795t2YI1Id01uHr1qq2LYkB3PT799FNbF8Usjbn+ze292jsGOQ7E3r4oTMnOzsb9998Pd3d3fPDBB1i3bh08PDxsVp6ff/6ZgYwD+vLLL7FixQpbF0NmL+V544038N1339m6GDa3cuVKBhItgSCHsXbtWgFAHDlyxNZFqdX//vc/AUAkJCTYuihCCCFmzZolTP0plJSUiIqKCiuXqOVpint34sSJom3btg06NikpSQAQb7/9doOOV6vVoqSkRKjVaouUx5I8PDxEfHy8wfbKykpRUlIiNBqN9QtVB41GI0pKSkRlZaXFztm1a1cxfPhwi52vOmPX31xN8V5bMrbkkNVlZmYCAHx9fW1bEDO4ubnBycnJ1sVoEkVFRbYugsNSKBRwc3ODQtG0H7EajQalpaUWOZdSqZS7j+2NJElwc3ODUqm0yevX92+lMdff1u/V0TDIaYFOnDiBO+64A97e3vD09MSoUaNw8OBBvX0qKiqwePFixMTEwM3NDQEBARgyZAgSEhLkfdLT0zF9+nS0adMGrq6uCA0NxT333FNrn/6IESMQHx8PAIiNjYUkSXjkkUcAAJGRkfL/1zxmxIgR8mNdf/fGjRvx+uuvo02bNnBzc8OoUaNw6dIlg+MPHTqECRMmwM/PDx4eHujRowfeffddAMAjjzyCDz74AID2w0X3T8dYTo459afrOty3bx/mzJmDoKAgeHh44N5778WNGzdM1g8AvPPOO5AkCcnJyQbPzZs3Dy4uLsjJydF7f+PHj4ePjw9UKhWGDx+Offv26R23aNEiSJKEs2fPYurUqfDz88OQIUMAmHcdTeUm1bxm5tw3tSkuLsbjjz+OgIAAeHt7Y9q0aXrvFQC2bNmCiRMnIiwsDK6uroiOjsY///lPqNVqeZ8RI0bgp59+QnJysnxNIyMj5edLS0uxaNEidOjQAW5ubggNDcXkyZNx+fJlgzJ99NFHiI6OhqurK2JjY3HkyJE630fNnIy6ylNWVoaFCxeiffv2cHV1RXh4OF588UWUlZXpnVeSJMyePRtffPEFunbtCldXV2zduhWA9r4ZNGgQAgIC4O7ujr59++Kbb74xOL6oqAifffaZXA7d9TOVk7Ny5Ur5tcLCwjBr1iyDHLoRI0agW7duOHv2LEaOHAmVSoXWrVvjrbfeMqib9957D127doVKpYKfnx/69euHL7/8stb6NJan8sgjj8DT0xPXrl3DpEmT4OnpiaCgIDz//PN694IxkZGROHPmDH755Re5HnSfMbp6+OWXXzBz5ky0atUKbdq0AQAkJydj5syZ6NixI9zd3REQEID77rvPoM6M5eSYW0eNfa/Z2dl4+OGH4e3tDV9fX8THx+O3335rsXk+jvkTlUw6c+YMhg4dCm9vb7z44otwdnbGf/7zH4wYMQK//PILBgwYAED7pbhkyRI8+uij6N+/P/Lz83H06FEcP34cY8aMAQBMmTIFZ86cwVNPPYXIyEhkZmYiISEBKSkpeh/g1c2fPx8dO3bERx99hFdffRVRUVGIjo5u0HtZunQpFAoFnn/+eeTl5eGtt97CQw89hEOHDsn7JCQk4M4770RoaCieeeYZhISE4Ny5c/jxxx/xzDPP4PHHH8f169eRkJCAdevWWaz+dJ566in4+flh4cKFuHr1KlasWIHZs2djw4YNJl/j/vvvx4svvoiNGzfihRde0Htu48aNGDt2LPz8/AAAO3fuxB133IG+ffti4cKFUCgUWLt2LW6//Xb8+uuv6N+/v97x9913H2JiYvDGG29ACAGgYdfRFHPum9rMnj0bvr6+WLRoES5cuIBVq1YhOTlZ/tIAtF9Cnp6emDNnDjw9PbFz504sWLAA+fn5ePvttwFo77O8vDz8+eef+Ne//gUA8PT0BACo1WrceeedSExMxAMPPIBnnnkGBQUFSEhIwOnTp/Xuxy+//BIFBQV4/PHHIUkS3nrrLUyePBlXrlyBs7Oz2fVSW3k0Gg3uvvtu7N27F4899hg6d+6MU6dO4V//+hf++OMPg/yZnTt3YuPGjZg9ezYCAwPla/Tuu+/i7rvvxkMPPYTy8nKsX78e9913H3788UdMnDgRALBu3Tr52jz22GMAUOvf36JFi7B48WKMHj0aTz75pHxNjhw5gn379unVQU5ODsaPH4/Jkyfj/vvvxzfffIOXXnoJ3bt3xx133AEAWL16NZ5++mn85S9/wTPPPIPS0lL8/vvvOHToEKZOnWp2feqo1WqMGzcOAwYMwDvvvIMdO3Zg2bJliI6OxpNPPmnyuBUrVuCpp56Cp6cn5s+fDwAIDg7W22fmzJkICgrCggUL5JacI0eOYP/+/XjggQfQpk0bXL16FatWrcKIESNw9uxZqFSqWstrTh015r1qNBrcddddOHz4MJ588kl06tQJW7ZskX9Ytki27i8jyzEnr2HSpEnCxcVFXL58Wd52/fp14eXlJYYNGyZv69mzp5g4caLJ8+Tk5DQ4Z8FUOdu2bWs0V2D48OF6fee7du0SAETnzp1FWVmZvP3dd98VAMSpU6eEENocg6ioKNG2bVuRk5Ojd87qeQe15eQAEAsXLpQfm1t/uvc4evRovdf6+9//LpRKpcjNzTX6ejoDBw4Uffv21dt2+PBhAUD897//ld9DTEyMGDdunN5rFBcXi6ioKDFmzBh528KFCwUA8eCDD+qd09zrWLMedGpes7ruG1N09dW3b19RXl4ub3/rrbcEALFlyxZ5W3FxscHxjz/+uFCpVKK0tFTeZioHZs2aNQKAWL58ucFzunrU5eQEBASImzdvys9v2bJFABA//PBDre9Hd4/u2rWrzvKsW7dOKBQK8euvv+pt//DDDwUAsW/fPnkbAKFQKMSZM2cMzlOzXsrLy0W3bt3E7bffrrfdVE6O7hokJSUJIYTIzMwULi4uYuzYsXq5Je+//74AINasWSNvGz58uN69KYQQZWVlIiQkREyZMkXeds8994iuXbsavHZddNdj7dq18rb4+HgBQLz66qt6+/bu3dvgb8cYUzk5unoYMmSIQV6MsXvvwIEDBu/d2PU3t44a816//fZbAUCsWLFC3qZWq8Xtt99ucM6Wgt1VLYharcb27dsxadIktGvXTt4eGhqKqVOnYu/evcjPzwegzZc5c+YMLl68aPRc7u7ucHFxwe7duw26E6xl+vTpcHFxkR8PHToUAHDlyhUA2m6lpKQkPPvsswb5Pw3JO6hP/ek89thjeq81dOhQqNVqo11R1cXFxeHYsWN63ScbNmyAq6sr7rnnHgDAyZMncfHiRUydOhXZ2dnIyspCVlYWioqKMGrUKOzZswcajUbvvE888YTeY0tfx7rum7o89thjeq0DTz75JJycnPDzzz/rlVmnoKAAWVlZGDp0KIqLi3H+/Pk6X+Pbb79FYGAgnnrqKYPnat4XcXFxcqsZYHiPWcLXX3+Nzp07o1OnTvI1zMrKwu233w4A2LVrl97+w4cPR5cuXQzOU71ecnJykJeXh6FDh+L48eMNKteOHTtQXl6OZ599Vi+3ZMaMGfD29sZPP/2kt7+npyf++te/yo9dXFzQv39/vbry9fXFn3/+aVaXn7lq3tNDhw61yPWZMWOGQV5M9TquqKhAdnY22rdvD19fX7Pq2Zw6qk1d73Xr1q1wdnbGjBkz5G0KhQKzZs0y6/yOiEFOC3Ljxg0UFxejY8eOBs917twZGo0GqampAIBXX30Vubm56NChA7p3744XXngBv//+u7y/q6sr3nzzTfzvf/9DcHAwhg0bhrfeegvp6elWez8RERF6j3VfRrova12A0K1bN4u8Xn3qz9wymnLfffdBoVDI3VpCCHz99ddyLhAAOZCIj49HUFCQ3r+PP/4YZWVlyMvL0ztvVFSU3mNLX8e67pu6xMTE6D329PREaGioXs7DmTNncO+998LHxwfe3t4ICgqSvzhqvl9jLl++jI4dO5qVUN7Q61cfFy9exJkzZwyuYYcOHQDcStTXqXkNdX788UfcdtttcHNzg7+/P4KCgrBq1Sqz6sQYXSBe8353cXFBu3btDAL1Nm3aGASJfn5+enX10ksvwdPTE/3790dMTAxmzZplkD9WH25ubggKCqr1NRvKWD2XlJRgwYIFCA8Ph6urKwIDAxEUFITc3Fyz6tmcOjLFnPeanJyM0NBQg26z9u3b13l+R8Ugh4waNmwYLl++jDVr1qBbt274+OOP0adPH3z88cfyPs8++yz++OMPLFmyBG5ubnjllVfQuXNnnDhxokGvaap1xVQSoanRB6Iq18QeNLSMYWFhGDp0KDZu3AgAOHjwIFJSUhAXFyfvo2ulefvtt5GQkGD0ny7vQ6f6L1GdxlzHmtfGnPumMXJzczF8+HD89ttvePXVV/HDDz8gISEBb775JgAYtFw1ljXuMY1Gg+7du5u8hjNnztTb39g1/PXXX3H33XfDzc0NK1euxM8//4yEhARMnTrVan8P5tRV586dceHCBaxfvx5DhgzBt99+iyFDhmDhwoUWfU1LMFbPTz31FF5//XXcf//92LhxI7Zv346EhAQEBASYde815n7iaKuGYeJxCxIUFASVSoULFy4YPHf+/HkoFAqEh4fL2/z9/TF9+nRMnz4dhYWFGDZsGBYtWoRHH31U3ic6OhrPPfccnnvuOVy8eBG9evXCsmXL8Pnnn9e7fH5+fkZnPk5OTtbrHjKXLqHy9OnTGD16tMn9zO26qm/9NVZcXBxmzpyJCxcuYMOGDVCpVLjrrrvk53Xvz9vbu9b3Z466rqOxa1NeXo60tDSDc5lz35hy8eJFjBw5Un5cWFiItLQ0TJgwAYB21Ep2djY2bdqEYcOGyfslJSUZnMvUdY2OjsahQ4dQUVFRr+ThxqqtPL/99htGjRrV4OHb3377Ldzc3LBt2za4urrK29euXWt2OWpq27YtAODChQt6f3/l5eVISkpq8D3n4eGBuLg4xMXFoby8HJMnT8brr7+OefPmwc3NrUHnbIiG1PU333yD+Ph4LFu2TN5WWlpqNzO2t23bFrt27UJxcbFea46xUactBVtyWhClUomxY8diy5Ytes3/GRkZ+PLLLzFkyBC5KyQ7O1vvWE9PT7Rv314e0lpcXGwwP0d0dDS8vLwMhr2aKzo6GgcPHkR5ebm87ccffzToAjJXnz59EBUVhRUrVhh8CFX/5aSbbbmuD6r61J8lTJkyBUqlEl999RW+/vpr3HnnnXozQ/ft2xfR0dF45513UFhYaHB8XUPVAfOvY3R0NPbs2aO330cffWR0+Gp1Ne+bunz00UeoqKiQH69atQqVlZXyyBPdr9nq16+8vBwrV640OJeHh4fRLoQpU6YgKysL77//vsFzTdnqYao8999/P65du4bVq1cbPFdSUmLWHC1KpRKSJOldj6tXrxqd2djDw8OsL+XRo0fDxcUF//73v/Xq5ZNPPkFeXp48Yqs+at4fLi4u6NKlC4QQetfdGsyth+qUSqXBPfLee+/VOWTdWsaNG4eKigq9e0mj0cjTZLREbMlxQGvWrJHnzqjumWeewWuvvYaEhAQMGTIEM2fOhJOTE/7zn/+grKxMb76GLl26YMSIEejbty/8/f1x9OhRfPPNN5g9ezYA4I8//sCoUaNw//33o0uXLnBycsLmzZuRkZGBBx54oEHlfvTRR/HNN99g/PjxuP/++3H58mV8/vnnDR5irlAosGrVKtx1113o1asXpk+fjtDQUJw/fx5nzpzBtm3bAGiDBQB4+umnMW7cOCiVSpPvwdz6s4RWrVph5MiRWL58OQoKCvS6qnTv7+OPP8Ydd9yBrl27Yvr06WjdujWuXbuGXbt2wdvbGz/88EOtr2HudXz00UfxxBNPYMqUKRgzZgx+++03bNu2DYGBgXrnq+u+qUt5eblcngsXLmDlypUYMmQI7r77bgDAoEGD4Ofnh/j4eDz99NOQJAnr1q0zGpz07dsXGzZswJw5cxAbGwtPT0/cddddmDZtGv773/9izpw5OHz4MIYOHYqioiLs2LEDM2fOlBO7Lc1UeR5++GFs3LgRTzzxBHbt2oXBgwdDrVbj/Pnz2LhxI7Zt24Z+/frVeu6JEydi+fLlGD9+PKZOnYrMzEx88MEHaN++vUFOVN++fbFjxw4sX74cYWFhiIqKMpj6ANC2XM6bNw+LFy/G+PHjcffdd8vXJDY2Vi+B1lxjx45FSEgIBg8ejODgYJw7dw7vv/8+Jk6cCC8vr3qfrzH69u2LVatW4bXXXkP79u3RqlUrOdnblDvvvBPr1q2Dj48PunTpggMHDmDHjh0ICAiwUqlrN2nSJPTv3x/PPfccLl26hE6dOuH777/HzZs3ATSs9arZs8WQLmoauqGPpv6lpqYKIYQ4fvy4GDdunPD09BQqlUqMHDlS7N+/X+9cr732mujfv7/w9fUV7u7uolOnTuL111+Xh/dmZWWJWbNmiU6dOgkPDw/h4+MjBgwYIDZu3Gh2OY0NdV+2bJlo3bq1cHV1FYMHDxZHjx41OYT866+/1jvW2NBLIYTYu3evGDNmjPDy8hIeHh6iR48e4r333pOfr6ysFE899ZQICgoSkiTpDSeHkaHT5tSfqfdobGhpbVavXi0ACC8vL1FSUmJ0nxMnTojJkyeLgIAA4erqKtq2bSvuv/9+kZiYKO+jG0J+48YNvWPNvY5qtVq89NJLIjAwUKhUKjFu3Dhx6dIlgyHkdd03pujq65dffhGPPfaY8PPzE56enuKhhx4S2dnZevvu27dP3HbbbcLd3V2EhYWJF198UWzbts2gXgsLC8XUqVOFr6+vAKA3fLu4uFjMnz9fREVFCWdnZxESEiL+8pe/yFMD1Lasg7F7oiZj17m28pSXl4s333xTdO3aVbi6ugo/Pz/Rt29fsXjxYpGXl6f32rNmzTL6mp988omIiYkRrq6uolOnTmLt2rXyda/u/PnzYtiwYcLd3V0AkK9fzSHkOu+//77o1KmTcHZ2FsHBweLJJ580mJJh+PDhRoeGx8fH673P//znP2LYsGHyvRodHS1eeOEFvfdojKlh1R4eHgb7GnvPxqSnp4uJEycKLy8vAUD+jKnt8yknJ0dMnz5dBAYGCk9PTzFu3Dhx/vx5g78DU0PIzamjxr7XGzduiKlTpwovLy/h4+MjHnnkEbFv3z4BQKxfv77OenE0khB2lKVJREREFvXdd9/h3nvvxd69ezF48GBbF8eqGOQQERE5iJKSEr2RYWq1GmPHjsXRo0eRnp5udNSYI2NODhERkYN46qmnUFJSgoEDB6KsrAybNm3C/v378cYbb7S4AAdgSw4REZHD+PLLL7Fs2TJcunQJpaWlaN++PZ588kmzk/8dDYMcIiIickicJ4eIiIgcEoMcIiIickgtOvFYo9Hg+vXr8PLyapmTJBERETVDQggUFBQgLCwMCoXp9poWHeRcv37domsNERERkfWkpqaiTZs2Jp9v0UGObhrx1NRUi645VFFRge3bt2Ps2LFWXQCwJWJdWw/r2npY19bDurYuS9V3fn4+wsPD61wOpEUHObouKm9vb4sHOSqVCt7e3vyjaWKsa+thXVsP69p6WNfWZen6rivVhInHRERE5JAY5BAREZFDYpBDREREDolBDhERETkkBjlERETkkBjkEBERkUNikENEREQOiUEOEREROSQGOUREROSQGOQQERGRQ2KQQ0RERA6JQY6VpOWVYP/lLKTlldi6KERERC1Ci16g01o2HEnBvE2noBGAQgKWTO6OuNgIWxeLiIjIobElp4ml5ZVgblWAAwAaAby86TRbdIiIiJoYg5wmlpRVBCH0t6mFwNWsYtsUiIiIqIVgkNPEogI9DLYpJQmRgSoblIaIiKjlYJDTxEK83eDurJQfKyTgjcndEOrjbsNSEREROT4mHjex1JslKKlQy48/iY/FyE6tbFgiIiKiloEtOU3s1LU8vceFZZU2KgkREVHLwiCnif1+LVfvccpNJhwTERFZA4OcJnbqT21LTpiPGwAgObvIlsUhIiJqMRjkNCGNRsjdVRN7hAIAkrPZkkNERGQNDHKaUEpOMQpKK+HipMDozsHabeyuIiIisgoGOU3o1LV8AECXUG+0b+UJAEjPL0VptdFWRERE1DQY5DShM9e1QU6PNj7w93CBp6sThAD+zGFrDhERUVNjkNOEdC053Vr7QJIkRPhrZzlmXg4REVHTY5DTRDRCvyUHANoGMMghIiKyFgY5TeRGKVBUroabswLtg7T5OBFVQQ6Tj4mIiJoeg5wmklIoAQC6hvnASamt5rb+2sU6OVcOERFR02OQ00RSi7RBTvfWPvI2dlcRERFZD4OcJpJaaBjk6BKPU3OKodYIm5SLiIiopWCQ0wTUGoE/q3qkdEnHABDm6w5npYQKtUBaXomNSkdERNQyMMhpAlduFKFcI0HlokS7qqRjAFAqJIT7VSUfs8uKiIioSTHIaQK/XsoCALQP8oBSIek9pxthlcwRVkRERE2KQY6FbTiSgiVb/wCgnQxww5EUvefbckJAIiIiq2CQY0FpeSWYt+mU/FgAeHnTab38m4gA7TDylJscRk5ERNSUGORYUFJWEWoOmlILgatZt1pt2JJDRERkHQxyLCgq0AM1UnCglCREBqrkx7q5clKyiyEEh5ETERE1FQY5FhTq444lk7vLgY5CAt6Y3A2hPu7yPuFVLTkFZZXIKa6wRTGJiIhaBCdbF8DRxMVGYGCUHzb+vAv3TxiJiEAvvefdnJUI8XZDen4prmYXwd/DxUYlJSIicmxsyWkCoT5uiPERCPVxM/p89S4rIiIiahoMcmyAa1gRERE1PQY5NtC2ahh5ch3DyNPySrD/chaXgCAiImoA5uTYgG6hztq6qzYcScG8TaegEdoE5iWTuyMuNsJaRSQiImr22JJjA7ruqouZhUZbaXSTCurm3NEIw0kFiYiIqHYMcmzgWHIOACCvpAKDl+40WPrBnEkFiYiIqHYMcqwsLa8E//zxrPzYWCtNcbna4LiakwoSERFR7RjkWFldrTQl5Wq88fM5g+Nev1d/UkEiIiKqHYMcKzO29AMApOeXIi2vBM9uOIErN4oQ7O2KH54aDGXVFRrcPtC6BSUiImrmGORYmW7pB6WkH+k8t/EkBi3ZiW1nMgAAE7qHontrX3QK8QYAnLmeb/WyEhERNWcMcmwgLjYCe+eOxFczbsOeF0ZgTOdgaARQvRfrv/uTkZZXgq5huiAnzzaFJSIiaqYY5NhIqI87BkYHICLAA48MijR4Xpen0621DwDg9DUGOURERPXByQDtQLtW2jyd6gnJutFULk7aOJTdVURERPXDlhw7UDNPRylJeGOydjRV51AvSBKQWVCGzPxSG5eUiIio+WBLjp2Ii43AsA5BuJpVjMhAlTxcXOXihOggT1zKLMSZ6/lo5W18ZXMiIiLSx5YcO6LL06k5H043Jh8TERHVG4OcZqBrmC75mHk5RERE5mKQ0wx0ba1tyTnNlhwiIiKzMchpBnQtOX/mlCCvuMLGpSEiImoeGOQ0Az7uzgj31+bpMC+HiIjIPAxymoluurwcBjlERERmsasg54MPPkBkZCTc3NwwYMAAHD582Kzj1q9fD0mSMGnSpKYtoA3pZj7mpIBERETmsZsgZ8OGDZgzZw4WLlyI48ePo2fPnhg3bhwyMzNrPe7q1at4/vnnMXToUCuV1Da6VA0j5/IORERE5rGbIGf58uWYMWMGpk+fji5duuDDDz+ESqXCmjVrTB6jVqvx0EMPYfHixWjXrp0VS2t9uu6qK1lFKCqrtHFpiIiI7J9dBDnl5eU4duwYRo8eLW9TKBQYPXo0Dhw4YPK4V199Fa1atcLf/vY3axTTpoK8XNHKyxVCAOfS2GVFRERUF7tY1iErKwtqtRrBwcF624ODg3H+/Hmjx+zduxeffPIJTp48afbrlJWVoaysTH6cn68NFioqKlBRYbmh2bpzWfKcANAl1AuZBWXYcuJPtPJ0RqgPl3hoqromQ6xr62FdWw/r2rosVd/mHm8XQU59FRQU4OGHH8bq1asRGBho9nFLlizB4sWLDbZv374dKpXKkkUEACQkJFj0fDcyFQAUWHcoFZ8fSkFcOw0GBos6j2sJLF3XZBrr2npY19bDurauxtZ3cXGxWftJQgibf0uWl5dDpVLhm2++0RshFR8fj9zcXGzZskVv/5MnT6J3795QKpXyNo1GA0DbzXXhwgVER0cbvI6xlpzw8HBkZWXB29vbYu+noqICCQkJGDNmDJydnS1yzrS8Ugx/Zw+qXyyFBOx+bliLbtFpirom41jX1sO6th7WtXVZqr7z8/MRGBiIvLy8Wr+/7aIlx8XFBX379kViYqIc5Gg0GiQmJmL27NkG+3fq1AmnTp3S2/aPf/wDBQUFePfddxEeHm70dVxdXeHq6mqw3dnZuUlubkue98+8PNSMRjUCuJZXjohAL4u8RnPWVNeQDLGurYd1bT2sa+tqbH2be6xdBDkAMGfOHMTHx6Nfv37o378/VqxYgaKiIkyfPh0AMG3aNLRu3RpLliyBm5sbunXrpne8r68vABhsdxRRgR5QSNrARkcpSYgMtHw3GxERkSOwmyAnLi4ON27cwIIFC5Ceno5evXph69atcjJySkoKFAq7GAxmE6E+7lgyuTte+lbbgiVJwBuTuyHUx93GJSMiIrJPdhPkAMDs2bONdk8BwO7du2s99tNPP7V8gexMXGwE9l/OxpaT1zHttraIi42wdZGIiIjsVsttGmmmeof7AgCu5ZbYtiBERER2jkFOM9MxRJtFfj69wMYlISIism8McpqZTiHakVR/5pSgkMs7EBERmcQgp5nx83BBKy/tMPgLbM0hIiIyiUFOM9SxqjXnjwwGOURERKYwyGmGdF1WbMkhIiIyjUFOM3Qr+ZirkRMREZnCIKcZ6hh8qyXHDpYeIyIisksMcpqhmGBPKCQgp7gCNwrK6j6AiIioBWKQ0wy5OSsRGeABALjA5GMiIiKjGOQ0Ux2ZfExERFQrBjnNlC7I4czHRERExjHIaaY4jJyIiKh2DHKaqQ7BtyYEVGs4woqIiKgmBjnNVNsAD7g5K1BWqUFydpGti0NERGR3GOQ0U0qFhJhWXN6BiIjIFAY5zRiTj4mIiExjkNOMMfmYiIjINAY5zRjnyiEiIjKNQU4zplvDKimrCFezmHxMRERUHYOcZmzn+UwAgAAwctlubDiSYtsCERER2REGOc1UWl4JXt58Sn4sBPDyptNIyyuxYamIiIjsB4OcZiopqwg15wBUC4GrWcW2KRAREZGdYZDTTEUFekAh6W9TShIiA1W2KRAREZGdYZDTTIX6uGPJ5O56gc68CZ0Q6uNuu0IRERHZEQY5zVhcbAT2zb0dEf7a1psQHzcbl4iIiMh+MMhp5kJ93DGqcysAwMEr2TYuDRERkf1gkOMAbmsXAAA4eOWmjUtCRERkPxjkOIABUf6QJOBSZiFuFJTZujhERER2gUGOA/BVuaBTiDcA4FASu6yIiIgABjkO47Z2/gCYl0NERKTDIMdBMC+HiIhIH4McB8G8HCIiIn0MchwE83KIiIj0MchxIMzLISIiuoVBjgNhXg4REdEtDHIcCPNyiIiIbmGQ40Cq5+WsO3gVaXklNi4RERGR7TDIcTD+Hs4AgH8nXsLgpTux4UiKjUtERERkGwxyHEhaXgn2X7qVdKwRwMubTrNFh4iIWiQGOQ4kKasIosY2tRC4mlVsk/IQERHZEoMcBxIV6AGFpL9NKUmIDFTZpkBEREQ2xCDHgYT6uGPJ5O7yY0kC3pjcDaE+7jYsFRERkW0wyHEwcbERuKdXGADgkYGRiIuNsHGJiIiIbINBjgPqFuYDAMgs5Fw5RETUcjHIcUDtgjwAAFduFNm4JERERLbDIMcBtQvyBABczSqCRlNzvBUREVHLwCDHAbXxc4eTQkJJhRrp+aW2Lg4REZFNMMhxQM5KBSICtMPG2WVFREQtFYMcB9UuUNtldSWr0MYlISIisg0GOQ4qmsnHRETUwjHIcVBRgVVBThaDHCIiapkY5Dgo3QirKzfYXUVERC0TgxwHpZsr51puCUor1DYuDRERkfUxyHFQAR4u8HJzghBAcjZXISciopaHQY6DkiSJXVZERNSiMchxYNFMPiYiohaMQY4D4xpWRETUkjHIcWBRnBCQiIhaMAY5Dqx6S44QXKiTiIhaFrsKcj744ANERkbCzc0NAwYMwOHDh03uu2nTJvTr1w++vr7w8PBAr169sG7dOiuW1v5FBXpAkoC8kgrcLCq3dXGIiIisym6CnA0bNmDOnDlYuHAhjh8/jp49e2LcuHHIzMw0ur+/vz/mz5+PAwcO4Pfff8f06dMxffp0bNu2zcolt19uzkqE+bgDAJKYfExERC2M3QQ5y5cvx4wZMzB9+nR06dIFH374IVQqFdasWWN0/xEjRuDee+9F586dER0djWeeeQY9evTA3r17rVxy+8bkYyIiaqnsIsgpLy/HsWPHMHr0aHmbQqHA6NGjceDAgTqPF0IgMTERFy5cwLBhw5qyqM1Ou6ph5JeZfExERC2Mk60LAABZWVlQq9UIDg7W2x4cHIzz58+bPC4vLw+tW7dGWVkZlEolVq5ciTFjxpjcv6ysDGVlZfLj/Px8AEBFRQUqKioa+S5u0Z3LkudsqLb+2u6qyxkFdlEeS7OnunZ0rGvrYV1bD+vauixV3+YebxdBTkN5eXnh5MmTKCwsRGJiIubMmYN27dphxIgRRvdfsmQJFi9ebLB9+/btUKlUFi9fQkKCxc9ZXzdyJQBKnErOxM8//2zr4jQZe6jrloJ1bT2sa+thXVtXY+u7uNi85YokYQdji8vLy6FSqfDNN99g0qRJ8vb4+Hjk5uZiy5YtZp3n0UcfRWpqqsnkY2MtOeHh4cjKyoK3t3ej3kN1FRUVSEhIwJgxY+Ds7Gyx8zbEtdwSjFj2K5yVEn5/ZRSclHbRQ2kx9lTXjo51bT2sa+thXVuXpeo7Pz8fgYGByMvLq/X72y5aclxcXNC3b18kJibKQY5Go0FiYiJmz55t9nk0Go1eEFOTq6srXF1dDbY7Ozs3yc3dVOetj4gAJ7g5K1BaoUFGYSUiq3J0HI091HVLwbq2Hta19bCuraux9W3usXYR5ADAnDlzEB8fj379+qF///5YsWIFioqKMH36dADAtGnT0Lp1ayxZsgSAtuupX79+iI6ORllZGX7++WesW7cOq1atsuXbsDsKhYTIAA+cTy/AT6euY3KfNgitGlZORETkyOwmyImLi8ONGzewYMECpKeno1evXti6daucjJySkgKF4lZXS1FREWbOnIk///wT7u7u6NSpEz7//HPExcXZ6i3YLWelBAB4e9sfWLb9DyyZ3B1xsRE2LhUREVHTspsgBwBmz55tsntq9+7deo9fe+01vPbaa1YoVfOWlleC09fy5ccaAby86TSGdQhiiw4RETk0x8pCJQNJWUWomVmuFgJXs8zLTCciImquGOQ4ON36VdUpJQmRgZYfMk9ERGRPGOQ4uFAfd7w4rqP8WCkBb0zuxq4qIiJyeAxyWoAZQ9tBUdWas2nmICYdExFRi8AgpwVwUirQ2k/bclNWafO5H4mIiKyCQU4LEe6nzcFJvcmEYyIiahkY5LQQEf5VQU4OgxwiImoZGOS0EOG6IOdmiY1LQkREZB0MclqINlU5OWzJISKiloJBTguha8n5kzk5RETUQjDIaSF0icdp+aUoq1TbuDRERERNj0FOCxHo6QJ3ZyWEAK7nltq6OERERE3O7AU6v//++3qffMyYMXB358y69kCSJLTxc8fFzEKk3ixGVKCHrYtERETUpMwOciZNmlSvE0uShIsXL6Jdu3b1LRM1kXB/lTbIYfIxERG1APXqrkpPT4dGozHrn0rFBSDtTbhuhBWHkRMRUQtgdpATHx9fr66nv/71r/D29m5QoahphHNCQCIiakHM7q5au3ZtvU68atWqeheGmhaHkRMRUUvC0VUtiLx+VQ67q4iIyPHVO8jJz89HeXm5wXaNRoP33nvPIoWiphHur+1uvFlUjsKyShuXhoiIqGnVK8hZuXIl/P390b59e5SU6LcGKBQKDB48GBs2bLBoAclyvNyc4atyBsDVyImIyPHVK8g5ePAg9u/fj4kTJ8LZ2dng+T59+uDDDz+0WOHI8uQuKwY5RETk4OoV5AwbNgwajQarVq2Ck5NhzvKxY8dw5MgRixWOLE/XZcW8HCIicnRmj64CgEceeQTDhw/HuHHjMGHCBPTu3RtKpVJ+/tNPP+WwcTvHlhwiImop6tWS4+TkhK+//hq//PIL+vfvDx8fH4wbNw7Lli1DamoqNBoNOnbs2FRlJQtooxtGzrlyiIjIwdV7dFVYWBgSExOxb98+PPPMMygtLcUrr7yCdu3aYc+ePQgJCWmKcpKFcNZjIiJqKerVXVXdwIEDMXDgQABARUUFDh8+jB07djAnx85FVJv1WAgBSZJsXCIiIqKm0eAgpzpnZ2cMHjwYgwcPxvHjxy1xSmoirf3cIUlAcbkaN4vKEeDpausiERERNQmzu6t+//13aDSaOvfr06cPAODMmTOorOSEc/bG1UmJYC83AEAKk4+JiMiBmR3k9O7dG9nZ2WafeODAgUhJSWlQoahpcRg5ERG1BGZ3Vwkh8Morr0ClUpm1v7GlH8g+hPupcORqDoeRExGRQzM7yBk2bBguXLhg9okHDhwId3f3BhWKmhaHkRMRUUtgdpCze/fuJiwGWROHkRMRUUtQ73lyqPkLr2rJuZhZgLQ8BjpEROSYGOS0QCdTcwEAGfllGLx0JzYcYYI4ERE5HgY5LUxaXgne2npefqwRwMubTrNFh4iIHA6DnBYmKasIGqG/TS0ErmYxCZmIiBwLg5wWJirQA4oaKzkoJQmRgeZNDUBERNRcNCjIKSkpQXHxrV/+ycnJWLFiBbZv326xglHTCPVxx5LJ3eXHkgS8MbkbQn043J+IiBxLg4Kce+65B//9738BALm5uRgwYACWLVuGe+65B6tWrbJoAcny4mIjMKJjEADg76M7IC42wsYlIiIisrwGBTnHjx/H0KFDAQDffPMNgoODkZycjP/+97/497//bdECUtPQtdxohKhjTyIiouapQUFOcXExvLy8AADbt2/H5MmToVAocNtttyE5OdmiBaSm4adyBgDkFlfYuCRERERNo0FBTvv27fHdd98hNTUV27Ztw9ixYwEAmZmZ8Pb2tmgBqWn4qVwAADnFXGOMiIgcU4OCnAULFuD5559HZGQkBgwYgIEDBwLQtur07t3bogWkpuFb1ZKTw5YcIiJyUGavXVXdX/7yFwwZMgRpaWno2bOnvH3UqFG49957LVY4ajq6lpxctuQQEZGDalCQU1JSAm9vb4SEhADQDiHfvHkzOnfujP79+1u0gNQ0/Dx0LTkMcoiIyDFZdAj5pEmTOIS8mfDVteQUsbuKiIgcE4eQt1C67qqCskpUqDU2Lg0REZHlcQh5C+Xj7gypankHDiMnIiJHxCHkLZRSIcHbTTdXDvNyiIjI8XAIeQvmx2HkRETkwDiEvAXzVbkA2cUcYUVERA6pQUEOAISEhMhDyHU4fLx5ubW0A4McIiJyPA0OcnJzc/HJJ5/g3LlzAICuXbvi//7v/+Dj42OxwlHTurW0A7uriIjI8TQoJ+fo0aOIjo7Gv/71L9y8eRM3b97E8uXLER0djePHj1u6jNREfLl+FRERObAGteT8/e9/x913343Vq1fDyUl7isrKSjz66KN49tlnsWfPHosWkpqG3F3FCQGJiMgBNSjIOXr0qF6AAwBOTk548cUX0a9fP4sVjpqWrwdbcoiIyHE1qLvK29sbKSkpBttTU1PlSQLJ/t1KPGZLDhEROZ4GBTlxcXH429/+hg0bNiA1NRWpqalYv349Hn30UTz44IOWLiM1ET/m5BARkQNrUHfVO++8A0mSMG3aNFRWVgIAnJ2d8eSTT+LNN9+0aAGp6fhyMkAiInJgDWrJcXFxwbvvvoucnBycPHkSJ0+exM2bN/Hcc89h9uzZli4jNRFdS05ucTmEEDYuDRERkWU1KMjRUalU6N69O7p37w6VSoXs7Gx88sknliobNTFdkFOpESgsq7RxaYiIiCyrUUGOpX3wwQeIjIyEm5sbBgwYgMOHD5vcd/Xq1Rg6dCj8/Pzg5+eH0aNH17o/GXJ3UcLVSXsLMPmYiIgcjd0EORs2bMCcOXOwcOFCHD9+HD179sS4ceOQmZlpdP/du3fjwQcfxK5du3DgwAGEh4dj7NixuHbtmpVL3rwx+ZiIiByV3QQ5y5cvx4wZMzB9+nR06dIFH374IVQqFdasWWN0/y+++AIzZ85Er1690KlTJ3z88cfQaDRITEy0csmbNyYfExGRo6rX6KrJkyfX+nxubm6DClFeXo5jx45h3rx58jaFQoHRo0fjwIEDZp2juLgYFRUV8Pf3N7lPWVkZysrK5Mf5+fkAgIqKClRUWO5LXncuS56zqfi6a2+BrPySZlHemppTXTd3rGvrYV1bD+vauixV3+YeX68gp67FN318fDBt2rT6nBIAkJWVBbVajeDgYL3twcHBOH/+vFnneOmllxAWFobRo0eb3GfJkiVYvHixwfbt27dDpVLVr9BmSEhIsPg5La00TwFAgf1HT8Lp2glbF6fBmkNdOwrWtfWwrq2HdW1dja3v4uJis/arV5Czdu3aBhWmqS1duhTr16/H7t274ebmZnK/efPmYc6cOfLj/Px8OZfH29vbYuWpqKhAQkICxowZA2dnZ4udtykcqDyLkzf/RFhUDCbc3t7Wxam35lTXzR3r2npY19bDurYuS9W3riemLg2aDNDSAgMDoVQqkZGRobc9IyMDISEhtR77zjvvYOnSpdixYwd69OhR676urq5wdXU12O7s7NwkN3dTndeSAjy19ZFfqrb7stamOdS1o2BdWw/r2npY19bV2Po291i7SDx2cXFB37599ZKGdUnEAwcONHncW2+9hX/+85/YunUrFwZtoFujq9gfTUREjsUuWnIAYM6cOYiPj0e/fv3Qv39/rFixAkVFRZg+fToAYNq0aWjdujWWLFkCAHjzzTexYMECfPnll4iMjER6ejoAwNPTE56enjZ7H82NL4eQExGRg7KbICcuLg43btzAggULkJ6ejl69emHr1q1yMnJKSgoUilsNT6tWrUJ5eTn+8pe/6J1n4cKFWLRokTWL3qxxJXIiInJUdhPkAMDs2bNNrn21e/duvcdXr15t+gK1AGzJISIiR2UXOTlkO2zJISIiR8Ugp4XTJR4XllWivFJj49IQERFZDoOcFs7b3RmSpP3/3BJ2WRERkeNgkNPCKRUSfNzZZUVERI6HQQ7dmiuniC05RETkOBjkEFciJyIih8Qgh+SWnFwOIyciIgfCIIfYkkNERA6JQQ6xJYeIiBwSgxySJwTkrMdERORIGORQtaUd2F1FRESOg0EO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DgDMmTMH8fHx6NevH/r3748VK1agqKhIHm01bdo0tG7dGkuWLAEAPPPMMxg+fDiWLVuGiRMnYv369Th69Cg++ugjW74NohatOX8YtmSOct0s9T4cpT7IjoKcuLg43LhxAwsWLEB6ejp69eqFrVu3IjhYO/dGSkoKFIpb8xUMGjQIX375Jf7xj3/g5ZdfRkxMDL777jt069bNVm+BiIiI7IjdBDkAMHv2bJPdU7t37zbYdt999+G+++5r4lIRERFRc2Q3Mx4TERERWRKDHCIiInJIDHKIiIjIITHIISIiIofEIIeIiIgcEoMcIiIickgMcoiIiMghMcghIiIih8Qgh4iIiBySXc14bG1CCADmL9luroqKChQXFyM/P5+rkDcx1rX1sK6th3VtPaxr67JUfeu+t3Xf46a06CCnoKAAABAeHm7jkhAREVF9FRQUwMfHx+TzkqgrDHJgGo0G169fh5eXFyRJsth58/PzER4ejtTUVHh7e1vsvGSIdW09rGvrYV1bD+vauixV30IIFBQUICwsTG/x7ppadEuOQqFAmzZtmuz83t7e/KOxEta19bCurYd1bT2sa+uyRH3X1oKjw8RjIiIickgMcoiIiMghMchpAq6urli4cCFcXV1tXRSHx7q2Hta19bCurYd1bV3Wru8WnXhMREREjostOUREROSQGOQQERGRQ2KQQ0RERA6JQQ4RERE5JAY5TeCDDz5AZGQk3NzcMGDAABw+fNjWRWrWlixZgtjYWHh5eaFVq1aYNGkSLly4oLdPaWkpZs2ahYCAAHh6emLKlCnIyMiwUYkdx9KlSyFJEp599ll5G+vasq5du4a//vWvCAgIgLu7O7p3746jR4/KzwshsGDBAoSGhsLd3R2jR4/GxYsXbVji5kmtVuOVV15BVFQU3N3dER0djX/+8596ax+xrhtmz549uOuuuxAWFgZJkvDdd9/pPW9Ovd68eRMPPfQQvL294evri7/97W8oLCxsfOEEWdT69euFi4uLWLNmjThz5oyYMWOG8PX1FRkZGbYuWrM1btw4sXbtWnH69Glx8uRJMWHCBBERESEKCwvlfZ544gkRHh4uEhMTxdGjR8Vtt90mBg0aZMNSN3+HDx8WkZGRokePHuKZZ56Rt7OuLefmzZuibdu24pFHHhGHDh0SV65cEdu2bROXLl2S91m6dKnw8fER3333nfjtt9/E3XffLaKiokRJSYkNS978vP766yIgIED8+OOPIikpSXz99dfC09NTvPvuu/I+rOuG+fnnn8X8+fPFpk2bBACxefNmvefNqdfx48eLnj17ioMHD4pff/1VtG/fXjz44IONLhuDHAvr37+/mDVrlvxYrVaLsLAwsWTJEhuWyrFkZmYKAOKXX34RQgiRm5srnJ2dxddffy3vc+7cOQFAHDhwwFbFbNYKCgpETEyMSEhIEMOHD5eDHNa1Zb300ktiyJAhJp/XaDQiJCREvP322/K23Nxc4erqKr766itrFNFhTJw4Ufzf//2f3rbJkyeLhx56SAjBuraUmkGOOfV69uxZAUAcOXJE3ud///ufkCRJXLt2rVHlYXeVBZWXl+PYsWMYPXq0vE2hUGD06NE4cOCADUvmWPLy8gAA/v7+AIBjx46hoqJCr947deqEiIgI1nsDzZo1CxMnTtSrU4B1bWnff/89+vXrh/vuuw+tWrVC7969sXr1avn5pKQkpKen69W3j48PBgwYwPqup0GDBiExMRF//PEHAOC3337D3r17cccddwBgXTcVc+r1wIED8PX1Rb9+/eR9Ro8eDYVCgUOHDjXq9Vv0Ap2WlpWVBbVajeDgYL3twcHBOH/+vI1K5Vg0Gg2effZZDB48GN26dQMApKenw8XFBb6+vnr7BgcHIz093QalbN7Wr1+P48eP48iRIwbPsa4t68qVK1i1ahXmzJmDl19+GUeOHMHTTz8NFxcXxMfHy3Vq7DOF9V0/c+fORX5+Pjp16gSlUgm1Wo3XX38dDz30EACwrpuIOfWanp6OVq1a6T3v5OQEf3//Rtc9gxxqVmbNmoXTp09j7969ti6KQ0pNTcUzzzyDhIQEuLm52bo4Dk+j0aBfv3544403AAC9e/fG6dOn8eGHHyI+Pt7GpXMsGzduxBdffIEvv/wSXbt2xcmTJ/Hss88iLCyMde3A2F1lQYGBgVAqlQYjTTIyMhASEmKjUjmO2bNn48cff8SuXbvQpk0beXtISAjKy8uRm5urtz/rvf6OHTuGzMxM9OnTB05OTnBycsIvv/yCf//733ByckJwcDDr2oJCQ0PRpUsXvW2dO3dGSkoKAMh1ys+UxnvhhRcwd+5cPPDAA+jevTsefvhh/P3vf8eSJUsAsK6bijn1GhISgszMTL3nKysrcfPmzUbXPYMcC3JxcUHfvn2RmJgob9NoNEhMTMTAgQNtWLLmTQiB2bNnY/Pmzdi5cyeioqL0nu/bty+cnZ316v3ChQtISUlhvdfTqFGjcOrUKZw8eVL+169fPzz00EPy/7OuLWfw4MEG0yH88ccfaNu2LQAgKioKISEhevWdn5+PQ4cOsb7rqbi4GAqF/leeUqmERqMBwLpuKubU68CBA5Gbm4tjx47J++zcuRMajQYDBgxoXAEalbZMBtavXy9cXV3Fp59+Ks6ePSsee+wx4evrK9LT021dtGbrySefFD4+PmL37t0iLS1N/ldcXCzv88QTT4iIiAixc+dOcfToUTFw4EAxcOBAG5bacVQfXSUE69qSDh8+LJycnMTrr78uLl68KL744guhUqnE559/Lu+zdOlS4evrK7Zs2SJ+//13cc8993BYcwPEx8eL1q1by0PIN23aJAIDA8WLL74o78O6bpiCggJx4sQJceLECQFALF++XJw4cUIkJycLIcyr1/Hjx4vevXuLQ4cOib1794qYmBgOIbdX7733noiIiBAuLi6if//+4uDBg7YuUrMGwOi/tWvXyvuUlJSImTNnCj8/P6FSqcS9994r0tLSbFdoB1IzyGFdW9YPP/wgunXrJlxdXUWnTp3ERx99pPe8RqMRr7zyiggODhaurq5i1KhR4sKFCzYqbfOVn58vnnnmGRERESHc3NxEu3btxPz580VZWZm8D+u6YXbt2mX0Mzo+Pl4IYV69ZmdniwcffFB4enoKb29vMX36dFFQUNDosklCVJvukYiIiMhBMCeHiIiIHBKDHCIiInJIDHKIiIjIITHIISIiIofEIIeIiIgcEoMcIiIickgMcoiIiMghMcghIpv59NNPDVY0r8vu3bshSZLB+lm2tmjRIvTq1cvWxSCiahjkELVwjzzyCCRJkv8FBARg/Pjx+P333+t1Hmt9yQ8aNAhpaWnw8fEB0LBAqbEkScJ3332nt+3555/XW5+HiGyPQQ4RYfz48UhLS0NaWhoSExPh5OSEO++809bFMsrFxQUhISGQJMmi51Wr1fJijQ3h6emJgIAAC5aIiBqLQQ4RwdXVFSEhIQgJCUGvXr0wd+5cpKam4saNG/I+L730Ejp06ACVSoV27drhlVdeQUVFBQBta8rixYvx22+/yS1Cn376KQAgNzcXjz/+OIKDg+Hm5oZu3brhxx9/1Hv9bdu2oXPnzvD09JQDLlOqd1ft3r0b06dPR15envy6ixYtAgCUlZXh+eefR+vWreHh4YEBAwZg9+7d8nl0LUDff/89unTpAldXV6SkpODIkSMYM2YMAgMD4ePjg+HDh+P48ePycZGRkQCAe++9F5IkyY9rtmRpNBq8+uqraNOmDVxdXdGrVy9s3bpVfv7q1auQJAmbNm3CyJEjoVKp0LNnTxw4cEDeJzk5GXfddRf8/Pzg4eGBrl274ueff67zehKRlpOtC0BE9qWwsBCff/452rdvr9cy4eXlhU8//RRhYWE4deoUZsyYAS8vL7z44ouIi4vD6dOnsXXrVuzYsQMA4OPjA41GgzvuuAMFBQX4/PPPER0djbNnz0KpVMrnLS4uxjvvvIN169ZBoVDgr3/9K55//nl88cUXdZZ10KBBWLFiBRYsWIALFy4A0LaoAMDs2bNx9uxZrF+/HmFhYdi8eTPGjx+PU6dOISYmRn7tN998Ex9//DECAgLQqlUrXLlyBfHx8XjvvfcghMCyZcswYcIEXLx4EV5eXjhy5AhatWqFtWvXYvz48Xrvpbp3330Xy5Ytw3/+8x/07t0ba9aswd13340zZ87Irw8A8+fPxzvvvIOYmBjMnz8fDz74IC5dugQnJyfMmjUL5eXl2LNnDzw8PHD27Fn5/RGRGRq9xCcRNWvx8fFCqVQKDw8P4eHhIQCI0NBQcezYsVqPe/vtt0Xfvn3lxwsXLhQ9e/bU22fbtm1CoVCYXMl57dq1AoC4dOmSvO2DDz4QwcHBJl9Xt+JxTk6OfA4fHx+9fZKTk4VSqRTXrl3T2z5q1Cgxb948vdc+efJkre9TrVYLLy8v8cMPP8jbAIjNmzfr7Vfz/YeFhYnXX39db5/Y2Fgxc+ZMIYQQSUlJAoD4+OOP5efPnDkjAIhz584JIYTo3r27WLRoUa3lIyLT2JJDRBg5ciRWrVoFAMjJycHKlStxxx134PDhw2jbti0AYMOGDfj3v/+Ny5cvo7CwEJWVlfD29q71vCdPnkSbNm3QoUMHk/uoVCpER0fLj0NDQ5GZmdmo93Pq1Cmo1WqD1y0rK9NrnXJxcUGPHj309snIyMA//vEP7N69G5mZmVCr1SguLkZKSorZr5+fn4/r169j8ODBetsHDx6M3377TW9b9dcPDQ0FAGRmZqJTp054+umn8eSTT2L79u0YPXo0pkyZYlBeIjKNOTlEBA8PD7Rv3x7t27dHbGwsPv74YxQVFWH16tUAgAMHDuChhx7ChAkT8OOPP+LEiROYP38+ysvLaz2vu7t7na/t7Oys91iSJAghGv5moO1yUyqVOHbsGE6ePCn/O3fuHN5991298tVMYI6Pj8fJkyfx7rvvYv/+/Th58iQCAgLqfK8NVf3968qiS4B+9NFHceXKFTz88MM4deoU+vXrh/fee69JykHkiBjkEJEBSZKgUChQUlICANi/fz/atm2L+fPno1+/foiJiUFycrLeMS4uLlCr1XrbevTogT///BN//PFHk5XV2Ov27t0barUamZmZcvCm+xcSElLr+fbt24enn34aEyZMQNeuXeHq6oqsrCy9fZydnQ1eszpvb2+EhYVh3759Bufu0qVLvd5feHg4nnjiCWzatAnPPfecHHgSUd3YXUVEKCsrQ3p6OgBtd9X777+PwsJC3HXXXQCAmJgYpKSkYP369YiNjcVPP/2EzZs3650jMjISSUlJcheVl5cXhg8fjmHDhmHKlClYvnw52rdvj/Pnz0OSJIwfP94iZY+MjERhYSESExPRs2dPqFQqdOjQAQ899BCmTZuGZcuWoXfv3rhx4wYSExPRo0cPTJw40eT5YmJisG7dOvTr1w/5+fl44YUXDFqkIiMjkZiYiMGDB8PV1RV+fn4G53nhhRewcOFCREdHo1evXli7di1OnjxpVkK1zrPPPos77rgDHTp0QE5ODnbt2oXOnTubXzlELRxbcogIW7duRWhoKEJDQzFgwAAcOXIEX3/9NUaMGAEAuPvuu/H3v/8ds2fPRq9evbB//3688soreueYMmUKxo8fj5EjRyIoKAhfffUVAODbb79FbGwsHnzwQXTp0gUvvvhira0g9TVo0CA88cQTiIuLQ1BQEN566y0AwNq1azFt2jQ899xz6NixIyZNmoQjR44gIiKi1vN98sknyMnJQZ8+ffDwww/j6aefRqtWrfT2WbZsGRISEhAeHo7evXsbPc/TTz+NOXPm4LnnnkP37t2xdetWfP/993ojq+qiVqsxa9YsdO7cGePHj0eHDh2wcuVKs48naukk0djObyIiIiI7xJYcIiIickgMcoiIiMghMcghIiIih8Qgh4iIiBwSgxwiIiJySAxyiIiIyCExyCEiIiKHxCCHiIiIHBKDHCIiInJIDHKIiIjIITHIISIiIofEIIeIiIgc0v8DFSk9DWzIc+sAAAAASUVORK5CYII=\n" |
|
|
1174 |
}, |
|
|
1175 |
"metadata": {} |
|
|
1176 |
} |
|
|
1177 |
], |
|
|
1178 |
"source": [ |
|
|
1179 |
"plt.figure()\n", |
|
|
1180 |
"plt.plot(results_dict[\"loss_history\"], \".-\")\n", |
|
|
1181 |
"plt.ylabel(\"Loss [$\\mathcal{L}$]\")\n", |
|
|
1182 |
"plt.xlabel(\"Batch iterations\")\n", |
|
|
1183 |
"plt.title(\"Loss function versus batch iterations in training\")\n", |
|
|
1184 |
"plt.grid()" |
|
|
1185 |
] |
|
|
1186 |
}, |
|
|
1187 |
{ |
|
|
1188 |
"cell_type": "markdown", |
|
|
1189 |
"metadata": { |
|
|
1190 |
"id": "bYEqtP5ha5MF" |
|
|
1191 |
}, |
|
|
1192 |
"source": [ |
|
|
1193 |
"Tuning the threshold $\\zeta$\n", |
|
|
1194 |
"============================\n", |
|
|
1195 |
"\n", |
|
|
1196 |
"When we have access to labelled anomalous series (as we do in our toy\n", |
|
|
1197 |
"problem here, often not the case in reality), we can tune the threshold\n", |
|
|
1198 |
"$\\zeta$ to maximize some success metric. We choose to maximize the\n", |
|
|
1199 |
"accuracy score as defined using the three electrons below.\n" |
|
|
1200 |
] |
|
|
1201 |
}, |
|
|
1202 |
{ |
|
|
1203 |
"cell_type": "code", |
|
|
1204 |
"execution_count": 24, |
|
|
1205 |
"metadata": { |
|
|
1206 |
"id": "v5VlKx0Xa5MF" |
|
|
1207 |
}, |
|
|
1208 |
"outputs": [], |
|
|
1209 |
"source": [ |
|
|
1210 |
"@ct.electron\n", |
|
|
1211 |
"def get_preds_given_threshold(zeta: float, scores: torch.Tensor) -> torch.Tensor:\n", |
|
|
1212 |
" \"\"\"For a given threshold, get the predicted labels (1 or -1), given the anomaly scores.\"\"\"\n", |
|
|
1213 |
" return torch.tensor([-1 if score > zeta else 1 for score in scores])\n", |
|
|
1214 |
"\n", |
|
|
1215 |
"\n", |
|
|
1216 |
"@ct.electron\n", |
|
|
1217 |
"def get_truth_labels(\n", |
|
|
1218 |
" normal_series_set: torch.Tensor, anomalous_series_set: torch.Tensor\n", |
|
|
1219 |
") -> torch.Tensor:\n", |
|
|
1220 |
" \"\"\"Get a 1D tensor containing the truth values (1 or -1) for a given set of\n", |
|
|
1221 |
" time series.\n", |
|
|
1222 |
" \"\"\"\n", |
|
|
1223 |
" norm = torch.ones(normal_series_set.size()[0])\n", |
|
|
1224 |
" anom = -torch.ones(anomalous_series_set.size()[0])\n", |
|
|
1225 |
" return torch.cat([norm, anom])\n", |
|
|
1226 |
"\n", |
|
|
1227 |
"\n", |
|
|
1228 |
"@ct.electron\n", |
|
|
1229 |
"def get_accuracy_score(pred: torch.Tensor, truth: torch.Tensor) -> torch.Tensor:\n", |
|
|
1230 |
" \"\"\"Given the predictions and truth values, return a number between 0 and 1\n", |
|
|
1231 |
" indicating the accuracy of predictions.\n", |
|
|
1232 |
" \"\"\"\n", |
|
|
1233 |
" return torch.sum(pred == truth) / truth.size()[0]" |
|
|
1234 |
] |
|
|
1235 |
}, |
|
|
1236 |
{ |
|
|
1237 |
"cell_type": "markdown", |
|
|
1238 |
"metadata": { |
|
|
1239 |
"id": "AJShU6aya5MF" |
|
|
1240 |
}, |
|
|
1241 |
"source": [ |
|
|
1242 |
"Then, knowing the anomaly scores $a_X(y)$ for a validation data set, we\n", |
|
|
1243 |
"can scan through various values of $\\zeta$ on a fine 1D grid and\n", |
|
|
1244 |
"calcuate the accuracy score. Our goal is to pick the $\\zeta$ with the\n", |
|
|
1245 |
"largest accuracy score.\n" |
|
|
1246 |
] |
|
|
1247 |
}, |
|
|
1248 |
{ |
|
|
1249 |
"cell_type": "code", |
|
|
1250 |
"execution_count": 25, |
|
|
1251 |
"metadata": { |
|
|
1252 |
"id": "aNI5zEbLa5MF" |
|
|
1253 |
}, |
|
|
1254 |
"outputs": [], |
|
|
1255 |
"source": [ |
|
|
1256 |
"@ct.electron\n", |
|
|
1257 |
"def threshold_scan_acc_score(\n", |
|
|
1258 |
" scores: torch.Tensor, truth_labels: torch.Tensor, zeta_min: float, zeta_max: float, steps: int\n", |
|
|
1259 |
") -> torch.Tensor:\n", |
|
|
1260 |
" \"\"\"Given the anomaly scores and truth values,\n", |
|
|
1261 |
" scan over a range of thresholds = [zeta_min, zeta_max] with a\n", |
|
|
1262 |
" fixed number of steps, calculating the accuracy score at each point.\n", |
|
|
1263 |
" \"\"\"\n", |
|
|
1264 |
" accs = torch.empty(steps)\n", |
|
|
1265 |
" for i, zeta in enumerate(torch.linspace(zeta_min, zeta_max, steps)):\n", |
|
|
1266 |
" preds = get_preds_given_threshold(zeta, scores)\n", |
|
|
1267 |
" accs[i] = get_accuracy_score(preds, truth_labels)\n", |
|
|
1268 |
" return accs\n", |
|
|
1269 |
"\n", |
|
|
1270 |
"\n", |
|
|
1271 |
"@ct.electron\n", |
|
|
1272 |
"def get_anomaly_score(\n", |
|
|
1273 |
" callable_proj: callable,\n", |
|
|
1274 |
" y: torch.Tensor,\n", |
|
|
1275 |
" T: torch.Tensor,\n", |
|
|
1276 |
" alpha_star: torch.Tensor,\n", |
|
|
1277 |
" mu_star: torch.Tensor,\n", |
|
|
1278 |
" sigma_star: torch.Tensor,\n", |
|
|
1279 |
" gamma_length: int,\n", |
|
|
1280 |
" n_samples: int,\n", |
|
|
1281 |
" get_time_resolved: bool = False,\n", |
|
|
1282 |
"):\n", |
|
|
1283 |
" \"\"\"Get the anomaly score for an input time series y. We need to pass the\n", |
|
|
1284 |
" optimal parameters (arguments with suffix _star). Optionally return the\n", |
|
|
1285 |
" time-resolved score (the anomaly score contribution at a given t).\n", |
|
|
1286 |
" \"\"\"\n", |
|
|
1287 |
" scores = torch.empty(T.size()[0])\n", |
|
|
1288 |
" for i in range(T.size()[0]):\n", |
|
|
1289 |
" scores[i] = (\n", |
|
|
1290 |
" 1\n", |
|
|
1291 |
" - F(\n", |
|
|
1292 |
" callable_proj,\n", |
|
|
1293 |
" y[i].unsqueeze(0),\n", |
|
|
1294 |
" T[i].unsqueeze(0),\n", |
|
|
1295 |
" alpha_star,\n", |
|
|
1296 |
" mu_star,\n", |
|
|
1297 |
" sigma_star,\n", |
|
|
1298 |
" gamma_length,\n", |
|
|
1299 |
" n_samples,\n", |
|
|
1300 |
" )\n", |
|
|
1301 |
" ).square()\n", |
|
|
1302 |
" if get_time_resolved:\n", |
|
|
1303 |
" return scores, scores.mean()\n", |
|
|
1304 |
" else:\n", |
|
|
1305 |
" return scores.mean()\n", |
|
|
1306 |
"\n", |
|
|
1307 |
"\n", |
|
|
1308 |
"@ct.electron\n", |
|
|
1309 |
"def get_norm_and_anom_scores(\n", |
|
|
1310 |
" X_norm: torch.Tensor,\n", |
|
|
1311 |
" X_anom: torch.Tensor,\n", |
|
|
1312 |
" T: torch.Tensor,\n", |
|
|
1313 |
" callable_proj: callable,\n", |
|
|
1314 |
" model_params: dict,\n", |
|
|
1315 |
" gamma_length: int,\n", |
|
|
1316 |
" n_samples: int,\n", |
|
|
1317 |
") -> torch.Tensor:\n", |
|
|
1318 |
" \"\"\"Get the anomaly scores assigned to input normal and anomalous time series instances.\n", |
|
|
1319 |
" model_params is a dictionary containing the optimal model parameters.\n", |
|
|
1320 |
" \"\"\"\n", |
|
|
1321 |
" alpha = model_params[\"alpha\"]\n", |
|
|
1322 |
" mu = model_params[\"mu\"]\n", |
|
|
1323 |
" sigma = model_params[\"sigma\"]\n", |
|
|
1324 |
" norm_scores = torch.tensor(\n", |
|
|
1325 |
" [\n", |
|
|
1326 |
" get_anomaly_score(callable_proj, xt, T, alpha, mu, sigma, gamma_length, n_samples)\n", |
|
|
1327 |
" for xt in X_norm\n", |
|
|
1328 |
" ]\n", |
|
|
1329 |
" )\n", |
|
|
1330 |
" anom_scores = torch.tensor(\n", |
|
|
1331 |
" [\n", |
|
|
1332 |
" get_anomaly_score(callable_proj, xt, T, alpha, mu, sigma, gamma_length, n_samples)\n", |
|
|
1333 |
" for xt in X_anom\n", |
|
|
1334 |
" ]\n", |
|
|
1335 |
" )\n", |
|
|
1336 |
" return torch.cat([norm_scores, anom_scores])" |
|
|
1337 |
] |
|
|
1338 |
}, |
|
|
1339 |
{ |
|
|
1340 |
"cell_type": "markdown", |
|
|
1341 |
"metadata": { |
|
|
1342 |
"id": "1ITCegXba5MF" |
|
|
1343 |
}, |
|
|
1344 |
"source": [ |
|
|
1345 |
"We now create our second `@ct.lattice`. We are to test the optimal model\n", |
|
|
1346 |
"against two random models. If our model is trainable, we should see that\n", |
|
|
1347 |
"the trained model is better.\n" |
|
|
1348 |
] |
|
|
1349 |
}, |
|
|
1350 |
{ |
|
|
1351 |
"cell_type": "code", |
|
|
1352 |
"execution_count": 26, |
|
|
1353 |
"metadata": { |
|
|
1354 |
"id": "Y1AsPTlta5MG" |
|
|
1355 |
}, |
|
|
1356 |
"outputs": [], |
|
|
1357 |
"source": [ |
|
|
1358 |
"@ct.lattice\n", |
|
|
1359 |
"def threshold_tuning_workflow(\n", |
|
|
1360 |
" opt_params: dict,\n", |
|
|
1361 |
" gamma_length: int,\n", |
|
|
1362 |
" n_samples: int,\n", |
|
|
1363 |
" probs_func: callable,\n", |
|
|
1364 |
" zeta_min: float,\n", |
|
|
1365 |
" zeta_max: float,\n", |
|
|
1366 |
" steps: int,\n", |
|
|
1367 |
" p: int,\n", |
|
|
1368 |
" num_series: int,\n", |
|
|
1369 |
" noise_amp: float,\n", |
|
|
1370 |
" spike_amp: float,\n", |
|
|
1371 |
" max_duration: int,\n", |
|
|
1372 |
" t_init: float,\n", |
|
|
1373 |
" t_end: float,\n", |
|
|
1374 |
" k: int,\n", |
|
|
1375 |
" U: callable,\n", |
|
|
1376 |
" W: callable,\n", |
|
|
1377 |
" D: callable,\n", |
|
|
1378 |
" n_qubits: int,\n", |
|
|
1379 |
" random_model_seeds: torch.Tensor,\n", |
|
|
1380 |
" W_layers: int,\n", |
|
|
1381 |
") -> tuple:\n", |
|
|
1382 |
" \"\"\"A workflow for tuning the threshold value zeta, in order to maximize the accuracy score\n", |
|
|
1383 |
" for a validation data set. Results are tested against random models at their optimal zetas.\n", |
|
|
1384 |
" \"\"\"\n", |
|
|
1385 |
" # Generate datasets\n", |
|
|
1386 |
" X_val_norm, T = generate_normal_time_series_set(p, num_series, noise_amp, t_init, t_end)\n", |
|
|
1387 |
" X_val_anom, T = generate_anomalous_time_series_set(\n", |
|
|
1388 |
" p, num_series, noise_amp, spike_amp, max_duration, t_init, t_end\n", |
|
|
1389 |
" )\n", |
|
|
1390 |
" truth_labels = get_truth_labels(X_val_norm, X_val_anom)\n", |
|
|
1391 |
"\n", |
|
|
1392 |
" # Initialize quantum functions\n", |
|
|
1393 |
" callable_proj = get_callable_projector_func(k, U, W, D, n_qubits, probs_func)\n", |
|
|
1394 |
"\n", |
|
|
1395 |
" accs_list = []\n", |
|
|
1396 |
" scores_list = []\n", |
|
|
1397 |
" # Evaluate optimal model\n", |
|
|
1398 |
" scores = get_norm_and_anom_scores(\n", |
|
|
1399 |
" X_val_norm, X_val_anom, T, callable_proj, opt_params, gamma_length, n_samples\n", |
|
|
1400 |
" )\n", |
|
|
1401 |
" accs_opt = threshold_scan_acc_score(scores, truth_labels, zeta_min, zeta_max, steps)\n", |
|
|
1402 |
" accs_list.append(accs_opt)\n", |
|
|
1403 |
" scores_list.append(scores)\n", |
|
|
1404 |
"\n", |
|
|
1405 |
" # Evaluate random models\n", |
|
|
1406 |
" for seed in random_model_seeds:\n", |
|
|
1407 |
" rand_params = get_initial_parameters(W, W_layers, n_qubits, seed)\n", |
|
|
1408 |
" scores = get_norm_and_anom_scores(\n", |
|
|
1409 |
" X_val_norm, X_val_anom, T, callable_proj, rand_params, gamma_length, n_samples\n", |
|
|
1410 |
" )\n", |
|
|
1411 |
" accs_list.append(threshold_scan_acc_score(scores, truth_labels, zeta_min, zeta_max, steps))\n", |
|
|
1412 |
" scores_list.append(scores)\n", |
|
|
1413 |
" return accs_list, scores_list" |
|
|
1414 |
] |
|
|
1415 |
}, |
|
|
1416 |
{ |
|
|
1417 |
"cell_type": "markdown", |
|
|
1418 |
"metadata": { |
|
|
1419 |
"id": "5k6WBWBwa5MG" |
|
|
1420 |
}, |
|
|
1421 |
"source": [ |
|
|
1422 |
"We now set the input parameters.\n" |
|
|
1423 |
] |
|
|
1424 |
}, |
|
|
1425 |
{ |
|
|
1426 |
"cell_type": "code", |
|
|
1427 |
"execution_count": 27, |
|
|
1428 |
"metadata": { |
|
|
1429 |
"id": "jrjCkf-ua5MG" |
|
|
1430 |
}, |
|
|
1431 |
"outputs": [], |
|
|
1432 |
"source": [ |
|
|
1433 |
"threshold_tuning_options = {\n", |
|
|
1434 |
" \"spike_amp\": 0.4,\n", |
|
|
1435 |
" \"max_duration\": 5,\n", |
|
|
1436 |
" \"zeta_min\": 0,\n", |
|
|
1437 |
" \"zeta_max\": 1,\n", |
|
|
1438 |
" \"steps\": 100000,\n", |
|
|
1439 |
" \"random_model_seeds\": [0, 1],\n", |
|
|
1440 |
" \"W_layers\": 2,\n", |
|
|
1441 |
" \"opt_params\": results_dict[\"opt_params\"],\n", |
|
|
1442 |
"}\n", |
|
|
1443 |
"\n", |
|
|
1444 |
"threshold_tuning_options.update(general_options)" |
|
|
1445 |
] |
|
|
1446 |
}, |
|
|
1447 |
{ |
|
|
1448 |
"cell_type": "markdown", |
|
|
1449 |
"metadata": { |
|
|
1450 |
"id": "E94sE87_a5MG" |
|
|
1451 |
}, |
|
|
1452 |
"source": [ |
|
|
1453 |
"As before, we dispatch the lattice to the `Covalent` server.\n" |
|
|
1454 |
] |
|
|
1455 |
}, |
|
|
1456 |
{ |
|
|
1457 |
"cell_type": "code", |
|
|
1458 |
"execution_count": 28, |
|
|
1459 |
"metadata": { |
|
|
1460 |
"id": "vgK3TbNGa5MG" |
|
|
1461 |
}, |
|
|
1462 |
"outputs": [], |
|
|
1463 |
"source": [ |
|
|
1464 |
"val_dispatch_id = ct.dispatch(threshold_tuning_workflow)(**threshold_tuning_options)\n", |
|
|
1465 |
"ct_val_results = ct.get_result(dispatch_id=val_dispatch_id, wait=True)\n", |
|
|
1466 |
"accs_list, scores_list = ct_val_results.result" |
|
|
1467 |
] |
|
|
1468 |
}, |
|
|
1469 |
{ |
|
|
1470 |
"cell_type": "markdown", |
|
|
1471 |
"metadata": { |
|
|
1472 |
"id": "gMzyfZyga5MG" |
|
|
1473 |
}, |
|
|
1474 |
"source": [ |
|
|
1475 |
"Now, we can plot the results:\n" |
|
|
1476 |
] |
|
|
1477 |
}, |
|
|
1478 |
{ |
|
|
1479 |
"cell_type": "code", |
|
|
1480 |
"execution_count": 29, |
|
|
1481 |
"metadata": { |
|
|
1482 |
"colab": { |
|
|
1483 |
"base_uri": "https://localhost:8080/", |
|
|
1484 |
"height": 486 |
|
|
1485 |
}, |
|
|
1486 |
"id": "6G62tWO-a5MG", |
|
|
1487 |
"outputId": "5402fc13-5de7-4808-ab05-8837856cf378" |
|
|
1488 |
}, |
|
|
1489 |
"outputs": [ |
|
|
1490 |
{ |
|
|
1491 |
"output_type": "display_data", |
|
|
1492 |
"data": { |
|
|
1493 |
"text/plain": [ |
|
|
1494 |
"<Figure size 640x480 with 6 Axes>" |
|
|
1495 |
], |
|
|
1496 |
"image/png": "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\n" |
|
|
1497 |
}, |
|
|
1498 |
"metadata": {} |
|
|
1499 |
} |
|
|
1500 |
], |
|
|
1501 |
"source": [ |
|
|
1502 |
"zeta_xlims = [(0, 0.001), (0.25, 0.38), (0.25, 0.38)]\n", |
|
|
1503 |
"titles = [\"Trained model\", \"Random model 1\", \"Random model 2\"]\n", |
|
|
1504 |
"zetas = torch.linspace(\n", |
|
|
1505 |
" threshold_tuning_options[\"zeta_min\"],\n", |
|
|
1506 |
" threshold_tuning_options[\"zeta_max\"],\n", |
|
|
1507 |
" threshold_tuning_options[\"steps\"],\n", |
|
|
1508 |
")\n", |
|
|
1509 |
"fig, axs = plt.subplots(ncols=3, nrows=2, sharey=\"row\")\n", |
|
|
1510 |
"for i in range(3):\n", |
|
|
1511 |
" axs[0, i].plot(zetas, accs_list[i])\n", |
|
|
1512 |
" axs[0, i].set_xlim(zeta_xlims[i])\n", |
|
|
1513 |
" axs[0, i].set_xlabel(\"Threshold [$\\zeta$]\")\n", |
|
|
1514 |
" axs[0, i].set_title(titles[i])\n", |
|
|
1515 |
" axs[1, i].boxplot(\n", |
|
|
1516 |
" [\n", |
|
|
1517 |
" scores_list[i][0 : general_options[\"num_series\"]],\n", |
|
|
1518 |
" scores_list[i][general_options[\"num_series\"] : -1],\n", |
|
|
1519 |
" ],\n", |
|
|
1520 |
" labels=[\"Normal\", \"Anomalous\"],\n", |
|
|
1521 |
" )\n", |
|
|
1522 |
" axs[1, i].set_yscale(\"log\")\n", |
|
|
1523 |
" axs[1, i].axhline(\n", |
|
|
1524 |
" zetas[torch.argmax(accs_list[i])], color=\"k\", linestyle=\":\", label=\"Optimal $\\zeta$\"\n", |
|
|
1525 |
" )\n", |
|
|
1526 |
" axs[1, i].legend()\n", |
|
|
1527 |
"axs[0, 0].set_ylabel(\"Accuracy score\")\n", |
|
|
1528 |
"axs[1, 0].set_ylabel(\"Anomaly score [$a_X(y)$]\")\n", |
|
|
1529 |
"fig.tight_layout()" |
|
|
1530 |
] |
|
|
1531 |
}, |
|
|
1532 |
{ |
|
|
1533 |
"cell_type": "markdown", |
|
|
1534 |
"metadata": { |
|
|
1535 |
"id": "BFKn_NMWa5MG" |
|
|
1536 |
}, |
|
|
1537 |
"source": [ |
|
|
1538 |
"Parsing the above, we can see that the optimal model achieves high\n", |
|
|
1539 |
"accuracy when the threshold is tuned using the validation data. On the\n", |
|
|
1540 |
"other hand, the random models return mostly random results (sometimes\n", |
|
|
1541 |
"even worse than random guesses), regardless of how we set the threshold.\n" |
|
|
1542 |
] |
|
|
1543 |
}, |
|
|
1544 |
{ |
|
|
1545 |
"cell_type": "markdown", |
|
|
1546 |
"metadata": { |
|
|
1547 |
"id": "ZyQ4_zyVa5MG" |
|
|
1548 |
}, |
|
|
1549 |
"source": [ |
|
|
1550 |
"Testing the model\n", |
|
|
1551 |
"=================\n", |
|
|
1552 |
"\n", |
|
|
1553 |
"Now with optimal thresholds for our optimized and random models, we can\n", |
|
|
1554 |
"perform testing. We already have all of the electrons to do this, so we\n", |
|
|
1555 |
"create the `@ct.lattice`\n" |
|
|
1556 |
] |
|
|
1557 |
}, |
|
|
1558 |
{ |
|
|
1559 |
"cell_type": "code", |
|
|
1560 |
"execution_count": 30, |
|
|
1561 |
"metadata": { |
|
|
1562 |
"id": "Ply0mPTka5MG" |
|
|
1563 |
}, |
|
|
1564 |
"outputs": [], |
|
|
1565 |
"source": [ |
|
|
1566 |
"@ct.lattice\n", |
|
|
1567 |
"def testing_workflow(\n", |
|
|
1568 |
" opt_params: dict,\n", |
|
|
1569 |
" gamma_length: int,\n", |
|
|
1570 |
" n_samples: int,\n", |
|
|
1571 |
" probs_func: callable,\n", |
|
|
1572 |
" best_zetas: list,\n", |
|
|
1573 |
" p: int,\n", |
|
|
1574 |
" num_series: int,\n", |
|
|
1575 |
" noise_amp: float,\n", |
|
|
1576 |
" spike_amp: float,\n", |
|
|
1577 |
" max_duration: int,\n", |
|
|
1578 |
" t_init: float,\n", |
|
|
1579 |
" t_end: float,\n", |
|
|
1580 |
" k: int,\n", |
|
|
1581 |
" U: callable,\n", |
|
|
1582 |
" W: callable,\n", |
|
|
1583 |
" D: callable,\n", |
|
|
1584 |
" n_qubits: int,\n", |
|
|
1585 |
" random_model_seeds: torch.Tensor,\n", |
|
|
1586 |
" W_layers: int,\n", |
|
|
1587 |
") -> list:\n", |
|
|
1588 |
" \"\"\"A workflow for calculating anomaly scores for a set of testing time series\n", |
|
|
1589 |
" given an optimal model and set of random models. We use the optimal zetas found in threshold tuning.\n", |
|
|
1590 |
" \"\"\"\n", |
|
|
1591 |
" # Generate time series\n", |
|
|
1592 |
" X_val_norm, T = generate_normal_time_series_set(p, num_series, noise_amp, t_init, t_end)\n", |
|
|
1593 |
" X_val_anom, T = generate_anomalous_time_series_set(\n", |
|
|
1594 |
" p, num_series, noise_amp, spike_amp, max_duration, t_init, t_end\n", |
|
|
1595 |
" )\n", |
|
|
1596 |
" truth_labels = get_truth_labels(X_val_norm, X_val_anom)\n", |
|
|
1597 |
"\n", |
|
|
1598 |
" # Prepare quantum functions\n", |
|
|
1599 |
" callable_proj = get_callable_projector_func(k, U, W, D, n_qubits, probs_func)\n", |
|
|
1600 |
"\n", |
|
|
1601 |
" accs_list = []\n", |
|
|
1602 |
" # Evaluate optimal model\n", |
|
|
1603 |
" scores = get_norm_and_anom_scores(\n", |
|
|
1604 |
" X_val_norm, X_val_anom, T, callable_proj, opt_params, gamma_length, n_samples\n", |
|
|
1605 |
" )\n", |
|
|
1606 |
" preds = get_preds_given_threshold(best_zetas[0], scores)\n", |
|
|
1607 |
" accs_list.append(get_accuracy_score(preds, truth_labels))\n", |
|
|
1608 |
" # Evaluate random models\n", |
|
|
1609 |
" for zeta, seed in zip(best_zetas[1:], random_model_seeds):\n", |
|
|
1610 |
" rand_params = get_initial_parameters(W, W_layers, n_qubits, seed)\n", |
|
|
1611 |
" scores = get_norm_and_anom_scores(\n", |
|
|
1612 |
" X_val_norm, X_val_anom, T, callable_proj, rand_params, gamma_length, n_samples\n", |
|
|
1613 |
" )\n", |
|
|
1614 |
" preds = get_preds_given_threshold(zeta, scores)\n", |
|
|
1615 |
" accs_list.append(get_accuracy_score(preds, truth_labels))\n", |
|
|
1616 |
" return accs_list" |
|
|
1617 |
] |
|
|
1618 |
}, |
|
|
1619 |
{ |
|
|
1620 |
"cell_type": "markdown", |
|
|
1621 |
"metadata": { |
|
|
1622 |
"id": "MEqrJNt0a5MG" |
|
|
1623 |
}, |
|
|
1624 |
"source": [ |
|
|
1625 |
"We dispatch it to the Covalent server with the appropriate parameters.\n" |
|
|
1626 |
] |
|
|
1627 |
}, |
|
|
1628 |
{ |
|
|
1629 |
"cell_type": "code", |
|
|
1630 |
"execution_count": 31, |
|
|
1631 |
"metadata": { |
|
|
1632 |
"id": "sHjxzzIGa5MG" |
|
|
1633 |
}, |
|
|
1634 |
"outputs": [], |
|
|
1635 |
"source": [ |
|
|
1636 |
"testing_options = {\n", |
|
|
1637 |
" \"spike_amp\": 0.4,\n", |
|
|
1638 |
" \"max_duration\": 5,\n", |
|
|
1639 |
" \"best_zetas\": [zetas[torch.argmax(accs)] for accs in accs_list],\n", |
|
|
1640 |
" \"random_model_seeds\": [0, 1],\n", |
|
|
1641 |
" \"W_layers\": 2,\n", |
|
|
1642 |
" \"opt_params\": results_dict[\"opt_params\"],\n", |
|
|
1643 |
"}\n", |
|
|
1644 |
"\n", |
|
|
1645 |
"testing_options.update(general_options)\n", |
|
|
1646 |
"\n", |
|
|
1647 |
"test_dispatch_id = ct.dispatch(testing_workflow)(**testing_options)\n", |
|
|
1648 |
"ct_test_results = ct.get_result(dispatch_id=test_dispatch_id, wait=True)\n", |
|
|
1649 |
"accs_list = ct_test_results.result" |
|
|
1650 |
] |
|
|
1651 |
}, |
|
|
1652 |
{ |
|
|
1653 |
"cell_type": "markdown", |
|
|
1654 |
"metadata": { |
|
|
1655 |
"id": "S7QEHFdla5MG" |
|
|
1656 |
}, |
|
|
1657 |
"source": [ |
|
|
1658 |
"Finally, we plot the results below.\n" |
|
|
1659 |
] |
|
|
1660 |
}, |
|
|
1661 |
{ |
|
|
1662 |
"cell_type": "code", |
|
|
1663 |
"execution_count": 32, |
|
|
1664 |
"metadata": { |
|
|
1665 |
"colab": { |
|
|
1666 |
"base_uri": "https://localhost:8080/", |
|
|
1667 |
"height": 452 |
|
|
1668 |
}, |
|
|
1669 |
"id": "n-9gbA0Ia5MG", |
|
|
1670 |
"outputId": "b1adf898-0a32-4f68-dbce-991cfb0a5575" |
|
|
1671 |
}, |
|
|
1672 |
"outputs": [ |
|
|
1673 |
{ |
|
|
1674 |
"output_type": "display_data", |
|
|
1675 |
"data": { |
|
|
1676 |
"text/plain": [ |
|
|
1677 |
"<Figure size 640x480 with 1 Axes>" |
|
|
1678 |
], |
|
|
1679 |
"image/png": "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E+zdu1ecZJyUlAQdnf8OLjk5OWHfvn2YOHEiGjduDEdHR4wfPx5Tp07VettEREQkTWW6zw0AKBQKtGjRApmZmdizZw/q1auHBg0aaL2eoKAgBAUFFfnc4cOHNdo8PT1x4sQJrbdDREREbwat59z069cPq1evBvD0O6WaN2+Ofv36oXHjxvjll1/KvUAiIiIibWgdbo4cOYK2bdsCAHbs2AFBEPDgwQN8+eWXJd5vhoiIiOhV0DrcPHz4ENWqVQMA7N27F71794axsTF8fHxw5cqVci+QiIiISBtahxsnJyccP34c2dnZ2Lt3L7p06QIAuH//PuRyebkXSERERKQNrScUT5gwAYMGDYJCoUCtWrXQoUMHAE9PV7m5uZV3fURERERa0TrcjB49Gq1atUJSUhI6d+4sXqpdu3ZtzrkhIiKiSlemS8E9PDzg4eGh1ubj41MuBRERERG9DK3n3BARERG9zhhuiIiISFIYboiIiEhSGG6IiIhIUrQON87Ozvj888+RlJRUEfUQERERvRStw82ECROwfft21K5dG507d8a2bduQm5tbEbURERERaa1M4SYuLg4xMTFo0KABxo4dC3t7ewQFBSE2NrYiaiQiIiIqtTLPuWnWrBm+/PJL3Lp1CyEhIVi/fj1atGiBJk2aYOPGjRAEoTzrJCIiIiqVMt3EDwDy8/OxY8cOhIeHIyoqCu+88w4CAwORkpKCGTNm4MCBA9iyZUt51kpERET0QlqHm9jYWISHh2Pr1q3Q0dGBv78/VqxYgfr164t9evbsiRYtWpRroURERESloXW4adGiBTp37oy1a9eiR48e0NfX1+jj4uKCAQMGlEuBRERERNrQOtz8+++/qFWrVol9TExMEB4eXuaiiIiIiMpK6wnFd+7cwcmTJzXaT548idOnT5dLUURERERlpXW4GTNmDJKTkzXab968iTFjxpRLUURERERlpXW4uXjxIpo1a6bR3rRpU1y8eLFciiIiIiIqK63DjaGhIdLS0jTab9++DT29Ml9ZTkRERFQutA43Xbp0wfTp0/Hw4UOx7cGDB5gxYwY6d+5crsURERERaUvrQy1Lly5Fu3btUKtWLTRt2hQAEBcXB1tbW3z//fflXiARERGRNrQON46Ojvj7778RERGBc+fOwcjICEOHDoWfn1+R97whIiIiepXKNEnGxMQEI0eOLO9a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\n" |
|
|
1680 |
}, |
|
|
1681 |
"metadata": {} |
|
|
1682 |
} |
|
|
1683 |
], |
|
|
1684 |
"source": [ |
|
|
1685 |
"plt.figure()\n", |
|
|
1686 |
"plt.bar([1, 2, 3], accs_list)\n", |
|
|
1687 |
"plt.axhline(0.5, color=\"k\", linestyle=\":\", label=\"Random accuracy\")\n", |
|
|
1688 |
"plt.xticks([1, 2, 3], [\"Trained model\", \"Random model 1\", \"Random model 2\"])\n", |
|
|
1689 |
"plt.ylabel(\"Accuracy score\")\n", |
|
|
1690 |
"plt.title(\"Accuracy scores for trained and random models\")\n", |
|
|
1691 |
"leg = plt.legend()" |
|
|
1692 |
] |
|
|
1693 |
}, |
|
|
1694 |
{ |
|
|
1695 |
"cell_type": "markdown", |
|
|
1696 |
"metadata": { |
|
|
1697 |
"id": "DKY1xKrYa5MH" |
|
|
1698 |
}, |
|
|
1699 |
"source": [ |
|
|
1700 |
"As can be seen, once more, the trained model is far more accurate than\n", |
|
|
1701 |
"the random models. Awesome! Now that we\\'re done with the calculations\n", |
|
|
1702 |
"in this tutorial, we just need to remember to shut down the Covalent\n", |
|
|
1703 |
"server\n" |
|
|
1704 |
] |
|
|
1705 |
}, |
|
|
1706 |
{ |
|
|
1707 |
"cell_type": "code", |
|
|
1708 |
"execution_count": 33, |
|
|
1709 |
"metadata": { |
|
|
1710 |
"id": "k0Wja1dHa5MH" |
|
|
1711 |
}, |
|
|
1712 |
"outputs": [], |
|
|
1713 |
"source": [ |
|
|
1714 |
"# Shut down the covalent server\n", |
|
|
1715 |
"stop = os.system(\"covalent stop\")" |
|
|
1716 |
] |
|
|
1717 |
}, |
|
|
1718 |
{ |
|
|
1719 |
"cell_type": "markdown", |
|
|
1720 |
"metadata": { |
|
|
1721 |
"id": "wjgM9uhia5MH" |
|
|
1722 |
}, |
|
|
1723 |
"source": [ |
|
|
1724 |
"Conclusions\n", |
|
|
1725 |
"===========\n", |
|
|
1726 |
"\n", |
|
|
1727 |
"We\\'ve now reached the end of this tutorial! Quickly recounting what we\n", |
|
|
1728 |
"have learnt, we:\n", |
|
|
1729 |
"\n", |
|
|
1730 |
"1. Learnt the background of how to detect anomalous time series\n", |
|
|
1731 |
" instances, *quantumly*,\n", |
|
|
1732 |
"2. Learnt how to build the code to achieve this using PennyLane and\n", |
|
|
1733 |
" PyTorch, and,\n", |
|
|
1734 |
"3. Learnt the basics of Covalent: a workflow orchestration tool for\n", |
|
|
1735 |
" heterogeneous computation\n", |
|
|
1736 |
"\n", |
|
|
1737 |
"If you want to learn more about QVR, you should consult the paper where\n", |
|
|
1738 |
"we generalize the math a little and test the algorithm on less trivial\n", |
|
|
1739 |
"time series data than was dealt with in this tutorial. We also ran some\n", |
|
|
1740 |
"experiments on real quantum computers, enhancing our results using error\n", |
|
|
1741 |
"mitigation techniques. If you want to play some more with Covalent,\n", |
|
|
1742 |
"check us out on [GitHub](https://github.com/AgnostiqHQ/covalent/) and/or\n", |
|
|
1743 |
"engage with other tutorials in our\n", |
|
|
1744 |
"[documentation](https://covalent.readthedocs.io/en/stable/).\n" |
|
|
1745 |
] |
|
|
1746 |
}, |
|
|
1747 |
{ |
|
|
1748 |
"cell_type": "markdown", |
|
|
1749 |
"metadata": { |
|
|
1750 |
"id": "MCpaNVlHa5MH" |
|
|
1751 |
}, |
|
|
1752 |
"source": [ |
|
|
1753 |
"References\n", |
|
|
1754 |
"==========\n", |
|
|
1755 |
"\n", |
|
|
1756 |
"About the authors \\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--.. include::\n", |
|
|
1757 |
"../\\_static/authors/jack\\_stephen\\_baker.txt .. include::\n", |
|
|
1758 |
"../\\_static/authors/santosh\\_kumar\\_radha.txt\n" |
|
|
1759 |
] |
|
|
1760 |
} |
|
|
1761 |
], |
|
|
1762 |
"metadata": { |
|
|
1763 |
"kernelspec": { |
|
|
1764 |
"display_name": "Python 3", |
|
|
1765 |
"language": "python", |
|
|
1766 |
"name": "python3" |
|
|
1767 |
}, |
|
|
1768 |
"language_info": { |
|
|
1769 |
"codemirror_mode": { |
|
|
1770 |
"name": "ipython", |
|
|
1771 |
"version": 3 |
|
|
1772 |
}, |
|
|
1773 |
"file_extension": ".py", |
|
|
1774 |
"mimetype": "text/x-python", |
|
|
1775 |
"name": "python", |
|
|
1776 |
"nbconvert_exporter": "python", |
|
|
1777 |
"pygments_lexer": "ipython3", |
|
|
1778 |
"version": "3.9.17" |
|
|
1779 |
}, |
|
|
1780 |
"colab": { |
|
|
1781 |
"provenance": [] |
|
|
1782 |
} |
|
|
1783 |
}, |
|
|
1784 |
"nbformat": 4, |
|
|
1785 |
"nbformat_minor": 0 |
|
|
1786 |
} |