From 570831c78e5fb067b041b418755ce5964d7ea34b Mon Sep 17 00:00:00 2001 From: Moon8888888 Date: Fri, 27 Mar 2026 15:56:35 +0800 Subject: [PATCH 1/2] docs(tutorial): add four English and Chinese tutorial notebook --- .../dense_subgraph/dense_subgraph_en.ipynb | 10931 +++ ...subgraph.ipynb => dense_subgraph_zh.ipynb} | 1511 +- .../graph_isomorphism_en.ipynb | 6192 ++ .../graph_isomorphism_zh.ipynb | 6192 ++ ...aph_isomorphism.ipynb => similarity.ipynb} | 941 +- .../molecular_docking_en.ipynb | 75035 ++++++++++++++++ ...cking.ipynb => molecular_docking_zh.ipynb} | 650 +- .../molecular_vibronic_spectra.ipynb | 45517 ---------- .../molecular_vibronic_spectra_en.ipynb | 9482 ++ .../molecular_vibronic_spectra_zh.ipynb | 10736 +++ 10 files changed, 120005 insertions(+), 47182 deletions(-) create mode 100644 cqlib_experiments/photonic/dense_subgraph/dense_subgraph_en.ipynb rename cqlib_experiments/photonic/dense_subgraph/{dense_subgraph.ipynb => dense_subgraph_zh.ipynb} (79%) create mode 100644 cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_en.ipynb create mode 100644 cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_zh.ipynb rename cqlib_experiments/photonic/graph_isomorphism/{graph_isomorphism.ipynb => similarity.ipynb} (91%) create mode 100644 cqlib_experiments/photonic/molecular_docking/molecular_docking_en.ipynb rename cqlib_experiments/photonic/molecular_docking/{molecular_docking.ipynb => molecular_docking_zh.ipynb} (99%) delete mode 100644 cqlib_experiments/photonic/molecular_vibronic_spectra/molecular_vibronic_spectra.ipynb create mode 100644 cqlib_experiments/photonic/molecular_vibronic_spectra/molecular_vibronic_spectra_en.ipynb create mode 100644 cqlib_experiments/photonic/molecular_vibronic_spectra/molecular_vibronic_spectra_zh.ipynb diff --git a/cqlib_experiments/photonic/dense_subgraph/dense_subgraph_en.ipynb b/cqlib_experiments/photonic/dense_subgraph/dense_subgraph_en.ipynb new file mode 100644 index 0000000..5d2c6f2 --- /dev/null +++ b/cqlib_experiments/photonic/dense_subgraph/dense_subgraph_en.ipynb @@ -0,0 +1,10931 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "da354cb7", + "metadata": {}, + "source": [ + "# Dense Subgraph Search Enhanced by Gaussian Boson Sampling\n", + "\n", + "This tutorial explains how to use the sampling bias of Gaussian Boson Sampling (GBS) to enhance the solution of the dense subgraph search problem. This problem appears widely in graph mining, social network analysis, anomalous structure identification, and a range of combinatorial optimization tasks.\n", + "\n", + "---\n", + "\n", + "## Principle\n", + "\n", + "### Problem Definition\n", + "\n", + "Many scientific computing and combinatorial optimization tasks can be abstracted as searching for a subset of vertices with strong internal compatibility on a graph. Dense subgraph search is one canonical form of this idea. Given a graph $G=(V,E)$ and its adjacency matrix $A$, the goal is to identify, among all vertex subsets of size exactly $k$, an induced subgraph with the strongest possible internal connectivity.\n", + "\n", + "More specifically, the problem contains the following three key elements:\n", + "\n", + "- The graph is represented by $G=(V,E)$, with adjacency matrix $A$;\n", + "- Exactly $k$ vertices must be selected from the full vertex set;\n", + "- The optimization objective is to maximize the internal connectivity of the induced subgraph formed by the selected vertices.\n", + "\n", + "A commonly used objective function is\n", + "\n", + "$$\n", + "\\rho(S)=\\frac{1}{k(k-1)}\\sum_{i,j\\in S}A_{ij}, \\qquad |S|=k.\n", + "$$\n", + "\n", + "Here, $S$ denotes a candidate vertex subset, and $\\rho(S)$ denotes the normalized density of the corresponding induced subgraph.\n", + "\n", + "For an unweighted simple graph with zero diagonal entries in its adjacency matrix, the expression can be further written as\n", + "\n", + "$$\n", + "\\rho(S)=\\frac{2|E(S)|}{k(k-1)}.\n", + "$$\n", + "\n", + "Here, $E(S)$ denotes the set of internal edges of subgraph $S$. Therefore, $\\rho(S)$ directly characterizes the connectivity density of the selected induced subgraph, and its value typically lies in the interval $[0,1]$. A larger value indicates that the subgraph is more densely connected internally.\n", + "\n", + "### Why This Problem Is Challenging ?\n", + "\n", + "Although the problem definition is straightforward, solving it is typically difficult. The reason is that the number of candidate vertex subsets of size $k$ is\n", + "\n", + "$$\n", + "\\binom{|V|}{k},\n", + "$$\n", + "\n", + "which grows combinatorially as the graph size increases. For larger graphs, exhaustive enumeration of all candidate subsets is usually infeasible. In practice, the problem is therefore often addressed using approximate optimization or heuristic search methods such as greedy methods, random search, and simulated annealing.\n", + "\n", + "### Why GBS Can Help ?\n", + "\n", + "Gaussian Boson Sampling is a sampling mechanism based on Gaussian optical states and photon measurements. When a graph structure is encoded into the corresponding optical system, the output samples are not drawn uniformly over all candidate subsets. Instead, certain vertex combinations with stronger structural features are assigned higher sampling probabilities.\n", + "\n", + "For the dense subgraph problem, this means that vertex subsets associated with highly connected and highly compatible regions are more likely to appear in GBS samples. In other words, GBS can provide a structurally biased candidate distribution for the classical search process, allowing the search to focus more quickly on high-quality regions rather than exploring the entire candidate space uniformly and blindly.\n", + "\n", + "### Basic Idea of This Tutorial\n", + "\n", + "Based on the above property, this tutorial adopts a hybrid strategy of **GBS sampling + classical heuristic search**. The main idea is:\n", + "\n", + "1. Construct the corresponding GBS sampling problem from the graph structure;\n", + "2. Generate GBS samples related to the graph structure;\n", + "3. Postselect the samples so that they correspond to candidate vertex subsets of size exactly $k$;\n", + "4. Use these samples as candidate sources for classical random search or simulated annealing;\n", + "5. Compare the search performance of classical methods and GBS-enhanced methods under the same budget.\n", + " \n", + "---\n", + "\n", + "## Technical Route\n", + "\n", + "### Overall Workflow\n", + "\n", + "This tutorial follows a comparative experimental route of classical baselines plus GBS enhancement. The overall workflow can be summarized into the following stages:\n", + "\n", + "1. **Import dependencies and initialize the environment**: introduce the basic libraries required for numerical computation, combinatorial enumeration, visualization, and GBS sampling.\n", + "2. **Define the objective function and search algorithms**: implement the dense subgraph objective function together with several classical and GBS-enhanced search algorithms.\n", + "3. **Construct the graph instance for the experiment**: load the example graph and specify key parameters such as target subgraph size and iteration budget.\n", + "4. **Run baseline algorithms**: execute classical greedy, random search, and simulated annealing methods to obtain reference results.\n", + "5. **Run GBS-enhanced algorithms**: generate a candidate subgraph database based on GBS samples and use it to run `RS-GBS` and `SA-GBS`.\n", + "6. **Aggregate and visualize the results**: plot performance curves of different methods versus iteration count, and compare their search efficiency and final outcomes.\n", + "\n", + "### Comparison Among Methods\n", + "\n", + "To explain the technical route more clearly, this tutorial compares the following methods:\n", + "\n", + "- **DGreedy**: a classical greedy deletion method, used as a fast and deterministic reference baseline;\n", + "- **Random Search**: uniform random sampling in the candidate space, used to reflect search capability without structural prior information;\n", + "- **Simulated Annealing**: a classical heuristic optimization method that escapes local optima by accepting inferior solutions with a certain probability;\n", + "- **RS-GBS**: directly uses GBS samples as candidate sources for random search, to examine the effect of sampling bias on search quality;\n", + "- **SA-GBS**: introduces GBS information into the proposal generation stage of simulated annealing, to evaluate how structurally informed sampling enhances local search efficiency.\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "76c55871", + "metadata": {}, + "source": [ + "\n", + "## 1. Import Dependencies\n", + "\n", + "This step imports the basic libraries required for numerical computation, random sampling, combinatorial enumeration, and visualization. In particular:\n", + "\n", + "- `thewalrus` is used for GBS-related sampling;\n", + "- `numpy` is used for matrix and array operations;\n", + "- `random` and `itertools.combinations` are used for random perturbations and candidate enumeration in classical search;\n", + "- `matplotlib` is used to plot the final performance curves.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5c8b14a3", + "metadata": {}, + "outputs": [], + "source": [ + "# Import the basic libraries and GBS-related tools required for this tutorial.\n", + "import thewalrus\n", + "import numpy as np\n", + "import random\n", + "from itertools import combinations\n", + "from matplotlib import pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "id": "7f9c97cb", + "metadata": {}, + "source": [ + "\n", + "## 2. Define the Objective Function and Search Algorithms\n", + "\n", + "This step provides the core functions used throughout the experiment:\n", + "\n", + "- `dense`: computes the dense-subgraph objective value of a candidate vertex subset;\n", + "- `DGreedy`: greedy deletion method;\n", + "- `RandomSearch`: uniform random sampling of candidate subgraphs;\n", + "- `RandomSearchGBSA`: random search performed directly on postselected GBS samples;\n", + "- `SimulatedAnnealing`: classical simulated annealing;\n", + "- `SimulatedAnnealingGBSA`: simulated annealing that uses GBS samples to design neighborhood perturbations.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e5bc541e", + "metadata": {}, + "outputs": [], + "source": [ + "# Define the dense-subgraph objective function, together with classical and GBS-enhanced search algorithms.\n", + "def dense(A,s):\n", + " return np.abs(np.sum(A[np.ix_(s,s)]))\n", + "\n", + "def DGreedy(A,k,f):\n", + " index=np.arange(len(A))\n", + " l=len(index)\n", + " while l > k:\n", + " candidate= np.array(list(combinations(range(l),l-1)))\n", + " tmp=np.array([f(A,index[i]) for i in candidate])\n", + " index=index[candidate[tmp.argmax()]]\n", + " l=len(index)\n", + " return index,tmp.max()\n", + "\n", + "def RandomSearch(N,k,A,f):\n", + " bestI=np.zeros(k,dtype = np.uint8)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " ind=np.arange(len(A),dtype = np.uint8)\n", + " for i in range(N):\n", + " l=np.random.choice(ind,k,replace=False)\n", + " h=f(A,l)\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=l\n", + " result[i]=largestH\n", + " return result,bestI\n", + "\n", + "def RandomSearchGBSA(N,A,DB,f):\n", + " bestI=np.zeros(np.sum(DB[0]),dtype = np.int64)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " candidate=np.random.choice(np.arange(len(DB)),size=N,replace=False)\n", + " for i in range(N):\n", + " s=DB[candidate[i]]\n", + " s = np.nonzero(s)[0]\n", + " h=f(A,s)\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=s\n", + " result[i]=largestH\n", + " return result,bestI\n", + "\n", + "def generateSample(S,k,l,DataBase):\n", + " m=random.randint(0,k-l-1)\n", + " s=np.zeros_like(S,dtype=np.uint8)\n", + " s[np.random.choice(np.nonzero(S)[0],m+l,replace=False) ]=1\n", + " Tori=DataBase[random.randint(0,len( DataBase)-1)]\n", + " t=np.zeros_like(Tori,dtype=np.uint8)\n", + " t[np.random.choice(np.nonzero(Tori)[0],k-l-m,replace=False) ]=1\n", + " return s,t\n", + "\n", + "def GBS_Tweak(S,l,DataBase):\n", + " k=np.uint16(np.sum(S))\n", + " s,t=generateSample(S,k,l,DataBase)\n", + " while(np.sum(t&s)>0):\n", + " s,t=generateSample(S,k,l,DataBase)\n", + " return (s|t).astype(np.uint8)\n", + "\n", + "def SimulatedAnnealing(N,k,A,C,T,f,ratio):\n", + " bestI=np.zeros(k,dtype=np.int64)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " ind=np.arange(len(A))\n", + " l0=np.random.choice(ind,k,replace=False)\n", + " h0=f(A,l0)\n", + "\n", + " for i in range(N):\n", + " m=random.randint(0,C-1)\n", + " tmp=np.random.choice(l0,k-C+m,replace=False)\n", + " l=np.concatenate((tmp,np.random.choice(np.array(list(set(ind)-set(tmp))),C-m,replace=False)))\n", + " h=f(A,l)\n", + " if h>h0:\n", + " h0=h\n", + " l0=l\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=l\n", + " elif np.random.random()h0:\n", + " h0=h\n", + " l0=r\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=tmp\n", + " else:\n", + " check = random.random()\n", + " if check" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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2bNnyw8//GCeL1++XL744gvp1auXec55Dr5gnVNtc84550hsbGyJ72ztct+5c2eVjjHiFpYLtj/++MP0ORa/4Cl9/v3337t2XNWZrjysNQhnnnmmtGnTxrymH3T9gOqH+eDzrNv8bUr7Pfi3odDkyZPl66+/lsWLFx9ySjjPwfPTTz/J888/L8OHD5d7773XnO9bb73VfI6vvfbawGeytM9s8c+0Bi7FRUdHm6Ccz3She+65x/yBoX+MREVFme/jRx55xNQaFP9vn/McPME6p3qvtToH78O/rWbNmpU+xqM++EBo/ipfuXKl+esFwaVLXN92220ya9YsU+CF0AbR+lffo48+ap5r5kM/1+PHjzfBB4Lj7bffltdff13eeOMNOemkk2TZsmXmjxctlOQ82+uo73Y55phjTLR98KgLfV6vXj3Xjqu6uuWWW2TGjBny2WefSYMGDQKv67nULq7MzMwyz7Pel/Z78G9DYbfKtm3bpH379uavEL3NnTtXnnnmGfNY/+rgPAeHjgJo3bp1iddatWplRmQV/0we7rtD7/X3VZyO3tJRBHymC+mINs1+XHbZZabb9eqrr5Zhw4aZEXSc59AI1mc3lN/ZR33woSnUDh06mD7H4n/x6PPOnTu7emzVidY0aeAxdepU+fTTTw9Jxek5jomJKXGetV9Qv8j951nvV6xYUeIDr3/h6zCvgy8CturWrZs5R/rXof+mf51ritr/mPMcHNptePBwca1LaNy4sXmsn3H9gi3+mdbuA+0PL/6Z1oBbg0Y//e9Dv2O0fx0i+/btM3UExekfhHqOOM+hEazPrrbRIb1az1f8O7tFixZV6nIxHEuG2mqV76RJk0yF70033WSG2hYfdYHDu/nmm82wrTlz5jibN28O3Pbt21diCKgOv/3000/NUNvOnTub28FDbXv06GGG63788cdO7dq1GWp7BMVHu3CegzuUOTo62gwFXbt2rfP66687iYmJzmuvvVZiuKJ+V7z//vvOt99+61x00UWlDlc85ZRTzHDdL774woxSYqjtAddee61z3HHHBYba6tBQHWJ/1113cZ6rOCJOpyzQm17Kn3rqKfP4l19+CdpnV0fI6FDbq6++2gy11Wup/jfCUNsKePbZZ82FUef70KG3Oq4Z5acf7tJuOveHn36o//a3v5mhWfoBvfjii02AUtzPP//s9OrVy4wV1y+gO+64w8nLy+NXUYHgg/McPNOnTzcBsf5x0rJlS+fFF18ssV2HLI4cOdJ8AWubbt26OWvWrCnRZvv27eYLW+eu0GHj1113nbkwoNDu3bvN51e/f+Pj453jjz/ezE9RfPgm57niPvvss1K/kzXYC+Y51TlCdEi67kODSA1qgsGj/1e13AkAAED5HfU1HwAAILIQfAAAgLAi+AAAAGFF8AEAAMKK4AMAAIQVwQcAAAgrgg8AABBWBB8AACCsCD4AAEBYEXwAAICwIvgAAABhRfABAAAknP4/mp9rxp8w0KgAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the performance curves of multiple methods and compare the search behavior before and after GBS enhancement.\n", + "plt.plot(M_SA, label='SA')\n", + "plt.plot(M_SAGBS, label='SA-GBS')\n", + "plt.plot(M_RS, label='RS')\n", + "plt.plot(M_RSGBS, label='RS-GBS')\n", + "plt.plot(\n", + " np.arange(N),M_D*np.ones(N),\"--\", label='DGreedy'\n", + ")\n", + "plt.legend()" + ] + }, + { + "cell_type": "markdown", + "id": "c17fd764", + "metadata": {}, + "source": [ + "\n", + "## 7. Conclusion\n", + "\n", + "This tutorial shows that GBS is not used here as a stand-alone replacement for classical algorithms. Instead, it is combined with classical heuristic search as a **physically inspired candidate-generation mechanism**. This hybrid paradigm of \"quantum sampling + classical optimization\" has the following characteristics:\n", + "\n", + "- It does not alter the original combinatorial optimization objective;\n", + "\n", + "- It is easily integrated with existing classical post-processing algorithms;\n", + "\n", + "- It can transform the structural bias in the quantum sampling distribution into a practical search advantage.\n", + "\n", + "In summary, this tutorial study helps readers understand that GBS is not merely \"sampling,\" but can serve as a high-quality candidate solution generation tool for practical optimization tasks." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "photon", + "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.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cqlib_experiments/photonic/dense_subgraph/dense_subgraph.ipynb b/cqlib_experiments/photonic/dense_subgraph/dense_subgraph_zh.ipynb similarity index 79% rename from cqlib_experiments/photonic/dense_subgraph/dense_subgraph.ipynb rename to cqlib_experiments/photonic/dense_subgraph/dense_subgraph_zh.ipynb index 46d2b0c..11062ca 100644 --- a/cqlib_experiments/photonic/dense_subgraph/dense_subgraph.ipynb +++ b/cqlib_experiments/photonic/dense_subgraph/dense_subgraph_zh.ipynb @@ -2,525 +2,386 @@ "cells": [ { "cell_type": "markdown", - "id": "dc7bab75", + "id": "da354cb7", "metadata": {}, "source": [ - "# Dense Subgraph with Gaussian Boson Sampling\n" - ] - }, - { - "cell_type": "markdown", - "id": "efd35505", - "metadata": {}, - "source": [ - "Principle\n", - "---------\n", - "This notebook presents a detailed workflow for solving the **fixed-size dense\n", - "subgraph problem** with **GBS-enhanced heuristics**.\n", + "# 基于高斯玻色采样增强的稠密子图搜索\n", "\n", - "### 1) Problem Definition and Docking-Relevant Motivation\n", - "Many scientific optimization tasks can be written as \"find a strongly\n", - "compatible subset\" on a graph. Dense-subgraph search is one canonical form:\n", - "- Graph $G=(V, E)$, adjacency matrix $A$.\n", - "- Choose exactly $k$ vertices.\n", - "- Maximize internal connectivity of the induced subgraph.\n", + "本案例介绍如何利用高斯玻色采样(Gaussian Boson Sampling, GBS)的采样偏置特性,对稠密子图搜索问题进行增强求解。该问题广泛存在于图挖掘、社交网络分析、异常结构识别等组合优化任务中。\n", "\n", - "A common objective is:\n", - "$\\rho(S) = \\frac{1}{k(k-1)} \\sum_{i,j \\in S} A_{ij}, \\quad \\text{with } |S| = k.$\n", + "---\n", "\n", - "For unweighted simple graphs (zero diagonal), this becomes:\n", - "$rho(S) = 2 * |E(S)| / (k * (k - 1)).$\n", + "## 原理\n", "\n", - "So $rho(S)$ directly measures induced-subgraph density in $[0, 1]$.\n", + "### 问题描述\n", "\n", - "### 2) Why the Task Is Computationally Difficult\n", - "The number of size-k subsets is $C(|V|, k)$, which grows combinatorially.\n", - "Exhaustive search becomes quickly infeasible as graph size increases.\n", - "Therefore, practical pipelines rely on approximate methods:\n", - "- Greedy elimination / construction heuristics\n", - "- Randomized search\n", - "- Simulated annealing and related local-search methods\n", + "许多科学计算与组合优化问题,都可以抽象为在图中寻找一个“内部高度兼容的顶点子集”,稠密子图搜索就是其中的一种典型形式。给定图 $G=(V,E)$ 及其邻接矩阵 $A$,目标是在所有大小为 $k$ 的顶点子集中,找出一个内部连接尽可能稠密的子图。\n", "\n", - "These methods trade optimality guarantees for speed and scalability.\n", + "具体来说,该问题包含以下三个基本要素:\n", "\n", - "### 3) Why GBS Can Help\n", - "In Gaussian Boson Sampling, squeezed-light inputs are transformed by a linear\n", - "interferometer, and photon-number measurement produces occupation patterns.\n", - "When the interferometer is graph-encoded, detection probabilities are related to\n", - "Hafnian/Torontonian quantities of graph-derived submatrices.\n", + "- 图结构由 $G=(V,E)$ 表示,对应邻接矩阵为 $A$;\n", + "- 需要从全部顶点中**恰好选出 $k$ 个顶点**;\n", + "- 优化目标是使所选顶点诱导出的子图具有尽可能高的内部连通性。\n", "\n", - "Practical consequence for optimization:\n", - "- Sampling is not uniform over subsets.\n", - "- Dense and structured regions tend to receive higher probability mass.\n", - "- The sampled subsets can serve as stronger proposals or initializations than\n", - " uniform random guesses.\n", + "一个常用的目标函数可写为:\n", "\n", - "This notebook uses that property as a **proposal-bias mechanism** inside\n", - "classical heuristics.\n", + "$$\n", + "\\rho(S)=\\frac{1}{k(k-1)}\\sum_{i,j\\in S}A_{ij}, \\qquad |S|=k.\n", + "$$\n", "\n", - "### 4) Hybrid Quantum-Classical Pipeline in This Notebook\n", - "The pipeline is intentionally modular:\n", - "1. Run classical baselines (DGreedy, Random Search, Simulated Annealing).\n", - "2. Load pre-generated GBS bitstring samples.\n", - "3. Postselect samples with exactly k photons so each sample maps to a size-k\n", - " vertex subset.\n", - "4. Run GBS-guided Random Search and GBS-guided Simulated Annealing.\n", - "5. Compare convergence curves and final best normalized density.\n", + "其中,$S$ 表示候选顶点集合,$\\rho(S)$ 表示对应诱导子图的归一化稠密度。\n", "\n", - "Interpretation rule used here:\n", - "If GBS-guided traces reach better values faster (or finish higher) under the\n", - "same compute budget, then the GBS sampling bias is beneficial for this graph.\n", + "对于无权简单图,并且邻接矩阵对角元为零时,上式可进一步写为:\n", "\n", - "### 5) Algorithmic Roles of Each Method\n", - "- DGreedy: deterministic baseline; fast and stable, but may get stuck in local\n", - " structure biases.\n", - "- RS (uniform): explores globally but sample efficiency can be low.\n", - "- SA (uniform proposals): balances exploration and exploitation with\n", - " temperature scheduling.\n", - "- RS-GBS: same budget as RS but candidates come from postselected GBS samples.\n", - "- SA-GBS: SA with GBS-informed proposal moves, often improving search quality\n", - " in the same iteration budget.\n", + "$$\n", + "\\rho(S)=\\frac{2|E(S)|}{k(k-1)}.\n", + "$$\n", "\n", - "### 6) Evaluation Metrics and Fairness\n", - "To ensure comparability:\n", - "- All stochastic methods use the same iteration budget $N$.\n", - "- All methods target the same subset size k.\n", - "- We track best-so-far objective curves and final normalized density.\n", + "其中,$E(S)$ 表示子图 $S$ 内部的边集合。由此可见,$\\rho(S)$ 直接刻画了所选诱导子图的连接密度,其取值通常位于 $[0,1]$ 区间内。数值越大,说明该子图内部连接越紧密。\n", "\n", - "This gives both:\n", - "- Final quality comparison (best density at step N)\n", - "- Search-efficiency comparison (how quickly methods improve)\n", + "### 为什么该问题具有挑战性?\n", "\n", - "### 7) Scope, Assumptions, and Limitations\n", - "Included in this tutorial:\n", - "- Graph-level dense-subgraph optimization.\n", - "- GBS-guided sampling as a heuristic accelerator.\n", + "尽管问题定义较为直接,但其求解难度通常较高。原因在于,所有大小为 $k$ 的候选顶点子集数量为\n", "\n", - "Not included:\n", - "- End-to-end photonic hardware execution details.\n", - "- Error mitigation/noise modeling.\n", - "- Proof of global optimality.\n", + "$$\n", + "\\binom{|V|}{k},\n", + "$$\n", + "\n", + "该数量会随图规模增大而呈组合爆炸增长。对于较大的图,穷举所有候选子集通常不可行,因此实际求解往往依赖近似优化或启发式搜索方法,例如贪心方法、随机搜索和模拟退火等。\n", + "\n", + "### 高斯玻色采样为什么能够提供帮助?\n", + "\n", + "高斯玻色采样是一种基于高斯光学态和光子测量的采样机制。当图结构被编码到相应的光学系统后,输出样本并不是对所有候选子集进行均匀抽样,而是会对某些具有更强结构特征的顶点组合赋予更高的采样概率。\n", + "\n", + "对于稠密子图问题,与高连通、高兼容区域相关的顶点子集往往更容易在 GBS 样本中出现。也就是说,GBS 可以为经典搜索过程提供一种具有结构偏置的候选分布,使搜索更快聚焦到高质量区域,而不是在整个候选空间中盲目均匀探索。\n", + "\n", + "### 整体思路\n", + "\n", + "基于上述特点,本案例的实验思路为:\n", + "\n", + "1. 先根据图结构构造对应的 GBS 采样问题;\n", + "2. 生成与图结构相关的 GBS 样本;\n", + "3. 对样本进行固定规模后选择,使其对应为大小恰为 $k$ 的候选顶点集;\n", + "4. 将这些样本作为经典随机搜索或模拟退火的候选来源;\n", + "5. 比较经典方法与 GBS 增强方法在相同预算下的搜索效果差异。\n", "\n", - "Prerequisites\n", - "-------------\n", - "- `strawberryfields` (graph datasets and plotting utilities)\n", - "- `numpy`, `networkx`, `matplotlib`\n", - "- Optional: `thewalrus` (only if regenerating GBS samples)\n" - ] - }, - { - "cell_type": "markdown", - "id": "5321bb87", - "metadata": {}, - "source": [ "---\n", "\n", - "## 1. Imports and Reproducibility Setup\n", - "Import required packages and create a fixed random generator so all stochastic\n", - "baselines are reproducible.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "id": "63a9adde", - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import combinations\n", - "from pathlib import Path\n", + "## 技术路线\n", "\n", - "import networkx as nx\n", - "import numpy as np\n", - "from matplotlib import pyplot as plt\n", - "from strawberryfields.apps import data, plot, sample, subgraph\n", - "import thewalrus\n", + "### 整体流程\n", + "\n", + "本案例采用“经典基线 + GBS 增强”的对比实验路线,整体流程可以概括为以下几个阶段:\n", + "\n", + "1. **导入依赖并初始化环境**:引入数值计算、组合枚举、绘图与 GBS 采样所需的基础库。\n", + "2. **定义评价函数与搜索算法**:实现稠密子图目标函数,以及多种经典搜索与 GBS 增强搜索算法。\n", + "3. **构造实验图实例**:读取示例图,并设定目标子图大小、迭代步数等关键参数。\n", + "4. **执行基线算法**:运行经典贪心、随机搜索与模拟退火方法,得到对照结果。\n", + "5. **执行 GBS 增强算法**:基于 GBS 采样生成候选子图数据库,并基于此运行 `RS-GBS` 与 `SA-GBS`。\n", + "6. **汇总与可视化结果**:绘制不同方法随迭代次数变化的性能曲线,并比较其搜索效率与最终结果。\n", "\n", - "# Fixed random seed for reproducible comparisons.\n", - "rng = np.random.default_rng(42)\n" + "### 方法对比关系\n", + "\n", + "为了更清晰地说明技术路线,本案例同时比较以下几类方法:\n", + "\n", + "- **DGreedy**:经典贪心删除法,用作快速、确定性的参考基线;\n", + "- **Random Search**:在候选空间中进行均匀随机采样,用于体现无结构先验条件下的搜索能力;\n", + "- **Simulated Annealing**:通过接受一定概率的“劣解”实现跳出局部最优,是经典启发式优化的重要代表;\n", + "- **RS-GBS**:将 GBS 样本直接作为随机搜索的候选来源,考察采样偏置对搜索质量的提升作用;\n", + "- **SA-GBS**:在模拟退火的候选生成阶段引入 GBS 信息,以验证结构感知采样对局部搜索效率的增强效果。\n", + "\n", + "---" ] }, { "cell_type": "markdown", - "id": "63a8fe52", + "id": "76c55871", "metadata": {}, "source": [ - "---\n", "\n", - "## 2. Objective and Shared Helper Utilities\n", - "Define the dense-subgraph score and utility helpers used by all algorithms.\n" + "## 1. 导入依赖\n", + "\n", + "这一步骤导入数值计算、随机采样、组合枚举与绘图所需的基础库。其中:\n", + "\n", + "- `thewalrus` 用于 GBS 相关采样;\n", + "- `numpy` 用于矩阵与数组计算;\n", + "- `random` 和 `itertools.combinations` 用于经典搜索中的随机扰动与候选枚举;\n", + "- `matplotlib` 用于最终性能曲线绘制。\n" ] }, { "cell_type": "code", - "execution_count": 111, - "id": "b149ca54", + "execution_count": 1, + "id": "5c8b14a3", "metadata": {}, "outputs": [], "source": [ - "def dense_score(adj: np.ndarray, nodes: np.ndarray) -> float:\n", - " # Unnormalized density score: sum(A_S,S).\n", - " return float(np.sum(adj[np.ix_(nodes, nodes)]))\n", - "\n", - "\n", - "def normalized_density(score: float, k: int) -> float:\n", - " # Normalized to [0, 1] for simple undirected graphs.\n", - " return score / (k * (k - 1))\n", - "\n", - "\n", - "def bitstring_to_nodes(bitstring: np.ndarray) -> np.ndarray:\n", - " # Convert a binary occupation vector to node indices.\n", - " return np.flatnonzero(bitstring).astype(int)\n", - "\n", - "\n", - "def acceptance_rule(delta: float, temperature: float, rng_obj: np.random.Generator) -> bool:\n", - " # Metropolis acceptance rule used in simulated annealing.\n", - " if delta >= 0:\n", - " return True\n", - " safe_temp = max(temperature, 1e-12)\n", - " return rng_obj.random() < np.exp(delta / safe_temp)\n" + "# 导入本案例所需的基础库与 GBS 相关工具。\n", + "import thewalrus\n", + "import numpy as np\n", + "import random\n", + "from itertools import combinations\n", + "from matplotlib import pyplot as plt" ] }, { "cell_type": "markdown", - "id": "7d326e56", + "id": "7f9c97cb", "metadata": {}, "source": [ - "---\n", "\n", - "## 3. Classical Baselines (Greedy / Random Search / Simulated Annealing)\n", - "Implement three classical algorithms as reference baselines under the same\n", - "subset size and iteration budget.\n" + "## 2. 定义目标函数与搜索算法\n", + "\n", + "本步骤给出整个实验用到的核心函数:\n", + "\n", + "- `dense`:计算候选顶点集对应的稠密度目标值;\n", + "- `DGreedy`:贪心删除法;\n", + "- `RandomSearch`:均匀随机采样候选子图;\n", + "- `RandomSearchGBSA`:直接在 GBS 后选择样本中进行随机搜索;\n", + "- `SimulatedAnnealing`:经典模拟退火;\n", + "- `SimulatedAnnealingGBSA`:利用 GBS 样本设计邻域扰动的模拟退火。\n" ] }, { "cell_type": "code", - "execution_count": 112, - "id": "17569d45", + "execution_count": 2, + "id": "e5bc541e", "metadata": {}, "outputs": [], "source": [ - "def d_greedy(adj: np.ndarray, k: int, score_fn) -> tuple[np.ndarray, float]:\n", - " # Backward greedy elimination until only k nodes remain.\n", - " active = np.arange(adj.shape[0], dtype=int)\n", - "\n", - " while active.size > k:\n", - " candidate_subsets = np.array(list(combinations(range(active.size), active.size - 1)))\n", - " candidate_scores = np.array([score_fn(adj, active[idx]) for idx in candidate_subsets], dtype=float)\n", - " active = active[candidate_subsets[np.argmax(candidate_scores)]]\n", - "\n", - " best_score = score_fn(adj, active)\n", - " return active, best_score\n", - "\n", - "\n", - "def random_search(adj: np.ndarray, k: int, num_steps: int, score_fn, rng_obj: np.random.Generator) -> tuple[np.ndarray, np.ndarray]:\n", - " # Uniform random sampling over all size-k subsets.\n", - " n = adj.shape[0]\n", - " universe = np.arange(n, dtype=int)\n", - "\n", - " best_nodes = rng_obj.choice(universe, size=k, replace=False)\n", - " best_score = score_fn(adj, best_nodes)\n", - " trace = np.zeros(num_steps, dtype=float)\n", - "\n", - " for step in range(num_steps):\n", - " candidate = rng_obj.choice(universe, size=k, replace=False)\n", - " candidate_score = score_fn(adj, candidate)\n", + "# 定义稠密子图目标函数,以及经典搜索与 GBS 增强搜索算法。\n", + "def dense(A,s):\n", + " return np.abs(np.sum(A[np.ix_(s,s)]))\n", "\n", - " if candidate_score > best_score:\n", - " best_score = candidate_score\n", - " best_nodes = candidate\n", + "def DGreedy(A,k,f):\n", + " index=np.arange(len(A))\n", + " l=len(index)\n", + " while l > k:\n", + " candidate= np.array(list(combinations(range(l),l-1)))\n", + " tmp=np.array([f(A,index[i]) for i in candidate])\n", + " index=index[candidate[tmp.argmax()]]\n", + " l=len(index)\n", + " return index,tmp.max()\n", "\n", - " trace[step] = best_score\n", + "def RandomSearch(N,k,A,f):\n", + " bestI=np.zeros(k,dtype = np.uint8)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " ind=np.arange(len(A),dtype = np.uint8)\n", + " for i in range(N):\n", + " l=np.random.choice(ind,k,replace=False)\n", + " h=f(A,l)\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=l\n", + " result[i]=largestH\n", + " return result,bestI\n", "\n", - " return trace, np.sort(best_nodes)\n", + "def RandomSearchGBSA(N,A,DB,f):\n", + " bestI=np.zeros(np.sum(DB[0]),dtype = np.int64)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " candidate=np.random.choice(np.arange(len(DB)),size=N,replace=False)\n", + " for i in range(N):\n", + " s=DB[candidate[i]]\n", + " s = np.nonzero(s)[0]\n", + " h=f(A,s)\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=s\n", + " result[i]=largestH\n", + " return result,bestI\n", "\n", + "def generateSample(S,k,l,DataBase):\n", + " m=random.randint(0,k-l-1)\n", + " s=np.zeros_like(S,dtype=np.uint8)\n", + " s[np.random.choice(np.nonzero(S)[0],m+l,replace=False) ]=1\n", + " Tori=DataBase[random.randint(0,len( DataBase)-1)]\n", + " t=np.zeros_like(Tori,dtype=np.uint8)\n", + " t[np.random.choice(np.nonzero(Tori)[0],k-l-m,replace=False) ]=1\n", + " return s,t\n", "\n", - "def simulated_annealing(\n", - " adj: np.ndarray,\n", - " k: int,\n", - " num_steps: int,\n", - " temperature: float,\n", - " cooling_ratio: float,\n", - " swap_size: int,\n", - " score_fn,\n", - " rng_obj: np.random.Generator,\n", - ") -> tuple[np.ndarray, np.ndarray]:\n", - " # Classical simulated annealing with subset-swap proposals.\n", - " n = adj.shape[0]\n", - " universe = np.arange(n, dtype=int)\n", - " swap_size = int(np.clip(swap_size, 1, k - 1))\n", + "def GBS_Tweak(S,l,DataBase):\n", + " k=np.uint16(np.sum(S))\n", + " s,t=generateSample(S,k,l,DataBase)\n", + " while(np.sum(t&s)>0):\n", + " s,t=generateSample(S,k,l,DataBase)\n", + " return (s|t).astype(np.uint8)\n", "\n", - " current = rng_obj.choice(universe, size=k, replace=False)\n", - " current_score = score_fn(adj, current)\n", + "def SimulatedAnnealing(N,k,A,C,T,f,ratio):\n", + " bestI=np.zeros(k,dtype=np.int64)\n", + " largestH=0.0\n", + " result=np.zeros(N)\n", + " ind=np.arange(len(A))\n", + " l0=np.random.choice(ind,k,replace=False)\n", + " h0=f(A,l0)\n", "\n", - " best_nodes = current.copy()\n", - " best_score = current_score\n", - " trace = np.zeros(num_steps, dtype=float)\n", + " for i in range(N):\n", + " m=random.randint(0,C-1)\n", + " tmp=np.random.choice(l0,k-C+m,replace=False)\n", + " l=np.concatenate((tmp,np.random.choice(np.array(list(set(ind)-set(tmp))),C-m,replace=False)))\n", + " h=f(A,l)\n", + " if h>h0:\n", + " h0=h\n", + " l0=l\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=l\n", + " elif np.random.random() best_score:\n", - " best_score = current_score\n", - " best_nodes = current.copy()\n", + " for i in range(N):\n", + " while True:\n", + " r=GBS_Tweak(l0,l,DBk_l)\n", + " check=(np.sum(np.abs(r-l0))!=0)\n", + " if check:\n", + " break\n", + " tmp=np.nonzero(r)[0]\n", + " h=f(A,tmp)\n", + " if h>h0:\n", + " h0=h\n", + " l0=r\n", + " if h>largestH:\n", + " largestH=h\n", + " bestI=tmp\n", + " else:\n", + " check = random.random()\n", + " if check np.ndarray:\n", - " # Keep only bitstrings with exactly k photons (k selected nodes).\n", - " if raw_samples.ndim != 2:\n", - " raise ValueError('raw_samples must be a 2D array of bitstrings.')\n", - "\n", - " fixed_k = raw_samples[np.sum(raw_samples, axis=1) == k]\n", - " if fixed_k.size == 0:\n", - " raise ValueError(f'No samples with exactly k={k} photons were found.')\n", - "\n", - " return fixed_k.astype(np.uint8)\n", - "\n", - "\n", - "def random_search_gbs(\n", - " adj: np.ndarray,\n", - " fixed_k_samples: np.ndarray,\n", - " num_steps: int,\n", - " score_fn,\n", - " rng_obj: np.random.Generator,\n", - ") -> tuple[np.ndarray, np.ndarray]:\n", - " # Random search over GBS-proposed size-k subsets.\n", - " indices = rng_obj.integers(0, len(fixed_k_samples), size=num_steps)\n", - "\n", - " best_nodes = bitstring_to_nodes(fixed_k_samples[indices[0]])\n", - " best_score = score_fn(adj, best_nodes)\n", - " trace = np.zeros(num_steps, dtype=float)\n", - "\n", - " for step, idx in enumerate(indices):\n", - " candidate_nodes = bitstring_to_nodes(fixed_k_samples[idx])\n", - " candidate_score = score_fn(adj, candidate_nodes)\n", - "\n", - " if candidate_score > best_score:\n", - " best_score = candidate_score\n", - " best_nodes = candidate_nodes\n", - "\n", - " trace[step] = best_score\n", - "\n", - " return trace, np.sort(best_nodes)\n", - "\n", - "\n", - "def gbs_tweak(\n", - " current_bitstring: np.ndarray,\n", - " fixed_k_samples: np.ndarray,\n", - " keep_at_least: int,\n", - " rng_obj: np.random.Generator,\n", - ") -> np.ndarray:\n", - " # Build a new proposal by mixing current subset with a GBS donor sample.\n", - " k = int(np.sum(current_bitstring))\n", - " keep_at_least = int(np.clip(keep_at_least, 0, k - 1))\n", - " current_nodes = bitstring_to_nodes(current_bitstring)\n", - "\n", - " for _ in range(100):\n", - " donor = fixed_k_samples[rng_obj.integers(0, len(fixed_k_samples))]\n", - " donor_nodes = bitstring_to_nodes(donor)\n", - "\n", - " keep_count = int(rng_obj.integers(keep_at_least, k + 1))\n", - " keep_nodes = rng_obj.choice(current_nodes, size=keep_count, replace=False)\n", - "\n", - " need = k - keep_count\n", - " donor_pool = np.setdiff1d(donor_nodes, keep_nodes, assume_unique=False)\n", - " if donor_pool.size < need:\n", - " continue\n", - "\n", - " add_nodes = rng_obj.choice(donor_pool, size=need, replace=False)\n", - " merged_nodes = np.concatenate([keep_nodes, add_nodes])\n", - "\n", - " proposal = np.zeros_like(current_bitstring, dtype=np.uint8)\n", - " proposal[merged_nodes] = 1\n", - "\n", - " if not np.array_equal(proposal, current_bitstring):\n", - " return proposal\n", - "\n", - " return current_bitstring.copy()\n", - "\n", - "\n", - "def simulated_annealing_gbs(\n", - " adj: np.ndarray,\n", - " fixed_k_samples: np.ndarray,\n", - " num_steps: int,\n", - " temperature: float,\n", - " cooling_ratio: float,\n", - " keep_at_least: int,\n", - " score_fn,\n", - " rng_obj: np.random.Generator,\n", - ") -> tuple[np.ndarray, np.ndarray]:\n", - " # SA variant where proposals are generated by GBS-guided tweaks.\n", - " current = fixed_k_samples[rng_obj.integers(0, len(fixed_k_samples))].copy()\n", - " current_nodes = bitstring_to_nodes(current)\n", - " current_score = score_fn(adj, current_nodes)\n", - "\n", - " best_nodes = current_nodes.copy()\n", - " best_score = current_score\n", - " trace = np.zeros(num_steps, dtype=float)\n", - "\n", - " for step in range(num_steps):\n", - " proposal_bits = gbs_tweak(current, fixed_k_samples, keep_at_least, rng_obj)\n", - " proposal_nodes = bitstring_to_nodes(proposal_bits)\n", - " proposal_score = score_fn(adj, proposal_nodes)\n", - "\n", - " delta = proposal_score - current_score\n", - " if acceptance_rule(delta, temperature, rng_obj):\n", - " current = proposal_bits\n", - " current_nodes = proposal_nodes\n", - " current_score = proposal_score\n", - "\n", - " if current_score > best_score:\n", - " best_score = current_score\n", - " best_nodes = current_nodes.copy()\n", - "\n", - " trace[step] = best_score\n", - " temperature *= cooling_ratio\n", - "\n", - " return trace, np.sort(best_nodes)\n" + "# 导入稠密子图实例、采样辅助工具和图可视化相关库。\n", + "from strawberryfields.apps import data, sample, subgraph, plot\n", + "import plotly\n", + "import networkx as nx" ] }, { "cell_type": "markdown", - "id": "4d1d5d72", + "id": "22646be3", "metadata": {}, "source": [ - "---\n", "\n", - "## 5. Load Benchmark Graph and Configure Hyperparameters\n", - "Use the `Planted` graph benchmark. Define subset size `k` and optimization\n", - "budget `N` shared by all methods for a fair comparison.\n" + "### 3.2 设置实验参数并读取图实例\n", + "\n", + "这里的三个关键参数含义如下:\n", + "\n", + "- `k`:目标子图顶点数;\n", + "- `N`:搜索或迭代步数;\n", + "- `C=k(k-1)`:结果归一化因子。\n", + "\n", + "`data.Planted()` 返回一个带有预设结构的图实例,其邻接矩阵记为 `A`。随后将其转换为 `networkx` 图对象,便于后续可视化。\n" ] }, { "cell_type": "code", - "execution_count": 114, - "id": "61105bc1", + "execution_count": 4, + "id": "bc37ef50", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Graph size: 30 nodes, 152 edges\n", - "Target subset size k = 8, optimization steps N = 1000\n" - ] - } - ], + "outputs": [], "source": [ - "# Core experiment configuration.\n", + "# 设置目标子图大小和搜索步数,并读取示例图的邻接矩阵。\n", "k = 8\n", "N = 1000\n", - "initial_temp = 0.1\n", - "cooling_ratio = 0.995\n", - "swap_size = k # Aligned with original notebook behavior after clipping in SA.\n", - "\n", - "# Load benchmark graph.\n", + "C = k*(k-1)\n", + "#读取图的邻接矩阵\n", "planted = data.Planted()\n", "A = planted.adj\n", - "graph = nx.to_networkx_graph(A)\n", - "\n", - "print(f'Graph size: {graph.number_of_nodes()} nodes, {graph.number_of_edges()} edges')\n", - "print(f'Target subset size k = {k}, optimization steps N = {N}')\n" + "pl_graph = nx.to_networkx_graph(A)\n", + "# print(planted.adj)" ] }, { "cell_type": "markdown", - "id": "6eb8434f", + "id": "7ceb4e41", "metadata": {}, "source": [ - "---\n", "\n", - "## 6. Run Classical Baselines\n", - "Evaluate Greedy, uniform Random Search, and classical Simulated Annealing on\n", - "the same graph and report normalized density scores.\n" + "## 4. 经典方法基线\n", + "\n", + "为了评估 GBS 增强搜索是否有效,首先运行三种经典方法作为对照:\n", + "\n", + "1. **DGreedy**:从全图开始,反复删除一个顶点,使剩余子图得分尽可能大;\n", + "2. **Random Search**:反复随机选取 $k$ 个顶点,记录历史最优值;\n", + "3. **Simulated Annealing**:通过随机扰动和温度控制,在搜索空间中逐步逼近更优解。\n" ] }, { - "cell_type": "code", - "execution_count": 115, - "id": "92ed1ccd", + "cell_type": "markdown", + "id": "5ae73de1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Greedy normalized density: 0.8214\n", - "RS normalized density: 0.6071\n", - "SA normalized density: 0.7857\n" - ] - } - ], "source": [ - "greedy_nodes, greedy_score = d_greedy(A, k=k, score_fn=dense_score)\n", "\n", - "trace_rs, rs_nodes = random_search(\n", - " adj=A,\n", - " k=k,\n", - " num_steps=N,\n", - " score_fn=dense_score,\n", - " rng_obj=rng,\n", - ")\n", + "### 4.1 DGreedy 贪心基线\n", "\n", - "trace_sa, sa_nodes = simulated_annealing(\n", - " adj=A,\n", - " k=k,\n", - " num_steps=N,\n", - " temperature=initial_temp,\n", - " cooling_ratio=cooling_ratio,\n", - " swap_size=swap_size,\n", - " score_fn=dense_score,\n", - " rng_obj=rng,\n", - ")\n", - "\n", - "print(f'Greedy normalized density: {normalized_density(greedy_score, k):.4f}')\n", - "print(f'RS normalized density: {normalized_density(trace_rs[-1], k):.4f}')\n", - "print(f'SA normalized density: {normalized_density(trace_sa[-1], k):.4f}')\n" + "该方法每一步都考虑删除一个顶点后剩余子图的得分,并保留当前最优的删除结果,直到顶点数降为 $k$。这是一种确定性的经典启发式方法。\n" ] }, { "cell_type": "code", - "execution_count": 116, - "id": "3bca5f58", + "execution_count": 5, + "id": "bab266d9", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.8214285714285714\n" + ] + }, { "data": { "application/vnd.plotly.v1+json": { @@ -2561,15 +2422,36 @@ } ], "source": [ - "plot.graph(graph, greedy_nodes)\n" + "# 运行贪心删除法,输出归一化后的子图稠密度,并绘制对应子图。\n", + "sub_D, M_D = DGreedy(planted.adj, k=k, f=dense)\n", + "print(M_D/C)\n", + "plot.graph(pl_graph, sub_D)" + ] + }, + { + "cell_type": "markdown", + "id": "f5cfe7ef", + "metadata": {}, + "source": [ + "\n", + "### 4.2 Random Search 随机搜索基线\n", + "\n", + "该方法每轮从全部顶点中均匀随机选取 $k$ 个顶点,适合作为最朴素的无结构基线,用来对比 GBS 的结构偏置是否真正带来收益。\n" ] }, { "cell_type": "code", - "execution_count": 117, - "id": "e49fe44d", + "execution_count": 18, + "id": "dd328730", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.7142857142857143\n" + ] + }, { "data": { "application/vnd.plotly.v1+json": { @@ -3512,108 +3394,126 @@ "type": "scatter", "x": [ 0.18435632202501803, - 0.05031263759344334, + -0.37116686956155864, null, - 0.05031263759344334, - 0.03060213470665498, + 0.18435632202501803, + -0.07885318452973908, null, - -0.3956887241402573, - -0.18151103629640256, + 0.18435632202501803, + -0.40532611677290364, null, - -0.3956887241402573, - 0.03060213470665498, + 0.18435632202501803, + 0.14677764857576173, null, - -0.3956887241402573, - 0.15431212004568914, + -0.7208882846209534, + -0.37116686956155864, null, - -0.3956887241402573, - 0.248419593911426, + -0.7208882846209534, + -0.22336859877041337, null, - -0.3956887241402573, - 0.3908630957605396, + -0.7208882846209534, + -0.07885318452973908, null, - -0.18151103629640256, - 0.03060213470665498, + -0.7208882846209534, + -0.40532611677290364, null, - -0.18151103629640256, - 0.15431212004568914, + -0.37116686956155864, + -0.22336859877041337, null, - -0.18151103629640256, - 0.248419593911426, + -0.37116686956155864, + -0.07885318452973908, null, - -0.18151103629640256, - 0.3908630957605396, + -0.37116686956155864, + -0.2979309785587452, null, - 0.03060213470665498, - 0.15431212004568914, + -0.37116686956155864, + -0.40532611677290364, null, - 0.03060213470665498, - 0.248419593911426, + -0.22336859877041337, + -0.2979309785587452, null, - 0.03060213470665498, - 0.3908630957605396, + -0.22336859877041337, + -0.40532611677290364, null, - 0.15431212004568914, - 0.248419593911426, + -0.22336859877041337, + 0.14677764857576173, null, - 0.15431212004568914, - 0.3908630957605396, + -0.07885318452973908, + -0.2979309785587452, null, - 0.248419593911426, - 0.3908630957605396, + -0.07885318452973908, + -0.40532611677290364, + null, + -0.07885318452973908, + 0.14677764857576173, + null, + -0.2979309785587452, + 0.14677764857576173, + null, + -0.40532611677290364, + 0.14677764857576173, null ], "y": [ 0.6755418727885357, - 0.2682105237491978, + 0.6155241452177715, null, - 0.2682105237491978, - -0.4661179763693123, + 0.6755418727885357, + 0.19911642630918874, null, - -0.563647664192087, - -0.614420347815626, + 0.6755418727885357, + 0.08489177830538007, null, - -0.563647664192087, - -0.4661179763693123, + 0.6755418727885357, + 0.06404510480218867, null, - -0.563647664192087, - -0.6737448520530867, + 0.37806433814458207, + 0.6155241452177715, null, - -0.563647664192087, - -0.45932284867708967, + 0.37806433814458207, + 0.3696489601965812, null, - -0.563647664192087, - -0.6824045681320201, + 0.37806433814458207, + 0.19911642630918874, null, - -0.614420347815626, - -0.4661179763693123, + 0.37806433814458207, + 0.08489177830538007, null, - -0.614420347815626, - -0.6737448520530867, + 0.6155241452177715, + 0.3696489601965812, null, - -0.614420347815626, - -0.45932284867708967, + 0.6155241452177715, + 0.19911642630918874, null, - -0.614420347815626, - -0.6824045681320201, + 0.6155241452177715, + -0.09471958904001797, null, - -0.4661179763693123, - -0.6737448520530867, + 0.6155241452177715, + 0.08489177830538007, null, - -0.4661179763693123, - -0.45932284867708967, + 0.3696489601965812, + -0.09471958904001797, null, - -0.4661179763693123, - -0.6824045681320201, + 0.3696489601965812, + 0.08489177830538007, null, - -0.6737448520530867, - -0.45932284867708967, + 0.3696489601965812, + 0.06404510480218867, null, - -0.6737448520530867, - -0.6824045681320201, + 0.19911642630918874, + -0.09471958904001797, null, - -0.45932284867708967, - -0.6824045681320201, + 0.19911642630918874, + 0.08489177830538007, + null, + 0.19911642630918874, + 0.06404510480218867, + null, + -0.09471958904001797, + 0.06404510480218867, + null, + 0.08489177830538007, + 0.06404510480218867, null ] }, @@ -3737,34 +3637,34 @@ "mode": "markers", "text": [ "2", - "3", - "20", - "21", - "22", - "25", - "26", - "27" + "9", + "10", + "12", + "14", + "15", + "17", + "18" ], "type": "scatter", "x": [ 0.18435632202501803, - 0.05031263759344334, - -0.3956887241402573, - -0.18151103629640256, - 0.03060213470665498, - 0.15431212004568914, - 0.248419593911426, - 0.3908630957605396 + -0.7208882846209534, + -0.37116686956155864, + -0.22336859877041337, + -0.07885318452973908, + -0.2979309785587452, + -0.40532611677290364, + 0.14677764857576173 ], "y": [ 0.6755418727885357, - 0.2682105237491978, - -0.563647664192087, - -0.614420347815626, - -0.4661179763693123, - -0.6737448520530867, - -0.45932284867708967, - -0.6824045681320201 + 0.37806433814458207, + 0.6155241452177715, + 0.3696489601965812, + 0.19911642630918874, + -0.09471958904001797, + 0.08489177830538007, + 0.06404510480218867 ] } ], @@ -4574,15 +4474,36 @@ } ], "source": [ - "plot.graph(graph, rs_nodes)\n" + "# 运行均匀随机搜索,记录历史最优解并绘制最终找到的子图。\n", + "M_RS, sub_RS = RandomSearch(N=N, A=A, k=k, f=dense)\n", + "print(M_RS[-1]/C)\n", + "plot.graph(pl_graph, sub_RS)" + ] + }, + { + "cell_type": "markdown", + "id": "6c764d3f", + "metadata": {}, + "source": [ + "\n", + "### 4.3 Simulated Annealing 模拟退火基线\n", + "\n", + "模拟退火在当前候选子图的基础上进行局部扰动。若新解更优则接受,若更差则以与温度相关的概率接受,从而在探索与利用之间取得平衡。\n" ] }, { "cell_type": "code", - "execution_count": 118, - "id": "c75fbb8f", + "execution_count": 7, + "id": "8e4b4b4a", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.8214285714285714\n" + ] + }, { "data": { "application/vnd.plotly.v1+json": { @@ -5524,32 +5445,35 @@ "mode": "lines", "type": "scatter", "x": [ - -0.19531975204966248, - 0.4894762932379749, + 0.18435632202501803, + 0.05031263759344334, null, - -0.19531975204966248, + 0.18435632202501803, -0.5434943630110244, null, - -0.19531975204966248, - 0.04623887567419372, - null, - -0.19531975204966248, + 0.18435632202501803, -0.37116686956155864, null, - -0.19531975204966248, - 0.26000309428692364, + 0.18435632202501803, + -0.07885318452973908, null, - -0.19531975204966248, + 0.18435632202501803, -0.40532611677290364, null, - 0.4894762932379749, + 0.18435632202501803, + 0.14677764857576173, + null, + 0.05031263759344334, + -0.5434943630110244, + null, + 0.05031263759344334, 0.04623887567419372, null, - 0.4894762932379749, - 0.26000309428692364, + 0.05031263759344334, + -0.37116686956155864, null, - 0.4894762932379749, - -0.22336859877041337, + 0.05031263759344334, + 0.14677764857576173, null, -0.5434943630110244, 0.04623887567419372, @@ -5558,7 +5482,7 @@ -0.37116686956155864, null, -0.5434943630110244, - -0.22336859877041337, + -0.07885318452973908, null, -0.5434943630110244, -0.40532611677290364, @@ -5567,57 +5491,60 @@ -0.37116686956155864, null, 0.04623887567419372, - 0.26000309428692364, + -0.07885318452973908, null, 0.04623887567419372, - -0.22336859877041337, + -0.40532611677290364, null, 0.04623887567419372, - -0.40532611677290364, + 0.14677764857576173, null, -0.37116686956155864, - -0.22336859877041337, + -0.07885318452973908, null, -0.37116686956155864, -0.40532611677290364, null, - 0.26000309428692364, - -0.22336859877041337, - null, - 0.26000309428692364, + -0.07885318452973908, -0.40532611677290364, null, - -0.22336859877041337, + -0.07885318452973908, + 0.14677764857576173, + null, -0.40532611677290364, + 0.14677764857576173, null ], "y": [ - 0.1704473488654897, - 0.6355675871180683, + 0.6755418727885357, + 0.2682105237491978, null, - 0.1704473488654897, + 0.6755418727885357, 0.48196625056663706, null, - 0.1704473488654897, - 0.6182760881124225, - null, - 0.1704473488654897, + 0.6755418727885357, 0.6155241452177715, null, - 0.1704473488654897, - -0.012354022419836217, + 0.6755418727885357, + 0.19911642630918874, null, - 0.1704473488654897, + 0.6755418727885357, 0.08489177830538007, null, - 0.6355675871180683, + 0.6755418727885357, + 0.06404510480218867, + null, + 0.2682105237491978, + 0.48196625056663706, + null, + 0.2682105237491978, 0.6182760881124225, null, - 0.6355675871180683, - -0.012354022419836217, + 0.2682105237491978, + 0.6155241452177715, null, - 0.6355675871180683, - 0.3696489601965812, + 0.2682105237491978, + 0.06404510480218867, null, 0.48196625056663706, 0.6182760881124225, @@ -5626,7 +5553,7 @@ 0.6155241452177715, null, 0.48196625056663706, - 0.3696489601965812, + 0.19911642630918874, null, 0.48196625056663706, 0.08489177830538007, @@ -5635,28 +5562,28 @@ 0.6155241452177715, null, 0.6182760881124225, - -0.012354022419836217, + 0.19911642630918874, null, 0.6182760881124225, - 0.3696489601965812, + 0.08489177830538007, null, 0.6182760881124225, - 0.08489177830538007, + 0.06404510480218867, null, 0.6155241452177715, - 0.3696489601965812, + 0.19911642630918874, null, 0.6155241452177715, 0.08489177830538007, null, - -0.012354022419836217, - 0.3696489601965812, - null, - -0.012354022419836217, + 0.19911642630918874, 0.08489177830538007, null, - 0.3696489601965812, + 0.19911642630918874, + 0.06404510480218867, + null, 0.08489177830538007, + 0.06404510480218867, null ] }, @@ -5779,35 +5706,35 @@ }, "mode": "markers", "text": [ - "0", - "4", + "2", + "3", "6", "8", "10", - "11", - "12", - "17" + "14", + "17", + "18" ], "type": "scatter", "x": [ - -0.19531975204966248, - 0.4894762932379749, + 0.18435632202501803, + 0.05031263759344334, -0.5434943630110244, 0.04623887567419372, -0.37116686956155864, - 0.26000309428692364, - -0.22336859877041337, - -0.40532611677290364 + -0.07885318452973908, + -0.40532611677290364, + 0.14677764857576173 ], "y": [ - 0.1704473488654897, - 0.6355675871180683, + 0.6755418727885357, + 0.2682105237491978, 0.48196625056663706, 0.6182760881124225, 0.6155241452177715, - -0.012354022419836217, - 0.3696489601965812, - 0.08489177830538007 + 0.19911642630918874, + 0.08489177830538007, + 0.06404510480218867 ] } ], @@ -6617,120 +6544,131 @@ } ], "source": [ - "plot.graph(graph, sa_nodes)\n" + "# 运行经典模拟退火搜索,并观察其在固定迭代预算下找到的最优子图。\n", + "M_SA, sub_SA = SimulatedAnnealing(A=A, k=k, f=dense, N=N, C=k, T=0.1, ratio=0.995)\n", + "print(M_SA[-1]/C)\n", + "plot.graph(pl_graph, sub_SA)" + ] + }, + { + "cell_type": "markdown", + "id": "2cdfa0b7", + "metadata": {}, + "source": [ + "\n", + "## 5. GBS 增强搜索\n", + "\n", + "这一部分是本案例的核心。将 GBS 的点击样本作为候选结构数据库,再结合经典搜索形成混合算法。\n", + "\n", + "这也是当前量子优化研究中非常常见且具有工程可行性的路线:\n", + "\n", + "- 量子部分负责给出有偏的高质量候选;\n", + "- 经典部分负责筛选、局部改进与结果评估。\n" + ] + }, + { + "cell_type": "markdown", + "id": "5bfeff9b", + "metadata": {}, + "source": [ + "\n", + "### 5.1 可选:使用 GBS 采样模拟器生成样本\n", + "\n", + "由于真实采样可能耗时过长,本案例默认直接加载预先保存好的样本文件。如您想使用模拟器执行 GBS 采样操作,可取消下列代码注释以重新生成 `GBS_samples`,并将其保存为 `.npy` 文件。此外,后续我们将陆续提供真机采样接口等丰富的功能。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fb106e55", + "metadata": {}, + "outputs": [], + "source": [ + "# 可选步骤:使用模拟器生成 GBS 样本。\n", + "# GBS_samples = thewalrus.samples.torontonian_sample_graph(A=A,n_mean=k+2,samples=20000,max_photons=9)\n", + "\n", + "# np.save('GBS_samples.npy', GBS_samples)" ] }, { "cell_type": "markdown", - "id": "e7121df4", + "id": "2f86d233", "metadata": {}, "source": [ - "---\n", + "### 5.2 读取预生成的 GBS 样本\n", "\n", - "## 7. Load (or Regenerate) GBS Samples\n", - "For reproducibility, this tutorial loads a pre-generated sample database\n", - "`GBS_samples.npy`. Optional generation code is included as comments.\n", - "If you want to regenerate samples, you can run the commented lines.\n" + "为了保证案例可复现、运行速度稳定,这里读取事先准备好的 `GBS_samples.npy` 文件。\n" ] }, { "cell_type": "code", - "execution_count": 119, - "id": "d5b243a7", + "execution_count": 9, + "id": "7ea6e594", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Loaded GBS samples: (20000, 30)\n" - ] - } - ], + "outputs": [], "source": [ - "sample_path = Path('GBS_samples.npy')\n", - "if not sample_path.exists():\n", - " raise FileNotFoundError(\n", - " 'GBS_samples.npy was not found in the current working directory. '\n", - " 'Please place it next to this notebook or generate new samples using '\n", - " 'the optional code below.'\n", - " )\n", - "\n", - "# Optional (expensive) generation route:\n", - "# from thewalrus.samples import torontonian_sample_graph\n", - "# gbs_samples = torontonian_sample_graph(\n", - "# A=A,\n", - "# n_mean=k + 2,\n", - "# samples=20000,\n", - "# max_photons=9,\n", - "# )\n", - "# np.save(sample_path, gbs_samples)\n", - "\n", - "gbs_samples = np.load(sample_path)\n", - "print(f'Loaded GBS samples: {gbs_samples.shape}')\n" + "# 加载 GBS 样本数据库。\n", + "GBS_samples = np.load('GBS_samples.npy')" ] }, { "cell_type": "markdown", - "id": "6c10ba01", + "id": "5f9d7de1", "metadata": {}, "source": [ - "---\n", "\n", - "## 8. Postselect k-Photon Samples and Run GBS-Guided Search\n", - "Filter the sample database to size-`k` subsets, then run GBS-guided Random\n", - "Search and GBS-guided Simulated Annealing.\n" + "### 5.3 后选择:只保留点击数恰好为 `k` 的样本\n", + "\n", + "GBS 采样得到的是一批二进制点击模式,每个样本中 1 的个数表示被选中的模式数。由于本任务要求最终子图大小固定为 $k$,因此需要进行 **post-selection**,仅保留点击数等于 $k$ 的样本。\n" ] }, { "cell_type": "code", - "execution_count": 120, - "id": "b73e7267", + "execution_count": 10, + "id": "43f6c029", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Postselected k-photon samples: 1497\n", - "RS-GBS normalized density: 1.0000\n", - "SA-GBS normalized density: 1.0000\n" - ] + "data": { + "text/plain": [ + "1497" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "fixed_k_samples = prepare_fixed_k_samples(gbs_samples, k=k)\n", - "print(f'Postselected k-photon samples: {len(fixed_k_samples)}')\n", - "\n", - "trace_rsgbs, rsgbs_nodes = random_search_gbs(\n", - " adj=A,\n", - " fixed_k_samples=fixed_k_samples,\n", - " num_steps=N,\n", - " score_fn=dense_score,\n", - " rng_obj=rng,\n", - ")\n", + "# 从 GBS 样本中筛选出点击数等于 k 的样本,作为后续搜索的候选数据库。\n", + "GBS_samples_sub = GBS_samples[np.sum(GBS_samples,axis=1)==k]\n", + "len(GBS_samples_sub)" + ] + }, + { + "cell_type": "markdown", + "id": "94bb3e95", + "metadata": {}, + "source": [ "\n", - "trace_sagbs, sagbs_nodes = simulated_annealing_gbs(\n", - " adj=A,\n", - " fixed_k_samples=fixed_k_samples,\n", - " num_steps=N,\n", - " temperature=initial_temp,\n", - " cooling_ratio=cooling_ratio,\n", - " keep_at_least=0,\n", - " score_fn=dense_score,\n", - " rng_obj=rng,\n", - ")\n", + "### 5.4 RS-GBS:在 GBS 候选库中进行随机搜索\n", "\n", - "print(f'RS-GBS normalized density: {normalized_density(trace_rsgbs[-1], k):.4f}')\n", - "print(f'SA-GBS normalized density: {normalized_density(trace_sagbs[-1], k):.4f}')\n" + "这里不再从所有顶点中均匀随机选子图,而是直接从后选择后的 GBS 样本库中随机抽取候选。\n" ] }, { "cell_type": "code", - "execution_count": 121, - "id": "0c80eb65", + "execution_count": 11, + "id": "7da657f3", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.0\n" + ] + }, { "data": { "application/vnd.plotly.v1+json": { @@ -7672,6 +7610,27 @@ "mode": "lines", "type": "scatter", "x": [ + -0.3956887241402573, + -0.18151103629640256, + null, + -0.3956887241402573, + 0.03060213470665498, + null, + -0.3956887241402573, + -0.14972057363919858, + null, + -0.3956887241402573, + 0.15431212004568914, + null, + -0.3956887241402573, + 0.248419593911426, + null, + -0.3956887241402573, + 0.3908630957605396, + null, + -0.3956887241402573, + 0.05803251920713222, + null, -0.18151103629640256, 0.03060213470665498, null, @@ -7688,9 +7647,6 @@ 0.3908630957605396, null, -0.18151103629640256, - 0.5485509574493862, - null, - -0.18151103629640256, 0.05803251920713222, null, 0.03060213470665498, @@ -7706,9 +7662,6 @@ 0.3908630957605396, null, 0.03060213470665498, - 0.5485509574493862, - null, - 0.03060213470665498, 0.05803251920713222, null, -0.14972057363919858, @@ -7721,9 +7674,6 @@ 0.3908630957605396, null, -0.14972057363919858, - 0.5485509574493862, - null, - -0.14972057363919858, 0.05803251920713222, null, 0.15431212004568914, @@ -7733,31 +7683,40 @@ 0.3908630957605396, null, 0.15431212004568914, - 0.5485509574493862, - null, - 0.15431212004568914, 0.05803251920713222, null, 0.248419593911426, 0.3908630957605396, null, 0.248419593911426, - 0.5485509574493862, - null, - 0.248419593911426, 0.05803251920713222, null, 0.3908630957605396, - 0.5485509574493862, - null, - 0.3908630957605396, - 0.05803251920713222, - null, - 0.5485509574493862, 0.05803251920713222, null ], "y": [ + -0.563647664192087, + -0.614420347815626, + null, + -0.563647664192087, + -0.4661179763693123, + null, + -0.563647664192087, + -0.8050557393360486, + null, + -0.563647664192087, + -0.6737448520530867, + null, + -0.563647664192087, + -0.45932284867708967, + null, + -0.563647664192087, + -0.6824045681320201, + null, + -0.563647664192087, + -0.9999999999999999, + null, -0.614420347815626, -0.4661179763693123, null, @@ -7774,9 +7733,6 @@ -0.6824045681320201, null, -0.614420347815626, - -0.5017267746804648, - null, - -0.614420347815626, -0.9999999999999999, null, -0.4661179763693123, @@ -7792,9 +7748,6 @@ -0.6824045681320201, null, -0.4661179763693123, - -0.5017267746804648, - null, - -0.4661179763693123, -0.9999999999999999, null, -0.8050557393360486, @@ -7807,9 +7760,6 @@ -0.6824045681320201, null, -0.8050557393360486, - -0.5017267746804648, - null, - -0.8050557393360486, -0.9999999999999999, null, -0.6737448520530867, @@ -7819,27 +7769,15 @@ -0.6824045681320201, null, -0.6737448520530867, - -0.5017267746804648, - null, - -0.6737448520530867, -0.9999999999999999, null, -0.45932284867708967, -0.6824045681320201, null, -0.45932284867708967, - -0.5017267746804648, - null, - -0.45932284867708967, -0.9999999999999999, null, -0.6824045681320201, - -0.5017267746804648, - null, - -0.6824045681320201, - -0.9999999999999999, - null, - -0.5017267746804648, -0.9999999999999999, null ] @@ -7963,34 +7901,34 @@ }, "mode": "markers", "text": [ + "20", "21", "22", "24", "25", "26", "27", - "28", "29" ], "type": "scatter", "x": [ + -0.3956887241402573, -0.18151103629640256, 0.03060213470665498, -0.14972057363919858, 0.15431212004568914, 0.248419593911426, 0.3908630957605396, - 0.5485509574493862, 0.05803251920713222 ], "y": [ + -0.563647664192087, -0.614420347815626, -0.4661179763693123, -0.8050557393360486, -0.6737448520530867, -0.45932284867708967, -0.6824045681320201, - -0.5017267746804648, -0.9999999999999999 ] } @@ -8801,15 +8739,36 @@ } ], "source": [ - "plot.graph(graph, rsgbs_nodes)\n" + "# 在 GBS 后选择样本库中进行随机搜索,并绘制最优候选对应的子图。\n", + "M_RSGBS, sub_RSGBS = RandomSearchGBSA(N=N, A=A, DB=GBS_samples_sub, f=dense)\n", + "print(M_RSGBS[-1]/C)\n", + "plot.graph(pl_graph, sub_RSGBS)" + ] + }, + { + "cell_type": "markdown", + "id": "098de5c1", + "metadata": {}, + "source": [ + "\n", + "### 5.5 SA-GBS:GBS 引导的模拟退火\n", + "\n", + "这一方法将 GBS 样本用于构造退火过程中的候选扰动。与经典模拟退火相比,它不是在全空间上做无偏局部更新,而是利用 GBS 样本库为扰动提供更强的结构先验。\n" ] }, { "cell_type": "code", - "execution_count": 122, - "id": "48940739", + "execution_count": 12, + "id": "b208202d", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.0\n" + ] + }, { "data": { "application/vnd.plotly.v1+json": { @@ -9751,27 +9710,6 @@ "mode": "lines", "type": "scatter", "x": [ - -0.3956887241402573, - -0.18151103629640256, - null, - -0.3956887241402573, - 0.03060213470665498, - null, - -0.3956887241402573, - -0.14972057363919858, - null, - -0.3956887241402573, - 0.15431212004568914, - null, - -0.3956887241402573, - 0.248419593911426, - null, - -0.3956887241402573, - 0.3908630957605396, - null, - -0.3956887241402573, - 0.05803251920713222, - null, -0.18151103629640256, 0.03060213470665498, null, @@ -9788,6 +9726,9 @@ 0.3908630957605396, null, -0.18151103629640256, + 0.5485509574493862, + null, + -0.18151103629640256, 0.05803251920713222, null, 0.03060213470665498, @@ -9803,6 +9744,9 @@ 0.3908630957605396, null, 0.03060213470665498, + 0.5485509574493862, + null, + 0.03060213470665498, 0.05803251920713222, null, -0.14972057363919858, @@ -9815,6 +9759,9 @@ 0.3908630957605396, null, -0.14972057363919858, + 0.5485509574493862, + null, + -0.14972057363919858, 0.05803251920713222, null, 0.15431212004568914, @@ -9824,40 +9771,31 @@ 0.3908630957605396, null, 0.15431212004568914, + 0.5485509574493862, + null, + 0.15431212004568914, 0.05803251920713222, null, 0.248419593911426, 0.3908630957605396, null, 0.248419593911426, + 0.5485509574493862, + null, + 0.248419593911426, 0.05803251920713222, null, 0.3908630957605396, + 0.5485509574493862, + null, + 0.3908630957605396, + 0.05803251920713222, + null, + 0.5485509574493862, 0.05803251920713222, null ], "y": [ - -0.563647664192087, - -0.614420347815626, - null, - -0.563647664192087, - -0.4661179763693123, - null, - -0.563647664192087, - -0.8050557393360486, - null, - -0.563647664192087, - -0.6737448520530867, - null, - -0.563647664192087, - -0.45932284867708967, - null, - -0.563647664192087, - -0.6824045681320201, - null, - -0.563647664192087, - -0.9999999999999999, - null, -0.614420347815626, -0.4661179763693123, null, @@ -9874,6 +9812,9 @@ -0.6824045681320201, null, -0.614420347815626, + -0.5017267746804648, + null, + -0.614420347815626, -0.9999999999999999, null, -0.4661179763693123, @@ -9889,6 +9830,9 @@ -0.6824045681320201, null, -0.4661179763693123, + -0.5017267746804648, + null, + -0.4661179763693123, -0.9999999999999999, null, -0.8050557393360486, @@ -9901,6 +9845,9 @@ -0.6824045681320201, null, -0.8050557393360486, + -0.5017267746804648, + null, + -0.8050557393360486, -0.9999999999999999, null, -0.6737448520530867, @@ -9910,15 +9857,27 @@ -0.6824045681320201, null, -0.6737448520530867, + -0.5017267746804648, + null, + -0.6737448520530867, -0.9999999999999999, null, -0.45932284867708967, -0.6824045681320201, null, -0.45932284867708967, + -0.5017267746804648, + null, + -0.45932284867708967, -0.9999999999999999, null, -0.6824045681320201, + -0.5017267746804648, + null, + -0.6824045681320201, + -0.9999999999999999, + null, + -0.5017267746804648, -0.9999999999999999, null ] @@ -10042,34 +10001,34 @@ }, "mode": "markers", "text": [ - "20", "21", "22", "24", "25", "26", "27", + "28", "29" ], "type": "scatter", "x": [ - -0.3956887241402573, -0.18151103629640256, 0.03060213470665498, -0.14972057363919858, 0.15431212004568914, 0.248419593911426, 0.3908630957605396, + 0.5485509574493862, 0.05803251920713222 ], "y": [ - -0.563647664192087, -0.614420347815626, -0.4661179763693123, -0.8050557393360486, -0.6737448520530867, -0.45932284867708967, -0.6824045681320201, + -0.5017267746804648, -0.9999999999999999 ] } @@ -10880,81 +10839,83 @@ } ], "source": [ - "plot.graph(graph, sagbs_nodes)\n" + "# 运行 GBS 引导的模拟退火,并观察其搜索性能。\n", + "M_SAGBS, sub_SAGBS = SimulatedAnnealingGBSA(N=N, A=A, l=0, T=0.1, DBk=GBS_samples_sub, DBk_l=GBS_samples_sub, f=dense, ratio=0.995)\n", + "print(M_SAGBS[-1]/C)\n", + "plot.graph(pl_graph, sub_SAGBS)" ] }, { "cell_type": "markdown", - "id": "c05e99c8", + "id": "b3d010ea", "metadata": {}, "source": [ - "---\n", "\n", - "## 9. Convergence Comparison and Final Summary\n", - "Plot best-so-far curves across methods and summarize normalized densities in a\n", - "single table-like printout.\n" + "## 6. 结果对比与分析\n", + "\n", + "最后绘制不同方法的历史最优值曲线。横轴为搜索迭代次数,纵轴为截至当前迭代找到的最优目标值。\n" ] }, { "cell_type": "code", - "execution_count": 123, - "id": "ed5ccfc5", + "execution_count": 13, + "id": "e417cc0b", "metadata": {}, "outputs": [ { "data": { - "image/png": "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wtKzZ085ePCg1za7d++Wbt26ScGCBc3jPPLII5KcnJzPrwaBaNSoURIWFiYPPvig+zaOKeTEn3/+Kbfffrv5LIqNjZUGDRrImjVr3PdrC4Cnn35aypcvb+5v37697Nixw+sxjhw5IrfddptZj6pYsWLSv39/OXXqFG9IiEpJSZFhw4ZJtWrVzDFTo0YNee6558yxZOG4woUsW7ZMunfvbhYP1//fzZ492+t+fx1DmzZtkquvvtqc3+sC6i+//LK9b442XkH+mT59uis6Oto1ceJE108//eS6++67XcWKFXMdPHiQtwEZdOrUyTVp0iTXli1bXBs2bHB17drVVblyZdepU6fc2wwcONBVqVIl18KFC11r1qxxNWvWzNWiRQv3/cnJya769eu72rdv71q/fr3rf//7n6tUqVKuJ554gj0e4latWuWqWrWqq2HDhq7Bgwe7b+eYgq+OHDniqlKliqtfv36ulStXun777TfX/PnzXb/++qt7m1GjRrni4uJcs2fPdm3cuNF13XXXuapVq+Y6e/ase5vOnTu7GjVq5FqxYoXru+++c9WsWdN166238oaEqBdeeMFVsmRJ19y5c127du1yffrpp67ChQu7XnvtNfc2HFe4kP/973+u//znP67PP/9cvx1wzZo1y+t+fxxDx48fd5UtW9Z12223mXO2jz/+2BUbG+t65513bHuDCPLy2ZVXXukaNGiQ+/eUlBRXhQoVXCNHjszvoSAIHTp0yHxALV261Px+7NgxV1RUlPkfn+Xnn3822/z444/uD7fw8HDXgQMH3Nu8/fbbrqJFi7oSEhJseBUIBCdPnnTVqlXL9e2337pat27tDvI4ppATjz32mOuqq67K8v7U1FRXuXLlXK+88or7Nj3WYmJizMmQ2rp1q/nsWr16tXubefPmucLCwlx//vknb0wI6tatm+uuu+7yuu3GG280J9KK4wq+knRBnr+OobfeestVvHhxr/Mq/VysXbu2bW8S5Zr5KDExUdauXWvSwJbw8HDz+48//pifQ0GQOn78uLkuUaKEudbjKSkpyeuYqlOnjlSuXNl9TOm1lk2VLVvWvU2nTp3kxIkT8tNPP+X7a0Bg0BJfLeH1PHYUxxRy4ssvv5QmTZrITTfdZErCL7vsMnnvvffc9+/atUsOHDjgdbzFxcWZKQuen1VaBqWPY9Ht9f+TK1eu5I0JQS1atJCFCxfK9u3bze8bN26U5cuXS5cuXczvHFfIrV1++mzSbVq1aiXR0dFe51o6xebo0aO2vFGRtjxriPr7779NfbnnybbS33/55RfbxoXgkJqaauZNtWzZUurXr29u0w8m/UDRD5/0x5TeZ22T2TFn3YfQM336dFm3bp2sXr06w30cU8iJ3377Td5++20ZOnSoPPnkk+bYeuCBB8znU9++fd2fNZl9Fnl+VmmA6CkyMtJ8qcVnVWh6/PHHzReS+uVlRESEOYd64YUXzNwoxXGF3Drgp88mvda5o+kfw7qvePHi+f5mEeQBQZR52bJli/kWE8ipPXv2yODBg+Xbb781k8MBf30Jpd9yv/jii+Z3zeTp59X48eNNkAfkxIwZM2Tq1Kkybdo0qVevnmzYsMF82akNNDiugPOjXDMflSpVynwTlb7zof5erly5/BwKgsx9990nc+fOlcWLF0vFihXdt+txo2XAx44dy/KY0uvMjjnrPoQWLcc8dOiQXH755eabSL0sXbpUXn/9dfOzfvPIMQVfaVe6unXret12ySWXmM6+np815/v/n17rselJuwBrVzs+q0KTdoLWbN4tt9xiph3ccccdMmTIENN5WnFcIbfK+emzKRDPtQjy8pGWrTRu3NjUl3t++6m/N2/ePD+HgiChc4Q1wJs1a5YsWrQoQymAHk9RUVFex5TWf+uJlXVM6fXmzZu9PqA0i6NtgNOflMH52rVrZ44H/UbcumgGRsufrJ85puArLSNPv7yLzqOqUqWK+Vk/u/REx/OzSsvwdD6L52eVfmGlX0RY9HNP/z+p82MQes6cOWPmPXnSL8v1mFAcV8itan76bNJtdKkG7ZPgea5Vu3ZtW0o1DdtavoTwEgrasWfy5MmmW8+AAQPMEgqenQ8Byz333GPa+i5ZssS1f/9+9+XMmTNe7e51WYVFixaZJRSaN29uLumXUOjYsaNZhuHrr792lS5dmiUU4ObZXZNjCjldjiMyMtK0vN+xY4dr6tSproIFC7o++ugjrzbl+v+7L774wrVp0yZXjx49Mm1Tftlll5llGJYvX246wLKEQujq27ev66KLLnIvoaAt8HUJoEcffdS9DccVstNNev369eaioc+rr75qfv7jjz/8dgxpR05dQuGOO+4wSyjo+b5+BrKEQoh54403zEm5rpenSyromhtAZvTDKLOLrp1n0Q+he++917Tu1Q+UG264wQSCnn7//XdXly5dzJot+j/Ihx56yJWUlMROR6ZBHscUcmLOnDnmCyX9IrNOnTqud9991+t+bVU+bNgwcyKk27Rr1861bds2r20OHz5sTpx0LTRd5uXOO+80J2gITSdOnDCfTXrOVKBAAVf16tXNemeebeo5rnAhixcvzvRcSr9E8OcxpGvs6VIy+hj65YQGj3YK0//Yk0MEAAAAAPgbc/IAAAAAwEEI8gAAAADAQQjyAAAAAMBBCPIAAAAAwEEI8gAAAADAQQjyAAAAAMBBCPIAAAAAwEEI8gAAAADAQQjyAADIJ1WrVpWxY8eyvwEAeYogDwDgSP369ZPrr7/e/NymTRt58MEH8+25J0+eLMWKFctw++rVq2XAgAH5Ng4AQGiKtHsAAAAEi8TERImOjs7xvy9durRfxwMAQGbI5AEAHJ/RW7p0qbz22msSFhZmLr///ru5b8uWLdKlSxcpXLiwlC1bVu644w75+++/3f9WM4D33XefyQKWKlVKOnXqZG5/9dVXpUGDBlKoUCGpVKmS3HvvvXLq1Clz35IlS+TOO++U48ePu5/vmWeeybRcc/fu3dKjRw/z/EWLFpVevXrJwYMH3ffrv7v00kvlww8/NP82Li5ObrnlFjl58mS+7T8AQPAhyAMAOJoGd82bN5e7775b9u/fby4amB07dkzatm0rl112maxZs0a+/vprE2BpoOXpgw8+MNm777//XsaPH29uCw8Pl9dff11++uknc/+iRYvk0UcfNfe1aNHCBHIatFnP9/DDD2cYV2pqqgnwjhw5YoLQb7/9Vn777Te5+eabvbbbuXOnzJ49W+bOnWsuuu2oUaPydJ8BAIIb5ZoAAEfT7JcGaQULFpRy5cq5b3/zzTdNgPfiiy+6b5s4caIJALdv3y4XX3yxua1WrVry8ssvez2m5/w+zbA9//zzMnDgQHnrrbfMc+lzagbP8/nSW7hwoWzevFl27dplnlNNmTJF6tWrZ+buXXHFFe5gUOf4FSlSxPyu2Ub9ty+88ILf9hEAwFnI5AEAQtLGjRtl8eLFplTSutSpU8edPbM0btw4w79dsGCBtGvXTi666CITfGngdfjwYTlz5ky2n//nn382wZ0V4Km6deuahi16n2cQaQV4qnz58nLo0KEcvWYAQGggkwcACEk6h6579+7y0ksvZbhPAymLzrvzpPP5rr32WrnnnntMNq1EiRKyfPly6d+/v2nMohlDf4qKivL6XTOEmt0DACArBHkAAMfTEsqUlBSv2y6//HKZOXOmyZRFRmb/f4dr1641Qdbo0aPN3Dw1Y8aMCz5fepdccons2bPHXKxs3tatW81cQc3oAQCQU5RrAgAcTwO5lStXmiycds/UIG3QoEGm6cmtt95q5sBpieb8+fNNZ8zzBWg1a9aUpKQkeeONN0yjFO18aTVk8Xw+zRTq3Dl9vszKONu3b286dN52222ybt06WbVqlfTp00dat24tTZo0yZP9AAAIDQR5AADH0+6WERERJkOma9Xp0gUVKlQwHTM1oOvYsaMJuLShis6JszJ0mWnUqJFZQkHLPOvXry9Tp06VkSNHem2jHTa1EYt2ytTnS9+4xSq7/OKLL6R48eLSqlUrE/RVr15dPvnkkzzZBwCA0BHmcrlcdg8CAAAAAOAfZPIAAAAAwEEI8gAAAADAQQjyAAAAAMBBCPIAAAAAwEEI8gAAAADAQQjyAAAAAMBBCPIAAAAAwEEI8gAAAADAQQjyAAAAAMBBCPIAAAAAwEEI8gAAAADAQQjyAAAAAECc4/8Bcdla2R43XHkAAAAASUVORK5CYII=", "text/plain": [ - "
" + "" ] }, + "execution_count": 13, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Final normalized density comparison:\n", - " DGreedy : 0.8214\n", - " RS : 0.6071\n", - " SA : 0.7857\n", - " RS-GBS : 1.0000\n", - " SA-GBS : 1.0000\n" - ] + "data": { + "image/png": "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BYAIo76YVdeHHbcgXBQ6deqkMxMq6Jg9e7Y8+eST/oyEuqkhr+q6+cYbb+hAQgUUvpsv+LjsssskNjZWHnvssRofhxrae+TIkQq3x8XF6aG7UTfaRR1w165d5cYbb5ShQ4cet/3xxx/X1bYqolIRmYoIVdpIDQNSkaKdWNUWAFAbajityiCoa6Cq8UhJSdEjWtS1b8iQIbJw4UI5cOCAjBw5UurWrXtcd43KiowePbrcfat5Q1TQMm7cONm/f7/OoqjrqHr86quv+oOLstR8HQUFBbrmQ3X1/Otf/9JBjKKOZc6cOboe5ZRTTtHJgQULFsh///tfPeTWVlYtqP993rx5/ucej8dq3Lix9cQTT/hfy8nJseLj46033nijSvvMzc3V+1X3wfbkos1Wy7sWWvfNXx/0fQMAqubIkSPWpk2b9H20KSgosO6++26rW7duVt26da2kpCSrffv21r333msdPnzYuvjii62LLrqo3P93xYoV+vq2bt26St9j8eLF1oUXXmilp6dbMTExVqNGjaxLLrnE+uCDD/xtPv74Y70v3021a926tfXXv/7Vys/P1222bdtmjRo1yjrllFOsxMREKy0tzTrzzDOtmTNnhuRnV53rd1BrPrZv3677qlRXi4+K/NSwH1Whq6KvY6lorexwpby8PAkVyk0BALWh6jYmT56sb+VRmYWKqNEmVRnympmZGXAdLY8aNfNb+2rTps1xM55GiqCOdlGBh3LsEB713LftWOoHqAIU36158+YSKhScAgBgP9uH2k6cOFFX9/puO3fuDPl7VjZRCwAAiKLgwzc0aM+ePQGvq+dlJ005NoWlJlUpewsV5vkAAOAECz5UVa4KMnyL2vhqONS44169eondmOEUAAD7VbvgVC2W89133wUUmaoxzGqcshompBbEeeihh/RkKb6htmps8yWXXCJ2o+AUAIAoDD7UeOayK+JNmDBB36u559XUsmpBHDUXyM0336xX/zvnnHP0Yjd2z/ERWHBKzQcAAFETfPzW8B5VzKkWtlG3SEW9KQAABo92CSdfwSl5DwAA7GNU8OEr+iDzAQCAfYwKPig4BQDAfmYFH95aFSYZAwDUhFrsTV1D1E2tQKtGdaqBFmpxN5+srCzp27evHgWalJSkR3+qQRlFRUWcdBODDx9qPgAANTVw4EDZvXu3fP/99zJlyhR58cUX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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "plt.figure(figsize=(9, 5))\n", - "plt.plot(trace_sa, label='SA')\n", - "plt.plot(trace_sagbs, label='SA-GBS')\n", - "plt.plot(trace_rs, label='RS')\n", - "plt.plot(trace_rsgbs, label='RS-GBS')\n", - "plt.plot(np.arange(N), greedy_score * np.ones(N), '--', label='DGreedy')\n", - "plt.xlabel('Iteration')\n", - "plt.ylabel('Best unnormalized score')\n", - "plt.title('Dense Subgraph Search: Classical vs GBS-Guided')\n", - "plt.legend()\n", - "plt.tight_layout()\n", - "plt.show()\n", + "# 绘制多种方法的性能曲线,对比 GBS 增强前后的搜索效果。\n", + "plt.plot(M_SA, label='SA')\n", + "plt.plot(M_SAGBS, label='SA-GBS')\n", + "plt.plot(M_RS, label='RS')\n", + "plt.plot(M_RSGBS, label='RS-GBS')\n", + "plt.plot(\n", + " np.arange(N),M_D*np.ones(N),\"--\", label='DGreedy'\n", + ")\n", + "plt.legend()" + ] + }, + { + "cell_type": "markdown", + "id": "c17fd764", + "metadata": {}, + "source": [ + "\n", + "## 7. 结论\n", + "\n", + "通过本案例可以看到,GBS 在这里并不是单独替代经典算法,而是作为一种 **物理启发的候选生成机制** 与经典启发式搜索相结合。这种“量子采样 + 经典优化”的混合范式具有以下特点:\n", "\n", - "summary = {\n", - " 'DGreedy': normalized_density(greedy_score, k),\n", - " 'RS': normalized_density(trace_rs[-1], k),\n", - " 'SA': normalized_density(trace_sa[-1], k),\n", - " 'RS-GBS': normalized_density(trace_rsgbs[-1], k),\n", - " 'SA-GBS': normalized_density(trace_sagbs[-1], k),\n", - "}\n", + "- 不改变原始组合优化目标;\n", + "- 便于与现有经典后处理算法集成;\n", + "- 能将量子采样分布中的结构偏置转化为实际搜索优势。\n", "\n", - "print('Final normalized density comparison:')\n", - "for method, value in summary.items():\n", - " print(f' {method:8s}: {value:.4f}')\n" + "综上所述,本案例有助于读者理解 GBS 并不只是“采样”,而是可以作为高质量候选解生成工具服务于实际优化任务。\n" ] } ], "metadata": { "kernelspec": { - "display_name": "Bell", + "display_name": "photon", "language": "python", "name": "python3" }, diff --git a/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_en.ipynb b/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_en.ipynb new file mode 100644 index 0000000..acfdcc0 --- /dev/null +++ b/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_en.ipynb @@ -0,0 +1,6192 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Graph Isomorphism Analysis Enhanced by Gaussian Boson Sampling\n", + "\n", + "This tutorial demonstrates how Gaussian Boson Sampling (**Gaussian Boson Sampling, GBS**) can be used to construct feature representations for graph structures, and how these representations can then be applied to **graph isomorphism analysis, graph similarity analysis, and graph classification** tasks.\n", + "\n", + "---\n", + "\n", + "## Principle\n", + "\n", + "### Problem Description\n", + "\n", + "The graph isomorphism problem asks whether, for two given graphs, there exists a relabeling of the vertices such that their adjacency relationships become exactly identical. If such a one-to-one correspondence exists, the two graphs are said to be **isomorphic**. From the graph-theoretic point of view, isomorphic graphs may have different vertex labels, but they are structurally identical.\n", + "\n", + "Compared with strict graph isomorphism testing, graph similarity analysis has a broader goal. It does not necessarily require two graphs to be exactly the same, but instead aims to characterize the extent to which they share similar connectivity patterns, local structures, and higher-order statistical properties. Such tasks are important in graph classification, graph retrieval, molecular comparison, and pattern recognition.\n", + "\n", + "Therefore, in practical applications, a common strategy is to first construct a representation that captures the structural characteristics of a graph, and then compare different graphs based on these representations. If two graphs have similar, or even identical, structural signatures, they are more likely to be isomorphic or at least highly similar in structure.\n", + "\n", + "### Why Can GBS Sampling Characterize Graph Structure?\n", + "\n", + "When a graph is encoded into a Gaussian Boson Sampling device, the output photon-counting distribution is closely related to the combinatorial structure of that graph. More specifically, sample probabilities are related to quantities such as Hafnians of graph-derived submatrices, and therefore reflect matching structures, connectivity patterns, and higher-order combinatorial properties of the graph.\n", + "\n", + "This means that GBS does not generate exactly the same sample distribution for different graphs. Even if two graphs have the same number of vertices and edges, differences in their internal structure will often lead to different statistical preferences in their GBS samples. Therefore, the GBS sample distribution can be regarded as a **graph-structural signature induced by quantum sampling**.\n", + "\n", + "### What Are Event and Orbit Features?\n", + "\n", + "To convert raw sample distributions into comparable numerical representations, this tutorial introduces two kinds of features.\n", + "\n", + "**Event features** focus on coarse-grained statistical properties of the samples. In this tutorial, a sample can be grouped according to its total photon number, and the frequencies of different total-photon-number events are then counted. The resulting feature vector reflects the graph’s sampling distribution at a relatively coarse-grained statistical level.\n", + "\n", + "**Orbit features** focus on the finer occupation structure inside each sample. For samples with the same total photon number, different photon occupation patterns correspond to different integer-partition structures, that is, different orbits. By counting the frequencies of several specified orbits in the samples, one can obtain a more fine-grained structural representation than event features provide.\n", + "\n", + "In other words, event features emphasize **which statistical event a sample belongs to**, whereas orbit features further distinguish **which occupation pattern the sample has within that event**.\n", + "\n", + "### Overall Idea\n", + "\n", + "The overall idea of this tutorial can be summarized into the following stages:\n", + "\n", + "1. Load several graph instances and inspect their original structures;\n", + "2. Prepare the corresponding GBS samples for each graph;\n", + "3. Convert the samples into event features or orbit features;\n", + "4. Compare the distributions of different graphs in feature space;\n", + "5. Use a support vector machine to perform simple graph classification and verify the discriminative power of these features.\n", + "\n", + "---\n", + "\n", + "## Technical Route\n", + "\n", + "### Overall Workflow\n", + "\n", + "The technical workflow of this tutorial can be summarized as follows:\n", + "\n", + "1. **Load multiple graph instances**: load the four graph datasets `Mutag0()` to `Mutag3()` and extract their adjacency matrices.\n", + "2. **Visualize the original graph structures**: use `networkx` and the Strawberry Fields plotting tools to inspect the connectivity patterns of different graphs.\n", + "3. **Prepare or load GBS samples**: optionally generate samples with the `thewalrus` sampler, or directly use pre-generated samples.\n", + "4. **Construct event feature vectors**: extract low-dimensional feature representations of the graphs from sample statistics according to specified event definitions.\n", + "5. **Construct orbit feature vectors**: convert samples into orbit representations and extract the corresponding features.\n", + "6. **Compare graphs in feature space**: use scatter plots and related tools to visualize whether different graphs can be distinguished.\n", + "7. **Perform a graph classification experiment**: feed the extracted features into a support vector machine and test their discriminative power for graph classes.\n", + "\n", + "---\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Load four Graph Instances\n", + "\n", + "This section imports the graph datasets, plotting tools, and similarity-analysis module, and loads the four example graphs `Mutag0()`, `Mutag1()`, `Mutag2()`, and `Mutag3()`. These graphs will serve as the objects for subsequent comparison and classification.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "259a1626", + "metadata": {}, + "outputs": [], + "source": [ + "from strawberryfields.apps import data, plot, similarity\n", + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", + "\n", + "m0 = data.Mutag0()\n", + "m1 = data.Mutag1()\n", + "m2 = data.Mutag2()\n", + "m3 = data.Mutag3()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Extract the Adjacency Matrices of the Graphs\n", + "\n", + "Here, the four graph objects are converted into adjacency-matrix form. The adjacency matrix is the fundamental data representation used later for sampling, feature computation, and graph-structure analysis.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1c3003f9", + "metadata": {}, + "outputs": [], + "source": [ + "m0_a = m0.adj\n", + "m1_a = m1.adj\n", + "m2_a = m2.adj\n", + "m3_a = m3.adj" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Import Graph Processing and Visualization Utilities\n", + "\n", + "This step additionally imports `networkx` and `plotly` to construct graph objects and support interactive visualization.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e3de6022", + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "import plotly" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Visualize the Four Original Graphs\n", + "\n", + "The structures of the four graphs are now plotted one by one. By inspecting these graphs, one can first build an intuitive understanding of their topological differences, which also helps interpret the subsequent distributions in feature space.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f635734c", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.1106749200820511, + 0.3325180282834503, + null, + 0.1106749200820511, + -0.10573201244961422, + null, + 0.3325180282834503, + 0.3183779686865032, + null, + 0.3183779686865032, + 0.10817894656323569, + null, + 0.10817894656323569, + -0.1258206158117392, + null, + 0.10817894656323569, + 0.08944551616123024, + null, + -0.1258206158117392, + -0.10573201244961422, + null, + -0.1258206158117392, + -0.35683606826960246, + null, + -0.35683606826960246, + -0.3746946767622438, + null, + -0.3746946767622438, + -0.16201507142000418, + null, + -0.16201507142000418, + 0.08944551616123024, + null, + -0.16201507142000418, + -0.17957964910137447, + null, + 0.08944551616123024, + 0.2639581661840744, + null, + 0.2639581661840744, + 0.23288582259230256, + null, + 0.23288582259230256, + -0.004090002015534177, + null, + -0.004090002015534177, + -0.17957964910137447, + null, + -0.004090002015534177, + -0.038531130421250566, + null, + -0.038531130421250566, + -0.23867208087265562, + null, + -0.038531130421250566, + 0.12993193857117113, + null + ], + "y": [ + 0.9109613341530329, + 0.7623231588277424, + null, + 0.9109613341530329, + 0.7584892195635953, + null, + 0.7623231588277424, + 0.5002924896086175, + null, + 0.5002924896086175, + 0.3325831579704782, + null, + 0.3325831579704782, + 0.4940021409430781, + null, + 0.3325831579704782, + 0.06187083194727157, + null, + 0.4940021409430781, + 0.7584892195635953, + null, + 0.4940021409430781, + 0.3575453539641614, + null, + 0.3575453539641614, + 0.09278291481906589, + null, + 0.09278291481906589, + -0.07160734861438502, + null, + -0.07160734861438502, + 0.06187083194727157, + null, + -0.07160734861438502, + -0.33762664558407796, + null, + 0.06187083194727157, + -0.14338931087274356, + null, + -0.14338931087274356, + -0.4054751685172854, + null, + -0.4054751685172854, + -0.5422076935972371, + null, + -0.5422076935972371, + -0.33762664558407796, + null, + -0.5422076935972371, + -0.802917760705588, + null, + -0.802917760705588, + -0.9676266739057261, + null, + -0.802917760705588, + -1, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16" + ], + "type": "scatter", + "x": [ + 0.1106749200820511, + 0.3325180282834503, + 0.3183779686865032, + 0.10817894656323569, + -0.1258206158117392, + -0.10573201244961422, + -0.35683606826960246, + -0.3746946767622438, + -0.16201507142000418, + 0.08944551616123024, + 0.2639581661840744, + 0.23288582259230256, + -0.004090002015534177, + -0.17957964910137447, + -0.038531130421250566, + -0.23867208087265562, + 0.12993193857117113 + ], + "y": [ + 0.9109613341530329, + 0.7623231588277424, + 0.5002924896086175, + 0.3325831579704782, + 0.4940021409430781, + 0.7584892195635953, + 0.3575453539641614, + 0.09278291481906589, + -0.07160734861438502, + 0.06187083194727157, + -0.14338931087274356, + -0.4054751685172854, + -0.5422076935972371, + -0.33762664558407796, + -0.802917760705588, + -0.9676266739057261, + -1 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m0_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b7ddf46f", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.6989554447413813, + 0.4446363061276493, + null, + 0.6989554447413813, + 0.5438914846302285, + null, + 0.4446363061276493, + 0.04464792421709926, + null, + 0.04464792421709926, + -0.204192119107545, + null, + 0.04464792421709926, + -0.11999491909362145, + null, + -0.204192119107545, + -0.6044384529514965, + null, + -0.6044384529514965, + -0.7714923431768627, + null, + -0.7714923431768627, + -0.5291983220100507, + null, + -0.5291983220100507, + -0.11999491909362145, + null, + -0.11999491909362145, + 0.14100625882157714, + null, + 0.14100625882157714, + 0.5438914846302285, + null, + 0.14100625882157714, + 0.11531436283452415, + null, + 0.11531436283452415, + -0.14885312434803125, + null, + 0.11531436283452415, + 0.3897174993151481, + null + ], + "y": [ + 0.19943320936933975, + 0.5117591191061869, + null, + 0.19943320936933975, + -0.16965278458321073, + null, + 0.5117591191061869, + 0.42809111540950934, + null, + 0.42809111540950934, + 0.7501969287197767, + null, + 0.42809111540950934, + 0.03008807013152098, + null, + 0.7501969287197767, + 0.7693401240903215, + null, + 0.7693401240903215, + 0.39988842627856575, + null, + 0.39988842627856575, + 0.07974141740262024, + null, + 0.07974141740262024, + 0.03008807013152098, + null, + 0.03008807013152098, + -0.29827216554532393, + null, + -0.29827216554532393, + -0.16965278458321073, + null, + -0.29827216554532393, + -0.7070898582139229, + null, + -0.7070898582139229, + -1, + null, + -0.7070898582139229, + -0.993523602165384, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12" + ], + "type": "scatter", + "x": [ + 0.6989554447413813, + 0.4446363061276493, + 0.04464792421709926, + -0.204192119107545, + -0.6044384529514965, + -0.7714923431768627, + -0.5291983220100507, + -0.11999491909362145, + 0.14100625882157714, + 0.5438914846302285, + 0.11531436283452415, + -0.14885312434803125, + 0.3897174993151481 + ], + "y": [ + 0.19943320936933975, + 0.5117591191061869, + 0.42809111540950934, + 0.7501969287197767, + 0.7693401240903215, + 0.39988842627856575, + 0.07974141740262024, + 0.03008807013152098, + -0.29827216554532393, + -0.16965278458321073, + -0.7070898582139229, + -1, + -0.993523602165384 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m1_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0fd75aa9", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.6418193777806868, + 0.33582251607079827, + null, + 0.6418193777806868, + 0.5605955443702613, + null, + 0.33582251607079827, + -0.0372042080290194, + null, + -0.0372042080290194, + -0.12229696899296028, + null, + -0.0372042080290194, + -0.3397181392877679, + null, + -0.12229696899296028, + -0.5293834487765021, + null, + -0.12229696899296028, + 0.1932164253360116, + null, + -0.5293834487765021, + -0.825166960741573, + null, + -0.825166960741573, + -0.7323531444109789, + null, + -0.7323531444109789, + -0.3397181392877679, + null, + 0.1932164253360116, + 0.5605955443702613, + null, + 0.1932164253360116, + 0.24521575187315073, + null, + 0.24521575187315073, + 0.04359736568772133, + null, + 0.24521575187315073, + 0.5658558891201715, + null + ], + "y": [ + 0.32544599922309664, + 0.5811356299722468, + null, + 0.32544599922309664, + -0.062493324440433144, + null, + 0.5811356299722468, + 0.424499731764875, + null, + 0.424499731764875, + 0.006650885589960059, + null, + 0.424499731764875, + 0.6907264092168071, + null, + 0.006650885589960059, + -0.022129969745260318, + null, + 0.006650885589960059, + -0.2633648468095954, + null, + -0.022129969745260318, + 0.2434250853555832, + null, + 0.2434250853555832, + 0.6339779943123541, + null, + 0.6339779943123541, + 0.6907264092168071, + null, + -0.2633648468095954, + -0.062493324440433144, + null, + -0.2633648468095954, + -0.6655639303172131, + null, + -0.6655639303172131, + -0.9999999999999999, + null, + -0.6655639303172131, + -0.8923096641224209, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12" + ], + "type": "scatter", + "x": [ + 0.6418193777806868, + 0.33582251607079827, + -0.0372042080290194, + -0.12229696899296028, + -0.5293834487765021, + -0.825166960741573, + -0.7323531444109789, + -0.3397181392877679, + 0.1932164253360116, + 0.5605955443702613, + 0.24521575187315073, + 0.04359736568772133, + 0.5658558891201715 + ], + "y": [ + 0.32544599922309664, + 0.5811356299722468, + 0.424499731764875, + 0.006650885589960059, + -0.022129969745260318, + 0.2434250853555832, + 0.6339779943123541, + 0.6907264092168071, + -0.2633648468095954, + -0.062493324440433144, + -0.6655639303172131, + -0.9999999999999999, + -0.8923096641224209 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m2_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "70b3e604", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.47137507343491375, + 0.6820711000880268, + null, + 0.47137507343491375, + 0.1742107742857007, + null, + 0.6820711000880268, + 0.5588144789730345, + null, + 0.5588144789730345, + 0.26336411527894155, + null, + 0.26336411527894155, + 0.050116319941363424, + null, + 0.26336411527894155, + 0.1010440757888845, + null, + 0.050116319941363424, + 0.1742107742857007, + null, + 0.050116319941363424, + -0.2471285603132008, + null, + -0.2471285603132008, + -0.5460941568020081, + null, + -0.2471285603132008, + -0.21972025925361904, + null, + -0.5460941568020081, + -0.824264873073218, + null, + -0.824264873073218, + -0.8038320855995099, + null, + -0.8038320855995099, + -0.5114212689742236, + null, + -0.5114212689742236, + -0.21972025925361904, + null, + -0.5114212689742236, + -0.4657056937090478, + null, + -0.21972025925361904, + 0.1010440757888845, + null, + 0.1010440757888845, + 0.13885763877102647, + null, + 0.13885763877102647, + -0.16529058717125392, + null, + 0.13885763877102647, + 0.35434854424122336, + null, + -0.16529058717125392, + -0.4657056937090478, + null, + 0.35434854424122336, + 0.33355820372585415, + null, + 0.35434854424122336, + 0.6556971603671127, + null + ], + "y": [ + 0.8505978288577702, + 0.6080537580286298, + null, + 0.8505978288577702, + 0.740466370080546, + null, + 0.6080537580286298, + 0.31295429104456673, + null, + 0.31295429104456673, + 0.18027224219863988, + null, + 0.18027224219863988, + 0.44330393960368564, + null, + 0.18027224219863988, + -0.1061600526872326, + null, + 0.44330393960368564, + 0.740466370080546, + null, + 0.44330393960368564, + 0.33537984601883364, + null, + 0.33537984601883364, + 0.4651707665053875, + null, + 0.33537984601883364, + 0.004804137162988258, + null, + 0.4651707665053875, + 0.30437196842471975, + null, + 0.30437196842471975, + -0.01809257980061243, + null, + -0.01809257980061243, + -0.16063632673909367, + null, + -0.16063632673909367, + 0.004804137162988258, + null, + -0.16063632673909367, + -0.48184781919050707, + null, + 0.004804137162988258, + -0.1061600526872326, + null, + -0.1061600526872326, + -0.43981728947721027, + null, + -0.43981728947721027, + -0.5903332413468529, + null, + -0.43981728947721027, + -0.6842421525639295, + null, + -0.5903332413468529, + -0.48184781919050707, + null, + -0.6842421525639295, + -1, + null, + -0.6842421525639295, + -0.764245686120329, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18" + ], + "type": "scatter", + "x": [ + 0.47137507343491375, + 0.6820711000880268, + 0.5588144789730345, + 0.26336411527894155, + 0.050116319941363424, + 0.1742107742857007, + -0.2471285603132008, + -0.5460941568020081, + -0.824264873073218, + -0.8038320855995099, + -0.5114212689742236, + -0.21972025925361904, + 0.1010440757888845, + 0.13885763877102647, + -0.16529058717125392, + -0.4657056937090478, + 0.35434854424122336, + 0.33355820372585415, + 0.6556971603671127 + ], + "y": [ + 0.8505978288577702, + 0.6080537580286298, + 0.31295429104456673, + 0.18027224219863988, + 0.44330393960368564, + 0.740466370080546, + 0.33537984601883364, + 0.4651707665053875, + 0.30437196842471975, + -0.01809257980061243, + -0.16063632673909367, + 0.004804137162988258, + -0.1061600526872326, + -0.43981728947721027, + -0.5903332413468529, + -0.48184781919050707, + -0.6842421525639295, + -1, + -0.764245686120329 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m3_a))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Obtain GBS Samples\n" + ] + }, + { + "cell_type": "markdown", + "id": "707020c9", + "metadata": {}, + "source": [ + "### 5.1 Optional: Generate Samples with a GBS Sampling Simulator\n", + "\n", + "Since actual sampling may be time-consuming, this tutorial loads pre-saved sample files by default. If you would like to run the GBS sampling simulator yourself, you can uncomment the following code to regenerate the GBS sample files and save them as `.npy` files. In addition, richer capabilities such as hardware-sampling interfaces will be provided in future updates.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d6826a19", + "metadata": {}, + "outputs": [], + "source": [ + "import thewalrus\n", + "# samples0 = thewalrus.samples.hafnian_sample_graph(m0_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples0.npy', samples0)\n", + "# samples1 = thewalrus.samples.hafnian_sample_graph(m1_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples1.npy', samples1)\n", + "# samples2 = thewalrus.samples.hafnian_sample_graph(m2_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples2.npy', samples2)\n", + "# samples3 = thewalrus.samples.hafnian_sample_graph(m3_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples3.npy', samples3)" + ] + }, + { + "cell_type": "markdown", + "id": "171f1f6a", + "metadata": {}, + "source": [ + "### 5.2 Load Pre-generated GBS Samples\n", + "\n", + "To ensure reproducibility and stable runtime for this tutorial, the pre-generated GBS sample files are loaded here.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "81b79e7c", + "metadata": {}, + "outputs": [], + "source": [ + "samples0 = np.load('samples0.npy')\n", + "samples1 = np.load('samples1.npy')\n", + "samples2 = np.load('samples2.npy')\n", + "samples3 = np.load('samples3.npy')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Inspect One Raw Sample\n", + "\n", + "Here, one sample is printed first in order to clarify the later processing chain of “sample → orbit / event → feature vector.” A sample is essentially the photon occupation result across all modes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d50c2433", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0], dtype=int64)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "samples0[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Convert a Sample into an Orbit Representation\n", + "\n", + "`sample_to_orbit` is used to convert a specific sample into its orbit representation. An orbit reflects the partition structure of the photon occupation pattern in the sample, rather than simply recording the exact location of each mode. This makes it more suitable for constructing statistical features related to graph structure.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c82c8705", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3 2 1]\n" + ] + } + ], + "source": [ + "# Compute the orbit corresponding to the sample. \n", + "print(np.array(similarity.sample_to_orbit(samples0[0])))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. List All Orbits for a Fixed Total Photon Number\n", + "\n", + "Here, all possible orbits with total photon number 5 are listed in order to illustrate the combinatorial structure of the orbit space itself.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "313a4294", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 1, 1, 1, 1], [2, 1, 1, 1], [3, 1, 1], [2, 2, 1], [4, 1], [3, 2], [5]]\n" + ] + } + ], + "source": [ + "# All orbits with total photon number 5.\n", + "print(list(similarity.orbits(5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 9. Convert Samples into Event Representations\n", + "\n", + "Here, two concrete samples are used to illustrate how a sample is mapped to an event. In the present example, events are defined by total photon number, so different samples are assigned to the same event category as long as they satisfy the same aggregated condition.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "3d7b0a08", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n" + ] + } + ], + "source": [ + "# Compute the event of the sample; here it is defined directly by total photon number.\n", + "print(similarity.sample_to_event([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "8d87a362", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "print(similarity.sample_to_event([0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 10. Construct Event Feature Vectors from Samples\n", + "\n", + "This part computes event feature vectors for the four graphs based on a specified set of events. The resulting features can be viewed as low-dimensional representations of the graphs in an “event-statistics space,” and can be used to compare structural differences between graphs.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "debf3fb8", + "metadata": {}, + "outputs": [], + "source": [ + "# Construct an event-based feature vector from the samples.\n", + "event = [8, 10]\n", + "Ve0 = similarity.feature_vector_events_sampling(samples0, event, 2)\n", + "Ve1 = similarity.feature_vector_events_sampling(samples1, event, 2)\n", + "Ve2 = similarity.feature_vector_events_sampling(samples2, event, 2)\n", + "Ve3 = similarity.feature_vector_events_sampling(samples3, event, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 11. Visualize Different Graphs in a Two-Dimensional Feature Space\n", + "\n", + "Here, the event features of the four graphs are plotted as scatter points in order to visualize whether they become separable in a low-dimensional space. If different graphs are distributed far apart in feature space, this indicates that the constructed features have good discriminative power.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b746c422", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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rFjRSJAggZE5c2Zj5MiRbj0vlqggIiKKfu5GYokKP/wjbihdurRMmjRJ860oaszCTkRERNHv+9vtnLCpU6fKZ599Jr///rvmh7E2FhEREVEk1QlD4PXGG2/YLUeDGvLDUPuLiIiIiDwchGHexXjx4ulk3S+bmE9EREQUW7kdhGGkIKYuQrkGIiIiIoqknDCUk7hw4UIEH46IiIiIItQS1rlzZ63X1aNHDylSpIh2TVoVLVqUR5aIiIgoHG6XqIgTJ2TjGfLCmJhvjyUqiIiIop97kViiwu2WsDNnznhnT4iIiIhiEbeDsICAAO/sCREREVEs4nYQBqdOndJ5Ho8eParXMZk38sRy5crl6f0jIiIiipHcHh3566+/atC1a9cuTcLHZefOnVKoUCFZu3atd/aSiIiIKLYn5pcoUUJq1aolI0eOtFveu3dv+e2332Tfvn2e3sdoiYn5RERE0c+9qDx3JLog27RpE2J569at5ciRI57aLyIiIqIYze0gLG3atHLgwIEQy7EsXbp0ntovIiIiohjN7cT8tm3bSrt27eT06dNSvnx5XbZ161YZNWqUdO/e3Rv7SERERBTjuJ0ThtUxMnLcuHFy+fJlXZYpUyatoN+lSxdO6P0/zAkjIiKKfu5FYk6Y20GY1f379/X/ZMmSeXKfYgQGYURERNHPvaheMf/58+eSJ08eu+DrxIkTOo9k9uzZPb2PRERERDGO24n5LVu2lG3btoVYjlphuI2IiIiIvBCE7d+/XypUqBBi+WuvveZ01CQREREReSAI8/Pzs+WCWaHvNDg42N3NEREREcVKbgdhlStXlhEjRtgFXPgbyypWrOjp/SMiIiKKkdxOzEc9MARi+fLlk0qVKumyzZs362iCDRs2eGMfiYiIiGIct1vCMHn3n3/+KY0aNZLr169r12SLFi3k2LFjUrhwYe/sJREREVEM81J1wih0rBNGREQU/dyLyhN4ExEREdHLYxBGRERE5AMMwoiIiIiiehCG9LHz58/LkydPvLdHRERERLGA20FY7ty55cKFC97bIyIiIqJYwK0gLE6cODpx961bt7y3R0RERESxgNs5YSNHjpQePXrI4cOHvbNHRERERLGA23XCUqZMKY8ePZLnz59L/PjxJVGiRHa3375929P7GC2xThgREVH0cy8S64S5PW3RhAkTvLMnRERERLGI20FY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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(Ve0[0], Ve0[1], label='Graph 0')\n", + "plt.scatter(Ve1[0], Ve1[1], label='Graph 1')\n", + "plt.scatter(Ve2[0], Ve2[1], label='Graph 2')\n", + "plt.scatter(Ve3[0], Ve3[1], label='Graph 3')\n", + "plt.legend()\n", + "plt.xlabel('Graph index')\n", + "plt.ylabel('Feature vector component for event [8,10]')\n", + "plt.title('Feature vector component for event [8,10] vs Graph index')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 12. Construct Orbit Feature Vectors from Samples\n", + "\n", + "In addition to event features, one can also construct feature vectors directly around several specified orbits. Compared with event features, orbit features are usually finer-grained because they explicitly focus on the internal occupation-structure patterns of the samples.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e2b6e1b5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.2034, 0.0, 0.14085, 0.05215]\n" + ] + } + ], + "source": [ + "# Construct an orbit-based feature vector from the samples.\n", + "print(similarity.feature_vector_orbits_sampling(samples0, [[1, 1], [2], [1, 1, 1, 1], [2, 1, 1]]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 13. Compute Event Features Directly from the Graph Adjacency Matrix\n", + "\n", + "Besides constructing features from existing sample statistics, this section also demonstrates how to compute event features directly from a graph object through the function interface. This further encapsulates the workflow of “graph → feature.”\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "e8ce45bc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.20442688 0.20820147]\n" + ] + } + ], + "source": [ + "# Compute an event-based feature vector directly from the graph adjacency matrix.\n", + "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2,n_mean=5.5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 14. Generate Samples from a Graph and Then Compute Event Features\n", + "\n", + "This step further shows that, even without explicitly saving samples in advance, one can estimate event features by generating a certain number of samples internally within the function. This illustrates the two usage modes of “direct feature computation” and “feature estimation through sampling.”\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "eca549fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.19095622 0.20107849]\n" + ] + } + ], + "source": [ + "# Generate samples from the graph adjacency matrix and compute an event-based feature vector.\n", + "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2, samples=1000,n_mean=5.5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 15. Use a Support Vector Machine for Graph Classification\n", + "\n", + "After feature extraction is completed, this tutorial further constructs a simple supervised learning task. Here, class labels are assigned to the four graphs, and the previously extracted event features are used as the inputs for graph classification.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "7d018638", + "metadata": {}, + "outputs": [], + "source": [ + "classes = [1, 0, 0, 1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 16. Construct the Classification Feature Matrix\n", + "\n", + "Here, the feature vectors corresponding to different graphs are organized into the matrix `R`, which serves as the input to the subsequent classifier. Each row corresponds to one graph, and each column corresponds to one feature dimension.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "cb97463f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.08065 0.0349 ]\n", + " [0.06375 0.02195]\n", + " [0.0635 0.02435]\n", + " [0.08895 0.03945]]\n" + ] + } + ], + "source": [ + "events = [8, 10]\n", + "max_count = 2\n", + "\n", + "f1 = similarity.feature_vector_events_sampling(samples0, events, max_count)\n", + "f2 = similarity.feature_vector_events_sampling(samples1, events, max_count)\n", + "f3 = similarity.feature_vector_events_sampling(samples2, events, max_count)\n", + "f4 = similarity.feature_vector_events_sampling(samples3, events, max_count)\n", + "\n", + "import numpy as np\n", + "\n", + "R = np.array([f1, f2, f3, f4])\n", + "\n", + "print(R)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 17. Train a Linear Support Vector Machine\n", + "\n", + "Here, the features are first standardized, and then a `LinearSVC` classifier is trained. This allows us to test whether the previously constructed GBS-based graph features already possess sufficient linear separability.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "c1717edf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
LinearSVC()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "LinearSVC()" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.svm import LinearSVC\n", + "from sklearn.preprocessing import StandardScaler\n", + "\n", + "R_scaled = StandardScaler().fit_transform(R) # Transform data to zero mean and unit variance\n", + "\n", + "classifier = LinearSVC()\n", + "classifier.fit(R_scaled, classes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 18. Visualize the Classification Boundary\n", + "\n", + "Finally, by plotting the separating line learned by the support vector machine in feature space, one can more intuitively observe how graphs of different classes are separated in that space.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "b395c9e5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "text", + "marker": { + "color": "#F2F2F2", + "line": { + "color": "black", + "width": 1.5 + }, + "size": 30 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3" + ], + "type": "scatter", + "x": { + "bdata": "xy5kd9q/4j8800xA7Xjuv0xWkS5UM++/Yf28ezN29T8=", + "dtype": "f8" + }, + "y": { + "bdata": "r6awSBrt5D+wu0ghSyPyv7p4xNKyrOm/uqRSZheD9D8=", + "dtype": "f8" + } + }, + { + "hoverinfo": "text", + "marker": { + "color": "#cc2529", + "line": { + "color": "black", + "width": 1.5 + }, + "size": 30 + }, + "mode": "markers", + "text": [ + "0", + "3" + ], + "type": "scatter", + "x": [ + 0.5859196025716863, + 1.3413576921010064 + ], + "y": [ + 0.65394319722437, + 1.2820047375665085 + ] + }, + { + "mode": "lines", + "type": "scatter", + "x": [ + -1, + 1 + ], + "y": [ + 0.8240485442699357, + -1.2684154950474817 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "white", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "w = classifier.coef_[0]\n", + "i = classifier.intercept_[0]\n", + "\n", + "m = -w[0] / w[1] # finding the values for y = mx + b\n", + "b = -i / w[1]\n", + "\n", + "xx = [-1, 1]\n", + "yy = [m * x + b for x in xx]\n", + "\n", + "fig = plot.points(R_scaled, classes)\n", + "fig.add_trace(plotly.graph_objects.Scatter(x=xx, y=yy, mode=\"lines\"))\n", + "\n", + "fig" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 19. Conclusion\n", + "\n", + "This tutorial shows that the value of GBS in graph isomorphism and graph similarity analysis lies in providing a sample-based feature representation that captures higher-order structural differences between graphs. Its main characteristics include:\n", + "\n", + "- GBS sample distributions can reflect combinatorial structural differences among graphs;\n", + "- event features and orbit features can compress sample statistics into low-dimensional representations;\n", + "- these representations can be used both for graph comparison and for simple graph classification;\n", + "- quantum sampling and classical machine learning can be naturally combined.\n", + "\n", + "In summary, this notebook illustrates the complete processing chain of **“graph structure → GBS samples → feature vectors → graph comparison / graph classification.”** Understanding this chain is the foundation for further study of GBS in graph learning, graph discrimination, and structured-data analysis.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "photon", + "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.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_zh.ipynb b/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_zh.ipynb new file mode 100644 index 0000000..3076344 --- /dev/null +++ b/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism_zh.ipynb @@ -0,0 +1,6192 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 基于高斯玻色采样增强的图同构分析\n", + "\n", + "本案例展示如何利用高斯玻色采样(**Gaussian Boson Sampling, GBS**)为图结构构造特征表示,并进一步用于**图同构判别、图相似性分析与图分类**等任务。\n", + "\n", + "---\n", + "\n", + "## 原理\n", + "\n", + "### 问题描述\n", + "\n", + "图同构问题关注的是:对于两个给定图,是否存在一个顶点重标记,使得它们的邻接关系完全一致。若存在这样的顶点一一对应关系,则称这两个图是**同构的**。从图论角度看,同构图虽然顶点编号可能不同,但在结构上是完全相同的。\n", + "\n", + "与严格的图同构判定相比,图相似性分析的目标更宽松一些。它不一定要求两个图在结构上完全一致,而是希望刻画两张图在多大程度上具有相似的连接模式、局部结构和高阶统计性质。这类任务在图分类、图检索、化学分子比较以及模式识别中都具有重要意义。\n", + "\n", + "因此,在实际应用中,一个常见思路是:先为图构造一个能够反映其结构特征的表示,再基于这些表示比较不同图之间的差异。如果两个图具有相近甚至一致的结构签名,它们更可能是同构图或至少是结构上高度相似的图。\n", + "\n", + "### 为什么高斯玻色采样可以用于增强图同构问题 ?\n", + "\n", + "当一个图被编码到高斯玻色采样装置后,其输出的光子计数分布会与该图的组合结构密切相关。更具体地说,样本出现的概率与图对应子矩阵的 Hafnian 等量有关,因此会反映图中匹配结构、连接模式以及更高阶的组合性质。\n", + "\n", + "这意味着,GBS 对不同图并不会产生完全相同的样本分布。即使两个图具有相同的顶点数和边数,只要它们的内部结构存在差异,其 GBS 样本统计也往往会表现出不同的偏好。因此,可以将 GBS 样本分布视为一种**由量子采样诱导的图结构签名**。\n", + "\n", + "### 事件(event)与轨道(orbit)特征的含义\n", + "\n", + "为了将原始样本分布转化为可比较的数值表示,本案例引入了两类特征:\n", + "\n", + "- **事件特征(event features)**:关注样本的宏观统计属性,可将样本按总光子数进行分组,并统计不同总光子数事件在采样结果中的出现频率。这样得到的特征向量反映了图在较粗粒度统计层面上的采样分布特征。\n", + "- **轨道特征(orbit features)**:关注样本内部更细致的占据结构。对于具有相同总光子数的样本,不同的光子占据方式可对应不同的整数分拆模式,也即不同轨道。通过统计若干指定轨道在样本中的出现频率,可以得到比事件特征更细粒度的结构表征。\n", + "\n", + "从表示学习的角度看,这两类特征都在做同一件事:把高维、离散、原始的采样结果,压缩成低维但具有结构辨识能力的特征向量。这样既便于可视化,也便于后续输入到分类器中进行监督学习。\n", + "\n", + "### 整体思路\n", + "\n", + "本案例的整体思路可以概括为以下几个阶段:\n", + "\n", + "1. 读取多个图实例,并观察它们的原始结构;\n", + "2. 为每个图准备对应的 GBS 样本;\n", + "3. 将样本转换为事件特征或轨道特征;\n", + "4. 比较不同图在特征空间中的分布位置;\n", + "5. 使用支持向量机对图进行简单分类,验证这些特征的判别能力。\n", + "\n", + "---\n", + "\n", + "## 技术路线\n", + "\n", + "### 整体流程\n", + "\n", + "本案例的技术路线可以概括为以下几个步骤:\n", + "\n", + "1. **读取多个图实例**:加载 `Mutag0()` 到 `Mutag3()` 四个图数据集,并提取它们的邻接矩阵。\n", + "2. **可视化原始图结构**:使用 `networkx` 与 Strawberry Fields 的绘图工具观察不同图的连接模式。\n", + "3. **准备或加载 GBS 样本**:可选地使用 `thewalrus` 采样器生成样本,也可以直接使用预生成样本。\n", + "4. **构造事件特征向量**:根据指定事件定义,从样本统计中提取图的低维特征表示。\n", + "5. **构造轨道特征向量**:将样本转换为轨道表示,并提取相应特征。\n", + "6. **比较图在特征空间中的分布**:通过散点图等方式直观观察不同图是否可以被区分。\n", + "7. **执行图分类实验**:将提取的特征输入支持向量机,检验其对图类别的区分能力。\n", + "\n", + "---\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. 读取四个图实例\n", + "\n", + "这一部分导入图数据、绘图工具和相似性分析模块,并读取四个示例图 `Mutag0()`、`Mutag1()`、`Mutag2()` 和 `Mutag3()`。这些图将作为后续比较与分类的对象。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "259a1626", + "metadata": {}, + "outputs": [], + "source": [ + "from strawberryfields.apps import data, plot, similarity\n", + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", + "\n", + "m0 = data.Mutag0()\n", + "m1 = data.Mutag1()\n", + "m2 = data.Mutag2()\n", + "m3 = data.Mutag3()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. 提取各图的邻接矩阵\n", + "\n", + "这里将四个图对象分别转换为邻接矩阵表示。邻接矩阵是后续进行采样、特征计算和图结构分析的基础数据形式。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "1c3003f9", + "metadata": {}, + "outputs": [], + "source": [ + "m0_a = m0.adj\n", + "m1_a = m1.adj\n", + "m2_a = m2.adj\n", + "m3_a = m3.adj" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. 导入图处理与可视化辅助库\n", + "\n", + "这一步额外导入 `networkx` 与 `plotly`,用于构造图对象和支持交互式可视化。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "e3de6022", + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "import plotly" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. 可视化四个原始图\n", + "\n", + "下面依次绘制四个图的结构。通过观察这些图,可以先建立对其拓扑差异的直观认识,这也有助于理解后续特征空间中的分布差别。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "f635734c", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.1106749200820511, + 0.3325180282834503, + null, + 0.1106749200820511, + -0.10573201244961422, + null, + 0.3325180282834503, + 0.3183779686865032, + null, + 0.3183779686865032, + 0.10817894656323569, + null, + 0.10817894656323569, + -0.1258206158117392, + null, + 0.10817894656323569, + 0.08944551616123024, + null, + -0.1258206158117392, + -0.10573201244961422, + null, + -0.1258206158117392, + -0.35683606826960246, + null, + -0.35683606826960246, + -0.3746946767622438, + null, + -0.3746946767622438, + -0.16201507142000418, + null, + -0.16201507142000418, + 0.08944551616123024, + null, + -0.16201507142000418, + -0.17957964910137447, + null, + 0.08944551616123024, + 0.2639581661840744, + null, + 0.2639581661840744, + 0.23288582259230256, + null, + 0.23288582259230256, + -0.004090002015534177, + null, + -0.004090002015534177, + -0.17957964910137447, + null, + -0.004090002015534177, + -0.038531130421250566, + null, + -0.038531130421250566, + -0.23867208087265562, + null, + -0.038531130421250566, + 0.12993193857117113, + null + ], + "y": [ + 0.9109613341530329, + 0.7623231588277424, + null, + 0.9109613341530329, + 0.7584892195635953, + null, + 0.7623231588277424, + 0.5002924896086175, + null, + 0.5002924896086175, + 0.3325831579704782, + null, + 0.3325831579704782, + 0.4940021409430781, + null, + 0.3325831579704782, + 0.06187083194727157, + null, + 0.4940021409430781, + 0.7584892195635953, + null, + 0.4940021409430781, + 0.3575453539641614, + null, + 0.3575453539641614, + 0.09278291481906589, + null, + 0.09278291481906589, + -0.07160734861438502, + null, + -0.07160734861438502, + 0.06187083194727157, + null, + -0.07160734861438502, + -0.33762664558407796, + null, + 0.06187083194727157, + -0.14338931087274356, + null, + -0.14338931087274356, + -0.4054751685172854, + null, + -0.4054751685172854, + -0.5422076935972371, + null, + -0.5422076935972371, + -0.33762664558407796, + null, + -0.5422076935972371, + -0.802917760705588, + null, + -0.802917760705588, + -0.9676266739057261, + null, + -0.802917760705588, + -1, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16" + ], + "type": "scatter", + "x": [ + 0.1106749200820511, + 0.3325180282834503, + 0.3183779686865032, + 0.10817894656323569, + -0.1258206158117392, + -0.10573201244961422, + -0.35683606826960246, + -0.3746946767622438, + -0.16201507142000418, + 0.08944551616123024, + 0.2639581661840744, + 0.23288582259230256, + -0.004090002015534177, + -0.17957964910137447, + -0.038531130421250566, + -0.23867208087265562, + 0.12993193857117113 + ], + "y": [ + 0.9109613341530329, + 0.7623231588277424, + 0.5002924896086175, + 0.3325831579704782, + 0.4940021409430781, + 0.7584892195635953, + 0.3575453539641614, + 0.09278291481906589, + -0.07160734861438502, + 0.06187083194727157, + -0.14338931087274356, + -0.4054751685172854, + -0.5422076935972371, + -0.33762664558407796, + -0.802917760705588, + -0.9676266739057261, + -1 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m0_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "b7ddf46f", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.6989554447413813, + 0.4446363061276493, + null, + 0.6989554447413813, + 0.5438914846302285, + null, + 0.4446363061276493, + 0.04464792421709926, + null, + 0.04464792421709926, + -0.204192119107545, + null, + 0.04464792421709926, + -0.11999491909362145, + null, + -0.204192119107545, + -0.6044384529514965, + null, + -0.6044384529514965, + -0.7714923431768627, + null, + -0.7714923431768627, + -0.5291983220100507, + null, + -0.5291983220100507, + -0.11999491909362145, + null, + -0.11999491909362145, + 0.14100625882157714, + null, + 0.14100625882157714, + 0.5438914846302285, + null, + 0.14100625882157714, + 0.11531436283452415, + null, + 0.11531436283452415, + -0.14885312434803125, + null, + 0.11531436283452415, + 0.3897174993151481, + null + ], + "y": [ + 0.19943320936933975, + 0.5117591191061869, + null, + 0.19943320936933975, + -0.16965278458321073, + null, + 0.5117591191061869, + 0.42809111540950934, + null, + 0.42809111540950934, + 0.7501969287197767, + null, + 0.42809111540950934, + 0.03008807013152098, + null, + 0.7501969287197767, + 0.7693401240903215, + null, + 0.7693401240903215, + 0.39988842627856575, + null, + 0.39988842627856575, + 0.07974141740262024, + null, + 0.07974141740262024, + 0.03008807013152098, + null, + 0.03008807013152098, + -0.29827216554532393, + null, + -0.29827216554532393, + -0.16965278458321073, + null, + -0.29827216554532393, + -0.7070898582139229, + null, + -0.7070898582139229, + -1, + null, + -0.7070898582139229, + -0.993523602165384, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12" + ], + "type": "scatter", + "x": [ + 0.6989554447413813, + 0.4446363061276493, + 0.04464792421709926, + -0.204192119107545, + -0.6044384529514965, + -0.7714923431768627, + -0.5291983220100507, + -0.11999491909362145, + 0.14100625882157714, + 0.5438914846302285, + 0.11531436283452415, + -0.14885312434803125, + 0.3897174993151481 + ], + "y": [ + 0.19943320936933975, + 0.5117591191061869, + 0.42809111540950934, + 0.7501969287197767, + 0.7693401240903215, + 0.39988842627856575, + 0.07974141740262024, + 0.03008807013152098, + -0.29827216554532393, + -0.16965278458321073, + -0.7070898582139229, + -1, + -0.993523602165384 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m1_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "0fd75aa9", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.6418193777806868, + 0.33582251607079827, + null, + 0.6418193777806868, + 0.5605955443702613, + null, + 0.33582251607079827, + -0.0372042080290194, + null, + -0.0372042080290194, + -0.12229696899296028, + null, + -0.0372042080290194, + -0.3397181392877679, + null, + -0.12229696899296028, + -0.5293834487765021, + null, + -0.12229696899296028, + 0.1932164253360116, + null, + -0.5293834487765021, + -0.825166960741573, + null, + -0.825166960741573, + -0.7323531444109789, + null, + -0.7323531444109789, + -0.3397181392877679, + null, + 0.1932164253360116, + 0.5605955443702613, + null, + 0.1932164253360116, + 0.24521575187315073, + null, + 0.24521575187315073, + 0.04359736568772133, + null, + 0.24521575187315073, + 0.5658558891201715, + null + ], + "y": [ + 0.32544599922309664, + 0.5811356299722468, + null, + 0.32544599922309664, + -0.062493324440433144, + null, + 0.5811356299722468, + 0.424499731764875, + null, + 0.424499731764875, + 0.006650885589960059, + null, + 0.424499731764875, + 0.6907264092168071, + null, + 0.006650885589960059, + -0.022129969745260318, + null, + 0.006650885589960059, + -0.2633648468095954, + null, + -0.022129969745260318, + 0.2434250853555832, + null, + 0.2434250853555832, + 0.6339779943123541, + null, + 0.6339779943123541, + 0.6907264092168071, + null, + -0.2633648468095954, + -0.062493324440433144, + null, + -0.2633648468095954, + -0.6655639303172131, + null, + -0.6655639303172131, + -0.9999999999999999, + null, + -0.6655639303172131, + -0.8923096641224209, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12" + ], + "type": "scatter", + "x": [ + 0.6418193777806868, + 0.33582251607079827, + -0.0372042080290194, + -0.12229696899296028, + -0.5293834487765021, + -0.825166960741573, + -0.7323531444109789, + -0.3397181392877679, + 0.1932164253360116, + 0.5605955443702613, + 0.24521575187315073, + 0.04359736568772133, + 0.5658558891201715 + ], + "y": [ + 0.32544599922309664, + 0.5811356299722468, + 0.424499731764875, + 0.006650885589960059, + -0.022129969745260318, + 0.2434250853555832, + 0.6339779943123541, + 0.6907264092168071, + -0.2633648468095954, + -0.062493324440433144, + -0.6655639303172131, + -0.9999999999999999, + -0.8923096641224209 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m2_a))" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "70b3e604", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "none", + "line": { + "color": "#CDCDCD", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0.47137507343491375, + 0.6820711000880268, + null, + 0.47137507343491375, + 0.1742107742857007, + null, + 0.6820711000880268, + 0.5588144789730345, + null, + 0.5588144789730345, + 0.26336411527894155, + null, + 0.26336411527894155, + 0.050116319941363424, + null, + 0.26336411527894155, + 0.1010440757888845, + null, + 0.050116319941363424, + 0.1742107742857007, + null, + 0.050116319941363424, + -0.2471285603132008, + null, + -0.2471285603132008, + -0.5460941568020081, + null, + -0.2471285603132008, + -0.21972025925361904, + null, + -0.5460941568020081, + -0.824264873073218, + null, + -0.824264873073218, + -0.8038320855995099, + null, + -0.8038320855995099, + -0.5114212689742236, + null, + -0.5114212689742236, + -0.21972025925361904, + null, + -0.5114212689742236, + -0.4657056937090478, + null, + -0.21972025925361904, + 0.1010440757888845, + null, + 0.1010440757888845, + 0.13885763877102647, + null, + 0.13885763877102647, + -0.16529058717125392, + null, + 0.13885763877102647, + 0.35434854424122336, + null, + -0.16529058717125392, + -0.4657056937090478, + null, + 0.35434854424122336, + 0.33355820372585415, + null, + 0.35434854424122336, + 0.6556971603671127, + null + ], + "y": [ + 0.8505978288577702, + 0.6080537580286298, + null, + 0.8505978288577702, + 0.740466370080546, + null, + 0.6080537580286298, + 0.31295429104456673, + null, + 0.31295429104456673, + 0.18027224219863988, + null, + 0.18027224219863988, + 0.44330393960368564, + null, + 0.18027224219863988, + -0.1061600526872326, + null, + 0.44330393960368564, + 0.740466370080546, + null, + 0.44330393960368564, + 0.33537984601883364, + null, + 0.33537984601883364, + 0.4651707665053875, + null, + 0.33537984601883364, + 0.004804137162988258, + null, + 0.4651707665053875, + 0.30437196842471975, + null, + 0.30437196842471975, + -0.01809257980061243, + null, + -0.01809257980061243, + -0.16063632673909367, + null, + -0.16063632673909367, + 0.004804137162988258, + null, + -0.16063632673909367, + -0.48184781919050707, + null, + 0.004804137162988258, + -0.1061600526872326, + null, + -0.1061600526872326, + -0.43981728947721027, + null, + -0.43981728947721027, + -0.5903332413468529, + null, + -0.43981728947721027, + -0.6842421525639295, + null, + -0.5903332413468529, + -0.48184781919050707, + null, + -0.6842421525639295, + -1, + null, + -0.6842421525639295, + -0.764245686120329, + null + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": "#3e9651", + "line": { + "width": 2 + }, + "size": 14 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18" + ], + "type": "scatter", + "x": [ + 0.47137507343491375, + 0.6820711000880268, + 0.5588144789730345, + 0.26336411527894155, + 0.050116319941363424, + 0.1742107742857007, + -0.2471285603132008, + -0.5460941568020081, + -0.824264873073218, + -0.8038320855995099, + -0.5114212689742236, + -0.21972025925361904, + 0.1010440757888845, + 0.13885763877102647, + -0.16529058717125392, + -0.4657056937090478, + 0.35434854424122336, + 0.33355820372585415, + 0.6556971603671127 + ], + "y": [ + 0.8505978288577702, + 0.6080537580286298, + 0.31295429104456673, + 0.18027224219863988, + 0.44330393960368564, + 0.740466370080546, + 0.33537984601883364, + 0.4651707665053875, + 0.30437196842471975, + -0.01809257980061243, + -0.16063632673909367, + 0.004804137162988258, + -0.1061600526872326, + -0.43981728947721027, + -0.5903332413468529, + -0.48184781919050707, + -0.6842421525639295, + -1, + -0.764245686120329 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "#ffffff", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot.graph(nx.Graph(m3_a))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. 获取 GBS 采样样本\n" + ] + }, + { + "cell_type": "markdown", + "id": "707020c9", + "metadata": {}, + "source": [ + "\n", + "### 5.1 可选:使用 GBS 采样模拟器生成样本\n", + "\n", + "由于真实采样可能耗时过长,本案例默认直接加载预先保存好的样本文件。如您想使用模拟器执行 GBS 采样操作,可取消下列代码注释以重新生成 GBS 样本文件,并将其保存为 `.npy` 文件。此外,后续我们将陆续提供真机采样接口等丰富的功能。" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "d6826a19", + "metadata": {}, + "outputs": [], + "source": [ + "import thewalrus\n", + "# samples0 = thewalrus.samples.hafnian_sample_graph(m0_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples0.npy', samples0)\n", + "# samples1 = thewalrus.samples.hafnian_sample_graph(m1_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples1.npy', samples1)\n", + "# samples2 = thewalrus.samples.hafnian_sample_graph(m2_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples2.npy', samples2)\n", + "# samples3 = thewalrus.samples.hafnian_sample_graph(m3_a, n_mean=5.5,samples=20000,max_photons=20)\n", + "# np.save('samples3.npy', samples3)" + ] + }, + { + "cell_type": "markdown", + "id": "171f1f6a", + "metadata": {}, + "source": [ + "### 5.2 读取预生成的 GBS 样本\n", + "\n", + "为了保证案例可复现、运行速度稳定,这里读取事先准备好的 GBS 样本文件。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "81b79e7c", + "metadata": {}, + "outputs": [], + "source": [ + "samples0 = np.load('samples0.npy')\n", + "samples1 = np.load('samples1.npy')\n", + "samples2 = np.load('samples2.npy')\n", + "samples3 = np.load('samples3.npy')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. 查看一个原始样本\n", + "\n", + "这里先输出一个样本,帮助理解后续“样本 → 轨道 / 事件 → 特征向量”的处理链路。一个样本本质上是各模式的光子占据结果。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "d50c2433", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0], dtype=int64)" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "samples0[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. 将样本转换为轨道表示\n", + "\n", + "`sample_to_orbit` 用于把一个具体样本转换为轨道表示。轨道表示反映的是该样本中光子占据模式的分拆结构,而不是简单记录每个模式上的具体位置,因此更适合用于构造与图结构相关的统计特征。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "c82c8705", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3 2 1]\n" + ] + } + ], + "source": [ + "# 计算样本对应的轨道 \n", + "print(np.array(similarity.sample_to_orbit(samples0[0])))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. 查看固定总光子数下的所有轨道\n", + "\n", + "这里列出总光子数为 5 时可能出现的全部轨道,用于说明轨道空间本身的组合结构。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "313a4294", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 1, 1, 1, 1], [2, 1, 1, 1], [3, 1, 1], [2, 2, 1], [4, 1], [3, 2], [5]]\n" + ] + } + ], + "source": [ + "# 总光子数为5的所有轨道\n", + "print(list(similarity.orbits(5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 9. 将样本转换为事件表示\n", + "\n", + "这里通过两个具体样本演示如何将样本映射为事件。当前示例中,事件是按总光子数来定义的,因此不同样本只要满足相同的汇总条件,就会被归入同一事件类别。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "3d7b0a08", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n" + ] + } + ], + "source": [ + "# 计算样本的event,这里直接定义为总光子数\n", + "print(similarity.sample_to_event([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "8d87a362", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "print(similarity.sample_to_event([0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 10. 从样本构造事件特征向量\n", + "\n", + "这一部分基于指定事件集合,为四个图分别计算事件特征向量。得到的特征可以视为图在“事件统计空间”中的低维表示,用于比较不同图之间的结构差异。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "debf3fb8", + "metadata": {}, + "outputs": [], + "source": [ + "# 从样本构造event刻画的特性向量\n", + "event = [8, 10]\n", + "Ve0 = similarity.feature_vector_events_sampling(samples0, event, 2)\n", + "Ve1 = similarity.feature_vector_events_sampling(samples1, event, 2)\n", + "Ve2 = similarity.feature_vector_events_sampling(samples2, event, 2)\n", + "Ve3 = similarity.feature_vector_events_sampling(samples3, event, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 11. 在二维特征空间中可视化不同图\n", + "\n", + "这里将四个图的事件特征绘制为散点,用于直观观察它们是否在低维空间中呈现出可分性。如果不同图在特征空间中分布较远,说明所构造的特征具有较好的判别能力。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "b746c422", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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rFjRSJAggZE5c2Zj5MiRbj0vlqggIiKKfu5GYokKP/wjbihdurRMmjRJ860oaszCTkRERNHv+9vtnLCpU6fKZ599Jr///rvmh7E2FhEREVEk1QlD4PXGG2/YLUeDGvLDUPuLiIiIiDwchGHexXjx4ulk3S+bmE9EREQUW7kdhGGkIKYuQrkGIiIiIoqknDCUk7hw4UIEH46IiIiIItQS1rlzZ63X1aNHDylSpIh2TVoVLVqUR5aIiIgoHG6XqIgTJ2TjGfLCmJhvjyUqiIiIop97kViiwu2WsDNnznhnT4iIiIhiEbeDsICAAO/sCREREVEs4nYQBqdOndJ5Ho8eParXMZk38sRy5crl6f0jIiIiipHcHh3566+/atC1a9cuTcLHZefOnVKoUCFZu3atd/aSiIiIKLYn5pcoUUJq1aolI0eOtFveu3dv+e2332Tfvn2e3sdoiYn5RERE0c+9qDx3JLog27RpE2J569at5ciRI57aLyIiIqIYze0gLG3atHLgwIEQy7EsXbp0ntovIiIiohjN7cT8tm3bSrt27eT06dNSvnx5XbZ161YZNWqUdO/e3Rv7SERERBTjuJ0ThtUxMnLcuHFy+fJlXZYpUyatoN+lSxdO6P0/zAkjIiKKfu5FYk6Y20GY1f379/X/ZMmSeXKfYgQGYURERNHPvaheMf/58+eSJ08eu+DrxIkTOo9k9uzZPb2PRERERDGO24n5LVu2lG3btoVYjlphuI2IiIiIvBCE7d+/XypUqBBi+WuvveZ01CQREREReSAI8/Pzs+WCWaHvNDg42N3NEREREcVKbgdhlStXlhEjRtgFXPgbyypWrOjp/SMiIiKKkdxOzEc9MARi+fLlk0qVKumyzZs362iCDRs2eGMfiYiIiGIct1vCMHn3n3/+KY0aNZLr169r12SLFi3k2LFjUrhwYe/sJREREVEM81J1wih0rBNGREQU/dyLyhN4ExEREdHLYxBGRERE5AMMwoiIiIiiehCG9LHz58/LkydPvLdHRERERLGA20FY7ty55cKFC97bIyIiIqJYwK0gLE6cODpx961bt7y3R0RERESxgNs5YSNHjpQePXrI4cOHvbNHRERERLGA23XCUqZMKY8ePZLnz59L/PjxJVGiRHa3375929P7GC2xThgREVH0cy8S64S5PW3RhAkTvLMnRERERLGI20FY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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(Ve0[0], Ve0[1], label='Graph 0')\n", + "plt.scatter(Ve1[0], Ve1[1], label='Graph 1')\n", + "plt.scatter(Ve2[0], Ve2[1], label='Graph 2')\n", + "plt.scatter(Ve3[0], Ve3[1], label='Graph 3')\n", + "plt.legend()\n", + "plt.xlabel('Graph index')\n", + "plt.ylabel('Feature vector component for event [8,10]')\n", + "plt.title('Feature vector component for event [8,10] vs Graph index')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 12. 从样本构造轨道特征向量\n", + "\n", + "除了事件特征外,也可以直接围绕若干指定轨道构造特征向量。与事件特征相比,轨道特征通常更细粒度,因为它们显式关注样本内部的占据结构模式。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "e2b6e1b5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.2034, 0.0, 0.14085, 0.05215]\n" + ] + } + ], + "source": [ + "# 从样本构造轨道刻画的特性向量\n", + "print(similarity.feature_vector_orbits_sampling(samples0, [[1, 1], [2], [1, 1, 1, 1], [2, 1, 1]]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 13. 从图的邻接矩阵直接计算事件特征\n", + "\n", + "除了从已有样本统计中构造特征外,这里还演示如何直接从图对象出发,通过函数接口计算事件特征。这样可以将“图 → 特征”的流程进一步封装化。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "e8ce45bc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.20442688 0.20820147]\n" + ] + } + ], + "source": [ + "# 从图的邻接矩阵直接计算event刻画的特性向量\n", + "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2,n_mean=5.5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 14. 通过图生成样本后再计算事件特征\n", + "\n", + "这一步骤进一步展示:即使不预先显式保存样本,也可以通过函数内部生成一定数量样本来估计事件特征。这体现了“直接解析特征”与“通过采样估计特征”两种使用方式。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "eca549fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.19424857 0.17485086]\n" + ] + } + ], + "source": [ + "# 从图的邻接矩阵生成样本计算event刻画的特性向量\n", + "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2, samples=1000,n_mean=5.5)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 15. 使用支持向量机进行图分类\n", + "\n", + "在完成特征提取之后,本案例进一步构造一个简单的监督学习任务。这里为四个图指定类别标签,并尝试使用前面提取的事件特征作为输入,对图进行分类。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "7d018638", + "metadata": {}, + "outputs": [], + "source": [ + "classes = [1, 0, 0, 1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 16. 构造分类特征矩阵\n", + "\n", + "这里将不同图对应的特征向量组织成矩阵 `R`,作为后续分类器的输入。每一行对应一个图,每一列对应一个特征维度。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "cb97463f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.08065 0.0349 ]\n", + " [0.06375 0.02195]\n", + " [0.0635 0.02435]\n", + " [0.08895 0.03945]]\n" + ] + } + ], + "source": [ + "events = [8, 10]\n", + "max_count = 2\n", + "\n", + "f1 = similarity.feature_vector_events_sampling(samples0, events, max_count)\n", + "f2 = similarity.feature_vector_events_sampling(samples1, events, max_count)\n", + "f3 = similarity.feature_vector_events_sampling(samples2, events, max_count)\n", + "f4 = similarity.feature_vector_events_sampling(samples3, events, max_count)\n", + "\n", + "import numpy as np\n", + "\n", + "R = np.array([f1, f2, f3, f4])\n", + "\n", + "print(R)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 17. 训练线性支持向量机\n", + "\n", + "这里首先对特征做标准化处理,再使用 `LinearSVC` 训练一个线性支持向量机分类器。这样可以检验前面构造的 GBS 图特征是否已经具备足够的线性可分性。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "c1717edf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
LinearSVC()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "LinearSVC()" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.svm import LinearSVC\n", + "from sklearn.preprocessing import StandardScaler\n", + "\n", + "R_scaled = StandardScaler().fit_transform(R) # Transform data to zero mean and unit variance\n", + "\n", + "classifier = LinearSVC()\n", + "classifier.fit(R_scaled, classes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 18. 可视化分类边界\n", + "\n", + "最后,通过绘制支持向量机在特征空间中的分割直线,可以更直观地观察不同类别图在该特征空间中的分离情况。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "b395c9e5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "text", + "marker": { + "color": "#F2F2F2", + "line": { + "color": "black", + "width": 1.5 + }, + "size": 30 + }, + "mode": "markers", + "text": [ + "0", + "1", + "2", + "3" + ], + "type": "scatter", + "x": { + "bdata": "xy5kd9q/4j8800xA7Xjuv0xWkS5UM++/Yf28ezN29T8=", + "dtype": "f8" + }, + "y": { + "bdata": "r6awSBrt5D+wu0ghSyPyv7p4xNKyrOm/uqRSZheD9D8=", + "dtype": "f8" + } + }, + { + "hoverinfo": "text", + "marker": { + "color": "#cc2529", + "line": { + "color": "black", + "width": 1.5 + }, + "size": 30 + }, + "mode": "markers", + "text": [ + "0", + "3" + ], + "type": "scatter", + "x": [ + 0.5859196025716863, + 1.3413576921010064 + ], + "y": [ + 0.65394319722437, + 1.2820047375665085 + ] + }, + { + "mode": "lines", + "type": "scatter", + "x": [ + -1, + 1 + ], + "y": [ + 0.8240485442699357, + -1.2684154950474817 + ] + } + ], + "layout": { + "height": 500, + "hovermode": "closest", + "margin": { + "b": 0, + "l": 0, + "r": 0, + "t": 25 + }, + "plot_bgcolor": "white", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "width": 500, + "xaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + }, + "yaxis": { + "showgrid": false, + "showticklabels": false, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "w = classifier.coef_[0]\n", + "i = classifier.intercept_[0]\n", + "\n", + "m = -w[0] / w[1] # finding the values for y = mx + b\n", + "b = -i / w[1]\n", + "\n", + "xx = [-1, 1]\n", + "yy = [m * x + b for x in xx]\n", + "\n", + "fig = plot.points(R_scaled, classes)\n", + "fig.add_trace(plotly.graph_objects.Scatter(x=xx, y=yy, mode=\"lines\"))\n", + "\n", + "fig" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 19. 结论\n", + "\n", + "通过本案例可以看到,GBS 在图同构与图相似性分析中的价值在于为图构造一种能够反映高阶结构差异的采样特征表示。其核心特点包括:\n", + "\n", + "- GBS 样本分布能够反映图的组合结构差异;\n", + "- 事件特征和轨道特征可以将样本统计压缩为低维表示;\n", + "- 这些表示既可用于图间比较,也可用于简单图分类;\n", + "- 量子采样与经典机器学习可以形成自然结合。\n", + "\n", + "综上所述,本案例体现的是“**图结构 → GBS 样本 → 特征向量 → 图比较 / 图分类**”这一完整处理链路。理解这一链路,是进一步研究 GBS 在图学习、图判别和结构数据分析中应用的基础。\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "photon", + "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.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism.ipynb b/cqlib_experiments/photonic/graph_isomorphism/similarity.ipynb similarity index 91% rename from cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism.ipynb rename to cqlib_experiments/photonic/graph_isomorphism/similarity.ipynb index 3f7da28..61fab06 100644 --- a/cqlib_experiments/photonic/graph_isomorphism/graph_isomorphism.ipynb +++ b/cqlib_experiments/photonic/graph_isomorphism/similarity.ipynb @@ -2,135 +2,57 @@ "cells": [ { "cell_type": "markdown", - "id": "3163736e", + "id": "72ef1901", "metadata": {}, "source": [ - "# Graph Isomorphism with Gaussian Boson Sampling\n" - ] - }, - { - "cell_type": "markdown", - "id": "d5f7c7fa", - "metadata": {}, - "source": [ - "Principle\n", - "---------\n", - "This notebook demonstrates a **GBS-based feature approach** for graph\n", - "isomorphism/similarity analysis.\n", - "\n", - "### 1) Graph isomorphism background\n", - "Two graphs G1 and G2 are isomorphic if there exists a vertex relabeling\n", - "(permutation) that makes their adjacency structures identical.\n", - "- Isomorphic graphs are structurally the same object under different labels.\n", - "- Non-isomorphic graphs differ in structure.\n", - "\n", - "A practical challenge is to build descriptors that are:\n", - "1. Sensitive to structural differences,\n", - "2. Invariant (or robust) under vertex relabeling.\n", - "\n", - "### 2) Why Gaussian Boson Sampling (GBS) is relevant\n", - "In graph-encoded GBS, each detection sample is a photon-number occupation\n", - "pattern over graph modes. Sampling statistics depend on graph structure through\n", - "Gaussian-state amplitudes (Hafnian/Torontonian-related quantities).\n", - "\n", - "Therefore, different graphs induce different sample distributions, and these\n", - "statistics can be used as graph signatures.\n", - "\n", - "### 3) Events and orbits as permutation-aware descriptors\n", - "This tutorial uses two key representations from `similarity`:\n", - "- **Event-based features**: probabilities/counts of selected aggregated events\n", - " (for example, total-photon conditions with capped counts).\n", - "- **Orbit-based features**: grouping samples by integer partitions (orbits)\n", - " rather than raw mode labels.\n", - "\n", - "Both approaches reduce dependence on explicit vertex labels and provide\n", - "low-dimensional descriptors useful for graph comparison and classification.\n", - "\n", - "### 4) Workflow in this notebook\n", - "1. Load four benchmark graphs (`Mutag0` to `Mutag3`).\n", - "2. Load (or optionally regenerate) GBS sample datasets.\n", - "3. Convert samples to event/orbit descriptors.\n", - "4. Build 2D event feature vectors and visualize graph separation.\n", - "5. Train a linear SVM on these descriptors as a simple downstream classifier.\n", - "\n", - "### 5) Interpretation and limitations\n", - "- This is a **feature-based heuristic pipeline**, not a formal complete GI\n", - " decision procedure.\n", - "- Good separation in feature space suggests structural differences.\n", - "- Overlapping features may require richer events, more samples, or stronger\n", - " models.\n", - "- Results depend on sampling budget, photon cutoff, event design, and noise.\n", - "\n", - "Prerequisites\n", - "-------------\n", - "- `strawberryfields` (`data`, `plot`, `similarity`)\n", - "- `numpy`, `networkx`, `matplotlib`, `scikit-learn`, `plotly`\n", - "- Optional: `thewalrus` (only if regenerating GBS samples)\n" - ] - }, - { - "cell_type": "markdown", - "id": "a55c0161", - "metadata": {}, - "source": [ - "---\n", - "\n", - "## 1. Imports and Reproducibility Setup\n", - "Import required packages and set a deterministic seed for reproducible baseline\n", - "operations.\n" + "# 读四个图" ] }, { "cell_type": "code", - "execution_count": 30, - "id": "195285fb", + "execution_count": 19, + "id": "259a1626", "metadata": {}, "outputs": [], "source": [ - "import networkx as nx\n", - "import numpy as np\n", - "import plotly\n", - "from matplotlib import pyplot as plt\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.svm import LinearSVC\n", "from strawberryfields.apps import data, plot, similarity\n", + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", "\n", - "np.random.seed(42)\n" + "m0 = data.Mutag0()\n", + "m1 = data.Mutag1()\n", + "m2 = data.Mutag2()\n", + "m3 = data.Mutag3()" ] }, { - "cell_type": "markdown", - "id": "78cad066", + "cell_type": "code", + "execution_count": 20, + "id": "1c3003f9", "metadata": {}, + "outputs": [], "source": [ - "---\n", - "\n", - "## 2. Load Benchmark Graphs (`Mutag0`-`Mutag3`)\n", - "Load graph instances and inspect basic structural statistics.\n" + "m0_a = m0.adj\n", + "m1_a = m1.adj\n", + "m2_a = m2.adj\n", + "m3_a = m3.adj" ] }, { "cell_type": "code", - "execution_count": 31, - "id": "ca8d9dcc", + "execution_count": 21, + "id": "e3de6022", "metadata": {}, "outputs": [], "source": [ - "m0 = data.Mutag0()\n", - "m1 = data.Mutag1()\n", - "m2 = data.Mutag2()\n", - "m3 = data.Mutag3()\n", - "\n", - "m0_a = m0.adj\n", - "m1_a = m1.adj\n", - "m2_a = m2.adj\n", - "m3_a = m3.adj\n" + "import networkx as nx\n", + "import plotly" ] }, { "cell_type": "code", - "execution_count": 32, - "id": "3c3cfb23", + "execution_count": 22, + "id": "f635734c", "metadata": {}, "outputs": [ { @@ -362,6 +284,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "bar" @@ -373,6 +300,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "barpolar" @@ -517,63 +449,13 @@ "type": "heatmap" } ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], "histogram": [ { "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "histogram" @@ -709,11 +591,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -768,6 +649,17 @@ "type": "scattergl" } ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], "scattermapbox": [ { "marker": { @@ -1173,13 +1065,13 @@ } ], "source": [ - "plot.graph(nx.Graph(m0_a))\n" + "plot.graph(nx.Graph(m0_a))" ] }, { "cell_type": "code", - "execution_count": 33, - "id": "8eac193b", + "execution_count": 23, + "id": "b7ddf46f", "metadata": {}, "outputs": [ { @@ -1369,6 +1261,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "bar" @@ -1380,6 +1277,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "barpolar" @@ -1524,63 +1426,13 @@ "type": "heatmap" } ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], "histogram": [ { "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "histogram" @@ -1716,11 +1568,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -1775,6 +1626,17 @@ "type": "scattergl" } ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], "scattermapbox": [ { "marker": { @@ -2185,8 +2047,8 @@ }, { "cell_type": "code", - "execution_count": 34, - "id": "3d46dacd", + "execution_count": 24, + "id": "0fd75aa9", "metadata": {}, "outputs": [ { @@ -2376,6 +2238,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "bar" @@ -2387,6 +2254,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "barpolar" @@ -2531,63 +2403,13 @@ "type": "heatmap" } ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], "histogram": [ { "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "histogram" @@ -2723,11 +2545,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -2782,6 +2603,17 @@ "type": "scattergl" } ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], "scattermapbox": [ { "marker": { @@ -3192,8 +3024,8 @@ }, { "cell_type": "code", - "execution_count": 35, - "id": "fa99b13a", + "execution_count": 25, + "id": "70b3e604", "metadata": {}, "outputs": [ { @@ -3449,6 +3281,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "bar" @@ -3460,6 +3297,11 @@ "line": { "color": "#E5ECF6", "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "barpolar" @@ -3604,63 +3446,13 @@ "type": "heatmap" } ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], "histogram": [ { "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 } }, "type": "histogram" @@ -3796,11 +3588,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -3855,6 +3646,17 @@ "type": "scattergl" } ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], "scattermapbox": [ { "marker": { @@ -4265,23 +4067,20 @@ }, { "cell_type": "markdown", - "id": "f3e9397c", + "id": "277554cb", "metadata": {}, "source": [ - "---\n", - "\n", - "## 3. Load (or Regenerate) GBS Samples\n", - "By default we load pre-generated sample files (`samples0.npy` ... `samples3.npy`).\n", - "If you want to regenerate samples, run the commented generation code.\n" + "# 从样本构造特性向量" ] }, { "cell_type": "code", - "execution_count": 36, - "id": "c2141e03", + "execution_count": 26, + "id": "d6826a19", "metadata": {}, "outputs": [], "source": [ + "import thewalrus\n", "# samples0 = thewalrus.samples.hafnian_sample_graph(m0_a, n_mean=5.5,samples=20000,max_photons=20)\n", "# np.save('samples0.npy', samples0)\n", "# samples1 = thewalrus.samples.hafnian_sample_graph(m1_a, n_mean=5.5,samples=20000,max_photons=20)\n", @@ -4294,98 +4093,129 @@ "samples0 = np.load('samples0.npy')\n", "samples1 = np.load('samples1.npy')\n", "samples2 = np.load('samples2.npy')\n", - "samples3 = np.load('samples3.npy')\n" + "samples3 = np.load('samples3.npy')" ] }, { - "cell_type": "markdown", - "id": "27e2bda3", + "cell_type": "code", + "execution_count": 27, + "id": "d50c2433", "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0], dtype=int64)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "---\n", - "\n", - "## 4. Understand Core Mappings: Sample -> Orbit / Event\n", - "Use one concrete sample to illustrate orbit and event conversions.\n" + "samples0[0]" ] }, { "cell_type": "code", - "execution_count": 37, - "id": "20080cad", + "execution_count": 28, + "id": "c82c8705", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Example sample from graph 0:\n", - "[0 0 0 1 0 0 0 0 0 3 2 0 0 0 0 0 0]\n", - "\n", - "Orbit representation:\n", - "[3 2 1]\n", - "\n", - "All orbits with total photon number 5:\n", - "[[1, 1, 1, 1, 1], [2, 1, 1, 1], [3, 1, 1], [2, 2, 1], [4, 1], [3, 2], [5]]\n", - "\n", - "Event examples (total-photon count with cap=3):\n", - "5\n", - "None\n" + "[3 2 1]\n" ] } ], "source": [ - "example_sample = samples0[0]\n", - "print('Example sample from graph 0:')\n", - "print(example_sample)\n", - "\n", - "print('\\nOrbit representation:')\n", - "print(np.array(similarity.sample_to_orbit(example_sample)))\n", - "\n", - "print('\\nAll orbits with total photon number 5:')\n", - "print(list(similarity.orbits(5)))\n", - "\n", - "print('\\nEvent examples (total-photon count with cap=3):')\n", - "print(similarity.sample_to_event([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0], 3))\n", - "print(similarity.sample_to_event([0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3))\n" + "# 计算样本对应的轨道 \n", + "print(np.array(similarity.sample_to_orbit(samples0[0])))" ] }, { - "cell_type": "markdown", - "id": "ceac37ac", + "cell_type": "code", + "execution_count": 29, + "id": "313a4294", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 1, 1, 1, 1], [2, 1, 1, 1], [3, 1, 1], [2, 2, 1], [4, 1], [3, 2], [5]]\n" + ] + } + ], "source": [ - "---\n", - "\n", - "## 5. Build Event-Based Feature Vectors from Samples\n", - "Construct 2D event features for each graph and visualize their positions in\n", - "feature space.\n" + "# 总光子数为5的所有轨道\n", + "print(list(similarity.orbits(5)))" ] }, { "cell_type": "code", - "execution_count": 38, - "id": "cb6a6adb", + "execution_count": 30, + "id": "3d7b0a08", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n" + ] + } + ], + "source": [ + "# 计算样本的event,这里直接定义为总光子数\n", + "print(similarity.sample_to_event([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "8d87a362", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "print(similarity.sample_to_event([0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "debf3fb8", "metadata": {}, "outputs": [], "source": [ + "# 从样本构造event刻画的特性向量\n", "event = [8, 10]\n", - "max_count = 2\n", - "\n", "Ve0 = similarity.feature_vector_events_sampling(samples0, event, 2)\n", "Ve1 = similarity.feature_vector_events_sampling(samples1, event, 2)\n", "Ve2 = similarity.feature_vector_events_sampling(samples2, event, 2)\n", - "Ve3 = similarity.feature_vector_events_sampling(samples3, event, 2)\n" + "Ve3 = similarity.feature_vector_events_sampling(samples3, event, 2)" ] }, { "cell_type": "code", - "execution_count": 39, - "id": "e64a8650", + "execution_count": 33, + "id": "b746c422", "metadata": {}, "outputs": [ { "data": { - "image/png": "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rFjRSJAggZE5c2Zj5MiRbj0vlqggIiKKfu5GYokKP/wjbihdurRMmjRJ860oaszCTkRERNHv+9vtnLCpU6fKZ599Jr///rvmh7E2FhEREVEk1QlD4PXGG2/YLUeDGvLDUPuLiIiIiDwchGHexXjx4ulk3S+bmE9EREQUW7kdhGGkIKYuQrkGIiIiIoqknDCUk7hw4UIEH46IiIiIItQS1rlzZ63X1aNHDylSpIh2TVoVLVqUR5aIiIgoHG6XqIgTJ2TjGfLCmJhvjyUqiIiIop97kViiwu2WsDNnznhnT4iIiIhiEbeDsICAAO/sCREREVEs4nYQBqdOndJ5Ho8eParXMZk38sRy5crl6f0jIiIiipHcHh3566+/atC1a9cuTcLHZefOnVKoUCFZu3atd/aSiIiIKLYn5pcoUUJq1aolI0eOtFveu3dv+e2332Tfvn2e3sdoiYn5RERE0c+9qDx3JLog27RpE2J569at5ciRI57aLyIiIqIYze0gLG3atHLgwIEQy7EsXbp0ntovIiIiohjN7cT8tm3bSrt27eT06dNSvnx5XbZ161YZNWqUdO/e3Rv7SERERBTjuJ0ThtUxMnLcuHFy+fJlXZYpUyatoN+lSxdO6P0/zAkjIiKKfu5FYk6Y20GY1f379/X/ZMmSeXKfYgQGYURERNHPvaheMf/58+eSJ08eu+DrxIkTOo9k9uzZPb2PRERERDGO24n5LVu2lG3btoVYjlphuI2IiIiIvBCE7d+/XypUqBBi+WuvveZ01CQREREReSAI8/Pzs+WCWaHvNDg42N3NEREREcVKbgdhlStXlhEjRtgFXPgbyypWrOjp/SMiIiKKkdxOzEc9MARi+fLlk0qVKumyzZs362iCDRs2eGMfiYiIiGIct1vCMHn3n3/+KY0aNZLr169r12SLFi3k2LFjUrhwYe/sJREREVEM81J1wih0rBNGREQU/dyLyhN4ExEREdHLYxBGRERE5AMMwoiIiIiiehCG9LHz58/LkydPvLdHRERERLGA20FY7ty55cKFC97bIyIiIqJYwK0gLE6cODpx961bt7y3R0RERESxgNs5YSNHjpQePXrI4cOHvbNHRERERLGA23XCUqZMKY8ePZLnz59L/PjxJVGiRHa3375929P7GC2xThgREVH0cy8S64S5PW3RhAkTvLMnRERERLGI20FY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", + "image/png": "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rFjRSJAggZE5c2Zj5MiRbj0vlqggIiKKfu5GYokKP/wjbihdurRMmjRJ860oaszCTkRERNHv+9vtnLCpU6fKZ599Jr///rvmh7E2FhEREVEk1QlD4PXGG2/YLUeDGvLDUPuLiIiIiDwchGHexXjx4ulk3S+bmE9EREQUW7kdhGGkIKYuQrkGIiIiIoqknDCUk7hw4UIEH46IiIiIItQS1rlzZ63X1aNHDylSpIh2TVoVLVqUR5aIiIgoHG6XqIgTJ2TjGfLCmJhvjyUqiIiIop97kViiwu2WsDNnznhnT4iIiIhiEbeDsICAAO/sCREREVEs4nYQBqdOndJ5Ho8eParXMZk38sRy5crl6f0jIiIiipHcHh3566+/atC1a9cuTcLHZefOnVKoUCFZu3atd/aSiIiIKLYn5pcoUUJq1aolI0eOtFveu3dv+e2332Tfvn2e3sdoiYn5RERE0c+9qDx3JLog27RpE2J569at5ciRI57aLyIiIqIYze0gLG3atHLgwIEQy7EsXbp0ntovIiIiohjN7cT8tm3bSrt27eT06dNSvnx5XbZ161YZNWqUdO/e3Rv7SERERBTjuJ0ThtUxMnLcuHFy+fJlXZYpUyatoN+lSxdO6P0/zAkjIiKKfu5FYk6Y20GY1f379/X/ZMmSeXKfYgQGYURERNHPvaheMf/58+eSJ08eu+DrxIkTOo9k9uzZPb2PRERERDGO24n5LVu2lG3btoVYjlphuI2IiIiIvBCE7d+/XypUqBBi+WuvveZ01CQREREReSAI8/Pzs+WCWaHvNDg42N3NEREREcVKbgdhlStXlhEjRtgFXPgbyypWrOjp/SMiIiKKkdxOzEc9MARi+fLlk0qVKumyzZs362iCDRs2eGMfiYiIiGIct1vCMHn3n3/+KY0aNZLr169r12SLFi3k2LFjUrhwYe/sJREREVEM81J1wih0rBNGREQU/dyLyhN4ExEREdHLYxBGRERE5AMMwoiIiIiiehCG9LHz58/LkydPvLdHRERERLGA20FY7ty55cKFC97bIyIiIqJYwK0gLE6cODpx961bt7y3R0RERESxgNs5YSNHjpQePXrI4cOHvbNHRERERLGA23XCUqZMKY8ePZLnz59L/PjxJVGiRHa3375929P7GC2xThgREVH0cy8S64S5PW3RhAkTvLMnRERERLGI20FY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", "text/plain": [ "
" ] @@ -4403,79 +4233,94 @@ "plt.xlabel('Graph index')\n", "plt.ylabel('Feature vector component for event [8,10]')\n", "plt.title('Feature vector component for event [8,10] vs Graph index')\n", - "plt.show()\n" + "plt.show()" ] }, { - "cell_type": "markdown", - "id": "d0881968", + "cell_type": "code", + "execution_count": 34, + "id": "e2b6e1b5", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.2034, 0.0, 0.14085, 0.05215]\n" + ] + } + ], "source": [ - "---\n", - "\n", - "## 6. Orbit Features and Direct Matrix-Based Event Features\n", - "Compare sample-based orbit features with event features computed directly from\n", - "adjacency-matrix models.\n" + "# 从样本构造轨道刻画的特性向量\n", + "print(similarity.feature_vector_orbits_sampling(samples0, [[1, 1], [2], [1, 1, 1, 1], [2, 1, 1]]))" ] }, { "cell_type": "code", - "execution_count": 40, - "id": "1c611ee2", + "execution_count": 35, + "id": "e8ce45bc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Graph 0 orbit feature vector (sample-based):\n", - "[0.2034, 0.0, 0.14085, 0.05215]\n", - "\n", - "Graph 0 event feature from graph model (analytical/sampling backend):\n", - "[0.20442688 0.20820147]\n", - "\n", - "Graph 0 event feature from generated samples (samples=1000):\n", - "[0.18272535 0.2447912 ]\n" + "[0.20442688 0.20820147]\n" ] } ], "source": [ - "orbit_patterns = [[1, 1], [2], [1, 1, 1, 1], [2, 1, 1]]\n", - "orbit_features_g0 = similarity.feature_vector_orbits_sampling(samples0, orbit_patterns)\n", - "\n", - "print('Graph 0 orbit feature vector (sample-based):')\n", - "print(orbit_features_g0)\n", - "\n", - "print('\\nGraph 0 event feature from graph model (analytical/sampling backend):')\n", - "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2, n_mean=5.5)))\n", - "\n", - "print('\\nGraph 0 event feature from generated samples (samples=1000):')\n", + "# 从图的邻接矩阵直接计算event刻画的特性向量\n", + "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2,n_mean=5.5)))" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "eca549fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.21071031 0.15736577]\n" + ] + } + ], + "source": [ + "# 从图的邻接矩阵生成样本计算event刻画的特性向量\n", "print(np.array(similarity.feature_vector_events(nx.Graph(m0_a), [2, 4], 2, samples=1000,n_mean=5.5)))" ] }, { "cell_type": "markdown", - "id": "b094e24e", + "id": "251b274c", "metadata": {}, "source": [ - "---\n", - "\n", - "## 7. Linear SVM Classification Demo\n", - "Use event features as inputs to a linear SVM and visualize the separating\n", - "hyperplane in scaled feature space.\n" + "# 用支持向量机对图进行分类" ] }, { "cell_type": "code", - "execution_count": 41, - "id": "02c7111b", + "execution_count": 37, + "id": "7d018638", + "metadata": {}, + "outputs": [], + "source": [ + "classes = [1, 0, 0, 1]" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "cb97463f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Scaled feature matrix:\n", "[[0.08065 0.0349 ]\n", " [0.06375 0.02195]\n", " [0.0635 0.02435]\n", @@ -4484,8 +4329,6 @@ } ], "source": [ - "classes = [1, 0, 0, 1]\n", - "\n", "events = [8, 10]\n", "max_count = 2\n", "\n", @@ -4494,22 +4337,23 @@ "f3 = similarity.feature_vector_events_sampling(samples2, events, max_count)\n", "f4 = similarity.feature_vector_events_sampling(samples3, events, max_count)\n", "\n", + "import numpy as np\n", + "\n", "R = np.array([f1, f2, f3, f4])\n", "\n", - "print('Scaled feature matrix:')\n", - "print(R)\n" + "print(R)" ] }, { "cell_type": "code", - "execution_count": 42, - "id": "648f8da3", + "execution_count": 39, + "id": "c1717edf", "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
LinearSVC()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.