264 lines
9.6 KiB
Plaintext
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
|
|
}
|