{ "cells": [ { "cell_type": "markdown", "id": "8ca9e27f", "metadata": {}, "source": [ "# Analysis of rates" ] }, { "cell_type": "markdown", "id": "04992dc1", "metadata": {}, "source": [ "By combining elements from graph theory, convex optimization, and linear algebra, we can have powerful results on the stability of a stochastic system and its set of feasible rates." ] }, { "cell_type": "markdown", "id": "6e744269", "metadata": {}, "source": [ "`stochastic matching` provides the following information (cf https://hal.archives-ouvertes.fr/hal-03502084 for details):\n", "\n", "- Graph type: injective-only, surjective-only, bijective, ``nonjective'';\n", "- Kernel structure (for node and edge kernels);\n", "- For given arrival rates: \n", " - stability of the matching model;\n", " - Maximin and Moore-Penrose solutions of the conservation equation;\n", " - if relevant, a complete description of the vertices of $\\Lambda_{\\geqslant 0}$.\n", "\n" ] }, { "cell_type": "markdown", "id": "0c70988e", "metadata": {}, "source": [ "The purpose of this notebook is to give a tour of these analysis on some examples." ] }, { "cell_type": "code", "execution_count": 1, "id": "d0cb1566", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.535453Z", "start_time": "2022-01-24T14:38:44.327612Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:32.329932Z", "iopub.status.busy": "2025-09-27T14:18:32.329932Z", "iopub.status.idle": "2025-09-27T14:18:39.072404Z", "shell.execute_reply": "2025-09-27T14:18:39.072086Z", "shell.execute_reply.started": "2025-09-27T14:18:32.329932Z" } }, "outputs": [], "source": [ "import stochastic_matching as sm\n", "from stochastic_matching.display import VIS_OPTIONS\n", "\n", "VIS_OPTIONS[\"height\"] = \"200px\"" ] }, { "cell_type": "code", "execution_count": 2, "id": "48f18fb6", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.550922Z", "start_time": "2022-01-24T14:38:45.537955Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.073095Z", "iopub.status.busy": "2025-09-27T14:18:39.073095Z", "iopub.status.idle": "2025-09-27T14:18:39.158951Z", "shell.execute_reply": "2025-09-27T14:18:39.158951Z", "shell.execute_reply.started": "2025-09-27T14:18:39.073095Z" } }, "outputs": [ { "data": { "text/plain": [ "{'interaction': {'navigationButtons': False},\n", " 'width': '100%',\n", " 'height': '200px'}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "VIS_OPTIONS" ] }, { "cell_type": "markdown", "id": "25015814", "metadata": {}, "source": [ "## Tadpole" ] }, { "cell_type": "markdown", "id": "8d70692a", "metadata": {}, "source": [ "### Bijective tadpole" ] }, { "cell_type": "markdown", "id": "2b5a160a", "metadata": {}, "source": [ "Consider a tadpole $T_{5, 3}$ with uniform arrival rates. Side note: if no rate is specified, degree-proportional rates are assumed, which ensure that the model is stabilizable if the graph is surjective." ] }, { "cell_type": "code", "execution_count": 3, "id": "99bf6801", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.581742Z", "start_time": "2022-01-24T14:38:45.553014Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.159958Z", "iopub.status.busy": "2025-09-27T14:18:39.159958Z", "iopub.status.idle": "2025-09-27T14:18:39.167816Z", "shell.execute_reply": "2025-09-27T14:18:39.167816Z", "shell.execute_reply.started": "2025-09-27T14:18:39.159958Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole = sm.Tadpole(m=5, n=3, rates=\"uniform\")\n", "tadpole.show_graph()" ] }, { "cell_type": "markdown", "id": "8fd084db", "metadata": {}, "source": [ "Its kernels are trivial: the graph is bijective." ] }, { "cell_type": "code", "execution_count": 4, "id": "bc20341e", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.596885Z", "start_time": "2022-01-24T14:38:45.584699Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.169824Z", "iopub.status.busy": "2025-09-27T14:18:39.168826Z", "iopub.status.idle": "2025-09-27T14:18:39.173825Z", "shell.execute_reply": "2025-09-27T14:18:39.173825Z", "shell.execute_reply.started": "2025-09-27T14:18:39.169824Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 8 nodes and 8 edges.\n", "Node dimension is 0.\n", "Edge dimension is 0\n", "Type: Bijective\n", "Node kernel:\n", "[]\n", "Edge kernel:\n", "[]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.kernel" ] }, { "cell_type": "markdown", "id": "3fd1ebe5", "metadata": {}, "source": [ "Let see the unique solution of the conservation equation:" ] }, { "cell_type": "code", "execution_count": 5, "id": "609e1c81", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.612931Z", "start_time": "2022-01-24T14:38:45.598748Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.174833Z", "iopub.status.busy": "2025-09-27T14:18:39.174833Z", "iopub.status.idle": "2025-09-27T14:18:39.181679Z", "shell.execute_reply": "2025-09-27T14:18:39.181679Z", "shell.execute_reply.started": "2025-09-27T14:18:39.174833Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole.show_flow()" ] }, { "cell_type": "markdown", "id": "dbedc900", "metadata": {}, "source": [ "This does not sound very stable..." ] }, { "cell_type": "code", "execution_count": 6, "id": "8eb6628c", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.628122Z", "start_time": "2022-01-24T14:38:45.613950Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.183691Z", "iopub.status.busy": "2025-09-27T14:18:39.183691Z", "iopub.status.idle": "2025-09-27T14:18:39.188687Z", "shell.execute_reply": "2025-09-27T14:18:39.188687Z", "shell.execute_reply.started": "2025-09-27T14:18:39.183691Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.stabilizable" ] }, { "cell_type": "markdown", "id": "41afe558", "metadata": {}, "source": [ "Let's change the arrival rates to have something nicer." ] }, { "cell_type": "code", "execution_count": 7, "id": "001f2e0c", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.643186Z", "start_time": "2022-01-24T14:38:45.630211Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.189766Z", "iopub.status.busy": "2025-09-27T14:18:39.189766Z", "iopub.status.idle": "2025-09-27T14:18:39.198885Z", "shell.execute_reply": "2025-09-27T14:18:39.197766Z", "shell.execute_reply.started": "2025-09-27T14:18:39.189766Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole.rates = [1, 1, 1, 1, 2, 2, 2, 1]\n", "tadpole.show_flow()" ] }, { "cell_type": "markdown", "id": "fa26b9fc", "metadata": {}, "source": [ "Sounds better..." ] }, { "cell_type": "code", "execution_count": 8, "id": "56f5207b", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.659344Z", "start_time": "2022-01-24T14:38:45.645186Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.198885Z", "iopub.status.busy": "2025-09-27T14:18:39.198885Z", "iopub.status.idle": "2025-09-27T14:18:39.203267Z", "shell.execute_reply": "2025-09-27T14:18:39.203267Z", "shell.execute_reply.started": "2025-09-27T14:18:39.198885Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.stabilizable" ] }, { "cell_type": "markdown", "id": "755c0be7", "metadata": {}, "source": [ "### Nonjective tadpole" ] }, { "cell_type": "markdown", "id": "72e8e82b", "metadata": {}, "source": [ "We now consider the bipartite tadpole $T_{4, 1}$, again with uniform arrival rates." ] }, { "cell_type": "code", "execution_count": 9, "id": "01f441fb", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.675286Z", "start_time": "2022-01-24T14:38:45.661266Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.204274Z", "iopub.status.busy": "2025-09-27T14:18:39.204274Z", "iopub.status.idle": "2025-09-27T14:18:39.213413Z", "shell.execute_reply": "2025-09-27T14:18:39.212405Z", "shell.execute_reply.started": "2025-09-27T14:18:39.204274Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole = sm.Tadpole(m=4, n=1, rates=\"uniform\")\n", "tadpole.show_graph()" ] }, { "cell_type": "markdown", "id": "71c788a5", "metadata": {}, "source": [ "Look at the kernel." ] }, { "cell_type": "code", "execution_count": 10, "id": "96fc31d4", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.690792Z", "start_time": "2022-01-24T14:38:45.677526Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.214412Z", "iopub.status.busy": "2025-09-27T14:18:39.214412Z", "iopub.status.idle": "2025-09-27T14:18:39.220267Z", "shell.execute_reply": "2025-09-27T14:18:39.219260Z", "shell.execute_reply.started": "2025-09-27T14:18:39.214412Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 5 nodes and 5 edges.\n", "Node dimension is 1.\n", "Edge dimension is 1\n", "Type: Nonjective\n", "Node kernel:\n", "[[ 1]\n", " [-1]\n", " [ 1]\n", " [-1]\n", " [ 1]]\n", "Edge kernel:\n", "[[ 1 -1 -1 1 0]]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.kernel" ] }, { "cell_type": "markdown", "id": "1b61720e", "metadata": {}, "source": [ "The node kernel shows the bipartite repartition of the nodes (*positive* and *negative* nodes)." ] }, { "cell_type": "markdown", "id": "924f1d58", "metadata": {}, "source": [ "The edge kernel shows how the rate flow can *slide* between edges. It can be displayed:" ] }, { "cell_type": "code", "execution_count": 11, "id": "9279f726", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.705814Z", "start_time": "2022-01-24T14:38:45.692304Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.220267Z", "iopub.status.busy": "2025-09-27T14:18:39.220267Z", "iopub.status.idle": "2025-09-27T14:18:39.225553Z", "shell.execute_reply": "2025-09-27T14:18:39.225553Z", "shell.execute_reply.started": "2025-09-27T14:18:39.220267Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole.show_kernel()" ] }, { "cell_type": "markdown", "id": "5a51826a", "metadata": {}, "source": [ "Note the black edge above: it indicates that the specific edge is unaffected by the kernel." ] }, { "cell_type": "markdown", "id": "b1dd2718", "metadata": {}, "source": [ "Let see the (attempt) solution of the conservation equation:" ] }, { "cell_type": "code", "execution_count": 12, "id": "cc8c0b45", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.721073Z", "start_time": "2022-01-24T14:38:45.709014Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.227562Z", "iopub.status.busy": "2025-09-27T14:18:39.226562Z", "iopub.status.idle": "2025-09-27T14:18:39.232560Z", "shell.execute_reply": "2025-09-27T14:18:39.232560Z", "shell.execute_reply.started": "2025-09-27T14:18:39.227562Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole.show_flow()" ] }, { "cell_type": "markdown", "id": "c8ea8e57", "metadata": {}, "source": [ "The red nodes indicate that the conservation equation is not satisfied. This is not surprising, as the total arrival rates on positive nodes, 3, is distinct from the total arrival rates on negative nodes, 2.\n", "\n", "We can change the rates in order to equalize the arrival rates." ] }, { "cell_type": "code", "execution_count": 13, "id": "85a2746f", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.736629Z", "start_time": "2022-01-24T14:38:45.722607Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.233951Z", "iopub.status.busy": "2025-09-27T14:18:39.233951Z", "iopub.status.idle": "2025-09-27T14:18:39.238227Z", "shell.execute_reply": "2025-09-27T14:18:39.238227Z", "shell.execute_reply.started": "2025-09-27T14:18:39.233951Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tadpole.rates = [1, 1, 1, 2, 1]\n", "tadpole.show_flow()" ] }, { "cell_type": "markdown", "id": "60b28965", "metadata": {}, "source": [ "Note that the respect of the conservation law is not sufficient for stability: the fact that the graph is not surjective forbids stability." ] }, { "cell_type": "code", "execution_count": 14, "id": "95c24a1b", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.752883Z", "start_time": "2022-01-24T14:38:45.738605Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.239233Z", "iopub.status.busy": "2025-09-27T14:18:39.239233Z", "iopub.status.idle": "2025-09-27T14:18:39.247133Z", "shell.execute_reply": "2025-09-27T14:18:39.247133Z", "shell.execute_reply.started": "2025-09-27T14:18:39.239233Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.stabilizable" ] }, { "cell_type": "markdown", "id": "18820273", "metadata": {}, "source": [ "This does not forbid considering the vertices of the positive solutions." ] }, { "cell_type": "code", "execution_count": 15, "id": "8fa449e2", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.767990Z", "start_time": "2022-01-24T14:38:45.755578Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.248138Z", "iopub.status.busy": "2025-09-27T14:18:39.248138Z", "iopub.status.idle": "2025-09-27T14:18:39.254578Z", "shell.execute_reply": "2025-09-27T14:18:39.253570Z", "shell.execute_reply.started": "2025-09-27T14:18:39.248138Z" } }, "outputs": [ { "data": { "text/plain": [ "[{'kernel_coordinates': array([-0.5]),\n", " 'edge_coordinates': array([0., 1., 1., 0., 1.]),\n", " 'null_edges': [0, 3],\n", " 'bijective': False},\n", " {'kernel_coordinates': array([0.5]),\n", " 'edge_coordinates': array([1., 0., 0., 1., 1.]),\n", " 'null_edges': [1, 2],\n", " 'bijective': False}]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tadpole.vertices" ] }, { "cell_type": "code", "execution_count": 16, "id": "b2644dad", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.783285Z", "start_time": "2022-01-24T14:38:45.769039Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.255578Z", "iopub.status.busy": "2025-09-27T14:18:39.254578Z", "iopub.status.idle": "2025-09-27T14:18:39.261577Z", "shell.execute_reply": "2025-09-27T14:18:39.261577Z", "shell.execute_reply.started": "2025-09-27T14:18:39.255578Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in range(len(tadpole.vertices)):\n", " tadpole.show_vertex(i, disp_rates=False)" ] }, { "cell_type": "markdown", "id": "3af59ecd", "metadata": {}, "source": [ "## The diamond graph" ] }, { "cell_type": "markdown", "id": "aad09999", "metadata": {}, "source": [ "Consider the following diamond:" ] }, { "cell_type": "code", "execution_count": 17, "id": "7272abee", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.798452Z", "start_time": "2022-01-24T14:38:45.785278Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.262819Z", "iopub.status.busy": "2025-09-27T14:18:39.262819Z", "iopub.status.idle": "2025-09-27T14:18:39.268713Z", "shell.execute_reply": "2025-09-27T14:18:39.268713Z", "shell.execute_reply.started": "2025-09-27T14:18:39.262819Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond = sm.CycleChain(rates=\"uniform\")\n", "diamond.show_graph()" ] }, { "cell_type": "markdown", "id": "07965089", "metadata": {}, "source": [ "The graph structure is as follows:" ] }, { "cell_type": "code", "execution_count": 18, "id": "fee5b584", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.814466Z", "start_time": "2022-01-24T14:38:45.800254Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.270720Z", "iopub.status.busy": "2025-09-27T14:18:39.269720Z", "iopub.status.idle": "2025-09-27T14:18:39.276077Z", "shell.execute_reply": "2025-09-27T14:18:39.275069Z", "shell.execute_reply.started": "2025-09-27T14:18:39.270720Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 4 nodes and 5 edges.\n", "Node dimension is 0.\n", "Edge dimension is 1\n", "Type: Surjective-only\n", "Node kernel:\n", "[]\n", "Edge kernel:\n", "[[ 1 -1 0 -1 1]]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond.kernel" ] }, { "cell_type": "markdown", "id": "c5eb3087", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T13:28:09.622625Z", "start_time": "2022-01-24T13:28:09.606990Z" } }, "source": [ "We can look at the kernel structure." ] }, { "cell_type": "code", "execution_count": 19, "id": "27457740", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.828987Z", "start_time": "2022-01-24T14:38:45.815989Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.277077Z", "iopub.status.busy": "2025-09-27T14:18:39.276077Z", "iopub.status.idle": "2025-09-27T14:18:39.282588Z", "shell.execute_reply": "2025-09-27T14:18:39.282588Z", "shell.execute_reply.started": "2025-09-27T14:18:39.277077Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_kernel(disp_flow=True)" ] }, { "cell_type": "markdown", "id": "cf11e536", "metadata": {}, "source": [ "We observe a null edge. As it is black (outside the edge kernel), it will remain null in all solutions of the conservation equation. In other words, the model is not stabilizable." ] }, { "cell_type": "code", "execution_count": 20, "id": "b1bad3e9", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.844878Z", "start_time": "2022-01-24T14:38:45.830995Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.283677Z", "iopub.status.busy": "2025-09-27T14:18:39.283677Z", "iopub.status.idle": "2025-09-27T14:18:39.290087Z", "shell.execute_reply": "2025-09-27T14:18:39.290087Z", "shell.execute_reply.started": "2025-09-27T14:18:39.283677Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond.stabilizable" ] }, { "cell_type": "markdown", "id": "522c07fb", "metadata": {}, "source": [ "Let make it stabilizable." ] }, { "cell_type": "code", "execution_count": 21, "id": "8a4cbdab", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.860356Z", "start_time": "2022-01-24T14:38:45.846164Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.295096Z", "iopub.status.busy": "2025-09-27T14:18:39.294093Z", "iopub.status.idle": "2025-09-27T14:18:39.298094Z", "shell.execute_reply": "2025-09-27T14:18:39.298094Z", "shell.execute_reply.started": "2025-09-27T14:18:39.295096Z" } }, "outputs": [], "source": [ "diamond.rates = [2, 3, 2, 1]" ] }, { "cell_type": "code", "execution_count": 22, "id": "dfa70ec9", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.875919Z", "start_time": "2022-01-24T14:38:45.861744Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.299243Z", "iopub.status.busy": "2025-09-27T14:18:39.299243Z", "iopub.status.idle": "2025-09-27T14:18:39.306481Z", "shell.execute_reply": "2025-09-27T14:18:39.305244Z", "shell.execute_reply.started": "2025-09-27T14:18:39.299243Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_kernel(disp_flow=True)" ] }, { "cell_type": "markdown", "id": "1ab1069f", "metadata": {}, "source": [ "Better! Note that the represented base flow is the Moore-Penrose inverse. We can use the maximin flow if we prefer." ] }, { "cell_type": "code", "execution_count": 23, "id": "e98812b6", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.891711Z", "start_time": "2022-01-24T14:38:45.877708Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.307481Z", "iopub.status.busy": "2025-09-27T14:18:39.306481Z", "iopub.status.idle": "2025-09-27T14:18:39.314096Z", "shell.execute_reply": "2025-09-27T14:18:39.314096Z", "shell.execute_reply.started": "2025-09-27T14:18:39.307481Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_kernel(disp_flow=True, flow=diamond.maximin)" ] }, { "cell_type": "markdown", "id": "e55493e7", "metadata": {}, "source": [ "Another feature: looking the incompressible flow, which is the minimal rate achieved in any positive solution." ] }, { "cell_type": "code", "execution_count": 24, "id": "07bb1397", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.907485Z", "start_time": "2022-01-24T14:38:45.893247Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.315107Z", "iopub.status.busy": "2025-09-27T14:18:39.315107Z", "iopub.status.idle": "2025-09-27T14:18:39.328805Z", "shell.execute_reply": "2025-09-27T14:18:39.328805Z", "shell.execute_reply.started": "2025-09-27T14:18:39.315107Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_flow(flow=diamond.incompressible_flow(), check_flow=False, disp_zero=False)" ] }, { "cell_type": "markdown", "id": "55d3814a", "metadata": {}, "source": [ "To finish, let have a look at the vertices." ] }, { "cell_type": "code", "execution_count": 25, "id": "d15e9f27", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.923144Z", "start_time": "2022-01-24T14:38:45.909585Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.329812Z", "iopub.status.busy": "2025-09-27T14:18:39.329812Z", "iopub.status.idle": "2025-09-27T14:18:39.335736Z", "shell.execute_reply": "2025-09-27T14:18:39.335736Z", "shell.execute_reply.started": "2025-09-27T14:18:39.329812Z" } }, "outputs": [ { "data": { "text/plain": [ "[{'kernel_coordinates': array([-0.25]),\n", " 'edge_coordinates': array([1., 1., 1., 1., 0.]),\n", " 'null_edges': [4],\n", " 'bijective': True},\n", " {'kernel_coordinates': array([0.75]),\n", " 'edge_coordinates': array([2., 0., 1., 0., 1.]),\n", " 'null_edges': [1, 3],\n", " 'bijective': False}]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond.vertices" ] }, { "cell_type": "code", "execution_count": 26, "id": "22d7c2ef", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.939492Z", "start_time": "2022-01-24T14:38:45.925146Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.336742Z", "iopub.status.busy": "2025-09-27T14:18:39.336742Z", "iopub.status.idle": "2025-09-27T14:18:39.343012Z", "shell.execute_reply": "2025-09-27T14:18:39.343012Z", "shell.execute_reply.started": "2025-09-27T14:18:39.336742Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in range(len(tadpole.vertices)):\n", " diamond.show_vertex(i)" ] }, { "cell_type": "markdown", "id": "4982ef9b", "metadata": {}, "source": [ "## Not connected simple graphs" ] }, { "cell_type": "markdown", "id": "1fc786a9", "metadata": {}, "source": [ "The package deals with simple graphs even if they are not connected. Consider a graph made of a square, a complete graph of size 4, a diamond, a paw and a three-edged star:" ] }, { "cell_type": "code", "execution_count": 27, "id": "e5bb9026", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:45.994338Z", "start_time": "2022-01-24T14:38:45.941608Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.344020Z", "iopub.status.busy": "2025-09-27T14:18:39.344020Z", "iopub.status.idle": "2025-09-27T14:18:39.354243Z", "shell.execute_reply": "2025-09-27T14:18:39.354243Z", "shell.execute_reply.started": "2025-09-27T14:18:39.344020Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "VIS_OPTIONS[\"height\"] = 600\n", "sample = sm.concatenate(\n", " [sm.Cycle(4), sm.Complete(4), sm.CycleChain(), sm.Tadpole(), sm.Star()], 0\n", ")\n", "sample.show_graph()" ] }, { "cell_type": "markdown", "id": "df760bd0", "metadata": {}, "source": [ "The kernel will display global information:" ] }, { "cell_type": "code", "execution_count": 28, "id": "5d769fcf", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.021584Z", "start_time": "2022-01-24T14:38:45.998850Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.355254Z", "iopub.status.busy": "2025-09-27T14:18:39.355254Z", "iopub.status.idle": "2025-09-27T14:18:39.360706Z", "shell.execute_reply": "2025-09-27T14:18:39.360706Z", "shell.execute_reply.started": "2025-09-27T14:18:39.355254Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 20 nodes and 22 edges.\n", "Node dimension is 2.\n", "Edge dimension is 4\n", "Type: Nonjective\n", "Node kernel:\n", "[[ 0 -1]\n", " [ 0 1]\n", " [ 0 -1]\n", " [ 0 1]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [ 0 0]\n", " [-1 0]\n", " [ 1 0]\n", " [ 1 0]\n", " [ 1 0]]\n", "Edge kernel:\n", "[[ 1 -1 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 1 -1 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 0 -1 1 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 0 0 0 0 0 0 1 -1 0 -1 1 0 0 0 0 0 0 0]]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sample.kernel" ] }, { "cell_type": "markdown", "id": "4333e760", "metadata": {}, "source": [ "- The two node vectors point to the bipartite connected components (the square and the star).\n", "- The four edge vectors point to the even cycles from the square, complete graph, and diamond." ] }, { "cell_type": "markdown", "id": "75d7c005", "metadata": {}, "source": [ "If we want further information, we can look at the `connected_components` attribute." ] }, { "cell_type": "code", "execution_count": 29, "id": "751ce9b6", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.032718Z", "start_time": "2022-01-24T14:38:46.023699Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.362720Z", "iopub.status.busy": "2025-09-27T14:18:39.361712Z", "iopub.status.idle": "2025-09-27T14:18:39.367838Z", "shell.execute_reply": "2025-09-27T14:18:39.367838Z", "shell.execute_reply.started": "2025-09-27T14:18:39.362720Z" } }, "outputs": [ { "data": { "text/plain": [ "[{'nodes': {0, 1, 2, 3},\n", " 'edges': {0, 1, 2, 3},\n", " 'spanner': {0, 1, 2},\n", " 'pivot': False,\n", " 'seeds': {3},\n", " 'type': 'Bipartite with cycle(s)'},\n", " {'nodes': {4, 5, 6, 7},\n", " 'edges': {4, 5, 6, 7, 8, 9},\n", " 'spanner': {4, 5, 6},\n", " 'pivot': 8,\n", " 'seeds': {7, 9},\n", " 'type': 'Non-bipartite polycyclic'},\n", " {'nodes': {8, 9, 10, 11},\n", " 'edges': {10, 11, 12, 13, 14},\n", " 'spanner': {10, 11, 13},\n", " 'pivot': 12,\n", " 'seeds': {14},\n", " 'type': 'Non-bipartite polycyclic'},\n", " {'nodes': {12, 13, 14, 15},\n", " 'edges': {15, 16, 17, 18},\n", " 'spanner': {15, 16, 18},\n", " 'pivot': 17,\n", " 'seeds': set(),\n", " 'type': 'Non-bipartite monocyclic'},\n", " {'nodes': {16, 17, 18, 19},\n", " 'edges': {19, 20, 21},\n", " 'spanner': {19, 20, 21},\n", " 'pivot': False,\n", " 'seeds': set(),\n", " 'type': 'Tree'}]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sample.connected_components" ] }, { "cell_type": "markdown", "id": "baa80cd7", "metadata": {}, "source": [ "Connected components give the following information for each connected component:\n", "- The nodes and edges that belong to that component (or more accurately their index);\n", "- A spanner of the component, e.g. a set of edges that form a spanning tree for the component;\n", "- If the component is surjective, a *pivot*, e.g. an edge that makes the spanner non-bipartite if we add it;\n", "- *Seeds*, which are a set of edges that can be used to build a edge kernel basis made of cycles and kayak paddles.\n", "- The type of the component. For example, for a connected component, injective-only is a synonym for tree." ] }, { "cell_type": "markdown", "id": "54325ce6", "metadata": {}, "source": [ "All operations that were previously performed can be done on graphs that are not connected." ] }, { "cell_type": "code", "execution_count": 30, "id": "2cfe5990", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.048224Z", "start_time": "2022-01-24T14:38:46.034208Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.368845Z", "iopub.status.busy": "2025-09-27T14:18:39.368845Z", "iopub.status.idle": "2025-09-27T14:18:39.375845Z", "shell.execute_reply": "2025-09-27T14:18:39.375845Z", "shell.execute_reply.started": "2025-09-27T14:18:39.368845Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sample.show_kernel(disp_flow=True)" ] }, { "cell_type": "markdown", "id": "e969fabb", "metadata": {}, "source": [ "## Hypergraphs" ] }, { "cell_type": "markdown", "id": "54f5202c", "metadata": {}, "source": [ "### Candy" ] }, { "cell_type": "markdown", "id": "2e9a8c40", "metadata": {}, "source": [ "The candy is a simple example of true hypergraph." ] }, { "cell_type": "code", "execution_count": 31, "id": "febabc89", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.063816Z", "start_time": "2022-01-24T14:38:46.051449Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.377263Z", "iopub.status.busy": "2025-09-27T14:18:39.377263Z", "iopub.status.idle": "2025-09-27T14:18:39.383642Z", "shell.execute_reply": "2025-09-27T14:18:39.383642Z", "shell.execute_reply.started": "2025-09-27T14:18:39.377263Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "candy = sm.HyperPaddle()\n", "candy.show_graph()" ] }, { "cell_type": "markdown", "id": "96c62a8f", "metadata": {}, "source": [ "It is a bijective graph." ] }, { "cell_type": "code", "execution_count": 32, "id": "f387623d", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.079358Z", "start_time": "2022-01-24T14:38:46.065337Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.384649Z", "iopub.status.busy": "2025-09-27T14:18:39.384649Z", "iopub.status.idle": "2025-09-27T14:18:39.389649Z", "shell.execute_reply": "2025-09-27T14:18:39.389649Z", "shell.execute_reply.started": "2025-09-27T14:18:39.384649Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 7 nodes and 7 edges.\n", "Node dimension is 0.\n", "Edge dimension is 0\n", "Type: Bijective\n", "Node kernel:\n", "[]\n", "Edge kernel:\n", "[]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "candy.kernel" ] }, { "cell_type": "markdown", "id": "746b0d95", "metadata": {}, "source": [ "With degree-proportional arrival rates, it is stabilizable." ] }, { "cell_type": "code", "execution_count": 33, "id": "27add91a", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.094545Z", "start_time": "2022-01-24T14:38:46.080333Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.390792Z", "iopub.status.busy": "2025-09-27T14:18:39.390792Z", "iopub.status.idle": "2025-09-27T14:18:39.396792Z", "shell.execute_reply": "2025-09-27T14:18:39.396792Z", "shell.execute_reply.started": "2025-09-27T14:18:39.390792Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "candy.stabilizable" ] }, { "cell_type": "markdown", "id": "c8925389", "metadata": {}, "source": [ "With uniform arrival rates, it is not stabilizable." ] }, { "cell_type": "code", "execution_count": 34, "id": "eb365f7c", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.109083Z", "start_time": "2022-01-24T14:38:46.096075Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.398298Z", "iopub.status.busy": "2025-09-27T14:18:39.398298Z", "iopub.status.idle": "2025-09-27T14:18:39.403523Z", "shell.execute_reply": "2025-09-27T14:18:39.402516Z", "shell.execute_reply.started": "2025-09-27T14:18:39.398298Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "candy.rates = \"uniform\"\n", "candy.stabilizable" ] }, { "cell_type": "code", "execution_count": 35, "id": "b0816aea", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.125107Z", "start_time": "2022-01-24T14:38:46.111098Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.404523Z", "iopub.status.busy": "2025-09-27T14:18:39.403523Z", "iopub.status.idle": "2025-09-27T14:18:39.409522Z", "shell.execute_reply": "2025-09-27T14:18:39.409522Z", "shell.execute_reply.started": "2025-09-27T14:18:39.404523Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "candy.show_flow()" ] }, { "cell_type": "markdown", "id": "3bcf6d33", "metadata": {}, "source": [ "### Fans" ] }, { "cell_type": "markdown", "id": "2934a8d1", "metadata": {}, "source": [ "Fans yield nice examples of hypergraphs with cool kernels. The basic fan is called a *clover*." ] }, { "cell_type": "code", "execution_count": 36, "id": "523185a3", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.141262Z", "start_time": "2022-01-24T14:38:46.126980Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.410544Z", "iopub.status.busy": "2025-09-27T14:18:39.410544Z", "iopub.status.idle": "2025-09-27T14:18:39.417546Z", "shell.execute_reply": "2025-09-27T14:18:39.417546Z", "shell.execute_reply.started": "2025-09-27T14:18:39.410544Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "clover = sm.Fan()\n", "clover.show_graph()" ] }, { "cell_type": "code", "execution_count": 37, "id": "a4500c91", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.156985Z", "start_time": "2022-01-24T14:38:46.142989Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.418739Z", "iopub.status.busy": "2025-09-27T14:18:39.418739Z", "iopub.status.idle": "2025-09-27T14:18:39.423231Z", "shell.execute_reply": "2025-09-27T14:18:39.423231Z", "shell.execute_reply.started": "2025-09-27T14:18:39.418739Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 9 nodes and 10 edges.\n", "Node dimension is 0.\n", "Edge dimension is 1\n", "Type: Surjective-only\n", "Node kernel:\n", "[]\n", "Edge kernel:\n", "[[-0.2773501 -0.2773501 0.2773501 -0.2773501 -0.2773501 0.2773501\n", " -0.2773501 -0.2773501 0.2773501 0.5547002]]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "clover.kernel" ] }, { "cell_type": "code", "execution_count": 38, "id": "2f22c791", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.172515Z", "start_time": "2022-01-24T14:38:46.159207Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.424241Z", "iopub.status.busy": "2025-09-27T14:18:39.424241Z", "iopub.status.idle": "2025-09-27T14:18:39.431573Z", "shell.execute_reply": "2025-09-27T14:18:39.430567Z", "shell.execute_reply.started": "2025-09-27T14:18:39.424241Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "clover.show_kernel()" ] }, { "cell_type": "markdown", "id": "79868c44", "metadata": {}, "source": [ "The double fan expands the kernel dimension." ] }, { "cell_type": "code", "execution_count": 39, "id": "29a10081", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.234114Z", "start_time": "2022-01-24T14:38:46.222601Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.432574Z", "iopub.status.busy": "2025-09-27T14:18:39.431573Z", "iopub.status.idle": "2025-09-27T14:18:39.438637Z", "shell.execute_reply": "2025-09-27T14:18:39.438637Z", "shell.execute_reply.started": "2025-09-27T14:18:39.432574Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "double = sm.Fan(hyperedges=2)\n", "double.show_graph()" ] }, { "cell_type": "code", "execution_count": 40, "id": "25468d43", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.249308Z", "start_time": "2022-01-24T14:38:46.236147Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.439645Z", "iopub.status.busy": "2025-09-27T14:18:39.439645Z", "iopub.status.idle": "2025-09-27T14:18:39.445557Z", "shell.execute_reply": "2025-09-27T14:18:39.444551Z", "shell.execute_reply.started": "2025-09-27T14:18:39.439645Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 9 nodes and 11 edges.\n", "Node dimension is 0.\n", "Edge dimension is 2\n", "Type: Surjective-only\n", "Node kernel:\n", "[]\n", "Edge kernel:\n", "[[-0.17089102 0.32672261 -0.32672261 -0.17089102 0.32672261 -0.32672261\n", " -0.17089102 0.32672261 -0.32672261 -0.15583159 0.49761363]\n", " [-0.41327504 -0.13510121 0.13510121 -0.41327504 -0.13510121 0.13510121\n", " -0.41327504 -0.13510121 0.13510121 0.54837625 0.27817383]]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "double.kernel" ] }, { "cell_type": "code", "execution_count": 41, "id": "f34c2d66", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.264866Z", "start_time": "2022-01-24T14:38:46.250842Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.446558Z", "iopub.status.busy": "2025-09-27T14:18:39.445557Z", "iopub.status.idle": "2025-09-27T14:18:39.452559Z", "shell.execute_reply": "2025-09-27T14:18:39.452559Z", "shell.execute_reply.started": "2025-09-27T14:18:39.446558Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "double.show_kernel()" ] }, { "cell_type": "markdown", "id": "4911e2d8", "metadata": {}, "source": [ "Last but not least, the *bipartite* fan created a large node kernel." ] }, { "cell_type": "code", "execution_count": 42, "id": "a37d9b40", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.234114Z", "start_time": "2022-01-24T14:38:46.222601Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.453735Z", "iopub.status.busy": "2025-09-27T14:18:39.453735Z", "iopub.status.idle": "2025-09-27T14:18:39.460734Z", "shell.execute_reply": "2025-09-27T14:18:39.460734Z", "shell.execute_reply.started": "2025-09-27T14:18:39.453735Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bip = sm.Fan(cycle_size=4)\n", "bip.show_graph()" ] }, { "cell_type": "code", "execution_count": 43, "id": "30c3bf71", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.249308Z", "start_time": "2022-01-24T14:38:46.236147Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.462109Z", "iopub.status.busy": "2025-09-27T14:18:39.462109Z", "iopub.status.idle": "2025-09-27T14:18:39.469190Z", "shell.execute_reply": "2025-09-27T14:18:39.468180Z", "shell.execute_reply.started": "2025-09-27T14:18:39.462109Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 12 nodes and 13 edges.\n", "Node dimension is 2.\n", "Edge dimension is 3\n", "Type: Nonjective\n", "Node kernel:\n", "[[-0.03577392 0.40667787]\n", " [ 0.03577392 -0.40667787]\n", " [-0.03577392 0.40667787]\n", " [ 0.03577392 -0.40667787]\n", " [ 0.37008033 -0.17235781]\n", " [-0.37008033 0.17235781]\n", " [ 0.37008033 -0.17235781]\n", " [-0.37008033 0.17235781]\n", " [-0.33430641 -0.23432006]\n", " [ 0.33430641 0.23432006]\n", " [-0.33430641 -0.23432006]\n", " [ 0.33430641 0.23432006]]\n", "Edge kernel:\n", "[[ 0.0879802 -0.0879802 -0.0879802 0.0879802 -0.46609144 0.46609144\n", " 0.46609144 -0.46609144 0.15817159 -0.15817159 -0.15817159 0.15817159\n", " 0. ]\n", " [-0.48975298 0.48975298 0.48975298 -0.48975298 -0.06690184 0.06690184\n", " 0.06690184 -0.06690184 0.07527389 -0.07527389 -0.07527389 0.07527389\n", " 0. ]\n", " [ 0.04900509 -0.04900509 -0.04900509 0.04900509 0.16817524 -0.16817524\n", " -0.16817524 0.16817524 0.46831142 -0.46831142 -0.46831142 0.46831142\n", " 0. ]]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bip.kernel" ] }, { "cell_type": "markdown", "id": "4ba2f4da", "metadata": {}, "source": [ "The node kernel can be interpreted as follows:\n", "- There are three *bipartite* components, one for each square. Along the square, the nodes value must alternate positively and negatively.\n", "- The central edge forces the sum of the weights of its adjacent nodes to be zero. so if we fix two squares, the values on the last square are fully determined." ] }, { "cell_type": "code", "execution_count": 44, "id": "e0f719ac", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.264866Z", "start_time": "2022-01-24T14:38:46.250842Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.470191Z", "iopub.status.busy": "2025-09-27T14:18:39.469190Z", "iopub.status.idle": "2025-09-27T14:18:39.475487Z", "shell.execute_reply": "2025-09-27T14:18:39.475487Z", "shell.execute_reply.started": "2025-09-27T14:18:39.470191Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bip.show_kernel()" ] }, { "cell_type": "markdown", "id": "03d724ff", "metadata": {}, "source": [ "Remark that in this example, the hyperedge is not part of the edge kernel. Only the three regular squares are." ] }, { "cell_type": "markdown", "id": "cd23d451", "metadata": {}, "source": [ "Just for the experience, let us add another hyperedge." ] }, { "cell_type": "code", "execution_count": 45, "id": "53a9dbd5", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.281076Z", "start_time": "2022-01-24T14:38:46.265868Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.476495Z", "iopub.status.busy": "2025-09-27T14:18:39.476495Z", "iopub.status.idle": "2025-09-27T14:18:39.483515Z", "shell.execute_reply": "2025-09-27T14:18:39.483515Z", "shell.execute_reply.started": "2025-09-27T14:18:39.476495Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bip = sm.Fan(cycle_size=4, hyperedges=2)\n", "bip.show_graph()" ] }, { "cell_type": "code", "execution_count": 46, "id": "8d020b97", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.296483Z", "start_time": "2022-01-24T14:38:46.282880Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.484523Z", "iopub.status.busy": "2025-09-27T14:18:39.484523Z", "iopub.status.idle": "2025-09-27T14:18:39.489935Z", "shell.execute_reply": "2025-09-27T14:18:39.489935Z", "shell.execute_reply.started": "2025-09-27T14:18:39.484523Z" } }, "outputs": [ { "data": { "text/plain": [ "Kernels of a graph with 12 nodes and 14 edges.\n", "Node dimension is 2.\n", "Edge dimension is 4\n", "Type: Nonjective\n", "Node kernel:\n", "[[ 0.32250561 -0.25031339]\n", " [-0.32250561 0.25031339]\n", " [ 0.32250561 -0.25031339]\n", " [-0.32250561 0.25031339]\n", " [-0.37803057 -0.15414136]\n", " [ 0.37803057 0.15414136]\n", " [-0.37803057 -0.15414136]\n", " [ 0.37803057 0.15414136]\n", " [ 0.05552495 0.40445475]\n", " [-0.05552495 -0.40445475]\n", " [ 0.05552495 0.40445475]\n", " [-0.05552495 -0.40445475]]\n", "Edge kernel:\n", "[[-0.56906235 0.1744534 0.1744534 -0.1744534 -0.39193558 -0.00267337\n", " -0.00267337 0.00267337 -0.2685181 -0.12609085 -0.12609085 0.12609085\n", " 0.39460895 0.39460895]\n", " [ 0.06237319 -0.30242679 -0.30242679 0.30242679 0.12293935 -0.36299295\n", " -0.36299295 0.36299295 -0.37551859 0.13546499 0.13546499 -0.13546499\n", " 0.2400536 0.2400536 ]\n", " [-0.02439087 0.08230634 0.08230634 -0.08230634 -0.14626481 0.20418028\n", " 0.20418028 -0.20418028 -0.41026921 0.46818468 0.46818468 -0.46818468\n", " -0.05791547 -0.05791547]\n", " [-0.23245569 0.36883003 0.36883003 -0.36883003 0.43844265 -0.30206831\n", " -0.30206831 0.30206831 0.0302644 0.10610994 0.10610994 -0.10610994\n", " -0.13637434 -0.13637434]]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bip.kernel" ] }, { "cell_type": "code", "execution_count": 47, "id": "a0523269", "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:38:46.312619Z", "start_time": "2022-01-24T14:38:46.299462Z" }, "execution": { "iopub.execute_input": "2025-09-27T14:18:39.490942Z", "iopub.status.busy": "2025-09-27T14:18:39.490942Z", "iopub.status.idle": "2025-09-27T14:18:39.497001Z", "shell.execute_reply": "2025-09-27T14:18:39.497001Z", "shell.execute_reply.started": "2025-09-27T14:18:39.490942Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bip.show_kernel()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.8" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 5 }