←
codex/symbolic-graphs/networkx_social.cat
#!/usr/bin/env catnip
# Réseau social : centralité, rôles, communautés (NetworkX)
# Graphe non orienté, 10 noeuds, métriques de centralité, plus court chemin
#
# Ref: https://en.wikipedia.org/wiki/Centrality
nx = import('networkx')
import('builtins', 'sorted')
# Modèle de données
struct Person { name; role; }
struct NodeReport {
name; role; degree; betweenness; category;
display(self) => {
f" {self.name} ({self.role}) : {self.betweenness} [{self.category}]"
}
}
# Classification par centralité (pattern matching sur seuils)
classify = (betweenness, degree) => {
match True {
_ if betweenness > 0.3 => { "hub" }
_ if betweenness > 0.05 => { "bridge" }
_ if degree > 0.4 => { "connector" }
_ => { "peripheral" }
}
}
# Construction du graphe
persons = list(
Person("alice", "lead"),
Person("bob", "dev"),
Person("charlie", "dev"),
Person("diana", "design"),
Person("eve", "pm"),
Person("frank", "dev"),
Person("grace", "data"),
Person("hector", "ops"),
Person("iris", "dev"),
Person("jules", "qa"),
)
G = nx.Graph()
for p in persons {
G.add_node(p.name, role=p.role)
}
# Arêtes : collaborations (topologie hub-spoke + sous-clusters)
edges = list(
tuple("alice", "bob"), tuple("alice", "charlie"),
tuple("alice", "diana"), tuple("alice", "eve"),
tuple("alice", "grace"), tuple("bob", "charlie"),
tuple("bob", "frank"), tuple("bob", "iris"),
tuple("charlie", "frank"), tuple("charlie", "iris"),
tuple("diana", "eve"), tuple("eve", "hector"),
tuple("eve", "grace"), tuple("grace", "hector"),
tuple("frank", "jules"), tuple("iris", "jules"),
)
G.add_edges_from(edges)
print(f"⇒ Réseau social ({len(persons)} personnes, {G.number_of_edges()} arêtes)")
# Métriques de centralité
deg = nx.degree_centrality(G)
bet = nx.betweenness_centrality(G)
# Broadcasting : construction des rapports depuis les métriques
reports = persons.[(p) => {
NodeReport(
p.name, p.role,
round(deg[p.name], 3),
round(bet[p.name], 3),
classify(bet[p.name], deg[p.name]),
)
}]
sorted_reports = sorted(reports, key=(r) => { -r.betweenness })
print()
print("⇒ Top 5 centralité (betweenness)")
for r in sorted_reports[:5] {
print(r.display())
}
# Plus court chemin
src = "jules"
dst = "diana"
path = nx.shortest_path(G, src, dst)
print(f"\n⇒ Plus court chemin {src} → {dst}")
print(f" {' → '.join(path)} ({len(path) - 1} sauts)")
# Communautés (Clauset-Newman-Moore greedy modularity)
communities = nx.community.greedy_modularity_communities(G)
print(f"\n⇒ Communautés détectées ({len(communities)})")
for i in range(len(communities)) {
print(f" Communauté {i + 1} : {', '.join(sorted(communities[i]))}")
}