Introduction à Graphviz

Graphviz ?

Graphviz (Graph Visualization Software) est un logiciel libre (sous licence http://www.eclipse.org/legal/epl-v10.html) de représentation de graphes. Il a été créé à l’origine par les laboratoires d’AT&T et est multiplateforme. Il permet donc de représenter des graphes très simplement, et de les exporter en de multiples formats : png, postscript…

Installation

Pour installer Graphviz dans une distribution Debian, il suffit donc :

apt-get install graphviz

Ainsi, nous avons tous les paquets nécessaires installés : dot (un interpréteur du language DOT), dotty (interface graphique)…

DOT

Afin de représenter des graphes, nous pouvons donc utiliser le language DOT. C’est un language ultra simple qui possède quelques similitudes avec le C.

Interpréteurs

Il existe plusieurs interpréteurs du language DOT, chacun ayant ses propres spécificités :

  • dot génère des graphes sous la forme d’arbres hiérarchiques,
  • circo est plus adapté aux rendus circulaires,
  • sfdp est plus adapté aux graphes non-orientés de très grande taille,
  • neato cherche à représenter les graphes de façon la plus homogène, en réduisant autant que possible la distance entre deux sommets.

Il convient donc d’utiliser l’interpréteur le plus adapté au rendu que l’on désire.

Arcs et sommets

Pour représenter un graphe, on le précise entre accolades :

graph monGraph {
     // Les éléments du graph seront placés à l'intérieur de ces accolades.
}

Comme en C, il est possible de commenter à l’aide des // ! Pratique :)

Voyons comment remplir notre graphe. Pour ajouter un élément à notre graphe, rien de plus simple ! Mettons le code suivant dans le fichier monGraph.dot :

graph monGraph {
    // On ajoute l'élément a.
    a
}

Sortons ensuite le graph en format png (de nombreux formats de sortie sont disponibles, voir en fin d’article):

dot -Tpng monGraph.dot -o monGraph.png

On obtient :

Relions deux éléments :

graph monGraph {
    // On relie l'élément a à b.
    a -- b;
}

On obtient :

Et avec une flèche, autrement dit faire un graphe orienté :

digraph monGraph {
    // On relie l'élément & à b avec une flèche.
    a -> b;
}

On obtient :

On remarquera l’importance du mot-clé digraph pour créer des graphes orientés, au lieu de graph pour les graphes non-orientés.

Et comment faire pour en relier trois ?

digraph monGraph {
    // On relie l'élément à a aux éléments b et c.
    a -> {b, c}
}

On obtient :

Attributs

Il est possible d’associer des attributs à chaque sommet du graph : couleurs, label, forme…

La synthaxe reste simple :

Labels

graph monGraph {
    a [label="Hello World !"];
    b [style=filled fillcolor=blue];
    a -- b;
}

De cette façon, le sommet a se nomme désormais “Hello World !" (et non plus “a”), et le sommet b est bleu :

La liste des attributs est conséquente et disponible sur cette page.

Il existe un grand nombre d’attributs, il est impossible de tous les détailler ici, mais voici déjà quelques attributs pratiques qui permettent de générer de jolis graphes :

Couleur et direction des arcs

digraph monGraph {
    a -> b [dir=both];
    c -> b [dir=none color="red:orange;0.25:yellow"];
}

Je pense que l’on peut se passer d’explications :

La liste des couleurs disponibles est présente sur le site officiel.

Forme des flèches

digraph monGraph {
    a -> b [arrowhead=crow arrowsize=2];
    c -> b [arrowhead=rveeoinv];
}

Ici, quelques explications sont requises. Pour modifier la tête de la flèche, on utilise l’attribut arrowhead (on utilisera arrowtail pour modifier la queue de la flèche) auquel on vient renseigner le style souhaité parmi les 11 choix de base. C’est ce qui a été fait entre a et b ici. On peut également jouer sur la taille de la tête de flèche par un facteur via arrowsize .

Entre c et b cependant, la chose est différente. On a *combiné deux formes de base auxquelles on a ajouté deux lettres : r et o .

On a donc créé une nouvelle forme qui se compose comme suit :

  • la partie droite de la forme de base vee : rvee
  • le contour de la forme de base inv : oinv

On assemble le tout, et on obient donc :

Forme des sommets

Outre les arcs, il est possible de modifier la forme d’ellipse par défaut pour les sommets.

digraph monGraph {
    a [shape="rectangle"];
    a -> b;
}

L’attribut concerné ici est donc shape auquel on renseigne la forme désirée. Cette forme peut se baser sur des polynômes, du HTML like ou du personnalisé.

digraph monGraph {
    {
        node [shape=plaintext]; // on supprime le contour en ellipse des sommets suivants
        struct1 [label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
        <TR><TD>Ceci</TD><TD PORT="f1">est</TD><TD PORT="f2">un</TD><TD PORT="f3">test</TD></TR>
        </TABLE>
        >];
    } // on referme le groupe
    b -> c; // les sommets ont la forme elliptique par défaut
}

Cet exemple en HTML donne :

On peut ainsi “regrouper” certains éléments du graphe pour leur appliquer un traitement commun (une couleur, un label..) en les plaçant entre accolades.

Contrainte et forme des arcs

digraph monGraph {
    a -> c [constraint=false];
    a -> b;
    c -> b;
}

On annule ici toute contrainte entre a et c, contrairement à a et b ou c et b :

Pour contrôler la forme des arcs, on peut utiliser l’attribut splines avec les valeurs suivantes :

  • none : les arcs ne sont pas affichés
  • line : les arcs sont représentés par un segment
  • polyline : les arcs sont représentés par plusieurs segments
  • curved : les arcs sont représentés courbés.

Si cet attribut n’est pas précisé, le compilateur sélectionne automatiquement le plus adapté.

Couleurs, polices, images

Pour colorer le fond d’un sommet, on peut utiliser l’attribut fillcolor en précisant style=filled. Pour colorer un label, on utilise l’attribut fontcolor et on peut préciser sa taille en points avec fontsize :

digraph monGraph {
    a [fillcolor=blue style=filled]; // On colore a en bleu
    b [label="Sommet"];
    a -> c;
    a -> b [fontcolor=red label="Arc"]; // On nomme l'arc et on colore le texte en rouge.
    c -> b;
}

Il est également possible d’insérer des images via image. Seuls les formats suivants sont supportés :

  • JPEG
  • PNG
  • GIF
  • BMP
  • SVG
  • Postscript

Ressources

Le site officiel de Graphviz contient une documentation extrêmement complète. Je vous invite à y jeter un coup d’oeil et à garder ces liens sous le coude, et notamment :