Tag Archives: igraph

La parité, comme condition d’équilibre stable non dégénéré (simulations)

J’avais mis en ligne hier soit un court billet, expliquant pourquoi la parité ne devait pas uniquement être vu sous un angle éthique, ou moral, mais qu’il convenait de regarder la dynamique d’un système. Et moyennant quelques hypothèses simples (simplistes ?) basées sur des faits stylisées de stigmatisation, on pouvait avoir l’intuition que si le taux de personnes issues de la minorité est trop faible, on converge vers un équilibre dégénéré.

C’est ce qu’on peut visualiser sur la figure suivante

sur une simulation de trajectoire sur 150 pas de temps (150 semaines si on veut, ou 150 jours). On pourrait objecter que c’est juste une simulation, mais en fait, ce comportement quand r_0 est trop faible, on le retrouve assez souvent

avec quelque chose qu’on pourrait interpréter comme un décrochage soudain, où quand r_t passe sous un certain seuil, r_{t+h} plonge vers 0, et (si on reste sur l’interprétation garçon-fille), on converge vers un “Boys’ Club” (ce qu’on appelle en maths, un équilibre dégénéré). Mon modèle est assez simple, et on pourrait le perfectionner (mais l’idée des billets de blog est de faire des choses assez simples). Si on regarde quand on commence proche de 35% pour r_0, on a un ensemble hétérogène de trajectoires, soit vertueuses (qui sont que r_t augmente, pour tendre vers un équilibre paritaire),  soit vicieuses, avec r_t baisse, avec le risque de baisser trop, et de retrouver la spirale infernale précédente.

C’est d’ailleurs très exactement ce qu’on observe si on va plus loin dans les simulations

Une fois ce seuil franchit, r_t plonge vers 0.

Je ne parlerais pas de la partie supérieure, parce que le défaut (ou un des défauts) de mon modèle, c’est que je tiens pas compte du fait que si on passe au dessus de 50%, la “minorité” devient la “majorité”, et donc on pourrait imaginer de manière symétrique le même genre de soucis dans la partie supérieure de la Figure. Au lieu de ces deux tendances, on pourrait imaginer une force de rappel autour de 50% pour maintenir cet état vertueux correspondant à la situation paritaire…

Je peux expliquer un peu comment j’ai obtenu ces figure, en décriant mon modèle dynamique de composition genrée dans un réseau social. On considère un ensemble de n individus connectés au sein d’un graphe aléatoire mixte, évoluant au cours du temps discret t = 0,1,2,\dots. Comme j’avais du mal à gérer les entrées et les sorties, on va constamment suivre n individus, avec à chaque pas de temps, un proportion de femmes est notée r_t \in (0,1) qui évoluera dynamiquement. Le nombre de filles et le nombre de garçons seront ici n_F(t) = \lfloor r_t \, n \rfloor, \quad n_M(t) = n - n_F(t).Les ensembles de nœuds féminins et masculins sont notés F_t et M_t.

Structure du réseau : modèle à blocs stochastiques

Le réseau G_t = (V_t, E_t) est tiré selon un modèle à blocs stochastiques (SBM) à deux blocs (femmes et hommes) avec une matrice de probabilités de connexion P(r_t) qui s’écritP(r) =\begin{pmatrix}p_{FF}(r) & p_{FM}(r) \\p_{FM}(r) & p_{MM}(r) \end{pmatrix}. Je vais définir la fonction logistique (sigmoïde) \sigma(x) = (1 + e^{-x})^{-1},et des fonctions de “rareté” :
\phi_F(r) = \frac{1 - r}{r}, \text{ et } \phi_M(r) = \frac{r}{1 - r}.Les probabilités de lien entre individus dans les groupes s’écrivent alors \begin{aligned}p_{FF}(r) &= \sigma(\theta_0 + \eta + 2\gamma\,\phi_F(r)),\\p_{MM}(r) &= \sigma(\theta_0 + \eta + 2\gamma\,\phi_M(r)),\\p_{FM}(r) &= \sigma(\theta_0 + \delta_{\text{mix}} + \gamma(\phi_F(r) + \phi_M(r))).\end{aligned}Les paramètres \eta et \gamma contrôlent respectivement l’homophilie et la sensibilité à la rareté d’un genre.

Je vais poursuivre la remarque introductive que je faisais auparavant: à chaque étape temporelle, le graphe G_t est resimulé intégralement à partir de la distribution P(r_t). Autrement dit, la structure des liens n’a aucune mémoire, le modèle supposant un mélange social complet à chaque période. Bien sûr, ce choix n’est pas réaliste (dans la réalité, les liens persistent), et donc empêche une vision ABM où on pourrait suivre des trajectoires individuelles… mais ça simplifie grandement la dynamique, en évitant d’avoir à suivre explicitement les entrées, sorties et réajustements de connexions individuels, etc. Mais pour mon billet de blog (qui n’a pas d’autre prétention), ce n’est pas gênant, le modèle représente ainsi une sorte d’état moyen du graph, plutôt qu’un réseau concret avec des individus identifiés.

Exposition locale et propension masculine

Pour chaque nœud masculin i \in M_t, on définit N_t(i) l’ensemble des voisins directs de i, et \deg_t(i)=\#\{N_t(i)\} le degré local (le nombre de voisins directs). On introduit alors s_i(t) = \frac{\#\{|N_t(i) \cap F_t\}}{\deg_t(i)},et z_i(t) = \frac{\#\{N_t(i) \cap M_t\}}{\deg_t(i)} = 1 - s_i(t),
et une mesure de proximité “triangulaire” féminine t_i(t) = \left(\frac{\#\{N_t(i) \cap F_t\}}{\deg_t(i)}\right)^2.Alors, j’ai mis un exposant 2 ici, dans cette formule de “mesure triangulaire féminine” pour avoir une “pondération non linéaire”. Autrement dit, ça permet de renforcer l’effet de la présence multiple de femmes dans le voisinage. L’idée est de représenter l’effet de cohésion féminine locale autour d’un individu masculin. Le but n’est pas de quantifier le fait d’avoir une femme dans le voisinage (déjà capturé par s_i), mais bien d’avoir plusieurs femmes connectées entre elles dans le voisinage, ce va rendre la “présence féminine” visible et normative. Autrement dit : si un homme est connecté à une seule femme, l’effet social reste faible (il peut ignorer la norme) alors que s’il est entouré de plusieurs femmes, qui elles-mêmes sont connectées entre elles, la norme collective est beaucoup plus forte. Il permet de capturer l’idée suivante : plus de femmes proches → plus de triangles F–M–F → plus de pression normative.

Dans ce modèle, la propension individuelle d’un homme à avoir un comportement déplacé (une petite phrase sexiste par exemple) est donnée par \pi_i(t)= \pi_0 \, N(r_t)\, e^{-\alpha\,s_i(t) - \alpha_2\,t_i(t)}\, e^{\zeta\,z_i(t)},N est une fonction normative.

Boucle vertueuse et norme sociale

La norme protectrice (ou “boucle vertueuse”) ne s’active que si la proportion de femmes dépasse un seuil r_{\text{protect}} (il faut qu’il y ait assez de femme). On définit ainsi :
{N}(r) =\begin{cases}\exp\!\big(-\beta_{\text{norm}} \, L(r)\big), & \text{si } r > r_{\text{protect}},\\1, &\text{sinon,}\end{cases}L(r) = \sigma\!\big(\kappa (r - r_\star)\big) est une fonction logistique “raide” (qui tend vers la fonction indicatrice), avec \kappa assez grand et r_\star \approx 0.45 le pivot normatif. Ainsi, lorsque r_t > r_{\text{protect}}, la norme sociale réduit la propension masculine moyenne (à avoir un comportement déplacé).

Incidents et sanctions

Chaque arête (i,j) reliant un homme i et une femme j peut donner lieu à un incident i \to j avec probabilité\mathbb{P}(\text{incident } i \to j) = \lambda \, \pi_i(t),\lambda est un paramètre global de fréquence des comportements déplacés.

On note \mathcal{O}_t l’ensemble des auteurs masculins et\mathcal{V}_t celui des victimes féminines. Quand r_t > r_{\text{protect}}, les auteurs sont sanctionnés avec une probabilité s(r_t) = s_{\max}\, L(r_t), ce qui augmente leur probabilité de sortie.

Sorties et recrutement

Les probabilités de sortie (ou d’abandon) sont données, pour les femmes, parq_j^F(t)= \big(\beta_F+ \tau_{\text{inc}}\,\mathbf{1}\{j\in \mathcal{V}_t\}+ \tau_{\text{iso}}\,\mathbf{1}\{s_j(t) < \theta_{\text{iso}}\}\big)\times B(r_t),et pour les hommes q_i^M(t) = \beta_M + \tau_{\text{sanction}} \, \mathbf{1}\{i \in \mathcal{O}_t \text{ sanctionné}\}.On tire ensuite le nombre de départs féminins X_t^F et masculins X_t^M,X_t^F \sim \mathrm{Binomial}(n_F(t), \bar{q}^F_t),\text{ et }X_t^M \sim \mathrm{Binomial}(n_M(t), \bar{q}^M_t).

Les départs sont compensés par un recrutement de nouveaux membres, avec probabilité p_t^{\text{newF}} d’être une femme :p_t^{\text{newF}}=\begin{cases}r_t, & \text{si } r_t \le r_{\text{protect}},\\[6pt]\mathrm{clamp}\big(r_t + k(0.5 - r_t), 0, 1\big),& \text{si } r_t > r_{\text{protect}}.\end{cases}

Loi d’évolution de la proportion féminine

Après sorties et recrutements, la proportion féminine à l’instantt+1 est r_{t+1} = \frac{n_F(t) - X_t^F + Y_t}{n}= r_t + \frac{Y_t - X_t^F}{n},
Y_t est le nombre de femmes recrutées au temps t. Et en prenant l’espérance conditionnelle, on obtient la dynamique moyenne,\mathbb{E}[r_{t+1}\mid r_t]= r_t + \frac{(X_t^F + X_t^M)\,p_t^{\text{newF}}- \sum_{j\in F_t} q_j^F(t)}{n}.

Interprétation qualitative

Le système présente deux régimes distincts :

  • Sous le seuil r_{\text{protect}} : la boucle vertueuse est inactive, les incidents augmentent, les femmes sortent et on observe l’effondrement dont je parlais en introduction
  • Au-dessus du seuil : la norme protectrice et les sanctions s’activent, les sorties féminines diminuent et on a (en moyenne, et en moyenne seulement comme on le voyait sur les figures introductives) une stabilisation autour de la parité.

Ce modèle reproduit une transition de phase sociale : avec un régime “entre-soi masculin” (boys’ club) et un régime mixte stabilisé par la norme collective. Et dans un monde idéal, on peut imaginer une structure hiérarchique, avec une dizaine de “groupes” (qui représentent une formation par exemple, à l’université), des blocs de blocs, avec la contrainte que si une personne quitte un groupe, forcément elle va dans un autre… et donc un déséquilibre fort dans une formation va avoir des conséquences sur tous les autres (d’autant plus si on met là aussi des matrices de transition entre formations). Donc une formation qui a une parité qui s’effondre, c’est malheureux localement, mais potentiellement dévastateur globalement…

Métro: centralité et robustesse

Demain matin, nous aurons un TP pour le cours sur les réseaux, les flux et les transports. En particulier, en nous inspirant des travaux de Sybil Derrible, nous allons commencer par étudier la centralité dans les différents systèmes de métro, mais aussi la robustesse. Les matrices d’adjacence d’une trentaine de métros dans le monde sont en ligne dans un fichier xls. Histoire de gagner un peu de temps, le code pour créer une matrice d’adjacence peut être le suivant

loc="/data/Metro_Networks_Adjacency.xls"
library(xlsx)
E=read.xlsx(loc,"StPetersburg")
n=nrow(E)
nom=as.character(E[3:(n-2),1])
Adj=E[3:(n-2),(4:ncol(E)-1)]
Adj[is.na(Adj)]=0
Adj=as.matrix(Adj)
colnames(Adj)=rownames(Adj)=nom

On est ensuite prêt à manipuler le réseau,

library(igraph)
iflo=graph_from_adjacency_matrix(Adj,mode = "undirected")
plot(iflo)

On va utiliser les notions vues en cours, sur la centralité, mais surtout, on travaillera sur Quantifying the robustness of metro networks, inspiré de The complexity and robustness of metro networks. Plusieurs fonctions utiles sont déjà programmées dans R, comme l’assortativité.

 

 

Networks with R

In order to practice with network data with R, we have been playing with the Padgett (1994) Florentine’s wedding dataset (discussed in the lecture). The dataset is available from

> library(network)
> data(flo)
> nflo=network(flo,directed=FALSE)
> plot(nflo, displaylabels = TRUE,
+ boxed.labels =
+ FALSE)

The next step was to move from the network package to igraph. Since we have the adjacency matrix, we can use it

> library(igraph)
> iflo=graph_from_adjacency_matrix(flo,
+ mode = "undirected")
> plot(iflo)

The good thing is that a lot of functions are available, for instance we can get shortest paths, between two specific nodes. And we can give appropriate colors to the nodes that we’ll cross

> AP=all_shortest_paths(iflo,
+ from="Peruzzi",
+ to="Ginori")
> L=AP$res[[1]]
> V(iflo)$color="yellow"
> V(iflo)$color[L[2:4]]="light blue"
> V(iflo)$color[L[c(1,5)]]="blue"
> plot(iflo)

We can also visualize edges, but I found it slightly more complicated (to extract edges from the output)

> liens=c(paste(as.character(L)[1:4],
+ "--",
+ as.character(L)[2:5],sep=""),
+ paste(as.character(L)[2:5],
+ "--",
+ as.character(L)[1:4],sep=""))
> df=as.data.frame(ends(iflo,E(iflo)))
> names(df)=c("src","target")
> lstn=sort(unique(c(as.character(df[,1]),as.character(df[,2]),"Pucci")))
> Eliens=paste(as.numeric(factor(df[,1],levels=lstn)),"--",
+ as.numeric(factor(df[,2],levels=lstn)),sep="")
> EU=unlist(lapply(Eliens,function(x) x%in%liens))
> E(iflo)$color=c("grey","black")[1+EU]
> plot(iflo)

But it works. It is also possible to use some D3js visualization

> library( networkD3 )
> simpleNetwork (df)

Then the next question was to add a vertice to the network. The most simple way to do it is probability through the adjacency matrix

> flo2=flo
> flo2["Pucci","Bischeri"]=1
> flo2["Bischeri","Pucci"]=1
> nflo2=network(flo2,directed=FALSE)
> plot(nflo2, displaylabels = TRUE,
+ boxed.labels =
+ FALSE)

Then, we’ve been playing with centrality measures.

> plot(iflo,vertex.size=betweenness(iflo))

The goal was to see how related they were. Here, for all of them, “Medici” is the central node. But what about the others?

> B=betweenness(iflo)
> C=closeness(iflo)
> D=degree(iflo)
> E=eigen_centrality(iflo)$vector
> base=data.frame(betw=B,close=C,deg=D,eig=E)
> cor(base)
betw close deg eig
betw 1.0000000 0.5763487 0.8333763 0.6737162
close 0.5763487 1.0000000 0.7572778 0.7989789
deg 0.8333763 0.7572778 1.0000000 0.9404647
eig 0.6737162 0.7989789 0.9404647 1.0000000

Those measures are quite correlated. It is also possible to use a hierarchical graph to visualize how close those centrality measures can be

> H=hclust(dist(t(base)),
+ method="ward")
> plot(H)

Instead of looking at values of centrality measures, it is possible to looks are ranks

> rbase=base
> for(i in 1:4) rbase[,i]=rank(base[,i])
> H=hclust(dist(t(rbase)),
+ method="ward")
> plot(H)

Here the eigenvector measure is very close to the degree of vertices.

Finally, it is possible to seek clusters (in the context of coalition here, in case a war should start between those families)

> kc <- fastgreedy.community ( iflo )

Here we have 3 classes (+1 for the node that is disconnected from the other families)

> V(iflo)$color=c("yellow","orange",
+ "light blue")[membership ( kc )]
> plot(iflo)

> plot(kc,iflo)