I. Introduction▲
Prolog, abréviation de PROgrammation LOGique est un langage de programmation particulier et extraordinaire. En effet, il montre qu'il existe d'autres méthodes pour programmer un ordinateur que les méthodes impératives. En Prolog, on décrit ce que l'on sait, la base de faits, on décrit les interactions entre les connaissances, la base de règles, on pose une question et Prolog nous donne les réponses à cette question, il se débrouille tout seul pour les trouver à partir des renseignements fournis.
Avec Prolog, on traite évidemment les problèmes logiques, mais aussi la programmation par contraintes. Prolog pour sa puissance déclarative est utilisé en IA dans l'écriture de systèmes experts. On retrouve aussi Prolog pour les problèmes de Traitement Automatique du Langage Naturel (TALN), Prolog ayant d'abord été conçu pour cela !
On pourra consulter avec intérêt les exemples Prolog sur developpez.com
Toutefois, Prolog n'a pas originellement été conçu pour gérer le graphisme. On peut, néanmoins, interfacer assez facilement Prolog avec C, C++, ou Java. À l'aide de ces langages et de leurs bibliothèques graphiques, on peut utiliser Prolog dans des applications graphiques, l' IHM étant réalisée en C par exemple, le moteur IA en Prolog.
Cependant, il existe une possibilité de faire du graphisme en Prolog, c'est XPCE avec SWI-Prolog, gratuit, mais aussi Sictus-Prolog et Quintus-Prolog payants.
II. Présentation de XPCE▲
II-A. XPCE et Prolog▲
La bibliothèque XPCE a été créée pour fournir une interface graphique à SWI-Prolog. XPCE est écrit en C pour des raisons de rapidité. XPCE est très facilement utilisable avec Prolog, mais peut-être utilisé avec d'autres langages (Lisp par exemple). Les codes XPCE sont multiplateformes Unix/Windows.
XPCE est distribué avec le système SWI-Prolog, c'est une bibliothèque de base, aucune installation spéciale n'est requise. Avec SWI-Prolog, elle est automatiquement chargée dès qu'un de ses prédicats (par exemple new/2) est appelé, ou elle est explicitement chargée par l'instruction :- use_module(library(pce)). formulée au début d'un source Prolog. Sous Windows, pour pouvoir utiliser XPCE, il faut obligatoirement lancer plwin.exe. On trouvera ici tous les renseignements possibles sur XPCE.
II-B. XPCE n'est pas Prolog▲
Les données manipulées par Prolog consistent en variables logiques, atomes, entiers, réels et termes structurés (listes, tuples).
XPCE a des équivalents pour les atomes (name) , les entiers (XPCE int) , les nombres en virgule flottante (real).
Les variables logiques et les objets structurés n'ont pas d'équivalent en XPCE.
Lorsque Prolog utilise une structure pour représenter un produit, par exemple produit(Reference, Nom, Quantite), XPCE utilise un objet :
:- pce_begin_class(produit(reference, nom, quantite), object).
variable(reference, name, both, "Référence du produit").
variable(nom, string, both, "Nom du produit").
variable(quantite, int, both, "Quantité en stock").
initialise(P, Reference:name, Nom:string, Quantite:int) :->
"Creation à partir de la marque, ancienneté et "::
send(P, reference, Reference),
send(P, nom, Nom),
send(P, quantite,Quantite).
:- pce_end_class.
Au prompt on obtient :
?- new(P, produit(a25b47, 'Pc Portable', 4)).
P = @39784520/produit
Yes
Le prédicat new/2 (new(?Reference, +NewTerm)) crée un objet dans l'environnement XPCE.
La variable P est unifiée avec la référence @39784520 (@/1 indique une référence), la valeur 39784520 est garantie être unique. Prolog dans sa grande bonté indique le type de l'objet créé.
Les deux représentations Prolog et XPCE ont des propriétés différentes :
Égalité : Prolog ne peut pas faire la distinction entre deux instances du même terme produit(a25b47, 'Pc Portable', 4), alors qu'en XPCE, deux instances d'une même classe ayant les mêmes attributs sont deux entités différentes ;
Attributs : un attribut d'un terme Prolog peut être une variable logique ou bien être instancié (lié) avec une donnée Prolog. En revanche, celui d'un objet XPCE peut être assigné. L'assignation est destructive ;
Types : Prolog n'est pas un langage typé. XPCE est un langage typé dynamiquement et les attributs des objets XPCE peuvent avoir des types.
III. Programmation graphique avec XPCE▲
III-A. La première fenêtre▲
Nous allons d'abord créer des fenêtres et boîtes de dialogue très simples en lignes de code.
Sous le prompt Prolog tapons :
?- new(D, window('Ma Première Fenêtre')).
D = @39170088/window
Yes
Pour faire apparaître la fenêtre, on lui envoie un message :
?- send(@39170088, open).
Nous obtenons cette première fenêtre :
Nous constatons que tout n'est pas affiché. Pour que le titre soit entièrement lisible, nous changeons la taille de la fenêtre :
?- send(@39170088, size, size(250,100)).
Lorsque nous n'avons plus besoin d'utiliser cette fenêtre, il est bien de libérer la mémoire qui lui est affectée par un free(@39170088).
III-B. La première boîte de dialogue.▲
Nous aurions pu créer une boîte de dialogue. Comme il est assez pénible d'écrire les nombres, on peut utiliser des références. La référence se note avec @ et un atome, donc la première lettre doit être minuscule :
?- new(@d, dialog('Ma première boîte de dialogue.')).
Yes
? send(@d, size, size(300,50)).
Yes
?- send(@d, append, button(OK, message(@d, destroy))).
Yes
? send(@d, open).
Yes
On a ajouté un bouton de fermeture, son nom est OK, par défaut le texte du bouton est OK. Le message associé est l'envoi à la boîte de dialogue @d du message destroy.
III-C. Le premier programme XPCE.▲
Nous allons pouvoir écrire notre premier programme, le célèbre « Hello World ».
mon_premier_program :-
% on crée la fenêtre
new(D, window('Ma première fenêtre')),
% on lui donne la bonne taille
send(D, size, size(250, 100)),
% on crée un composant texte
new(T, text('Hello World !')),
% on demande à la fenêtre de l'afficher à peu près au milieu
send(D, display, T, point(80, 40)),
% on envoie à la fenêtre le message d'affichage.
send(D, open).
III-D. Le prédicat send▲
Comme on peut le constater, le prédicat send est très utilisé. Il sert à envoyer des informations aux objets.
Les deux premiers arguments de send sont l'objet visé, et le message envoyé ensuite à cet objet. En fonction de la cible et du message, il est ajouté ou non des paramètres supplémentaires. Par exemple, comme on peut le voir, le message open n'a pas de paramètre, alors que le message size en a un.
Le prédicat send a deux prototypes send/[2_12] ou send/2.
Nous avons donné une taille à nos fenêtres avec send(D, size, size(250, 100)), nous aurions pu écrire send(D, size(size(250, 100))) ce qui explique les deux versions de send : send(D, size, size(250, 100)) correspond à send/[2-12], et send(D, size(size(250, 100))) à send/2.
Parallèlement à send pour fournir des informations à un objet, on peut en obtenir avec le prédicat get qui lui aussi a deux formes get/3 et get/[3-13].
III-E. Un programme de calcul en XPCE▲
Ce programme permet de calculer la valeur d'une expression arithmétique à l'aide du prédicat is.
% Le prédicat de calcul de l'expression est très simple
calcule(Atom, A) :-
term_to_atom(Expr, Atom),
A is Expr.
% le prédicat principal du programme
calcul :-
% on crée la boîte de dialogue
new(D, dialog('Prolog au travail !')),
% on ajoute d'abord un champ de saisie précédé du
% libellé 'Saisissez votre calcul'
send(D, append,
new(ExprItem, text_item('Saisissez votre calcul '))),
% on ajoute ensuite un champ texte, un label en terme XPCE
send(D, append, new(Resultat, label(''))),
% on lui donne la couleur rouge
send(Resultat, colour, red),
% il sera écrit en caractères gras de taille 18
send(Resultat, font, font(times, bold, 18)),
% On ajoute un bouton de nom calcul, son libellé
% sera Calcul par défaut, et son action consistera
% a appelé le prédicat Prolog lance_calcul avec
% deux arguments, la saisie effectuée et le composant
% ou écrire le résultat
send(D, append,
button(calcul, message(@prolog, lance_calcul,
ExprItem?selection, Resultat))),
% on ajoute un bouton de nom cancel dont la fonction
% est de détruire la fenêtre
send(D, append,
button(cancel, message(D, destroy))),
% enfin on ouvre la fenêtre
send(D, open).
% le prédicat d'interaction entre la fenêtre et le prédicat calcul
lance_calcul(Expr, Resultat) :-
calcule(Expr, Res),
% le résultat est écrit dans une chaîne de caractères
% comme le sprintf du C
sformat(Str, '~w = ~w', [Expr, Res]),
% on envoie au label Resultat la chaîne
send(Resultat, selection, Str).
IV. L'éditeur de boîte de dialogue de XPCE▲
IV-A. Création d'une boîte de dialogue▲
XPCE propose un éditeur qui permet de construire rapidement des boîtes de dialogue et de gérer les actions entre les composants. Cet IDE s'obtient en affichant le manuel de XPCE (commande manpce. sous le prompt Prolog ou en cliquant sur le menu Help/XPCE (GUI) manual qui fait apparaître ceci :
Sur cette boîte de dialogue, on clique sur Tools/Dialog Editor pour obtenir
On donne un nom et notre première boîte de dialogue vide est faite :
Nous sommes automatiquement en mode de création.
IV-B. Signification des icônes▲
La signification des dessins de la barre du bas est indiquée lorsqu'on passe le pointeur de la souris dessus.
Ici, le pointeur était placé sur la deuxième icône à partir de la gauche.
IV-C. Insertion des composants dans la boîte de dialogue▲
Pour insérer un composant dans notre boîte de dialogue, il suffit de faire glisser le composant voulu de la barre des composants dans la boîte de dialogue. En 4 glisser-déposer notre boîte de dialogue est fabriquée.
IV-D. Modifications des variables des composants▲
Il faut maintenant définir les caractéristiques des différents composants. Pour cela, un double clic sur le composant voulu fait apparaître un éditeur de propriétés : par exemple si on clique sur le composant de saisie de texte :
Il faut valider par Entrée les modifications pour qu'elles soient prises en compte.
IV-E. Aide sur les composants▲
On peut obtenir une aide pour renseigner les différents champs en cliquant sur Help :
Les liens verts permettent une navigation hypertexte.
IV-F. Signification des symboles▲
V signifie qu'on a affaire à une propriété de l'objet (variable en langage XPCE).
Ainsi type est une variable du composant, la notation <-> signifie que cette variable est accessible dans les deux sens, -> on peut lui attribuer une valeur, <- on peut demander sa valeur.
Voici un tableau résumé des différents symboles :
V class - selector: type |
Variable inaccessible directement |
V class <- selector: type |
Variable pouvant être lue, mais pas modifiée |
V class <->selector: type |
Variable pouvant être lue et modifiée |
V class ->selector: type |
Variable qui ne peut qu'être lue |
M class ->selector: type … |
Méthode Send avec argument typé |
M class <- selector: type … -->type |
Méthode Get avec arguments typés, retournant une valeur de ce type |
R Class.attribute: type |
Variable de Classe avec type |
IV-G. Browser de classe▲
On peut obtenir un browser des classes en sélectionnant une des options du menu obtenu par un clic droit dans la page affichée.
On peut naviguer dans le browser de classe en cliquant sur les mots dans la barre en haut à droite ou sur les + dans le texte du dessous.
IV-H. Obtention du code associé dans un source Prolog▲
Une fois que toutes les valeurs des propriétés des composants ont été fixées, on peut obtenir le code correspondant à la boîte en glissant l'ID de la boîte de dialogue dans un fichier source Prolog.
On peut bien sûr modifier ce code à la main, en particulier le layout.
Pour visualiser la boîte de dialogue, écrivons un petit programme très court :
xpce_calcul :-
make_dialog(D, 'C_Prolog'),
send(D,open).
IV-I. Implémentation des actions des boutons▲
Il ne reste plus qu'à implémenter les actions des boutons Calcul et Cancel.
En cliquant sur le bouton Action de la boîte de dialogue initiale, on fait apparaître un bouton behaviour model.
En cliquant sur le bouton behaviour model, on fait apparaître une autre boîte de dialogue.
On fait glisser les différents composants de la boîte de dialogue C_prolog dans cette boîte, pour en définir les interactions.
Ici, on va faire interagir le bouton calcul avec le champ de saisie Expr_Item et le label d'affichage Resultat_Item. selection dans le rectangle de Resultat_Item représente la saisie utilisateur
Cette interaction appellera Prolog, il faut donc ajouter Prolog dans cette boîte, cela se fait par un clic droit sur une zone vide de la boîte de dialogue.
Un nom du fichier pour enregistrer le code Prolog est automatiquement proposé (ici C_Prolog.pl), on peut en saisir un autre. Le prédicat Prolog appelé est le prédicat lance_calcul du programme précédent. Pour le créer dans la fenêtre behaviour, il faut, en utilisant le clic droit sur la zone @prolog, ajouter un send port de type other.Il faut tout de suite taper le nom de ce port, c'est lance_calcul.
Cette opération de saisie du nom n'est pas évidente du tout, il faut y penser, car on ne voit apparaître que le petit triangle rouge de saisie au bord d'un trait vertical. Il n'est pas évident de comprendre qu'on a le droit d'écrire quelque chose !
Maintenant, avec un glisser de message du bouton calcul vers lance_calcul on crée une liaison symbolisée par une flèche noire, avec un disque au milieu. On glisse selection du champ de saisie vers le disque pour signifier que le champ de saisie sera utilisé comme argument.
Pour signifier que Resultat_Item doit être un argument du prédicat, on ajoute à l'aide du clic droit un « get port » self.
Ensuite, on fait glisser le self vers le rectangle « lance_calcul », le chiffre 2 apparaît au milieu de la flèche. L'interaction entre le bouton, le champ de saisie et le label d'affichage est déclarée.
Comme l'IDE ne gère pas les couleurs ni les fontes, on peut ajouter à la boîte de dialogue une méthode initialise qui s'en chargera.
Il ne nous reste plus qu'a faire glisser comme précédemment l'ID de la boîte de dialogue dans un fichier programme Prolog (C_Prolog.pl ou un autre).
dialog('C_Prolog',
[ object :=
C_Prolog,
parts :=
[ C_Prolog := dialog('Prolog au travail !'),
Expr_Item := text_item(text_item),
Resultat_Item := label(name, 'I'),
Calcul := button('Calcul'),
Cancel := button('Cancel')
],
modifications :=
[ Expr_item := [ label := 'Saisissez votre calcul'
],
Calcul := [ default_button = @on
]
],
layout :=
[ area(Text_item,
area(20, 15, 300, 24)),
area(Name,
area(20, 65, 300, 18)),
area(Calcul,
area(100, 110, 80, 24)),
area(Cancel,
area(220, 110, 80, 24))
],
behaviour :=
[ Calcul := [ message := message(@prolog,
lance_calcul,
Expr_Item?selection,
Resultat_Item)
]
],
initialise :=
[]
]).
L'action des boutons est définie dans la section behaviour. On peut donc ajouter aisément le code du bouton Cancel qui consiste à envoyer le message destroy à la boîte de dialogue. On ajoute à la fin les codes manquants pour l'initialisation de la couleur et la taille des fontes.
On a rajouté dans le source le code des prédicats, calcule et lance_calcul et le programme est terminé.
dialog('C_Prolog',
[ object :=
C_Prolog,
parts :=
[ C_Prolog := dialog('Prolog au travail !'),
Expr_Item := text_item(text_item),
Resultat_Item := label(name, ''),
Calcul := button('Calcul'),
Cancel := button('Cancel')
],
modifications :=
[ Expr_Item := [ label := 'Saisissez votre calcul'
],
Calcul := [ default_button = @on
]
],
layout :=
[ area(Expr_Item,
area(20, 15, 300, 24)),
area(Resultat_Item,
area(20, 65, 300, 18)),
area(Calcul,
area(100, 110, 80, 24)),
area(Cancel,
area(220, 110, 80, 24))
],
behaviour :=
[ Calcul := [ message := message(@prolog,
lance_calcul,
Expr_Item?selection,
Resultat_Item)
],
Cancel := [
message := message(C_Prolog, destroy)
]
],
initialise :=
[
send(Resultat_Item, colour, red),
send(Resultat_Item, font, font(times, bold, 18))
]
]).
calcule(Atom, A) :-
term_to_atom(Expr, Atom),
À is Expr.
lance_calcul(Expr, Resultat) :-
calcule(Expr, Res),
sformat(Str, '~w = ~w', [Expr, Res]),
send(Resultat, selection, Str).
xpce_calcul :-
make_dialog(D, 'C_Prolog'),
send(D,open).
On obtient :
IV-J. Construction d'un programme Prolog▲
Pour terminer, on peut créer un exécutable indépendant appelant Prolog.
Sous le prompt Prolog, on tape
?- qsave_program('xpce_calcul.exe', [goal(xpce_calcul), stand_alone(true)]).
Nous obtenons un programme xpce_calcul.exe qui devra être placé dans le répertoire /Program Files/pl/bin pour fonctionner correctement.
Un double clic sur xpce_calcul.exe dans l'explorateur Windows permet le lancement.
V. Interfaçage de Prolog avec d'autres langages, exemple en C▲
On peut interfacer Prolog avec Java ou C, tout en gardant le moteur IA de Prolog. Une bibliothèque JPL, est proposée par SWI-Prolog pour l'interfaçage avec Java.
Nous développerons ici une liaison avec C++ à l'aide d'une Dll d'appel à SWI-Prolog écrite en C. Le programme est écrit avec Visual C6. Cet exemple a été testé sous Windows XP Pro, pack 2 et l'IHM est téléchargeable ici.
On reprend le programme Prolog de calcul da la valeur d'une expression arithmétique, (calcul qui n'est pas simple à programmer en C !).
L' IHM écrit en C++ permet de saisir cette expression, à l'aide d'une dll écrite en C, le programme appelle Prolog pour le calcul de l'expression, et ensuite le résultat du calcul est affiché.
V-A. Code Prolog▲
Le code Prolog est uniquement celui de l'appel au calcul et est contenu dans un fichier source Prolog appelé calcule.pl.
calcule(Atom, A) :-
term_to_atom(Expr, Atom),
À is Expr.
V-B. Code C de la Dll d'appel à Prolog▲
Le code de la dll, de nom calcule.dll, pour appeler Prolog est contenu dans le fichier calcule.c.
Ce source est inspiré de la présentation de l'interfaçage Prolog/C de la documentation de SWI-Prolog.
#include <stdio.h>
#include <SWI-Prolog.h>
#define MAXLINE 1024
/* Énumération de quelques types Prolog */
typedef enum {T_NIL, T_ATOM, T_INT, T_DOUBLE, T_STRING, T_LIST, T_COMPOUND, T_UNKNOWN } Pl_Type;
Pl_Type Pl_GetType(term_t u)
{
/* Fonctions de test du type du terme Prolog u */
if (PL_is_atom(u))
return T_ATOM;
if (PL_is_string(u))
return T_STRING;
if (PL_is_integer(u))
return T_INT;
/* Petite particularité les float au sens Prolog sont des
* doubles au sens C
*/
if (PL_is_float(u))
return T_DOUBLE;
if (PL_is_list(u))
return T_LIST;
if (PL_is_compound(u))
return T_COMPOUND;
return T_UNKNOWN;
}
/* Une des méthodes pour initialiser Prolog, est de lui passer le nom du
* programme appelant
*/
__declspec(dllexport) void Init_Prolog(char *prog)
{
char *plav[2];
plav[0] = prog;
plav[1] = NULL;
/* initialise Prolog , si cette initialisation échoue
* on sort avec le code d'erreur 1
*/
if ( !PL_initialise(1, plav) )
PL_halt(1);
}
/* On passe à la fonction d'appel deux chaînes in et out
* in pour les données d'entrée
* out pour les données de sortie, out est supposée assez longue
*/
__declspec(dllexport) void Appel_Prolog(char *in, char *out)
{
char expression[MAXLINE] = {0};
/* le predicat appelé est dans le fichier Prolog calcule.pl
* passé en argument de la ligne de commande du compilateur plld
*/
predicate_t pred = PL_predicate("calcule", 2, "user");
term_t h0 = PL_new_term_refs(2);
int ival, rval;
double fval;
strcpy(expression, in);
PL_put_atom_chars(h0, expression);
rval = PL_call_predicate(NULL, PL_Q_NORMAL, pred, h0);
switch(Pl_GetType(h0+1))
{
case T_INT :
PL_get_integer(h0+1, &ival);
sprintf(out, "%d", ival);
break;
case T_ DOUBLE :
PL_get_float(h0+1, &fval);
sprintf(out, "%lf", fval);
break;
default :
strcpy(out, "Problème de calcul");
break;
}
}
__declspec(dllexport) void Fin_Prolog(void)
{
/* Fonction inverse de PL_initialise */
PL_cleanup(0);
}
Nous ne développerons pas ici les différents détails d'implémentation, les renseignements sur les différentes fonctions de préfixe PL_ peuvent être trouvés à cette adresse.
Pour compiler ce source, dans un premier temps et pour éviter les problèmes d'accès aux répertoires, il vaut mieux mettre les fichiers calcule.c et calcule.pl dans le répertoire /Program Files/pl/bin.
La compilation a lieu avec la commande :
plld -dll -o calcule.dll calcule.c calcule.pl.
Le compilateur plld est fourni avec SWI-Prolog.
V-C. Code C++ de l'IHM▲
Il a été créé une application Visual C6 « dialogbased » utilisant MFC.
Toujours pour des problèmes de chemin d'accès, il est préférable de lancer le programme dans le répertoire/Program Files/pl/bin.
Un exemple de résultat est :
Le seul code intéressant est l'interaction avec Prolog, faite dans le fichier calculedlg.cpp.
V-C-1. Déclaration des types de fonctions et des fonctions▲
typedef void T_Init_Prolog(char *);
typedef void T_Appel_Prolog(char *, char *);
typedef void T_Fin_Prolog(void);
T_Init_Prolog *Init_Prolog;
T_Appel_Prolog *Appel_Prolog;
T_Fin_Prolog *Fin_Prolog;
V-C-2. Appel de la Dll et initalisation de Prolog▲
BOOL CCalculeDlg::OnInitDialog()
{
CDialog::OnInitDialog();
/* Set the icon for this dialog. The framework does this automatically */
/* when the application's main window is not a dialog */
SetIcon(m_hIcon, TRUE); /* Set big icon */
SetIcon(m_hIcon, FALSE); /* Set small icon */
/* TODO: Add extra initialization here */
/* Chargement de la Dll appelant Prolog */
hdl = LoadLibrary("D:/Program Files/pl/bin/calcule.dll");
if (hdl != NULL)
{
Init_Prolog = (T_Init_Prolog *)GetProcAddress(hdl, "Init_Prolog");
Appel_Prolog = (T_Appel_Prolog *)GetProcAddress(hdl, "Appel_Prolog");
Fin_Prolog = (T_Fin_Prolog *)GetProcAddress(hdl, "Fin_Prolog");
if (Init_Prolog == NULL || Appel_Prolog == NULL || Fin_Prolog == NULL)
{
AfxMessageBox("Chargement des fonctions de la dll incorrect");
EndDialog(1);
}
/* Ici IL FAUT initaliser Prolog avec le nom de l'exécutable qui
* lance Prolog (ici c'est la Dll calcule.dll, donc on met "calcule.dll" ou "calcule"
*/
Init_Prolog("calcule");
}
else
{
AfxMessageBox("Chargement de la dll incorrect");
EndDialog(1);
}
/* Autres initalisations */
return TRUE; /* return TRUE unless you set the focus to a control */
}
V-C-3. Appel du prédicat de calcul Prolog▲
void CCalculeDlg::OnOK()
{
/* TODO: Add extra validation here*/
char in[256], out[256];
GetDlgItemText(IDC_EDIT1, in, 256);
Appel_Prolog(in, out);
SetDlgItemText(IDC_STATIC2, CString(in) + CString(" = ") + CString(out));
}
Cet interfaçage avec le C++ est relativement simple à réaliser, mais il n'est pas portable. Il faut le refaire à chaque fois que l'on change d'environnement de développement alors que le code Prolog reste identique. Le code complet de l'IHM est téléchargeable ici.
VI. Conclusion▲
L'apprentissage de l'IDE demande évidemment un certain temps (comme pour tous les IDE).
XPCE permet de faire rapidement des applications graphiques portables et entièrement en Prolog, sans installer de bibliothèques externes. Pour des applications graphiques complexes ou nécessitant des composants graphiques propres à certaines bibliothèques, on peut interfacer Prolog avec un autre langage tel que C, C++ ou Java. Prolog est un langage très souple et s'intègre très bien aux autres technologies existantes.