{ "cells": [ { "cell_type": "markdown", "source": [ "# Optimizing QAOA by Bayesian Optimization (BO)" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "## Overview" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "In this tutorial, we show how to use Bayesian optimization to optimize QAOA. For the introduction of QAOA, please refer to the [previous tutorial](qaoa.ipynb). Bayesian optimization in this tutorial is based on $\\text{ODBO}$, please refer to [Cheng, Yang, Hsieh, Liao and Zhang](https://doi.org/10.48550/arXiv.2205.09548) for details and this [repository](https://github.com/tencent-quantum-lab/ODBO) for source code and [installation](https://github.com/tencent-quantum-lab/ODBO#installation). In this tutorial, the updated modules of BO, TuRBO and DARBO are packaged." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "## Setup" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "source": [ "import tensorcircuit as tc\n", "from jax import numpy as jnp\n", "import optax\n", "import torch\n", "import networkx as nx\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import cotengra as ctg\n", "from typing import Union\n", "import time\n", "import odbo\n", "from IPython.display import clear_output\n", "\n", "K = tc.set_backend(\"jax\")\n", "tc.set_dtype(\"complex128\")\n", "dtype = torch.float64\n", "\n", "# cotengra package to speed up the calculation\n", "opt_ctg = ctg.ReusableHyperOptimizer(\n", " methods=[\"greedy\", \"kahypar\"],\n", " parallel=True,\n", " minimize=\"combo\",\n", " max_time=20,\n", " max_repeats=128,\n", " progbar=True,\n", ")\n", "\n", "tc.set_contractor(\"custom\", optimizer=opt_ctg, preprocessing=True)\n", "\n", "nlayers = 10\n", "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", "acqfn = \"ucb\"" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "## MAX-CUT Hamiltonian" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "### Define the Graph" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 3, "source": [ "# a graph instance\n", "graph_dict = {\n", " 0: {1: {\"weight\": 1.0}, 7: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", " 1: {0: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", " 2: {1: {\"weight\": 1.0}, 3: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", " 3: {1: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", " 4: {7: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", " 5: {6: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 2: {\"weight\": 1.0}},\n", " 6: {7: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", " 7: {4: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", "}\n", "\n", "graph = nx.to_networkx_graph(graph_dict)\n", "pos = nx.spring_layout(graph)\n", "nx.draw_networkx(graph, with_labels=True, pos=pos)\n", "ax = plt.gca()\n", "ax.set_facecolor(\"w\")" ], "outputs": [ { "data": { "text/plain": "
", "image/png": "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" }, "metadata": {}, "output_type": "display_data" } ], "metadata": { "ExecuteTime": { "end_time": "2023-07-15T07:42:26.571397400Z", "start_time": "2023-07-15T07:42:26.444088200Z" } } }, { "cell_type": "markdown", "source": [ "### Brutal Force Result" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 4, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "bit string: ['01010101', '10101010'] \n", "max cut: 10.0\n" ] }, { "data": { "text/plain": "
", "image/png": "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LxUqVKB///4YjUb69u3rshcFBZGVlcWwYcPYsGEDq1evdpo7rJyRhAENOnbsGMOHD2fv3r2MGzeOadOmlakrgvj4eKKiohzhIDY2FoCGDRs6gkF4eDiNGjVyifuhhSisS5cusWzZMkwmEzt37sTb25t+/fphNBp58MEHXWLt0N3Kzs7GaDTy008/sWrVKvr27at2SU5NwoBGWSwW5syZw5QpU7jnnntYunQpnTp1UrusEnHz5s0c4WD//v0oikL9+vVzhIMmTZpIOBAuKy4ujhUrVmAymdi6dSuenp488MADGI1GBgwY4HS3GJcki8XCv//9b3788UdWrlxJ//791S7J6UkY0LhDhw4xfPhwYmNjmTBhApMnTy5TC4fuJCEhga1btzrCwb59+7DZbNStWzfHtEKzZs0kHAindu3aNVauXInJZCIyMhJ3d3f69OmD0WjkoYce0uT+IBaLhUcffZTly5ezfPlyHn74YbVLcgkSBgTZ2dm89dZbvPHGG9x7770sXbpUUz26ExMTc4SD6OhobDYbtWvXzhEOWrRoIeFAqO7GjRusXLkSs9nMr7/+ik6no1evXhgMBgYOHKjpPUCsVivDhw/n+++/x2w2M3jwYLVLchkSBoTD/v37GT58OEeOHGHy5MlMmDChTNxfXFhJSUls27bNEQ727t2L1WqlZs2aOcJBq1atJByIUpGQkMCqVaswm81s2rQJm81Gjx49MBgMDB48mOrVq6tdouqsViujRo3im2++4bvvvmPYsGFql+RSJAyIHLKyspgxYwYzZ84kICCApUuXOt3e46UtOTmZ7du3O8LBnj17sFgs1KhRg+7duzvCwb333utS/dmFc0tKSuLHH3/EZDKxceNGLBYL3bt3x2AwMGTIEGrWrKl2iU7DZrMxZswYlixZwtdff82///1vtUtyORIGxB3t3buX4cOHc/LkSaZOncrLL7/s0m1Ii1NqamqOcLB7926ys7OpXr16jnDQpk0bCQeiUFJSUlizZg0mk4n169eTmZlJ165dMRqNDBkyRLpu3oHNZuOJJ57giy++4Msvv+SRRx5RuySXJGFA5CojI4Np06bxzjvv0KlTJ5YsWUKrVq3ULsvppKWlsWPHDkc42LVrF1lZWVStWjVHOGjXrp2EA/EPqamprFu3DpPJxE8//URGRgbBwcEYjUaGDh1K/fr11S7R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" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def classical_solver(graph):\n", " num_nodes = len(graph)\n", " max_cut = [0]\n", " best_case = [0] # \"01\" series with max cut\n", " for i in range(2**num_nodes):\n", " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", " cat1, cat2 = [], []\n", " for j in range(num_nodes):\n", " if str(case)[j] == \"0\":\n", " cat1.append(j)\n", " else:\n", " cat2.append(j)\n", "\n", " # calculate the cost function\n", " cost = 0\n", " for node1 in cat1:\n", " for node2 in cat2:\n", " if graph[node1].get(node2):\n", " cost += graph[node1][node2][\"weight\"]\n", " cost = round(cost, 4) # elimate minor error\n", " if max_cut[-1] <= cost:\n", " max_cut.append(cost)\n", " best_case.append(case)\n", "\n", " # optimal cases maybe more than 1, but they are all at the end\n", " index = max_cut.index(max_cut[-1])\n", "\n", " return max_cut[-1], best_case[index:]\n", "\n", "\n", "max_cut, best_case = classical_solver(graph_dict)\n", "print(\"bit string:\", best_case, \"\\nmax cut:\", max_cut)\n", "\n", "colors = [\"r\" if best_case[0][i] == \"0\" else \"c\" for i in graph.nodes]\n", "weighted_graph = nx.to_networkx_graph(graph_dict)\n", "nx.draw_networkx(weighted_graph, with_labels=True, node_color=colors, pos=pos)\n", "ax = plt.gca()\n", "ax.set_facecolor(\"w\")" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T07:42:29.489809800Z", "start_time": "2023-07-15T07:42:29.368921400Z" } } }, { "cell_type": "markdown", "source": [ "## QAOA Ansatz" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 46, "outputs": [], "source": [ "def QAOAansatz(params, each=1, return_circuit=False):\n", " n = graph.number_of_nodes() # the number of nodes\n", "\n", " # PQC loop\n", " def pqc_loop(s_, params_):\n", " c_ = tc.Circuit(n, inputs=s_)\n", " for j in range(each):\n", " # driving layer\n", " for a, b in graph.edges:\n", " c_.RZZ(a, b, theta=graph[a][b][\"weight\"] * params_[2 * j])\n", " # mixing layer\n", " for i in range(n):\n", " c_.RX(i, theta=params_[2 * j + 1])\n", " s_ = c_.state()\n", " return s_\n", "\n", " c0 = tc.Circuit(n)\n", " for i in range(n):\n", " c0.H(i)\n", " s0 = c0.state()\n", " s = K.scan(pqc_loop, K.reshape(params, [nlayers // each, 2 * each]), s0)\n", " c = tc.Circuit(n, inputs=s)\n", "\n", " # whether to return the circuit\n", " if return_circuit is True:\n", " return c\n", "\n", " # calculate the loss function\n", " loss = 0.0\n", " for a, b in graph.edges:\n", " loss += c.expectation_ps(z=[a, b]) * graph[a][b][\"weight\"]\n", "\n", " return K.real(loss)" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.534488800Z", "start_time": "2023-07-15T05:12:41.483853500Z" } } }, { "cell_type": "code", "execution_count": 47, "outputs": [], "source": [ "QAOA_vag = K.jit(\n", " tc.backend.value_and_grad(QAOAansatz, argnums=0), static_argnums=(1, 2)\n", ")\n", "QAOA_nograd = K.jit(QAOAansatz, static_argnums=(1, 2))\n", "\n", "\n", "def eval_objective(x):\n", " \"\"\"This is a helper function we use to unnormalize and evalaute a point\"\"\"\n", " return -torch.from_numpy(np.asarray(QAOA_nograd(jnp.asarray(x.ravel()))))" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.541255500Z", "start_time": "2023-07-15T05:12:41.484406100Z" } } }, { "cell_type": "markdown", "source": [ "## Adam Optimizer" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 48, "outputs": [], "source": [ "opt = K.optimizer(optax.adam(1e-2))" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.603802800Z", "start_time": "2023-07-15T05:12:41.585764800Z" } } }, { "cell_type": "markdown", "source": [ "## BO Optimizer" ], "metadata": {} }, { "cell_type": "code", "execution_count": 49, "source": [ "class BO_optimizer:\n", " def __init__(self, eval_func, batch_size: int = 1, device=\"cpu\"):\n", " self.eval_func = eval_func\n", " self.device = device\n", " self.batch_size = batch_size\n", " self.best_dict = {\"X\": None, \"Y\": torch.tensor(-float(\"inf\"))}\n", "\n", " def compute_Y(self, X):\n", " return torch.tensor(\n", " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", " ).unsqueeze(-1)\n", "\n", " def update_best(self, X_next, Y_next):\n", " new_Y, new_idx = torch.max(Y_next, dim=0)\n", " new_Y = new_Y.squeeze()\n", " if new_Y > self.best_dict[\"Y\"]:\n", " self.best_dict[\"Y\"] = new_Y\n", " self.best_dict[\"X\"] = X_next[new_idx]\n", "\n", " def update(\n", " self,\n", " X,\n", " Y=None,\n", " acqfn: str = \"ucb\",\n", " normalize: bool = False,\n", " verbose: bool = False,\n", " ):\n", " if Y is None:\n", " Y = self.compute_Y(X)\n", " X_next = odbo.run_exp.bo_design(\n", " X=X,\n", " Y=Y,\n", " batch_size=self.batch_size,\n", " acqfn=acqfn,\n", " normalize=normalize,\n", " verbose=verbose,\n", " )[0].reshape(self.batch_size, X.shape[-1])\n", " Y_next = self.compute_Y(X_next)\n", "\n", " self.update_best(X_next, Y_next)\n", "\n", " # Update training set\n", " X = torch.cat((X, X_next), dim=0)\n", " Y = torch.cat((Y, Y_next), dim=0)\n", "\n", " return X, Y, Y_next.mean()" ], "outputs": [], "metadata": { "scrolled": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.603802800Z", "start_time": "2023-07-15T05:12:41.586291Z" } } }, { "cell_type": "code", "execution_count": 50, "outputs": [], "source": [ "batch_size = 1\n", "\n", "bo_opt = BO_optimizer(eval_objective, batch_size, device)" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.603802800Z", "start_time": "2023-07-15T05:12:41.586291Z" } } }, { "cell_type": "markdown", "source": [ "## TuRBO Optimizer" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 51, "outputs": [], "source": [ "class TuRBO_optimizer(BO_optimizer):\n", " def __init__(\n", " self, eval_func, num_params, tr_length, failure_tolerance, device=\"cpu\"\n", " ):\n", " super(TuRBO_optimizer, self).__init__(eval_func, device=device)\n", " self.batch_size = 1 # There is a bug in odbo.run_exp.turbo_design, batch_size can only be 1 right now.\n", " self.tr_length = tr_length\n", " self.state = odbo.turbo.TurboState(\n", " dim=num_params,\n", " batch_size=batch_size,\n", " length=tr_length,\n", " n_trust_regions=len(tr_length),\n", " failure_tolerance=failure_tolerance,\n", " )\n", "\n", " def inverse_transform(self, X):\n", " \"\"\"\n", " Note TuRBO is working on only [0,1] parameter range\n", " We need to transform parameters from [0,1] to [-pi,pi] before using eval_func\n", " \"\"\"\n", " return X * 2 * np.pi - np.pi\n", "\n", " def transform(self, X):\n", " \"\"\"\n", " Note TuRBO is working on only [0,1] parameter range\n", " We need to transform parameters from [-pi,pi] to [0,1] before using odbo.run_exp.turbo_design\n", " \"\"\"\n", " return X / 2 / np.pi + 0.5\n", "\n", " def compute_Y(self, X, transformed_input: bool = True):\n", " if transformed_input:\n", " X = self.inverse_transform(X)\n", " return torch.tensor(\n", " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", " ).unsqueeze(-1)\n", "\n", " def get_next(self, X, Y, acqfn, normalize, verbose):\n", " X_next = odbo.run_exp.turbo_design(\n", " state=self.state,\n", " X=X,\n", " Y=Y,\n", " n_trust_regions=len(self.tr_length),\n", " batch_size=self.batch_size,\n", " acqfn=acqfn,\n", " normalize=normalize,\n", " verbose=verbose,\n", " )[0].reshape(len(self.tr_length) * self.batch_size, X.shape[-1])\n", " Y_next = self.compute_Y(X_next)\n", " return X_next, Y_next\n", "\n", " def update_state(self, Y_next):\n", " self.state = odbo.turbo.update_state(\n", " state=self.state,\n", " Y_next=Y_next.reshape(len(self.tr_length), self.batch_size, 1),\n", " )\n", "\n", " def preprocess(self, X, Y, transformed_input):\n", " if not transformed_input:\n", " X = self.transform(X)\n", " if Y is None:\n", " Y = self.compute_Y(X)\n", " best_Y, best_idx = torch.max(Y, dim=0)\n", " best_Y = best_Y.squeeze()\n", " if best_Y > self.best_dict[\"Y\"]:\n", " self.state.best_value = best_Y.item()\n", " self.best_dict[\"Y\"] = best_Y\n", " self.best_dict[\"X\"] = X[best_idx]\n", " return X, Y\n", "\n", " def postprocess(self, X, Y, X_next, Y_next, transformed_output):\n", " X = torch.cat((X, X_next), dim=0)\n", " Y = torch.cat((Y, Y_next), dim=0)\n", " if not transformed_output:\n", " X = self.inverse_transform(X)\n", " return X, Y\n", "\n", " def update(\n", " self,\n", " X,\n", " Y=None,\n", " acqfn: str = \"ucb\",\n", " normalize: bool = False,\n", " verbose: bool = False,\n", " transformed_input: bool = False,\n", " transformed_output: bool = False,\n", " ):\n", " X, Y = self.preprocess(X, Y, transformed_input)\n", "\n", " X_next, Y_next = self.get_next(X, Y, acqfn, normalize, verbose)\n", "\n", " self.update_best(X_next, Y_next)\n", "\n", " self.update_state(Y_next)\n", "\n", " X, Y = self.postprocess(X, Y, X_next, Y_next, transformed_output)\n", "\n", " return X, Y, Y_next.mean()" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.603802800Z", "start_time": "2023-07-15T05:12:41.586798100Z" } } }, { "cell_type": "code", "execution_count": 52, "outputs": [], "source": [ "failure_tolerance = 10\n", "tr_length = [1.6]\n", "\n", "turbo_opt = TuRBO_optimizer(\n", " eval_objective, 2 * nlayers, tr_length, failure_tolerance, device\n", ")" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.645737200Z", "start_time": "2023-07-15T05:12:41.586798100Z" } } }, { "cell_type": "markdown", "source": [ "## DARBO Optimizer" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "Please refer to [Cheng, Chen, Zhang and Zhang](https://doi.org/10.48550/arXiv.2303.14877) for details." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 53, "outputs": [], "source": [ "class DARBO_optimizer(TuRBO_optimizer):\n", " def __init__(\n", " self,\n", " eval_func,\n", " num_params,\n", " tr_length,\n", " failure_tolerance,\n", " mode: Union[bool, str] = True,\n", " device=\"cpu\",\n", " ):\n", " super(DARBO_optimizer, self).__init__(\n", " eval_func, num_params, tr_length, failure_tolerance, device\n", " )\n", " self.switch_counter = 0\n", " if mode == True or mode == \"large\":\n", " self.mode = True\n", " else:\n", " self.mode = False\n", " self.best_dict = {\n", " \"X\": None,\n", " \"Y\": torch.tensor(self.state.best_value),\n", " \"mode\": self.mode,\n", " }\n", "\n", " def get_mode(self):\n", " return \"large\" if self.mode else \"small\"\n", "\n", " def compute_Y(self, X, transformed_input: bool = True, mode=None):\n", " if transformed_input:\n", " X = self.inverse_transform(X, mode)\n", " return torch.tensor(\n", " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", " ).unsqueeze(-1)\n", "\n", " def inverse_transform(self, X, mode=None):\n", " \"\"\"\n", " Note TuRBO is working on only [0,1] parameter range\n", " We need to transform parameters from [0, 1] to [-pi, pi] or [-pi / 2, pi / 2] before using eval_func\n", " \"\"\"\n", " if mode is None:\n", " mode = self.mode\n", " if mode: # [0, 1] to [-pi, pi]\n", " return X * 2 * np.pi - np.pi\n", " else: # [0, 1] to [-pi / 2, pi / 2]\n", " return X * np.pi - np.pi / 2\n", "\n", " def transform(self, X, mode=None):\n", " \"\"\"\n", " Note TuRBO is working on only [0,1] parameter range\n", " We need to transform parameters from [-pi,pi] or [-pi / 2, pi / 2] to [0,1] before using odbo.run_exp.turbo_design\n", " \"\"\"\n", " if mode is None:\n", " mode = self.mode\n", " if mode: # [-pi, pi] to [0, 1]\n", " return X / 2 / np.pi + 0.5\n", " else: # [-pi / 2, pi / 2] to [0, 1]\n", " return X / np.pi + 0.5\n", "\n", " def update_best(self, X_next, Y_next):\n", " new_Y, new_idx = torch.max(Y_next, dim=0)\n", " new_Y = new_Y.squeeze()\n", " if new_Y > self.best_dict[\"Y\"]:\n", " self.best_dict[\"Y\"] = new_Y\n", " self.best_dict[\"X\"] = X_next[new_idx]\n", " self.best_dict[\"mode\"] = self.mode\n", " else:\n", " self.switch_counter += 1\n", "\n", " def update(\n", " self,\n", " X,\n", " Y=None,\n", " acqfn: str = \"ucb\",\n", " normalize: bool = False,\n", " verbose: bool = False,\n", " transformed_input: bool = False,\n", " transformed_output: bool = False,\n", " frequency: int = 4,\n", " ):\n", " X, Y = self.preprocess(X, Y, transformed_input)\n", "\n", " # check if we need to switch the searching parameter range.\n", " if self.switch_counter >= frequency:\n", " if self.mode:\n", " X = X * 2 - 0.5\n", " self.mode = False # small\n", " else:\n", " X = X / 2 + 0.25\n", " self.mode = True # large\n", " self.switch_counter = 0\n", "\n", " X_next, Y_next = self.get_next(X, Y, acqfn, normalize, verbose)\n", "\n", " self.update_best(X_next, Y_next)\n", "\n", " self.update_state(Y_next)\n", "\n", " X, Y = self.postprocess(X, Y, X_next, Y_next, transformed_output)\n", "\n", " return X, Y, Y_next.mean()" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.645737200Z", "start_time": "2023-07-15T05:12:41.627215300Z" } } }, { "cell_type": "code", "execution_count": 54, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "initial mode: small\n" ] } ], "source": [ "mode = \"small\"\n", "\n", "darbo_opt = DARBO_optimizer(\n", " eval_objective, 2 * nlayers, tr_length, failure_tolerance, mode, device\n", ")\n", "print(f\"initial mode: {darbo_opt.get_mode()}\")" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:12:41.645737200Z", "start_time": "2023-07-15T05:12:41.627726200Z" } } }, { "cell_type": "markdown", "source": [ "## Optimization" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 55, "outputs": [ { "data": { "text/plain": "
", "image/png": "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iDSeQo2X2W3mlroPCzWHGjIEkpIgLw++/74JCyciIhLAFGq8rErz08E+NYez2+Hss81r9asRERHxDoUaL6vS/LR7d43HnXuuWX/9dRMUSkREpBVQqPGyKjU1GRlQVFTtcUOGmPW2beZxbxEREWkchRov89TUOA7e2p07qz0uIcGsXS7IyWmKkomIiAQ2hRov89TUBB+cAH379mqPCwkxj3oD7NvXBAUTEZGAMWHCBGw2GzabjaCgIJKSkjj99NN56623cLvdRxw/duxYHA4HS5cuPeq5unTpwt13301xcXGV4yqOsdlsOJ1OOnbsyF/+8hdKSkqqHLdr1y6uueYaUlJSCA4OplOnTtx6663s37/fuzehGgo1XuZ5+inYTJfAjh01HltRW6NQIyIi9TVu3DjS0tLYvn07M2bMYOTIkdx6662cc845lJeXe47buXMnCxcuZNKkSbz11lu1nmvr1q288MIL/POf/+Shhx464ri3336btLQ0tm3bxquvvsq7777LY4895tm/detWBg8ezK+//soHH3zA5s2bef3115k9ezbDhg0jKyvL+zfiEE6fnr0V8jQ/BZl1TTU1YELN9u0KNSIiUn8hISEkJycD0L59e44//nhOPPFERo8ezdSpU/nTn/4EmCByzjnncNNNN3HiiSfy/PPPExYWVuO5UlNTGTNmDLNmzeLvf/97leNiY2OrHHfeeeexYsUKz/6JEycSHBzMt99+67lGx44dOe644+jWrRv33Xcfr732mm9uCKqp8TpP85OzbqEGFGpERJoLy7JwuQqafLG89MTIqFGjGDhwIJ999pnn+7z99ttcfvnl9O7dm+7du/PJJ5/Ueo61a9eycOFCgoODaz1u06ZNzJkzh6FDhwKQlZXFN998w80333xEaEpOTuayyy7jf//7n9e+a3VUU+NlR3QUrkPzUxM0M4qISB243YX88ENkk1/3lFPycTgivHKu3r17s3r1agC+++47CgsLGTt2LACXX345b775JldccUWVz0yfPp3IyEjKy8spKSnBbrfz8ssvH3HuSy65BIfD4TnunHPOYfLkyQD8+uuvWJZFnz59qi1Xnz59OHDgAJmZmbRt29Yr3/VwqqnxMk9NjcNmNqimRkREmpBlWdhs5nfQW2+9xUUXXYTTaeowLrnkEhYsWMCWLVuqfGbkyJGsXLmSn376iauuuoqrr76aCy644Ihzv/DCC6xcuZJVq1Yxffp0Nm3adERA8mVNzNGopsbLPB2F7QdDTVoalJSYx50Oo1AjItK82O3hnHJKvl+u6y3r16+nS5cuZGVl8fnnn1NWVlalH4vL5eKtt97i8ccf92yLiIige/fugAlCAwcO5M033+Taa6+tcu7k5GTPcb169SIvL49LLrmExx57jO7du2Oz2Vi/fj2///3vqy1XXFwciYmJXvuuh1NNjZdVjihsQViYGVlv165qj23TxqwVakREmgebzYbDEdHkS0XNSmPNmTOHNWvWcMEFF/D+++/ToUMHVq1axcqVKz3Lc889x9SpU3G5XNWew263c++993L//fdTVMMAshUcDvM7r6ioiDZt2nD66afz6quvHvG59PR03n//fS666CKvfddqy+6zM7dSnuYnt8tMzQ019qtRTY2IiDRUSUkJ6enp7N69mxUrVvDEE09w3nnncc4553DllVfy5ptv8sc//pF+/fpVWa699lr27dvHzJkzazz3hRdeiMPh4JVXXqmyPTs7m/T0dPbs2cP8+fN59NFH6dmzp6cfzcsvv0xJSQljx47l+++/Z9euXcycOZPTTz+d9u3bV6kd8gWFGi/z1NRYh4SabduqPVahRkREGmrmzJm0a9eOzp07M27cOObOncs//vEPvvzyS0+/l+r6xcTExDB69GjefPPNGs/tdDqZNGkSTz/9NAUFBZ7tV199Ne3ataNDhw5ccsklHHPMMcyYMcPTZ6dHjx4sW7aMrl27Mn78eLp168b111/PyJEjWbRoEfHx8d6/EYewWf7s0dMAr7zyCs888wzp6ekMHDiQl156iRNOOKFOn83NzSUmJoacnByio6N9Ur4tWVvo/lJ3IoIiyE+/Bl56Ce66C55++ohj166F/v1NuMnM9ElxRESkBsXFxWzbto0uXboQGhrq7+K0erX9edT193eLqqn53//+x1/+8hceeughVqxYwcCBAxk7diwZGRn+LppHlZqa3r3Nxg0bqj22oqYmKwuqGdVaRERE6qFFhZrnn3+e6667jquvvpq+ffvy+uuvEx4eXuOwz/7gefrJckOvXmbjxo3VHlvRUdjthuzsJiiciIhIAGsxoaa0tJTly5czZswYzza73c6YMWNYtGhRtZ8pKSkhNze3yuJrVToKV4SarVuhrOyIY4OCICbGvFa/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KMnJl5OUdDlBQfG4XAV+K4f61IiIiEij9ejxCi5XASEh/nuyTaFGREREGs3pjMbp9O8YcGp+EhERkYCgUCMiIiIBQaFGREREAoJCjYiIiAQEhRoREREJCAo1IiIiEhAUakRERCQgKNSIiIhIQFCoERERkYCgUCMiIiIBQaFGREREAoJCjYiIiAQEhRoREREJCK1qlm7LsgDIzc31c0lERESkrip+b1f8Hq9Jqwo1eXl5AKSmpvq5JCIiIlJfeXl5xMTE1LjfZh0t9gQQt9vNnj17iIqKwmazee28ubm5pKamsmvXLqKjo7123kCl+1V3ulf1o/tVd7pXdad7VT++uF+WZZGXl0dKSgp2e809Z1pVTY3dbqdDhw4+O390dLR+4OtB96vudK/qR/er7nSv6k73qn68fb9qq6GpoI7CIiIiEhAUakRERCQgKNR4QUhICA899BAhISH+LkqLoPtVd7pX9aP7VXe6V3Wne1U//rxfraqjsIiIiAQu1dSIiIhIQFCoERERkYCgUCMiIiIBQaFGREREAoJCjRe88sordO7cmdDQUIYOHcqSJUv8XSS/e/jhh7HZbFWW3r17e/YXFxczceJE2rRpQ2RkJBdccAF79+71Y4mb1vfff8+5555LSkoKNpuNL774osp+y7J48MEHadeuHWFhYYwZM4Zff/21yjFZWVlcdtllREdHExsby7XXXkt+fn4TfoumcbR7NWHChCN+1saNG1flmNZyr5588kmGDBlCVFQUbdu25fzzz2fjxo1VjqnL372dO3dy9tlnEx4eTtu2bbnrrrsoLy9vyq/ic3W5VyNGjDjiZ+vGG2+sckxruFcAr732GgMGDPAMqDds2DBmzJjh2d9cfq4Uahrpf//7H3/5y1946KGHWLFiBQMHDmTs2LFkZGT4u2h+d8wxx5CWluZZfvzxR8++22+/nWnTpvHxxx8zf/589uzZwx/+8Ac/lrZpFRQUMHDgQF555ZVq9z/99NP84x//4PXXX+enn34iIiKCsWPHUlxc7DnmsssuY926dcyaNYvp06fz/fffc/311zfVV2gyR7tXAOPGjavys/bBBx9U2d9a7tX8+fOZOHEiixcvZtasWZSVlXHGGWdQUFDgOeZof/dcLhdnn302paWlLFy4kP/85z9MnTqVBx980B9fyWfqcq8Arrvuuio/W08//bRnX2u5VwAdOnTgqaeeYvny5SxbtoxRo0Zx3nnnsW7dOqAZ/VxZ0ignnHCCNXHiRM97l8tlpaSkWE8++aQfS+V/Dz30kDVw4MBq92VnZ1tBQUHWxx9/7Nm2fv16C7AWLVrURCVsPgDr888/97x3u91WcnKy9cwzz3i2ZWdnWyEhIdYHH3xgWZZl/fLLLxZgLV261HPMjBkzLJvNZu3evbvJyt7UDr9XlmVZV111lXXeeefV+JnWeq8sy7IyMjIswJo/f75lWXX7u/f1119bdrvdSk9P9xzz2muvWdHR0VZJSUnTfoEmdPi9sizLOu2006xbb721xs+01ntVIS4uzvr3v//drH6uVFPTCKWlpSxfvpwxY8Z4ttntdsaMGcOiRYv8WLLm4ddffyUlJYWuXbty2WWXsXPnTgCWL19OWVlZlfvWu3dvOnbsqPsGbNu2jfT09Cr3JyYmhqFDh3ruz6JFi4iNjWXw4MGeY8aMGYPdbuenn35q8jL727x582jbti29evXipptuYv/+/Z59rfle5eTkABAfHw/U7e/eokWL6N+/P0lJSZ5jxo4dS25urud/5YHo8HtV4f333ychIYF+/foxefJkCgsLPfta671yuVx8+OGHFBQUMGzYsGb1c9WqJrT0tn379uFyuar8IQEkJSWxYcMGP5WqeRg6dChTp06lV69epKWl8cgjj3DKKaewdu1a0tPTCQ4OJjY2tspnkpKSSE9P90+Bm5GKe1Ddz1XFvvT0dNq2bVtlv9PpJD4+vtXdw3HjxvGHP/yBLl26sGXLFu69917OPPNMFi1ahMPhaLX3yu12c9ttt3HSSSfRr18/gDr93UtPT6/2Z69iXyCq7l4BXHrppXTq1ImUlBRWr17NX//6VzZu3Mhnn30GtL57tWbNGoYNG0ZxcTGRkZF8/vnn9O3bl5UrVzabnyuFGvGJM8880/N6wIABDB06lE6dOvHRRx8RFhbmx5JJoLn44os9r/v378+AAQPo1q0b8+bNY/To0X4smX9NnDiRtWvXVunLJtWr6V4d2u+qf//+tGvXjtGjR7Nlyxa6devW1MX0u169erFy5UpycnL45JNPuOqqq5g/f76/i1WFmp8aISEhAYfDcUQP771795KcnOynUjVPsbGx9OzZk82bN5OcnExpaSnZ2dlVjtF9MyruQW0/V8nJyUd0Ri8vLycrK6vV38OuXbuSkJDA5s2bgdZ5ryZNmsT06dOZO3cuHTp08Gyvy9+95OTkan/2KvYFmpruVXWGDh0KUOVnqzXdq+DgYLp3786gQYN48sknGThwIC+++GKz+rlSqGmE4OBgBg0axOzZsz3b3G43s2fPZtiwYX4sWfOTn5/Pli1baNeuHYMGDSIoKKjKfdu4cSM7d+7UfQO6dOlCcnJylfuTm5vLTz/95Lk/w4YNIzs7m+XLl3uOmTNnDm632/MPb2v122+/sX//ftq1awe0rntlWRaTJk3i888/Z86cOXTp0qXK/rr83Rs2bBhr1qypEgRnzZpFdHQ0ffv2bZov0gSOdq+qs3LlSoAqP1ut4V7VxO12U1JS0rx+rrzW5biV+vDDD62QkBBr6tSp1i+//GJdf/31VmxsbJUe3q3RHXfcYc2bN8/atm2btWDBAmvMmDFWQkKClZGRYVmWZd14441Wx44drTlz5ljLli2zhg0bZg0bNszPpW46eXl51s8//2z9/PPPFmA9//zz1s8//2zt2LHDsizLeuqpp6zY2Fjryy+/tFavXm2dd955VpcuXayioiLPOcaNG2cdd9xx1k8//WT9+OOPVo8ePaxLLrnEX1/JZ2q7V3l5edadd95pLVq0yNq2bZv13XffWccff7zVo0cPq7i42HOO1nKvbrrpJismJsaaN2+elZaW5lkKCws9xxzt7155ebnVr18/64wzzrBWrlxpzZw500pMTLQmT57sj6/kM0e7V5s3b7YeffRRa9myZda2bdusL7/80uratat16qmnes7RWu6VZVnWPffcY82fP9/atm2btXr1auuee+6xbDab9e2331qW1Xx+rhRqvOCll16yOnbsaAUHB1snnHCCtXjxYn8Xye8uuugiq127dlZwcLDVvn1766KLLrI2b97s2V9UVGTdfPPNVlxcnBUeHm79/ve/t9LS0vxY4qY1d+5cCzhiueqqqyzLMo91P/DAA1ZSUpIVEhJijR492tq4cWOVc+zfv9+65JJLrMjISCs6Otq6+uqrrby8PD98G9+q7V4VFhZaZ5xxhpWYmGgFBQVZnTp1sq677roj/lPRWu5VdfcJsN5++23PMXX5u7d9+3brzDPPtMLCwqyEhATrjjvusMrKypr42/jW0e7Vzp07rVNPPdWKj4+3QkJCrO7du1t33XWXlZOTU+U8reFeWZZlXXPNNVanTp2s4OBgKzEx0Ro9erQn0FhW8/m5slmWZXmv3kdERETEP9SnRkRERAKCQo2IiIgEBIUaERERCQgKNSIiIhIQFGpEREQkICjUiIiISEBQqBEREZGAoFAjIiIiAUGhRkRalc6dOzNlyhR/F0NEfEChRkR8ZsKECZx//vkAjBgxgttuu63Jrj116lRiY2OP2L506VKuv/76JiuHiDQdp78LICJSH6WlpQQHBzf484mJiV4sjYg0J6qpERGfmzBhAvPnz+fFF1/EZrNhs9nYvn07AGvXruXMM88kMjKSpKQkrrjiCvbt2+f57IgRI5g0aRK33XYbCQkJjB07FoDnn3+e/v37ExERQWpqKjfffDP5+fkAzJs3j6uvvpqcnBzP9R5++GHgyOannTt3ct555xEZGUl0dDTjx49n7969nv0PP/wwxx57LO+++y6dO3cmJiaGiy++mLy8PN/eNBGpN4UaEfG5F198kWHDhnHdddeRlpZGWloaqampZGdnM2rUKI477jiWLVvGzJkz2bt3L+PHj6/y+f/85z8EBwezYMECXn/9dQDsdjv/+Mc/WLduHf/5z3+YM2cOd999NwDDhw9nypQpREdHe6535513HlEut9vNeeedR1ZWFvPnz2fWrFls3bqViy66qMpxW7Zs4YsvvmD69OlMnz6d+fPn89RTT/nobolIQ6n5SUR8LiYmhuDgYMLDw0lOTvZsf/nllznuuON44oknPNveeustUlNT2bRpEz179gSgR48ePP3001XOeWj/nM6dO/PYY49x44038uqrrxIcHExMTAw2m63K9Q43e/Zs1qxZw7Zt20hNTQXgnXfe4ZhjjmHp0qUMGTIEMOFn6tSpREVFAXDFFVcwe/ZsHn/88cbdGBHxKtXUiIjfrFq1irlz5xIZGelZevfuDZjakQqDBg064rPfffcdo0ePpn379kRFRXHFFVewf/9+CgsL63z99evXk5qa6gk0AH379iU2Npb169d7tnXu3NkTaADatWtHRkZGvb6riPieampExG/y8/M599xz+fvf/37Evnbt2nleR0REVNm3fft2zjnnHG666SYef/xx4uPj+fHHH7n22mspLS0lPDzcq+UMCgqq8t5ms+F2u716DRFpPIUaEWkSwcHBuFyuKtuOP/54Pv30Uzp37ozTWfd/jpYvX47b7ea5557DbjcVzh999NFRr3e4Pn36sGvXLnbt2uWprfnll1/Izs6mb9++dS6PiDQPan4SkSbRuXNnfvrpJ7Zv386+fftwu91MnDiRrKwsLrnkEpYuXcqWLVv45ptvuPrqq2sNJN27d6esrIyXXnqJrVu38u6773o6EB96vfz8fGbPns2+ffuqbZYaM2YM/fv357LLLmPFihUsWbKEK6+8ktNOO43Bgwd7/R6IiG8p1IhIk7jzzjtxOBz07duXxMREdu7cSUpKCgsWLMDlcnHGGWfQv39/brvtNmJjYz01MNUZOHAgzz//PH//+9/p168f77//Pk8++WSVY4YPH86NN97IRRddRGJi4hEdjcE0I3355ZfExcVx6qmnMmbMGLp27cr//vc/r39/EfE9m2VZlr8LISIiItJYqqkRERGRgKBQIyIiIgFBoUZEREQCgkKNiIiIBASFGhEREQkICjUiIiISEBRqREREJCAo1IiIiEhAUKgRERGRgKBQIyIiIgFBoUZEREQCwv8DMUDZP+gMBJwAAAAASUVORK5CYII=" }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 299 min loss: -5.837215998677346\t-6.87628698348999\t-6.8708058821631575\t-7.000515157123274\n", "Epoch 299 time: 13.83302903175354\tTotal time: 2123.8649847507477\n" ] } ], "source": [ "# initial parameters\n", "params = K.implicit_randu(shape=(2 * nlayers,))\n", "initial_X = torch.from_numpy(np.asarray(params)).type(dtype)\n", "\n", "# First point by BO is actually just a random selection, to have a better search, we pick the most distant point\n", "X_new = []\n", "for i in initial_X:\n", " if i <= 0.5:\n", " X_new.append(i + 0.5)\n", " else:\n", " X_new.append(i - 0.5)\n", "X_new = torch.tensor(X_new)\n", "\n", "X_bo = torch.stack((initial_X, X_new), dim=0)\n", "Y_bo = None\n", "X_turbo = X_bo.clone()\n", "Y_turbo = None\n", "X_darbo = X_bo.clone()\n", "Y_darbo = None\n", "\n", "losses, losses_bo, losses_turbo, losses_darbo = [], [], [], []\n", "t0 = ts = time.time()\n", "\n", "for i in range(300):\n", " loss, grads = QAOA_vag(params)\n", " params = opt.update(grads, params) # gradient descent\n", " losses.append(loss)\n", "\n", " X_bo, Y_bo, _ = bo_opt.update(X_bo, Y_bo, acqfn)\n", " losses_bo.append(-bo_opt.best_dict[\"Y\"].item())\n", "\n", " X_turbo, Y_turbo, _ = turbo_opt.update(\n", " X_turbo,\n", " Y_turbo,\n", " acqfn,\n", " transformed_input=False if i == 0 else True,\n", " transformed_output=True,\n", " )\n", " losses_turbo.append(-turbo_opt.best_dict[\"Y\"].item())\n", "\n", " X_darbo, Y_darbo, _ = darbo_opt.update(\n", " X_darbo,\n", " Y_darbo,\n", " acqfn,\n", " transformed_input=False if i == 0 else True,\n", " transformed_output=True,\n", " )\n", " losses_darbo.append(-darbo_opt.best_dict[\"Y\"].item())\n", "\n", " # visualise the progress\n", " clear_output(wait=True)\n", " plt.figure()\n", " plt.xlabel(\"Iteration\")\n", " plt.ylabel(\"Cost\")\n", " plt.plot(range(i + 1), losses, c=\"r\", label=\"Adam\")\n", " plt.plot(range(i + 1), losses_bo, c=\"b\", label=\"BO\")\n", " plt.plot(range(i + 1), losses_turbo, c=\"g\", label=\"TuRBO\")\n", " plt.plot(range(i + 1), losses_darbo, c=\"y\", label=\"DARBO\")\n", " plt.legend()\n", " plt.show()\n", "\n", " print(\n", " f\"Epoch {i} min loss: {min(losses)}\\t{losses_bo[-1]}\\t{losses_turbo[-1]}\\t{losses_darbo[-1]}\"\n", " )\n", "\n", " te = time.time()\n", " print(f\"Epoch {i} time: {te - ts}\\tTotal time: {te - t0}\")\n", " ts = te" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "## Results" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "After inputting the optimized parameters back to the ansatz circuit, we can perform the projective measurement on the output quantum state to get the solution. Here we directly use the bit string with the maximum probability as the solution since we know all information of the probability distribution of the output quantum state, but which is not feasible in the experiment." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 56, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Adam\n", "loss: -5.837558827215271\tprob: 0.318607790021735\tbit strings: ['10101010']\n", "\n", "BO\n", "loss: -6.876287191047742\tprob: 0.3434109359024678\tbit strings: ['10101010']\n", "\n", "TuRBO\n", "loss: -6.8708058821631575\tprob: 0.3339171040448526\tbit strings: ['10101010']\n", "\n", "DARBO\n", "loss: -7.000515157123274\tprob: 0.36778546095898973\tbit strings: ['01010101']\n" ] } ], "source": [ "params_bo = jnp.asarray(bo_opt.best_dict[\"X\"])\n", "params_turbo = jnp.asarray(turbo_opt.inverse_transform(turbo_opt.best_dict[\"X\"]))\n", "params_darbo = jnp.asarray(\n", " darbo_opt.inverse_transform(\n", " darbo_opt.best_dict[\"X\"], mode=darbo_opt.best_dict[\"mode\"]\n", " )\n", ")\n", "\n", "\n", "# find the states with max probabilities\n", "def find_max(params):\n", " loss = QAOA_nograd(params)\n", " c = QAOAansatz(params, return_circuit=True)\n", " probs = K.numpy(c.probability())\n", " max_prob = max(probs)\n", " index = np.where(probs == max_prob)[0]\n", " states = []\n", " for i in index:\n", " states.append(f\"{bin(i)[2:]:0>{graph.number_of_nodes()}}\")\n", " return loss, max_prob, states\n", "\n", "\n", "loss, prob, states = find_max(params)\n", "loss_bo, prob_bo, states_bo = find_max(params_bo)\n", "loss_turbo, prob_turbo, states_turbo = find_max(params_turbo)\n", "loss_darbo, prob_darbo, states_darbo = find_max(params_darbo)\n", "print(f\"Adam\\nloss: {loss}\\tprob: {prob}\\tbit strings: {states}\\n\")\n", "print(f\"BO\\nloss: {loss_bo}\\tprob: {prob_bo}\\tbit strings: {states_bo}\\n\")\n", "print(f\"TuRBO\\nloss: {loss_turbo}\\tprob: {prob_turbo}\\tbit strings: {states_turbo}\\n\")\n", "print(f\"DARBO\\nloss: {loss_darbo}\\tprob: {prob_darbo}\\tbit strings: {states_darbo}\")" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:48:09.478379400Z", "start_time": "2023-07-15T05:48:05.566717500Z" } } }, { "cell_type": "code", "execution_count": 57, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", "Python version: 3.10.11\n", "Numpy version: 1.23.5\n", "Scipy version: 1.11.0\n", "Pandas version: 2.0.2\n", "TensorNetwork version: 0.4.6\n", "Cotengra version: 0.2.1.dev15+g120379e\n", "TensorFlow version: 2.12.0\n", "TensorFlow GPU: []\n", "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", "Jax version: 0.4.13\n", "Jax installation doesn't support GPU\n", "JaxLib version: 0.4.13\n", "PyTorch version: 2.0.1\n", "PyTorch GPU support: False\n", "PyTorch GPUs: []\n", "Cupy is not installed\n", "Qiskit version: 0.24.1\n", "Cirq version: 1.1.0\n", "TensorCircuit version 0.10.0\n" ] } ], "source": [ "tc.about()" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-07-15T05:48:09.478379400Z", "start_time": "2023-07-15T05:48:09.477371900Z" } } } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12" } }, "nbformat": 4, "nbformat_minor": 5 }