Files
graphes-l3/Seance_5_Composantes_Diffusion.ipynb

264 lines
9.6 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Séance 5 — Diffusion d'une information (BFS) et composantes connexes\n",
"\n",
"## Objectifs\n",
"- Comprendre intuitivement ce qu'est un **parcours en largeur** (BFS) et relier ce concept à la **diffusion d'une information, d'une rumeur ou d'une idée** dans un réseau social.\n",
"- Mesurer des **distances sociales** et comparer l'effet du point de départ de la diffusion.\n",
"- Comparer intuitivement le BFS au **parcours en profondeur (DFS)**.\n",
"- Identifier les **composantes connexes** d'un réseau et interpréter la position d'un individu isolé."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Introduction sociologique : une rumeur se propage\n",
"Imaginez qu'une personne — appelons-la **Alice** — partage une nouvelle dans son groupe d'ami·es.\n",
"Chacun·e la répète à ses proches, et ainsi de suite.\n",
"\n",
"L'information se diffuse **par cercles successifs** : d'abord les ami·es direct·es d'Alice, puis les ami·es des ami·es, etc.\n",
"\n",
"C'est exactement ce que fait un **parcours en largeur** : explorer un réseau *niveau par niveau*.\n",
"\n",
"→ En sociologie des réseaux, cela correspond à la **distance sociale** entre individus."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Exemple manuel : propagation d'une information\n",
"Considérons ce réseau à 7 personnes :\n",
"\n",
"```\n",
"Alice — Bob — Chloé — David\n",
" │ │ │\n",
" Emma Félix Gaël\n",
"```\n",
"\n",
"Supposons qu'Alice commence à diffuser une nouvelle.\n",
"\n",
"**Étapes :**\n",
"1. Niveau 0 : Alice\n",
"2. Niveau 1 : les personnes directement connectées à Alice → {Bob, Emma}\n",
"3. Niveau 2 : les ami·es de Bob (hors Alice) → {Chloé, Félix}\n",
"4. Niveau 3 : les ami·es de Chloé → {David, Gaël}\n",
"\n",
"Chaque *niveau* correspond à une **distance sociale** par rapport à la source."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Construire le réseau avec Python"
]
},
{
"cell_type": "code",
"metadata": {},
"execution_count": null,
"outputs": [],
"source": [
"import networkx as nx\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Création du graphe\n",
"G = nx.Graph()\n",
"G.add_edges_from([\n",
" ('Alice', 'Bob'), ('Alice', 'Emma'),\n",
" ('Bob', 'Chloé'), ('Bob', 'Félix'),\n",
" ('Chloé', 'David'), ('Chloé', 'Gaël')\n",
"])\n",
"\n",
"pos = nx.spring_layout(G, seed=0)\n",
"plt.figure(figsize=(6,4))\n",
"nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=1000)\n",
"plt.title('Réseau social — Diffusion de la nouvelle')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Explorer le réseau en largeur depuis Alice\n",
"On peut utiliser la fonction `nx.bfs_tree()` pour construire un arbre de parcours à partir d'un point de départ."
]
},
{
"cell_type": "code",
"metadata": {},
"execution_count": null,
"outputs": [],
"source": [
"source = 'Alice'\n",
"T = nx.bfs_tree(G, source=source)\n",
"\n",
"plt.figure(figsize=(6,4))\n",
"nx.draw(T, with_labels=True, node_color='lightgreen', node_size=1000)\n",
"plt.title(f'Arbre BFS à partir de {source}')\n",
"plt.show()\n",
"\n",
"print('Ordre du parcours BFS :')\n",
"print(list(nx.bfs_edges(G, source)))\n",
"\n",
"distances = nx.single_source_shortest_path_length(G, source)\n",
"print('\\nDistances sociales depuis Alice :')\n",
"for k, v in distances.items():\n",
" print(f'{k} : {v}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Interprétation sociologique\n",
"- Les **valeurs faibles** indiquent des individus **proches** d'Alice (accès direct à l'information).\n",
"- Les **valeurs élevées** indiquent des individus **périphériques** : ils n'apprennent la nouvelle que tardivement.\n",
"\n",
"→ Cela permet d'analyser la **vitesse de diffusion** ou la **position sociale** dans le réseau.\n",
"\n",
"**Questions :**\n",
"1. Dans quel ordre les personnes reçoivent-elles l'information ?\n",
"2. Quel est le rôle d'Alice dans cette diffusion ?\n",
"3. Quelle est la distance maximale observée ? Que signifie-t-elle socialement ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Comparaison intuitive : BFS vs DFS\n",
"Pour bien comprendre la logique du BFS (revu en Séance 4), comparons-le brièvement à l'autre stratégie : le **DFS**.\n",
"\n",
"| Stratégie | Métaphore | Manière d'explorer | Exemple |\n",
"|:-----------|:-----------|:------------------|:---------|\n",
"| BFS (largeur) | diffusion sociale | explore les cercles autour de la source | bouche-à-oreille, message collectif |\n",
"| DFS (profondeur) | exploration ciblée | suit un chemin jusqu'au bout avant de revenir | enquête, filiation, exploration hiérarchique |\n",
"\n",
"Le BFS **propagera rapidement une information**, tandis que le DFS **creusera une piste en profondeur**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Le point de départ change-t-il tout ? Recommençons depuis Chloé\n",
"Recommençons la diffusion mais cette fois **à partir de Chloé**. Observez les différences de structure et de distances."
]
},
{
"cell_type": "code",
"metadata": {},
"execution_count": null,
"outputs": [],
"source": [
"source2 = 'Chloé'\n",
"T2 = nx.bfs_tree(G, source=source2)\n",
"\n",
"plt.figure(figsize=(6,4))\n",
"nx.draw(T2, with_labels=True, node_color='lightcoral', node_size=1000)\n",
"plt.title(f'Arbre BFS à partir de {source2}')\n",
"plt.show()\n",
"\n",
"print('Distances sociales depuis Chloé :')\n",
"for k, v in nx.single_source_shortest_path_length(G, source2).items():\n",
" print(f'{k} : {v}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Questions :**\n",
"1. Quelles différences remarquez-vous par rapport au départ depuis Alice ?\n",
"2. Quelle personne semble jouer un rôle « de pont » dans la diffusion (voir la notion de coefficient de clustering, Séance 3) ?\n",
"3. Que peut-on dire de la position de Chloé dans le réseau ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Composantes connexes : un acteur isolé\n",
"\n",
"Jusqu'ici, tout le monde pouvait recevoir l'information de proche en proche. Mais que se passe-t-il si une personne n'est reliée à **personne** ?\n",
"\n",
"Ajoutons une nouvelle personne, **Hugo**, qui n'est reliée à personne dans le réseau."
]
},
{
"cell_type": "code",
"metadata": {},
"execution_count": null,
"outputs": [],
"source": [
"# Ajout d'une personne isolée\n",
"G.add_node('Hugo')\n",
"\n",
"plt.figure(figsize=(6,4))\n",
"pos = nx.spring_layout(G, seed=1)\n",
"nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=1000)\n",
"plt.title('Réseau social avec une personne isolée (Hugo)')\n",
"plt.show()\n",
"\n",
"print('Composantes connexes du graphe :')\n",
"for i, comp in enumerate(nx.connected_components(G)):\n",
" print(f'Composante {i+1} : {comp}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Interprétation :** une **composante connexe** est un sous-ensemble du réseau où tout le monde peut s'atteindre par une suite de liens, mais qui n'a aucun lien vers le reste du réseau. Un individu isolé forme, à lui seul, sa propre composante.\n",
"\n",
"**Questions :**\n",
"1. Hugo peut-il recevoir l'information ? Pourquoi ?\n",
"2. Que représente un acteur isolé dans un réseau social réel ?\n",
"3. Comment cette notion d'isolement peut-elle s'interpréter en sociologie (accès à l'information, exclusion sociale, marginalité) ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Pour aller plus loin (facultatif)\n",
"1. Ajoutez de nouvelles relations pour rendre le graphe plus connecté.\n",
"2. Essayez de trouver une configuration où tout le monde est relié en deux étapes maximum.\n",
"3. Reliez Hugo au reste du réseau : combien de composantes reste-t-il ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Synthèse\n",
"- Le **BFS** explore un réseau **par cercles successifs** à partir d'une source, et permet de mesurer la **distance sociale**.\n",
"- Le point de départ de la diffusion **change radicalement** l'ordre et la vitesse à laquelle l'information circule.\n",
"- Le **DFS** suit une logique d'exploration **en profondeur**, utile pour détecter des sous-groupes plutôt que pour simuler une diffusion rapide.\n",
"- Une **composante connexe** est un sous-groupe où tout le monde est atteignable, mais coupé du reste. Un individu isolé ne reçoit jamais l'information : cela peut traduire une exclusion ou une marginalisation sociale."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}