{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple and Hyper Graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Stochastic Matchings* allows to build arbitrary models from their graph adjacency or incidence matrix, but also to directly instantiate some families. This tutorial gives a tour of these families and details the graph behavior of a *Model* instance." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we load the package." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.811008Z", "start_time": "2022-01-24T14:53:16.373336Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:25.203097Z", "iopub.status.busy": "2025-09-27T08:33:25.202096Z", "iopub.status.idle": "2025-09-27T08:33:26.409665Z", "shell.execute_reply": "2025-09-27T08:33:26.409665Z", "shell.execute_reply.started": "2025-09-27T08:33:25.203097Z" } }, "outputs": [], "source": [ "import stochastic_matching as sm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simple graph: manual definition and basic usage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple graph can be defined by providing its adjacency or incidence matrix. We give a tour of the possibilities using the diamond graph as running example." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.857431Z", "start_time": "2022-01-24T14:53:17.813021Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.410901Z", "iopub.status.busy": "2025-09-27T08:33:26.409665Z", "iopub.status.idle": "2025-09-27T08:33:26.415934Z", "shell.execute_reply": "2025-09-27T08:33:26.415934Z", "shell.execute_reply.started": "2025-09-27T08:33:26.410901Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond_adjacency = [[0, 1, 1, 0], [1, 0, 1, 1], [1, 1, 0, 1], [0, 1, 1, 0]]\n", "diamond = sm.Model(adjacency=diamond_adjacency)\n", "diamond.show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you input an incidence matrix, the graph is treated as a hypergraph." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.872587Z", "start_time": "2022-01-24T14:53:17.860420Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.417322Z", "iopub.status.busy": "2025-09-27T08:33:26.417322Z", "iopub.status.idle": "2025-09-27T08:33:26.425180Z", "shell.execute_reply": "2025-09-27T08:33:26.425180Z", "shell.execute_reply.started": "2025-09-27T08:33:26.417322Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond_incidence = [[1, 1, 0, 0, 0], [1, 0, 1, 1, 0], [0, 1, 1, 0, 1], [0, 0, 0, 1, 1]]\n", "\n", "diamond = sm.Model(incidence=diamond_incidence)\n", "diamond.show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Model possesses many attributes.\n", "\n", "Number of edges and nodes:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.888491Z", "start_time": "2022-01-24T14:53:17.875463Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.426601Z", "iopub.status.busy": "2025-09-27T08:33:26.425180Z", "iopub.status.idle": "2025-09-27T08:33:26.430558Z", "shell.execute_reply": "2025-09-27T08:33:26.430558Z", "shell.execute_reply.started": "2025-09-27T08:33:26.426601Z" } }, "outputs": [ { "data": { "text/plain": [ "(4, 5)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond.n, diamond.m" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Adjacency matrix does not exist for hypergraphs:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.904134Z", "start_time": "2022-01-24T14:53:17.890943Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.431564Z", "iopub.status.busy": "2025-09-27T08:33:26.430558Z", "iopub.status.idle": "2025-09-27T08:33:26.434898Z", "shell.execute_reply": "2025-09-27T08:33:26.434898Z", "shell.execute_reply.started": "2025-09-27T08:33:26.431564Z" } }, "outputs": [], "source": [ "diamond.adjacency" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.919655Z", "start_time": "2022-01-24T14:53:17.906544Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.435910Z", "iopub.status.busy": "2025-09-27T08:33:26.435910Z", "iopub.status.idle": "2025-09-27T08:33:26.442077Z", "shell.execute_reply": "2025-09-27T08:33:26.442077Z", "shell.execute_reply.started": "2025-09-27T08:33:26.435910Z" } }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 1, 0],\n", " [1, 0, 1, 1],\n", " [1, 1, 0, 1],\n", " [0, 1, 1, 0]])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond = sm.Model(adjacency=diamond_adjacency)\n", "diamond.adjacency" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Incidence (nodes X edges):" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.935271Z", "start_time": "2022-01-24T14:53:17.920674Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.442077Z", "iopub.status.busy": "2025-09-27T08:33:26.442077Z", "iopub.status.idle": "2025-09-27T08:33:26.447366Z", "shell.execute_reply": "2025-09-27T08:33:26.447366Z", "shell.execute_reply.started": "2025-09-27T08:33:26.442077Z" } }, "outputs": [ { "data": { "text/plain": [ "array([[1, 1, 0, 0, 0],\n", " [1, 0, 1, 1, 0],\n", " [0, 1, 1, 0, 1],\n", " [0, 0, 0, 1, 1]])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diamond.incidence" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As already seen, you can visualize the graph with the `show_graph` method." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.950041Z", "start_time": "2022-01-24T14:53:17.937949Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.448374Z", "iopub.status.busy": "2025-09-27T08:33:26.448374Z", "iopub.status.idle": "2025-09-27T08:33:26.453529Z", "shell.execute_reply": "2025-09-27T08:33:26.453529Z", "shell.execute_reply.started": "2025-09-27T08:33:26.448374Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can customize display with `vis_options` (the options will be pass to the vis engine). For example, to display a red graph with no navigation button:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.965300Z", "start_time": "2022-01-24T14:53:17.952155Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.454536Z", "iopub.status.busy": "2025-09-27T08:33:26.454536Z", "iopub.status.idle": "2025-09-27T08:33:26.458792Z", "shell.execute_reply": "2025-09-27T08:33:26.458792Z", "shell.execute_reply.started": "2025-09-27T08:33:26.454536Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.show_graph(\n", " vis_options={\n", " \"nodes\": {\"color\": \"red\"},\n", " \"height\": 200,\n", " \"interaction\": {\"navigationButtons\": True}\n", " }\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Names can be specified." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.981175Z", "start_time": "2022-01-24T14:53:17.967996Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.459801Z", "iopub.status.busy": "2025-09-27T08:33:26.459801Z", "iopub.status.idle": "2025-09-27T08:33:26.465244Z", "shell.execute_reply": "2025-09-27T08:33:26.465244Z", "shell.execute_reply.started": "2025-09-27T08:33:26.459801Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.names = [\"Ga\", \"Bu\", \"Zo\", \"Meu\"]\n", "diamond.show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Automatic letter labeling can be obtained using `alpha` as input for `names`" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:17.996783Z", "start_time": "2022-01-24T14:53:17.982522Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.466254Z", "iopub.status.busy": "2025-09-27T08:33:26.466254Z", "iopub.status.idle": "2025-09-27T08:33:26.471742Z", "shell.execute_reply": "2025-09-27T08:33:26.471742Z", "shell.execute_reply.started": "2025-09-27T08:33:26.466254Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "diamond.names = \"alpha\"\n", "diamond.show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pre-defined models" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For convenience, many graph families are provided. You can have the list with the `get_class` method." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.011971Z", "start_time": "2022-01-24T14:53:17.999974Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.472748Z", "iopub.status.busy": "2025-09-27T08:33:26.471742Z", "iopub.status.idle": "2025-09-27T08:33:26.477751Z", "shell.execute_reply": "2025-09-27T08:33:26.477751Z", "shell.execute_reply.started": "2025-09-27T08:33:26.472748Z" } }, "outputs": [ { "data": { "text/plain": [ "{'Path': stochastic_matching.graphs.Path,\n", " 'Star': stochastic_matching.graphs.Star,\n", " 'Cycle': stochastic_matching.graphs.Cycle,\n", " 'Complete': stochastic_matching.graphs.Complete,\n", " 'Codomino': stochastic_matching.graphs.Codomino,\n", " 'Erdös-Rényi': stochastic_matching.graphs.ErdosRenyi,\n", " 'Nazari-Stolyar': stochastic_matching.graphs.NS19,\n", " 'Pyramid': stochastic_matching.graphs.Pyramid,\n", " 'Tadpole': stochastic_matching.graphs.Tadpole,\n", " 'Lollipop': stochastic_matching.graphs.Lollipop,\n", " 'Kayak Paddle': stochastic_matching.graphs.KayakPaddle,\n", " 'Barbell': stochastic_matching.graphs.Barbell,\n", " 'Cycle Chain': stochastic_matching.graphs.CycleChain,\n", " 'Hyper Kayak Paddle': stochastic_matching.graphs.HyperPaddle,\n", " 'Fan': stochastic_matching.graphs.Fan}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sm.common.get_classes(sm.Model)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Path graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Paths are defined by a parameter $n$ (the size, e.g. number of nodes) that defaults to 2." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.028154Z", "start_time": "2022-01-24T14:53:18.013972Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.477751Z", "iopub.status.busy": "2025-09-27T08:33:26.477751Z", "iopub.status.idle": "2025-09-27T08:33:26.483489Z", "shell.execute_reply": "2025-09-27T08:33:26.483489Z", "shell.execute_reply.started": "2025-09-27T08:33:26.477751Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Path().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.044059Z", "start_time": "2022-01-24T14:53:18.029883Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.484499Z", "iopub.status.busy": "2025-09-27T08:33:26.483489Z", "iopub.status.idle": "2025-09-27T08:33:26.490899Z", "shell.execute_reply": "2025-09-27T08:33:26.490899Z", "shell.execute_reply.started": "2025-09-27T08:33:26.483489Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Path(names=\"alpha\", n=5).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cycle graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cycles are defined by a parameter $n$ that defaults to 3." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.059798Z", "start_time": "2022-01-24T14:53:18.045604Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.492293Z", "iopub.status.busy": "2025-09-27T08:33:26.490899Z", "iopub.status.idle": "2025-09-27T08:33:26.496303Z", "shell.execute_reply": "2025-09-27T08:33:26.496303Z", "shell.execute_reply.started": "2025-09-27T08:33:26.492293Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Cycle().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.075546Z", "start_time": "2022-01-24T14:53:18.062544Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.497702Z", "iopub.status.busy": "2025-09-27T08:33:26.496303Z", "iopub.status.idle": "2025-09-27T08:33:26.503744Z", "shell.execute_reply": "2025-09-27T08:33:26.503744Z", "shell.execute_reply.started": "2025-09-27T08:33:26.496303Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Cycle(names=\"alpha\", n=5).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Star graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Stars are defined by a parameter $n$ (the number of nodes) that defaults to 4." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.123033Z", "start_time": "2022-01-24T14:53:18.077524Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.503744Z", "iopub.status.busy": "2025-09-27T08:33:26.503744Z", "iopub.status.idle": "2025-09-27T08:33:26.510632Z", "shell.execute_reply": "2025-09-27T08:33:26.510632Z", "shell.execute_reply.started": "2025-09-27T08:33:26.503744Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Star().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.138265Z", "start_time": "2022-01-24T14:53:18.124033Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.510632Z", "iopub.status.busy": "2025-09-27T08:33:26.510632Z", "iopub.status.idle": "2025-09-27T08:33:26.516774Z", "shell.execute_reply": "2025-09-27T08:33:26.516774Z", "shell.execute_reply.started": "2025-09-27T08:33:26.510632Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Star(names=\"alpha\", n=5).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Complete graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete graphs are defined by a parameter $n$ that defaults to 3." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.156068Z", "start_time": "2022-01-24T14:53:18.140121Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.517782Z", "iopub.status.busy": "2025-09-27T08:33:26.517782Z", "iopub.status.idle": "2025-09-27T08:33:26.522784Z", "shell.execute_reply": "2025-09-27T08:33:26.522784Z", "shell.execute_reply.started": "2025-09-27T08:33:26.517782Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Complete().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.169715Z", "start_time": "2022-01-24T14:53:18.159342Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.524197Z", "iopub.status.busy": "2025-09-27T08:33:26.522784Z", "iopub.status.idle": "2025-09-27T08:33:26.528526Z", "shell.execute_reply": "2025-09-27T08:33:26.528526Z", "shell.execute_reply.started": "2025-09-27T08:33:26.524197Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Complete(names=\"alpha\", n=5).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tadpole graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A tadpole combines a cycle of length $m$ and a path of length $n$. Default is the paw graph ($m=3, n=1$)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.185906Z", "start_time": "2022-01-24T14:53:18.172226Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.529902Z", "iopub.status.busy": "2025-09-27T08:33:26.529902Z", "iopub.status.idle": "2025-09-27T08:33:26.534765Z", "shell.execute_reply": "2025-09-27T08:33:26.534765Z", "shell.execute_reply.started": "2025-09-27T08:33:26.529902Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Paw graph\n", "sm.Tadpole().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.201978Z", "start_time": "2022-01-24T14:53:18.187665Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.535916Z", "iopub.status.busy": "2025-09-27T08:33:26.535916Z", "iopub.status.idle": "2025-09-27T08:33:26.540407Z", "shell.execute_reply": "2025-09-27T08:33:26.540407Z", "shell.execute_reply.started": "2025-09-27T08:33:26.535916Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Tadpole(n=4).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.217188Z", "start_time": "2022-01-24T14:53:18.203156Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.541658Z", "iopub.status.busy": "2025-09-27T08:33:26.541658Z", "iopub.status.idle": "2025-09-27T08:33:26.547432Z", "shell.execute_reply": "2025-09-27T08:33:26.547432Z", "shell.execute_reply.started": "2025-09-27T08:33:26.541658Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Banner graph\n", "sm.Tadpole(m=4).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.233440Z", "start_time": "2022-01-24T14:53:18.219263Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.547432Z", "iopub.status.busy": "2025-09-27T08:33:26.547432Z", "iopub.status.idle": "2025-09-27T08:33:26.553993Z", "shell.execute_reply": "2025-09-27T08:33:26.553993Z", "shell.execute_reply.started": "2025-09-27T08:33:26.547432Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Ursa major\n", "sm.Tadpole(\n", " n=3, m=4, names=[\"Dubhe\", \"Merak\", \"Phecda\", \"Megrez\", \"Alioth\", \"Mizar\", \"Alkaid\"]\n", ").show_graph(vis_options={\"height\": 400})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lollipop graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A lollipop combines a complete graph of size $m$ and a path of length $n$. Default is the paw graph ($m=3, n=1$)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.249334Z", "start_time": "2022-01-24T14:53:18.235132Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.553993Z", "iopub.status.busy": "2025-09-27T08:33:26.553993Z", "iopub.status.idle": "2025-09-27T08:33:26.559755Z", "shell.execute_reply": "2025-09-27T08:33:26.559755Z", "shell.execute_reply.started": "2025-09-27T08:33:26.553993Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Paw graph\n", "sm.Lollipop().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.264699Z", "start_time": "2022-01-24T14:53:18.250808Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.560815Z", "iopub.status.busy": "2025-09-27T08:33:26.560815Z", "iopub.status.idle": "2025-09-27T08:33:26.566526Z", "shell.execute_reply": "2025-09-27T08:33:26.566526Z", "shell.execute_reply.started": "2025-09-27T08:33:26.560815Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Lollipop(m=4).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.280823Z", "start_time": "2022-01-24T14:53:18.267704Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.566526Z", "iopub.status.busy": "2025-09-27T08:33:26.566526Z", "iopub.status.idle": "2025-09-27T08:33:26.572521Z", "shell.execute_reply": "2025-09-27T08:33:26.572521Z", "shell.execute_reply.started": "2025-09-27T08:33:26.566526Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Lollipop(n=3, m=5).show_graph(vis_options={\"height\": 400})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Kayak paddle graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Combines a cycle of length $k$, a path of length $l$, and a cycle of length $m$. Defaults to $k=3, l=1, m=k$." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.311240Z", "start_time": "2022-01-24T14:53:18.288696Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.572521Z", "iopub.status.busy": "2025-09-27T08:33:26.572521Z", "iopub.status.idle": "2025-09-27T08:33:26.577633Z", "shell.execute_reply": "2025-09-27T08:33:26.577633Z", "shell.execute_reply.started": "2025-09-27T08:33:26.572521Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.KayakPaddle().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.327127Z", "start_time": "2022-01-24T14:53:18.314131Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.578639Z", "iopub.status.busy": "2025-09-27T08:33:26.578639Z", "iopub.status.idle": "2025-09-27T08:33:26.583583Z", "shell.execute_reply": "2025-09-27T08:33:26.583583Z", "shell.execute_reply.started": "2025-09-27T08:33:26.578639Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.KayakPaddle(5, 2).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.358179Z", "start_time": "2022-01-24T14:53:18.331087Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.583583Z", "iopub.status.busy": "2025-09-27T08:33:26.583583Z", "iopub.status.idle": "2025-09-27T08:33:26.590500Z", "shell.execute_reply": "2025-09-27T08:33:26.590500Z", "shell.execute_reply.started": "2025-09-27T08:33:26.583583Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## Fish graph\n", "sm.KayakPaddle(l=0, m=4).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Barbell graph" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Combines a complete graph of size $k$, a path of length $l$, and a complete graph of size $m$. Defaults to $k=3, l=1, m=k$." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.374493Z", "start_time": "2022-01-24T14:53:18.361177Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.590500Z", "iopub.status.busy": "2025-09-27T08:33:26.590500Z", "iopub.status.idle": "2025-09-27T08:33:26.596812Z", "shell.execute_reply": "2025-09-27T08:33:26.596812Z", "shell.execute_reply.started": "2025-09-27T08:33:26.590500Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Barbell().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.405113Z", "start_time": "2022-01-24T14:53:18.377624Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.597820Z", "iopub.status.busy": "2025-09-27T08:33:26.597820Z", "iopub.status.idle": "2025-09-27T08:33:26.603717Z", "shell.execute_reply": "2025-09-27T08:33:26.603717Z", "shell.execute_reply.started": "2025-09-27T08:33:26.597820Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Barbell(5, 2).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.421096Z", "start_time": "2022-01-24T14:53:18.407865Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.605021Z", "iopub.status.busy": "2025-09-27T08:33:26.603717Z", "iopub.status.idle": "2025-09-27T08:33:26.608686Z", "shell.execute_reply": "2025-09-27T08:33:26.608686Z", "shell.execute_reply.started": "2025-09-27T08:33:26.605021Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Barbell(l=0, m=4).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Chained cycle graphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Concatenates cycles of size $n$, $c$ of them. Each cycle has $o$ nodes that overlap with the next one. Defaults to $n=3, c=2, o=2$." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.436473Z", "start_time": "2022-01-24T14:53:18.424317Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.608686Z", "iopub.status.busy": "2025-09-27T08:33:26.608686Z", "iopub.status.idle": "2025-09-27T08:33:26.613941Z", "shell.execute_reply": "2025-09-27T08:33:26.613941Z", "shell.execute_reply.started": "2025-09-27T08:33:26.608686Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Diamond\n", "sm.CycleChain().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.451569Z", "start_time": "2022-01-24T14:53:18.438495Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.615428Z", "iopub.status.busy": "2025-09-27T08:33:26.613941Z", "iopub.status.idle": "2025-09-27T08:33:26.618676Z", "shell.execute_reply": "2025-09-27T08:33:26.618676Z", "shell.execute_reply.started": "2025-09-27T08:33:26.615428Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Triamond\n", "sm.CycleChain(c=3).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.467600Z", "start_time": "2022-01-24T14:53:18.453740Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.620029Z", "iopub.status.busy": "2025-09-27T08:33:26.618676Z", "iopub.status.idle": "2025-09-27T08:33:26.623491Z", "shell.execute_reply": "2025-09-27T08:33:26.623491Z", "shell.execute_reply.started": "2025-09-27T08:33:26.620029Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Domino\n", "sm.CycleChain(n=4).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.483097Z", "start_time": "2022-01-24T14:53:18.469095Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.623491Z", "iopub.status.busy": "2025-09-27T08:33:26.623491Z", "iopub.status.idle": "2025-09-27T08:33:26.629565Z", "shell.execute_reply": "2025-09-27T08:33:26.629565Z", "shell.execute_reply.started": "2025-09-27T08:33:26.623491Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The triangular snake graph TS_9 (cf https://mathworld.wolfram.com/TriangularSnakeGraph.html)\n", "sm.CycleChain(c=4, o=1).show_graph(vis_options={\"height\": 400})" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.499404Z", "start_time": "2022-01-24T14:53:18.485093Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.631067Z", "iopub.status.busy": "2025-09-27T08:33:26.629565Z", "iopub.status.idle": "2025-09-27T08:33:26.634575Z", "shell.execute_reply": "2025-09-27T08:33:26.634575Z", "shell.execute_reply.started": "2025-09-27T08:33:26.631067Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# 3 separated squares\n", "sm.CycleChain(n=4, c=3, o=0).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.606389Z", "start_time": "2022-01-24T14:53:18.502340Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.634575Z", "iopub.status.busy": "2025-09-27T08:33:26.634575Z", "iopub.status.idle": "2025-09-27T08:33:26.640309Z", "shell.execute_reply": "2025-09-27T08:33:26.640309Z", "shell.execute_reply.started": "2025-09-27T08:33:26.634575Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# A big chain of triangle\n", "sm.CycleChain(c=30, names=\"alpha\").show_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Erdös-Rényi graph" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Standard random graph with default parameters $n=10$, $d=3$, $seed=None$." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "execution": { "iopub.execute_input": "2025-09-27T08:33:26.641593Z", "iopub.status.busy": "2025-09-27T08:33:26.641593Z", "iopub.status.idle": "2025-09-27T08:33:26.646450Z", "shell.execute_reply": "2025-09-27T08:33:26.646450Z", "shell.execute_reply.started": "2025-09-27T08:33:26.641593Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.ErdosRenyi(seed=42).show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "execution": { "iopub.execute_input": "2025-09-27T08:33:26.646450Z", "iopub.status.busy": "2025-09-27T08:33:26.646450Z", "iopub.status.idle": "2025-09-27T08:33:26.652088Z", "shell.execute_reply": "2025-09-27T08:33:26.651584Z", "shell.execute_reply.started": "2025-09-27T08:33:26.646450Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.ErdosRenyi(n=20, d=2, seed=42).show_graph(vis_options={\"height\": 400})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Concatenation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Building more elaborate graphs on top of the provided generators is relatively easy.).\n", "\n", "One way to build these graphs is to use concatenation.\n", "\n", "Concatenation generalizes the chained cycles above. It uses a list of graphs and the overlapping between graph. Overlapping can be uniform or heterogeneous (you need then to provide a list of overlaps)." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.637454Z", "start_time": "2022-01-24T14:53:18.610206Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.652088Z", "iopub.status.busy": "2025-09-27T08:33:26.652088Z", "iopub.status.idle": "2025-09-27T08:33:26.658083Z", "shell.execute_reply": "2025-09-27T08:33:26.658083Z", "shell.execute_reply.started": "2025-09-27T08:33:26.652088Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# House\n", "sm.concatenate([sm.Cycle(), sm.Cycle(4)], 2).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.669017Z", "start_time": "2022-01-24T14:53:18.642464Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.659091Z", "iopub.status.busy": "2025-09-27T08:33:26.659091Z", "iopub.status.idle": "2025-09-27T08:33:26.664362Z", "shell.execute_reply": "2025-09-27T08:33:26.664362Z", "shell.execute_reply.started": "2025-09-27T08:33:26.659091Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Barred house\n", "sm.concatenate([sm.Cycle(), sm.Complete(4)], 2).show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.684692Z", "start_time": "2022-01-24T14:53:18.671658Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.665469Z", "iopub.status.busy": "2025-09-27T08:33:26.665469Z", "iopub.status.idle": "2025-09-27T08:33:26.671476Z", "shell.execute_reply": "2025-09-27T08:33:26.671476Z", "shell.execute_reply.started": "2025-09-27T08:33:26.665469Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# House with a triangle on top\n", "sm.concatenate([sm.Cycle(), sm.Cycle(), sm.Cycle(4)], [1, 2]).show_graph(\n", " vis_options={\"height\": 200}\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For some examples proposed in https://hal.archives-ouvertes.fr/hal-03502084, direct shortcut is provided:\n", "- the co-domino graph;\n", "- the *Egyptian pyramid* graph (please see the above paper for the origin of the name." ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.700147Z", "start_time": "2022-01-24T14:53:18.686323Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.671476Z", "iopub.status.busy": "2025-09-27T08:33:26.671476Z", "iopub.status.idle": "2025-09-27T08:33:26.676137Z", "shell.execute_reply": "2025-09-27T08:33:26.676137Z", "shell.execute_reply.started": "2025-09-27T08:33:26.671476Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Codomino\n", "sm.Codomino().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.716360Z", "start_time": "2022-01-24T14:53:18.702166Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.677143Z", "iopub.status.busy": "2025-09-27T08:33:26.676137Z", "iopub.status.idle": "2025-09-27T08:33:26.680435Z", "shell.execute_reply": "2025-09-27T08:33:26.680435Z", "shell.execute_reply.started": "2025-09-27T08:33:26.677143Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Pyramid\n", "sm.Pyramid().show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Package logo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The logo of `stochastic matching` was made with `stochastic matching`. Here is the code that produced the big version." ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.747856Z", "start_time": "2022-01-24T14:53:18.717878Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.680435Z", "iopub.status.busy": "2025-09-27T08:33:26.680435Z", "iopub.status.idle": "2025-09-27T08:33:26.688934Z", "shell.execute_reply": "2025-09-27T08:33:26.688934Z", "shell.execute_reply.started": "2025-09-27T08:33:26.680435Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from stochastic_matching.graphs import concatenate_adjacency, path_adjacency\n", "\n", "\n", "def random_color(n=100, i=None, name=\"rainbow\"):\n", " if i is None:\n", " i = np.random.randint(n)\n", " r, g, b, a = plt.get_cmap(name, n)(i)\n", " return f\"rgba({int(256 * r)}, {int(256 * g)}, {int(256 * b)}, 1)\"\n", "\n", "\n", "adja = concatenate_adjacency([path_adjacency(10), path_adjacency(8)], 0)\n", "for i, j in [(1, 11), (16, 7), (5, 15), (12, 3)]:\n", " adja[i, j] = 1\n", " adja[j, i] = 1\n", "\n", "g = sm.Model(adjacency=adja, names=[c for c in \"StochasticMatching\"])\n", "nodes_dict1 = [\n", " {\"color\": {\"background\": random_color(10, i)}, \"font\": {\"color\": \"black\"}}\n", " for i in range(10)\n", "]\n", "nodes_dict2 = [\n", " {\"color\": {\"background\": random_color(8, 8 - i - 1)}, \"font\": {\"color\": \"white\"}}\n", " for i in range(8)\n", "]\n", "options = {\"width\": \"1000px\", \"nodes\": {\"font\": {\"size\": 80}}}\n", "g.show_graph(nodes_info=nodes_dict1 + nodes_dict2, vis_options=options)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An here is the code for the short version. Note the option `png=True` which creates a mirror png image that can be saved!" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.764079Z", "start_time": "2022-01-24T14:53:18.749693Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.689944Z", "iopub.status.busy": "2025-09-27T08:33:26.688934Z", "iopub.status.idle": "2025-09-27T08:33:26.695900Z", "shell.execute_reply": "2025-09-27T08:33:26.695900Z", "shell.execute_reply.started": "2025-09-27T08:33:26.689944Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\"Right\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "adja = concatenate_adjacency([path_adjacency(5), path_adjacency(5)], 0)\n", "for i, j in [(1, 6), (2, 6), (3, 7), (3, 8)]:\n", " adja[i, j] = 1\n", " adja[j, i] = 1\n", "g = sm.Model(adjacency=adja, names=[c for c in \"StochMatch\"])\n", "nodes_dict1 = [\n", " {\"color\": {\"background\": random_color(5, i)}, \"font\": {\"color\": \"black\"}}\n", " for i in range(5)\n", "]\n", "nodes_dict2 = [\n", " {\"color\": {\"background\": random_color(5, 4 - i)}, \"font\": {\"color\": \"white\"}}\n", " for i in range(5)\n", "]\n", "options = {\"width\": \"1000px\", \"nodes\": {\"font\": {\"size\": 80}}}\n", "g.show_graph(nodes_info=nodes_dict1 + nodes_dict2, vis_options=options, png=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hypergraphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hypergraph egdes can link an arbitrary number of nodes (nor necessarily 2). Hypergraphs mainly differ from simple graphs by the absence of adjacency matrix (only the incidence matrix is used) and a different way of been displayed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simple graphs as hypergraphs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All simple graphs are hypergraphs if you remove the adjacency. " ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.779512Z", "start_time": "2022-01-24T14:53:18.766288Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.696907Z", "iopub.status.busy": "2025-09-27T08:33:26.695900Z", "iopub.status.idle": "2025-09-27T08:33:26.700907Z", "shell.execute_reply": "2025-09-27T08:33:26.700907Z", "shell.execute_reply.started": "2025-09-27T08:33:26.696907Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "paw = sm.Tadpole()\n", "paw.adjacency = None\n", "paw.show_graph(vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ":::note\n", "\n", "Hypergraph convention: edges are represented by small black nodes, and the edges displayed alway link one single node to one edge. Also note that it is possible to make the bipartite structure between nodes and edges more apparent by passing the `bipartite` flag.\n", ":::" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.825114Z", "start_time": "2022-01-24T14:53:18.781155Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.702000Z", "iopub.status.busy": "2025-09-27T08:33:26.702000Z", "iopub.status.idle": "2025-09-27T08:33:26.705445Z", "shell.execute_reply": "2025-09-27T08:33:26.705445Z", "shell.execute_reply.started": "2025-09-27T08:33:26.702000Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "paw.show_graph(bipartite=True, vis_options={\"height\": 200})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nazari-Stolyar example" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hypergraph from https://arxiv.org/pdf/1608.01646 (no parameter)." ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "execution": { "iopub.execute_input": "2025-09-27T08:33:26.706456Z", "iopub.status.busy": "2025-09-27T08:33:26.705445Z", "iopub.status.idle": "2025-09-27T08:33:26.710635Z", "shell.execute_reply": "2025-09-27T08:33:26.710635Z", "shell.execute_reply.started": "2025-09-27T08:33:26.706456Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.NS19().show_graph(vis_options={\"height\": 300})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hyper paddle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A variation of the regular paddle where the two cycles are linked by 3-egdes. Default to $k=3$, $m=3$, $l=1$.\n", "\n", "The default version, named *Candy* graph, is one of the simplest graph for which one can find stabilizable rates that no greedy policy can stabilize." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.841536Z", "start_time": "2022-01-24T14:53:18.826825Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.711141Z", "iopub.status.busy": "2025-09-27T08:33:26.711141Z", "iopub.status.idle": "2025-09-27T08:33:26.716164Z", "shell.execute_reply": "2025-09-27T08:33:26.716164Z", "shell.execute_reply.started": "2025-09-27T08:33:26.711141Z" } }, "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", "metadata": {}, "source": [ "A larger version." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.856185Z", "start_time": "2022-01-24T14:53:18.843741Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.717182Z", "iopub.status.busy": "2025-09-27T08:33:26.716164Z", "iopub.status.idle": "2025-09-27T08:33:26.721980Z", "shell.execute_reply": "2025-09-27T08:33:26.721980Z", "shell.execute_reply.started": "2025-09-27T08:33:26.717182Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "poodle = sm.HyperPaddle(k=4, l=3)\n", "poodle.show_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fans" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fans are cycles linked by hyperedges. Default to $cycles=3$, $cycle_size=3$, $hyperedges=1$.\n", "\n", "Fans are useful to study the equivalent of bipartite graphs (non-trivial left kernel) in the hypergraphs world.\n", "\n", "The default fan is called a *clover*." ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.872211Z", "start_time": "2022-01-24T14:53:18.858189Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.722986Z", "iopub.status.busy": "2025-09-27T08:33:26.721980Z", "iopub.status.idle": "2025-09-27T08:33:26.727255Z", "shell.execute_reply": "2025-09-27T08:33:26.727255Z", "shell.execute_reply.started": "2025-09-27T08:33:26.722986Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Fan().show_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next one is a highly degenerated example (as shown in another notebook)!" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "ExecuteTime": { "end_time": "2022-01-24T14:53:18.888019Z", "start_time": "2022-01-24T14:53:18.875001Z" }, "execution": { "iopub.execute_input": "2025-09-27T08:33:26.728262Z", "iopub.status.busy": "2025-09-27T08:33:26.727255Z", "iopub.status.idle": "2025-09-27T08:33:26.732554Z", "shell.execute_reply": "2025-09-27T08:33:26.732554Z", "shell.execute_reply.started": "2025-09-27T08:33:26.728262Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "
\n", " Reload\n", "\n", "\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sm.Fan(cycle_size=4, hyperedges=2).show_graph()" ] } ], "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": 4 }