Vous êtes sur la page 1sur 7

Recherche Opérationnelle

TP1 : premiers pas avec R et RStudio

igraph
Laurent Tichit & Alberto Valdeolivas Urbelz
Le but de ce TP est de prendre en main le paquetage R igraph
Vous aurez à rendre un compte rendu au format Rmd (cf. trucs et astuces plus bas), constitué de d’une suite
d’instructions R et de réponses aux questions. Ce fichier Rmd doit pouvoir être compilable (i.e. tricotable, knitable) en
HTML ou PDF par nos soins. Ce compte-rendu doit être déposé sous Ametice pour la veille de la prochaine séance,
23h.

Préliminaires
• Lancez RStudio
• installez le package igraph (à ne faire qu’une seule fois) :

install.packages("igraph", repos="http://cran.biotools.fr")

Cette commande télécharge le code source de la version la plus récente du package igraph depuis la
machine http://cran.biotools.fr, télécharge récursivement toutes ses dépendances (i.e. les autres packages
que igraph utilise), tente de les compiler (il faut donc que des outils de développement C, C++, Java et Fortran soient
installés), puis les installe sur votre système. En mode utilisateur, ils sont installés dans $HOME/R/.

Notes
Pour ce TP, vous avez l’avantage de pouvoir bénéficier de la puissance de RStudio, ce qui peut vous faciliter la tâche
(RStudio vous permet par exemple d’installer des paquetages, de les configurer, et de produire des documents en
quelques clics de souris). Notez cependant, que dans un cadre de travail, vous serez parfois amenés à devoir travailler
sur des machines distantes (de haute performance) sur lesquelles l’environnement d’exécution R sera installé, mais sur
lesquelles RStudio ne sera pas disponible.

Trucs et astuces
• Vous pouvez écrire votre compte-rendu + code dans un fichier Rmd que RStudio peut exécuter et exporter
vers du HTML/PDF/DOC (il vous faut, pour ce faire, connaître la syntaxe Markdown. Celle-ci
est relativement simple. Voir https://dhaine.github.io/clinicR/src/20150108-
rmarkdown.html et http://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf)
• Pour voir accès à la liste des fonctions, objets, etc. du package igraph : library(help=igraph)
• Sous R, pour connaître la structure de n’importe quel objet o : str(o)
• Vous pouvez consulter la doc en tapant ? suivi de n’importe quel nom connu par R. Exemple
: ?igraph, ?setwd, ?write.graph, etc. Vous pouvez également accéder à la liste des fonctions, objets, etc. en
lien avec votre requête en tapant : ??igraph, etc.
• Pour visualiser un graphe quelconque g, à n’importe quel moment : plot(g) ou tkplot(g)
• Enfin, la doc en ligne : http://igraph.org/r/doc/aaa-igraph-package.html

À la découverte d’igraph
Importer le paquetage dans votre environnement
library(igraph)

Savoir si un package est à jour


Connaître la version d’un package sur le dépôt distant

available.packages(repos="http://cran.biotools.fr")["igraph",
][["Version"]]

Connaître la version d’un package installé localement


Pour connaître la version d’un package donné, une fois la commande library(igraph) exécutée, vous pouvez
exécuter la commande suivante :

sessionInfo()

Dans le résultat de cette commande, vous devriez trouver la version de igraph installée sur votre système.
Exécutez la commande :

names(sessionInfo())

Question 1 : Expliquez ce que produit l’exécution de la commande précédente (la commande str() vous permet de
connaître le type de l’objet retourné par sessionInfo()). Quel est le rôle de la fonction names() ?
Question 1bis : sessionInfo()$otherPkgs (ou sessionInfo()[["otherPkgs"]]) permet de lister les autres packages
chargés (grâce aux appels antérieurs à la fonction library()) et names(sessionInfo()$otherPkgs) permet d’obtenir
leur nom.
Comment demander à R d’afficher, comme ci-dessous, seulement la version du package igraph installée sur votre
système, à partir d’un appel à la fonction sessionInfo() ou grâce à un appel à une autre fonction dont le rôle est
d’afficher la version d’un package donné~?

## [1] "1.2.2"
## [1] "1.2.2"
## [1] '1.2.2'

Mettre à jour un package donné

update.packages("igraph", repos='http://cran.biotools.fr')

Changer de répertoire de travail


Modifiez cette ligne pour vous placer dans votre répertoire préféré

# setwd("~/sync/Enseignement/GRIB/igraph")

Création de graphes
Création d’un graphe g1 à 10 sommets (numérotés de 1 à 10).

g1 <- graph.empty(n=10)

Création d’un graphe complet à 10 sommets

g2 <- graph.full(n=10)

Question 2 : Comment construire un graphe complet contenant également des arêtes de chaque sommet vers lui-
même (boucles=arcs allant d’un sommet vers lui-même) ? Pour répondre à cette question (ainsi qu’à la grande majorité
des questions de ce TP) : ?graph.full
Création d’un graphe étoilé à 10 sommets. Le mode "out" crée un graphe orienté, les arcs allant du centre vers la
périphérie

g3 <- graph.star(n=10, mode="out")

Question 3 : Comment construire un graphe étoilé non orienté (i.e. les arcs n’ont pas de direction, on parle alors
d’arêtes) ?
Création d’un anneau à 10 sommets

g4 <- graph.ring(n=10)

Visualisation
Pour visualiser un graphe (ici g4) :

plot(g4)

Pour exporter le dessin en PDF :

pdf("Graph.pdf")
plot(g4)
dev.off()

Question 4 : Comment exporter le graphe sous forme de fichier image (PNG par exemple) ?

Création de graphes plus intéressants


Définition d’une liste d’arcs grâce à un vecteur numérique V de longueur paire. Chaque couple d’élément d’indice 2i-
1, 2i (pour i allant de 1 à length(V)/2) représente les extrémités de chaque arc

edges <- c(1,2, 3,2, 2,4, 7,9)

Création directe d’un graphe orienté à partir de cette liste d’arêtes

g <- graph(edges)

Question 5 : Le graphe obtenu est un graphe orienté. Comment le transformer en graphe non orienté ?
Question 6 : Comment construire directement une version non-orientée de ce graphe à partir du vecteur edges, sans
devoir créer un graphe orienté au préalable ?
Question 7 : Au passage, quelle fonction booléenne appeler pour savoir si un graphe donné g est connexe
(i.e. connecté) ?
Question 8 : Expliquez le résultat des deux instructions ci-dessous. Que retourne la fonction cohesion() ?

cohesion(g3) # equals 0, because ?


cohesion(graph.full(5)) # equals |V|-1, because ?

Informations sur la structure du graphe


Pour connaître le nombre de sommets (vertices) et d’arêtes (edges) d’un graphe :

vcount(g)
## [1] 9
ecount(g)
## [1] 4
Pour avoir accès à la séquence des sommets et des arêtes d’un graphe g:

V(g)
## + 9/9 vertices, from 0d45d73:
## [1] 1 2 3 4 5 6 7 8 9
E(g)
## + 4/4 edges from 0d45d73:
## [1] 1->2 3->2 2->4 7->9

Question 9 : Que font les deux instructions R suivantes ? Expliquer le rôle de chacun de leurs arguments

neighbors(g, V(g)[1], mode = 1)


incident(g, V(g)[2], mode=c("all", "out", "in", "total"))

Deux sommets sont-ils connectés ?


Question 10 : Comment savoir si un graphe est orienté (dirigé) ou pas ?
Question 11 : Comment savoir si deux sommets i et j sont connectés (adjacents)

Modifier la structure d’un graphe


Pour rajouter un certain nombre de sommets à un graphe :

g5 <- add.vertices(g, 4)

Pour supprimer des sommets spécifiques :

g6 <- delete.vertices(g, c(2,5,7,9))

Pour ajouter des arêtes spécifiques :

g7 <- add.edges(g, c(4,2, 8,6, 1,3))

Pour supprimer certaines arêtes

g8 <- delete.edges(g, c(1,2))

Pour supprimer des sommets isolés :

g9 <- delete.vertices(g, V(g)[degree(g)==0])

Pour supprimer les boucles

g10 <- simplify(g, remove.loops = TRUE)

Attributs : sommets étiquettés, couleurs


Il est possible de créer un graphe avec 10 sommets rouges et 10 sommets bleus

g <- graph.empty() + vertices(letters[1:10], color="red") +


vertices(letters[11:20], color="blue")

Et de tirer aléatoirement (avec remise) 15 couples de sommets à relier

g <- g + edges(sample(V(g), 30, replace=TRUE), color="green")


Modifier les attributs d’un graphe
Par défaut, un graphe ne contient pas d’informations supplémentaires en dehors de sa structure. Il est heureusement
possible d’associer des attributs (des informations textuelles) aux sommets et arêtes du graphe, ainsi qu’au graphe lui-
même.

Du graphe
Pour ajouter un attribut "nom" de valeur "mon graphe" à un graphe g :

g$nom <- "mon graphe"

Pour connaître la valeur de l’attribut nom de mon graphe g :

g$nom
## [1] "mon graphe"

Pour supprimer l’attribut "nom" d’un graphe g :

g <- delete_graph_attr(g, "nom")

Des sommets
L’appel à la fonction vertices() plus haut a fait en sorte que chaque sommet possède un attribut "name" et un
attribut "color". Pour ajouter, par exemple, un attribut "size" de valeur 0.9 au sommet 3 du graphe g :

V(g)[3]$size <- 0.9

Pour connaître la valeur de l’attribut "size" pour chaque sommet de g :

V(g)$size
## [1] NA NA 0.9 NA NA NA NA NA NA NA NA NA NA NA NA NA NA
## [18] NA NA NA

Pour connaître la valeur de l’attribut "size" pour le sommet 3 de g :

V(g)[3]$size
## [1] 0.9

Pour supprimer l’attribut "size" sur les sommets de g :

g <- delete_vertex_attr(g, "size")

Des arêtes
Question 12 : l’appel précédent à la fonction edges() a permit de donner un attribut "color" à chaque arête. Comme
précédemment, quelles sont les 4 instructions R permettant de jouer avec les attributs des arêtes ?

## [1] NA NA "edge1" NA NA NA NA NA
## [9] NA NA NA NA NA NA NA
## [1] "edge1"

Travailler sur des données réelles


Pour importer un graphe à partir d’un fichier :

g1 <- read.graph("http://www.dil.univ-mrs.fr/~tichit/bin/tp1/depts.txt",
format="edgelist")
g2 <- read.graph("http://cneurocvs.rmki.kfki.hu/igraph/karate.net",
format="pajek")
g3 <- read.graph("http://www.dil.univ-mrs.fr/~tichit/bin/tp1/depts.lgl",
format="ncol")

Exporter vers un fichier CSV


Nous pouvons récupérer la liste des arêtes sous forme de data.frame et l’exporter vers un fichier texte de la façon
suivante :

el <- get.edgelist(g)
write.table(el, file = "graph.out", sep=";", row.names=FALSE,
col.names=FALSE)

Exporter vers un format standard


Pour exporter un graphe vers un des formats connus de igraph :

write.graph(g1, file='copy_depts.txt', format="edgelist")


write.graph(g2, file='copy_karate.net', format="pajek")
write.graph(g3, file='copy_depts.lgl', format="ncol")

Interaction avec d’autres logiciels


Cytoscape est une plate-forme logicielle open source pour la visualisation de réseaux d’interactions.
Question 13 : Citez deux formats de fichiers reconnus par igraph et Cytoscape. Ouvrez un graphe produit
par igraph vers Cytoscape.
Question 14 : Sous Cytoscape, ouvrez un réseau exemple (l’un des réseaux situé dans le
dossier $HOME/Cytoscape_vX.Y.Z/sampleData ou /usr/local/share/Cytoscape_vX.Y.Z/sampleData ), puis exportez
le dans le format le plus facilement reconnu par igraph (export CSV devrait être une bonne méthode. Il vous faudra
néanmoins modifier le fichier à l’aide d’un tableur, ou ouvrir puis récupérer les bonnes colonnes grâce
à read.table ou read.csv). Ouvrez-le avec igraph et affichez son nombre de sommets et d’arêtes.

Matrices d’adjacence
Récupérez, grâce à un code R classique le fichier CSV suivant et enregistrez-le sous forme de data frame, puis
comme matrice d’adjacence.

df <-read.table(file="http://www.dil.univ-mrs.fr/~tichit/bin/tp1/g1.csv",
header=TRUE, row.names=1, sep=";")
am <- as.matrix(df)

Il est possible maintenant d’en faire un graphe

g <- graph.adjacency(am, mode = "undirected")

L’idée de cet exercice est de déterminer si 2 graphes donnés se ressemblent, i.e. si ils possèdent des caractéristiques
similaires.
Question 15 : Développer un script R (i.e. une suite d’instructions R) qui permet de mesurer un graphe non-orienté
donné, c’est-à-dire, donner :

• nombre de sommets
• nombre d’arêtes
• degré minimal et maximal
• densité
• diamètre
• moyenne de la longueur des chemins (appelée également distance moyenne)
• coefficient de clustering (appelé également transitivité)
• la coreness maximale
• la maille

En ce qui concerne les 6 dernières caractéristiques, il vous sera demandé d’expliquer (ou de réexpliquer) leur définition.
Il ne vous est pas demandé d’explications très mathématiques, mais quelque chose d’assez précis et rigoureux pouvant
être compris par l’average scientist.

## name v.nb e.nb min.d max.d dens diam avg.path.len clust.coef kcore
girth
## 1 g1 89 218 2 7 0.02 11 4.0 0.40 3
3
## 2 g2 34 78 1 17 0.13 5 2.4 0.25 4
3
## 3 g3 89 218 2 7 0.05 12 5.0 0.40 3
3
## 4 gf 20 15 0 7 0.03 4 1.6 0.00 4
0

Une autre mesure intéressante est la distribution des degrés :

degree.distribution(g2)
## [1] 0.00000000 0.02941176 0.32352941 0.20588235 0.14705882 0.08823529
## [7] 0.05882353 0.00000000 0.00000000 0.02941176 0.02941176 0.00000000
## [13] 0.00000000 0.02941176 0.00000000 0.00000000 0.02941176 0.02941176

On peut afficher la distribution correspondante pour avoir une représentation visuelle

plot(degree.distribution(g3))

ferhat imane