2024-06-04 02:25:15 +02:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 11. Spacery losowe po grafach: algorytm wyszukiwania klastrów\n",
"\n",
"Dla dużych grafów istotną informacją jest wykrycie podgrafów, które są silnie ze sobą powiązane. Za pomocą spacerów losowych po grafach zaprojektuj algorytm, który odkrywa strukturę klastrów w grafie (clustering algorithm). Wykorzystaj swój algorytm do wskazania krytycznych wierzchołków, tj. wierzchołków, których usunięcie rozspójnia graf. Przeanalizuj wariant algorytmu dla grafów skierowanych i grafów nieskierowanych."
]
},
{
"cell_type": "code",
"execution_count": 404,
"metadata": {},
"outputs": [],
"source": [
"import networkx as nx\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Graf skierowany z wagami"
]
},
{
"cell_type": "code",
"execution_count": 405,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{(0, 1): 0.5,\n",
" (0, 2): 0.5,\n",
" (1, 0): 0.33,\n",
" (1, 3): 0.33,\n",
" (1, 4): 0.33,\n",
" (2, 0): 0.33,\n",
" (2, 5): 0.33,\n",
" (2, 6): 0.33,\n",
" (3, 1): 1.0,\n",
" (4, 1): 1.0,\n",
" (5, 2): 1.0,\n",
" (6, 2): 1.0}"
]
},
"execution_count": 405,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"G = nx.balanced_tree(2, 2)\n",
"pos = nx.spring_layout(G)\n",
"\n",
"A = nx.adjacency_matrix(G)\n",
"x, y = A.shape\n",
"\n",
"new_G = nx.DiGraph()\n",
"for current_node in range(x):\n",
" for adjacent_node in range(y):\n",
" if A[current_node, adjacent_node] == 1:\n",
" p = round(1 / G.degree(current_node), 2)\n",
" new_G.add_edge(current_node, adjacent_node, weight=p)\n",
"\n",
"pos = nx.spring_layout(new_G)\n",
"nx.draw(new_G, pos, with_labels=True)\n",
"nx.get_edge_attributes(new_G, 'weight')\n",
"\n",
"# DiGraph example\n",
"# nx.draw(new_G, pos, with_labels=True, arrows=True, connectionstyle='arc3, rad = 0.1')\n",
"# labels = nx.get_edge_attributes(new_G, 'weight')\n",
"# nx.draw_networkx_edge_labels(new_G, pos, edge_labels=labels)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Eksperymenty z stationary distribution"
]
},
{
"cell_type": "code",
"execution_count": 406,
"metadata": {},
"outputs": [],
"source": [
"\n",
"def stationary_distrib_1(P):\n",
" eigenvals, eigenvects = np.linalg.eig(P.T)\n",
" close_to_1_idx = np.isclose(eigenvals, 1)\n",
" target_eigenvect = eigenvects[:,close_to_1_idx]\n",
" target_eigenvect = target_eigenvect[:,0]\n",
"\n",
" return target_eigenvect / sum(target_eigenvect)\n",
"\n",
"def stationary_distrib_2(G, P, k=100, starting_node=0):\n",
" nodes_num = len(G.nodes())\n",
" pi = np.zeros((nodes_num, 1))\n",
" pi[starting_node] = 1\n",
" # pi = np.full((1, nodes_num), 1 / nodes_num).flatten()\n",
" # print(pi)\n",
" for _ in range(k):\n",
" new_pi = np.dot(P.T, pi)\n",
" if np.allclose(pi, new_pi):\n",
" return pi\n",
" pi = new_pi\n",
" return pi.reshape(1, -1).flatten()\n",
"\n",
"def pagerank_test(G):\n",
" print(\"PageRank\")\n",
" p_dict = nx.pagerank(G)\n",
" p_sort = sorted(p_dict.items(), key=lambda x: x[1], reverse=True) \n",
" print(p_dict)\n",
" for i in p_sort: \n",
" print(i[0], end=\", \")\n",
" print(\"\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Funkcje - transition matrix i adjacency matrix"
]
},
{
"cell_type": "code",
"execution_count": 407,
"metadata": {},
"outputs": [],
"source": [
"def adj_matrix(G):\n",
" A = nx.adjacency_matrix(G)\n",
" A = A.todense()\n",
" return np.array(A, dtype = np.float64)\n",
"\n",
"def transition_matrix_1(A):\n",
" D = np.diag(np.sum(A, axis=0))\n",
" return np.dot(np.linalg.inv(D), A)\n",
" \n",
"def transition_matrix_2(A):\n",
" return A / A.sum(axis=1, keepdims=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2024-06-09 19:38:16 +02:00
"## Testy funkcji"
2024-06-04 02:25:15 +02:00
]
},
{
"cell_type": "code",
"execution_count": 408,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Distrib2 - random walk\n",
"{0: 0.3333333333333333, 1: 0.0, 2: 0.0, 3: 0.16666666666666666, 4: 0.16666666666666666, 5: 0.16666666666666666, 6: 0.16666666666666666}\n",
"0, 3, 4, 5, 6, 1, 2, \n",
"\n",
"PageRank\n",
"{0: 0.1581719960780273, 1: 0.2413134344543876, 2: 0.2413134344543876, 3: 0.08980028375329936, 4: 0.08980028375329936, 5: 0.08980028375329936, 6: 0.08980028375329936}\n",
"1, 2, 0, 3, 4, 5, 6, \n",
"\n"
]
}
],
"source": [
"A = adj_matrix(G)\n",
"P1 = transition_matrix_1(A)\n",
"P2 = transition_matrix_2(A)\n",
"\n",
"assert np.array_equal(P1, P2)\n",
"P = P1\n",
"\n",
"# print(\"Distrib1\")\n",
"# S1 = stationary_distrib_1(P)\n",
"# S1_dict = {i: S1[i] for i in range(len(S1))}\n",
"# p_sort = sorted(S1_dict.items(), key=lambda x: x[1], reverse=True) \n",
"# print(S1_dict)\n",
"# for i in p_sort: \n",
"# print(i[0], end=\", \")\n",
"# print(\"\\n\")\n",
"\n",
"print(\"Distrib2 - random walk\")\n",
"S2 = stationary_distrib_2(G, P, k=104, starting_node=0)\n",
"S2_dict = {i: S2[i] for i in range(len(S2))}\n",
"p_sort = sorted(S2_dict.items(), key=lambda x: x[1], reverse=True) \n",
"print(S2_dict)\n",
"for i in p_sort: \n",
" print(i[0], end=\", \")\n",
"print(\"\\n\")\n",
"\n",
"\n",
"pagerank_test(G)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2024-06-09 19:38:16 +02:00
"# Wykrywanie klastrów"
2024-06-04 02:25:15 +02:00
]
},
{
"cell_type": "code",
"execution_count": 442,
"metadata": {},
"outputs": [],
"source": [
"def pk_visit(P, k):\n",
" pk = np.array([])\n",
" for i in range(1, k + 1):\n",
" pk = np.append(pk, P**i)\n",
" pk = pk.reshape(k, P.shape[0], P.shape[1])\n",
" return pk\n",
"\n",
"def pk_sum(pk, k, node):\n",
" p = pk[0]\n",
" for i in range(1, k):\n",
" p += pk[i]\n",
" return p[node]\n",
"\n",
"def l1_norm(v1, v2):\n",
" return np.sum(np.abs(v1 - v2))\n",
"\n",
"def sim_k(k, v1, v2):\n",
" return np.exp(2 * k - l1_norm(v1, v2)) - 1\n",
"\n",
"def sim_mat(G, P, k, threshold = 1):\n",
" sim_m = np.array([])\n",
" pk = pk_visit(P.copy(), k)\n",
" for frm, to in G.edges():\n",
" s = sim_k(k, pk_sum(pk.copy(), k, frm), pk_sum(pk.copy(), k, to))\n",
" if s <= threshold:\n",
" G[frm][to]['color'] = 'blue'\n",
" G[frm][to]['weights'] = 0.5\n",
" else:\n",
" G[frm][to]['color'] = 'green'\n",
" G[frm][to]['weights'] = 2\n",
" sim_m = np.append(sim_m, s)\n",
" return sim_m\n",
"\n",
"def mark_clusters(G, k = 1, threshold = 1):\n",
" A = adj_matrix(G)\n",
" P = transition_matrix_2(A)\n",
" \n",
" sim_mat(G, P, k, threshold=threshold)\n",
"\n",
"def draw(G, pos):\n",
" edge_colors = [G[u][v]['color'] for u,v in G.edges()]\n",
" weights = [G[u][v][\"weights\"] for u,v in G.edges()]\n",
" nx.draw(G, pos, with_labels=True, edge_color=edge_colors, node_color=\"green\", width=weights)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2024-06-09 19:38:16 +02:00
"# Testy"
2024-06-04 02:25:15 +02:00
]
},
{
"cell_type": "code",
"execution_count": 458,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAaMAAAGjCAYAAACBlXr0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABmBUlEQVR4nO2deXxU9bn/3zMMJEDYgigCahICSkBFjOJuEwolCG3Vq3ZxqRVugIrXrrdV2l/vLbm2tre3GgqkxGrrUrdqW5AoUaO4gWBAxUElCyqrAQIkhiyTzO+PZ07mzL5kwix53q/XvCZz1m+SOedznuf7LBan0+lEURRFUeKINd4DUBRFURQVI0VRFCXuqBgpiqIocUfFSFEURYk7KkaKoihK3FExUhRFUeKOipGiKIoSd1SMFEVRlLijYqQoiqLEHRUjRVEUJe6oGCmKoihxR8VIURRFiTsqRoqiKErcUTFSFEVR4o6KkaIoihJ3VIwURVGUuKNipCiKosQdFSNFURQl7qgYKYqiKHFHxUhRFEWJOypGiqIoStxRMVIURVHijoqRoiiKEndUjBRFUZS4o2KkKIqixB0VI0VRFCXuqBgpiqIocUfFSFEURYk7KkaKoihK3FExUhRFUeKOLd4DUJRoaG5vpuZwDW2ONtJsaeRm5pIxICPew1IUJUpUjJSkwd5gZ9WWVazbuY66xjqcOLvXWbCQMyKHORPmsDB/IXmj8uI4UkVRIsXidDqdoTdTlPhR31hP8dpiKusqsVlsOJyOgNsa62fmzKRsbhnZI7JP4EgVRYkWFSMloSmvLmdJxRIcXQ4cXYFFyBub1YbNaqO0qJT50+b34ggVRYkFGsCgJCwlG0pYsGYBrY7WiIQIwNHloNXRyoI1CyjZUNJLI1QUJVaoZaScUMINPCivLmfBmgUxO2/5vHJum3ZbzI6nKEpsUTFSep1IAw/qG+vJW5FHq6PV/wEPAS8DnwLHgWHA2cAlwAD/u6Tb0rEvtusckqIkKCpGSq8RbeDB8Y7jbNyz0b9r7iiwEkgD8oGBwG5gG3Am8M0Ax7faKMgqYP1N63v2SymK0iuoGCm9QrSBB/0s/eh0dgbeYANiFS0GTjYtfxZ4F/hPRKACYF9sZ9KoSWGPR1GUE4MGMCgxpyeBB0GFCKDN9T7Ya3kGYAH6Bd7VZrWxcsvKiMajKMqJQcVIiSnl1eUsrVraeyfIcr3/C9iHuO22A1uA6QScMwKJsKuoqei9sSmKEjXqplNiRnfgwRet8CYyl7MHaAW+BpznZ6cG4HkkGKEfMBH4Cr6Wj5lXgdcAs9F1OTAj9BgtWDj2s2NaOkhREgy1jJSYUby2mI7ODmhBBOMgMDrIDkeBB4HDiJBcAnwM/BVPofFmOHAGMA+4HhG514BNocfoxEnN4ZrQGyqKckLR2nRKj7E32Pmf1/6HyrpKWTAE+KHrfQ+wOsCOrwHtwL8jAgMwFngYiY7L97PP+8AaYAkS0g2QBziBF5EQ70HBx9vmaAu+gaIoJxwVIyVqzKHbFizuFTZEiEKxA3HLDTctGw+MBD7AvxhtBk7FLUQGZyICts91jCCk2dLCGJyiKCcSFSMlKsyh24BHImtYHAO+AMb4WTcW2Blgvy+AdD/LjSC8ruCntWAhNzM3vDEqinLC0DkjJWJ6ErrdTZPr3Z8FlYFUVvB36JHAfmQ+ysx2JLT7lOCnHZ85XoMXFCUBUctIiYiYhW4bQuMvL8j4Vnbg+w29BLGaHgQuRBJcPwZqgGnA0MCntFltFOUWRT1kRVF6DxUjJWzqG+tZUrFEEk9DhW53IRURtro+r3XtMwURFOOb5y/H1RCq/n7WZQG3Aa8g80ctwAigELg0+PgdXQ4W5S8KvpGiKHFBxUgJm+K1xeKWM0K3hyGh27v8bNwB/BN3yZ4piBvtFaAeuNq1vMlnT2hGLJ5A385xwI2Rjd2oTaelgBQlMVExUsLC3mCPLHS7H/Bd1/tqxKI5D4mcewWZ8xkE7PWz7x6C5ydFgc1qo2xuWWwPqihKzFAxUsJi1ZZV7srb4YRu24DTEWExMwm3GOUh4dhHkSi5l4BPEDedBQnTPjU2419etFzbRyhKAqNipITFup3rgraA8GETMpdkuOE+RsK5D7s+D0JK+HwAPIC45oz0nwzEzfcQsAA4qUdDp6SwRBvrKUqCo2KkhKSprYm6xrrIdnoTsXgMdrheIMVMc5F5oVsR0elyvSYhtemcQCliLd0Q+ZhtVhs2q43lRctViBQlCVAxUkJS21gbeVLr9/0sM3oRzcTdc+hkxC2Xh9SZM3MGYlG14baaQmCz2nB0OSjIKqBsbpm65hQlSVAxUkISk1pu2xEhOg+4wGtdJ/7DuPu71n0OnBb6FLmZuRTlFrEof5FGzSlKkqFipISkx7XcapFOrBOBuX7Wj0Rylrpw1wRx4A5+8Bf+7cWXc75M5U2VPRunoihxQ8sBKSHJzcz1LIQaCbuBx5EadNfhv+LCBcAhJC/pc+AAIl6GCHWEPs2nRz+NbnyKoiQEahkpIckYkEHOiBxqG2vD28Go0FAHfOZaNgVfV9xuJLR7DxLK/a7rBSJelyJtJoJ0bzX4vPnz8MamKEpComKkhMWcCXNYuXmlO7w7UOg2SDuHV8HDmDqAW2gAMpF6ctVIcdNMxDq6FanKfQrSnwjEjReCI21HaHO0aXsIRUlStO24Ehb2BjuTV0x2L/g/PEO3zdyOCFV5kAOei0TVpSEW03NIrblfmrb5E5J/dCdhOZTr7qjT6DlFSVLUMlLCIm9UHjNzZlK1q0rq0/kL3fbml7jLBXkXUg3FdqRU0CzCntncfWy3ipGiJCkawKCETdncMmzWXnh+2QV86Pq5GvgX8HckMXZ68F2tFvdXeE+Td+0hRVGSBRUjJWyyR2RTWlQa+wMPxT2/9BzwKdIS4hv4j74z0eV0t3bdc0zFSFGSFRUjJSLmT5vPsoJlsT1oJhL0APBzZM7pckI6kW1WG/lj8rs/b967mW37t9Hc3hzb8SmK0uvonJESMXdfcTenZJzC7etup60zBtUZosTpdLK3yd2D4okPnuCJD57AgoWcETnMmTCHhfkLyRuVF7cxKooSHmoZKVExf9p8rpl0TVzH4MRTjMzLaxtrWbl5JZNXTGbWw7Oob6yPwwgVRQkXFSMlKg62HOTZD5+N6xjM80X+MHKiqnZVkbcij/LqYLHmiqLEExUjJSpWbl5Jq6M13sMIC0eXg1ZHKwvWLKBkQ0m8h6Moih806VWJmFZHK2f84Qw+/yJICR5zhYYtSJ8io5X4dKTKwhHcVRk+RnKSClyfhyOJsb1A+bxy7XGkKAmGBjAoEfPoe48GFyII3lzvHESMGoEqr/2Mz2fgK0ZGzbvdiHC14j+Z9h3gPaS1eSvSIj0LuBIYAbdX3E5hdqEmyCpKAqGWkRIRTqeTKSunYG+wdy+zYGH62Ols2bdFqjP0Fo3AfcAwYASSLOtPjNYilb5PwW2BvYN0j10ItuE2CrIKWH/T+t4bq6IoEaFzRkpEvFD7gocQgUTWPXbtYx7VEGLBgH5e5bqHAD9EShHNDLLjXOBq4BJgGpJA+22gBXhX5pAq6yrZ0bAjyEEURTmRqBgpfmlub2bb/m1s2r3JI5H0f9/6X4/thqYNZVnhMvYc20NnV2dMx3DZ6Zdhs5g8yTZEkKJhuOvdFXNhs9pYuWVl9INTFCWm6JyR0o29wc6qLatYt3MddY11OHF7cC1YGDt0LLuP7fbY5+dX/Jzaw7XMeHgGnc7YiVFJYQl/3vpnd8uKaGhBusceRVpaAOTIm6PLQUVNRc8GqShKzFAxUqhvrKd4bTGVdZXYLDa/AuDE6SNEZww7g+ljp/Olv3yJ9s727uXXTbqONTvX4OhyRDSHZLPasFltLC9azvWTr2fpy0uj/p0A+F/A0MeBQBEw3r269nAtze3NZAzI6Nl5FEXpMeqm6+OUV5eTtyKPql0SxhaJJbKnaQ8FfynwEKLlRct58vonsS+2U5AlcdqhKn0b6wuyCrAvtnPbtNuobaz1sMyi4kZkrmgWEvTQ7rnaiZOawzU9O4eiKDF
"text/plain": [
"<Figure size 400x400 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Gs = [nx.balanced_tree(1, 3), nx.balanced_tree(2, 3), nx.connected_caveman_graph(4, 10), nx.ring_of_cliques(5, 5), nx.ring_of_cliques(10, 10), nx.connected_caveman_graph(7, 7)]\n",
"\n",
"for i, G in enumerate(Gs):\n",
" plt.figure(figsize=(4,4))\n",
" plt.figure(i+1)\n",
"\n",
" pos = nx.spring_layout(G)\n",
" mark_clusters(G, k=1, threshold=1)\n",
" draw(G, pos)"
]
},
{
"cell_type": "code",
"execution_count": 471,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABMQAAATECAYAAACEMNn6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzddXRUZ7v+8e8kEyVYcHcL7hR3d61RaClO7a27nLaUCi0Uh1IolKKlOAWKW4sUDRAIbsECxG3m/LE7OxkyMaSlzfX5rbPOzN7Plsl71vqxrve+78dit9vtiIiIiIiIiIiIZBJu//QLiIiIiIiIiIiI/J0UiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpKBATEREREREREZFMRYGYiIiIiIiIiIhkKgrEREREREREREQkU1EgJiIiIiIiIiIimYoCMRERERERERERyVQUiImIiIiIiIiISKaiQExERERERERERDIVBWIiIiIiIiIiIpKpWP/pFxARERER+buFx4Zz4sYJYuJj8LJ6Udq/NH6efv/0a4mIiMjfRIGYiIiIiGQKgVcDmbR7EiuPr+Rk6Ens2M1zFiyUzFmS9mXaM6TWEALyBPyDbyoiIiIPmsVut9vTXiYiIiIi8u90KvQUg5cPZu3JtVgtVuLt8SmudZxvVbIVkztOpkTOEn/jm4qIiMjfRYGYiIiIiPxnTds7jedWPUe8LZ54W8pB2J2sblasbla+bfctz9Z49gG+oYiIiPwTNFRfRERERP6TPtn8CQOXDSQ6PjpDYRhAvC2e6PhoBi4byCebP3lAbygiIiL/FFWIiYiIiMh/zrS90xi4bGDyEzHAduA8cAGIBroA1dO4X6dpDKgx4H6/poiIiPxDVCEmIiIiIv8pp0JP8dyq51yfjAQ2AdeA/Om/54hVIzgVeuo+vJ2IiIg8DBSIiYiIiMh/yuDlg1NukcwKvAy8BLRK/z3jbfEMXj74PrydiIiIPAwUiImIiIjIf0bg1UDWnlybciBmxQjFMijeFs/ak2s5cvXIPb2fiIiIPBwUiImIiIjIf8ak3ZOwWqwP5N5WNysTd098IPcWERGRv5cCMRERERH5z1h5fCXx9oztKJle8bZ4Vp1Y9UDuLSIiIn8vBWIiIiIi8p8QFhPGydCTD/QZwTeCCY8Nf6DPEBERkQdPgZiIiIiI/CcEhwZjx/5An2HHzokbJx7oM0REROTBUyAmIiIiIv8JMfEx/6nniIiIyIOjQExERERE/hO8rF7/qeeIiIjIg6NATERERET+9aLjozl69egDf44FC6X9Sz/w54iIiMiD9WD2pBYRERERecCi4qJYfWI1CwIXsCxoWfqH3f8ORANhf30PAm7/9bku4J3ypaX8S+Hn6Xe3rywiIiIPCQViIiIiIvKvEREbwaoTq1gYuJDlQcuJiIvI+E22A7eSfD/y1/8AVCHFQMzqZqVd6XYZf56IiIg8dCx2u/3BbsUjIiIiInIPwmPDWRG0goVHFrLy+Eoi4yKTrcnhnYOu5btSp2Adhq0c9sDeJXBYIBXyVHhg9xcREZG/hyrEREREROShExYTxvKg5SwIXMCqE6uIjo9Otsbfx5+u5brSq2Ivmpdojqe7JwCLjixi/an12Ll//72v1c1Ks+LNFIaJiIj8RygQExEREZGHwq3oWywLWsaCwAX8euJXYhJikq3J7ZubbuW70TOgJ82KN8PD3cPp/I2oG9yOuX1fwzAwArHJHSff13uKiIjIP0eBmIiIiIj8Y0KjQll6bCkLjyxkTfAaYhNik63JmyUv3ct3p2dAT5oUb4LVzfU/YU+FnqL9nPYcvXb/d5sc124cJXKWuO/3FRERkX+GAjERERER+VvdiLrBL0d/YWHgQtadXEecLS7Zmvx++elevju9KvaiUdFGuLu5p3rP3Rd303FOR0IiQgAjROtQpgPf7/v+nt/3k+afMKDGgHu+j4iIiDw8FIiJiIiIyAN3LfIavxz9hQWBC1h/aj3xtvhkawpmLUiPCj3oFdCL+kXqpxmCOSwPWk6fhX3MYfvlcpVj1ROr+GTLJ3f9vlY3K1Y3K+PajVMYJiIi8h+kXSZFRERE5IG4EnGFxUcWs/DIQjac2kCCPSHZmsLZCtOzQk96BvTkkSKP4GZxy9AzJu6ayIhVI7DZbQA0LNqQJY8uYd/lfbT4oQUAWTyy4OnuSWh0aLrv26pkKyZ3nKw2SRERkf8oVYiJiIiI/MuFx4Zz4sYJYuJj8LJ6Udq/NH6efv/Iu1wOv8zPR35mYeBCNp3ZZAZVSRXLXoyeAUYIVqdQnQyHYAA2u403173J59s/N4/1qdiHGV1nYLPbGLhsoHl8VKtRvLLmlXTfu1XJVqzpuybD7yQiIiL/HgrERERERP6FAq8GMmn3JFYeX8nJ0JNOuypasFAyZ0nal2nPkFpDCMgT8EDf5WLYRRYFLmLhkYVsObPF5Q6PJXKUoGdAT3oF9KJWwVpYLJa7fl5MfAz9l/Rn7qG55rHX6r/GyJYjcbO48dra1zgZehKARkUbUTpnaaLjo53ukdsnN1Z3K5fDL5PLJxcnnj9BuXHluBJxhU1nNhEaFUpOn5x3/Y4iIiLycFPLpIi
"text/plain": [
"<Figure size 1200x1200 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import random\n",
"\n",
"# Generate synthetic graph with clusters\n",
"def generate_clustered_graph():\n",
" G = nx.Graph()\n",
" \n",
" # Define clusters\n",
" clusters = {\n",
" 0: range(0, 10),\n",
" 1: range(10, 20),\n",
" 2: range(20, 30),\n",
" 3: range(30, 40),\n",
" 4: range(40, 50),\n",
" 5: range(50, 60),\n",
" }\n",
" \n",
" # Add edges within clusters\n",
" for cluster_id, nodes in clusters.items():\n",
" for i in nodes:\n",
" for j in nodes:\n",
" if i != j and random.random() < 0.8: # Higher probability of edge within cluster\n",
" G.add_edge(i, j)\n",
" \n",
" # Add some edges between clusters\n",
" for i in range(10):\n",
" G.add_edge(random.choice(list(clusters[0])), random.choice(list(clusters[1])))\n",
" G.add_edge(random.choice(list(clusters[1])), random.choice(list(clusters[2])))\n",
" G.add_edge(random.choice(list(clusters[0])), random.choice(list(clusters[2])))\n",
" G.add_edge(random.choice(list(clusters[3])), random.choice(list(clusters[2])))\n",
" G.add_edge(random.choice(list(clusters[4])), random.choice(list(clusters[2])))\n",
" G.add_edge(random.choice(list(clusters[5])), random.choice(list(clusters[1])))\n",
" \n",
" return G\n",
"\n",
"# Create the clustered graph\n",
"G = generate_clustered_graph()\n",
"pos = nx.spring_layout(G)\n",
"\n",
"plt.figure(figsize=(12, 12))\n",
"mark_clusters(G, k=1, threshold=1)\n",
"draw(G, pos)"
]
}
],
"metadata": {
"kernelspec": {
2024-06-09 19:38:16 +02:00
"display_name": "Python 3 (ipykernel)",
2024-06-04 02:25:15 +02:00
"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",
2024-06-09 19:38:16 +02:00
"version": "3.10.4"
2024-06-04 02:25:15 +02:00
}
},
"nbformat": 4,
2024-06-09 19:38:16 +02:00
"nbformat_minor": 4
2024-06-04 02:25:15 +02:00
}