• Aucun résultat trouvé

Syntaxe

Nous en arrivons enfin aux programmes Prolog III. Ceux-ci sont constitués de règles ; chacune comporte une tête, qui est un terme, et une queue formée d'une suite de buts et d'un système de contraintes. La suite de buts peut être vide, le système de contraintes aussi. Quand le système de contraintes est vide, il peut être omis.

<règle> ::= <tête>

-> { <but> } [ , <système de contraintes> ] ;

<requête>

::= { <but> } [ , <système de contraintes> ] ; <but>

::= /

::= <terme> <tête>

::= <terme>

Voici des exemples de règles correctes :

r e p a s ( X , Y , Z ) - > h o r s _ d _ o e u v r e ( X ) p l a t ( Y ) d e s s e r t ( Z ) ;

s o m m e ( < X > . L , S ) - > s o m m e ( L , S 0 ) , { S = S 0 + X } ;

p o u l e s _ l a p i n s ( P , L , P + L , 2 P + 4 L ) - > ;

Pour activer un programme on doit composer une requête. Une requête est la même chose qu'une queue de règle. Voici des exemples de requêtes cor- rectes :

h o r s _ d _ o e u v r e ( X ) p l a t ( Y ) d e s s e r t ( Z ) ;

r e p a s ( H , s o l e , D ) , { H # s a l a d e } ;

p o u l e s _ l a p i n s ( P , L , 1 6 , 4 4 ) ;

c i r c u i t ( A , B , C ) / , { C | A & ~ B = 0 ' , D = > C , D # B } ;

Signification d'un programme Prolog III

Examinons maintenant la signification d'un programme Prolog III. Elle est double : d'une part il constitue la définition récursive d'un ensemble d'arbres qui sont considérés comme des faits vrais par le programmeur ; c'est ce qu'on appelle la sémantique déclarative du langage. D'autre part, un programme se traduit, pour l'interprète de Prolog III, en une suite d'actions à exécuter, de deux sortes : des résolutions de systèmes de contraintes et des appels de procédures. Nous appellerons cela la sémantique opérationnelle de Prolog III. L'ensemble des faits définis par un programme Prolog III

Un programme est fait de règles de la forme :

t0  t1 t2 … tn , S ; (1)

où t0 est un terme, t1 … tn sont des termes1 et S est un ensemble de

contraintes. Nous savons que chaque affectation A de l'ensemble des variables de cette règle transforme les termes ti en des arbres ai = ti/A et

l'ensemble S de contraintes en un ensemble C = S/A de conditions sur des

arbres. Par conséquent, une règle telle que (1) engendre tout un ensemble de règles portant sur des arbres, une pour chaque affectation A qui rend vraies

les conditions C = S/A, de la forme :

a0  a1 a2 … an ; (2)

1 Nous ignorerons pour le moment le cas de la coupure /, qui peut figurer dans une queue

Une telle règle sans variable exprime une propriété logique, qui s'énonce : « si a1, a2 … an sont des faits, alors a0 est un fait ».

Dans le cas n = 0 on a une règle sans queue :

a0  ; (3)

la propriété logique correspondante est tout simplement « a0 est un fait ». Dans ces conditions, l'ensemble qu'un programme Prolog III définit est le plus petit ensemble de faits satisfaisant à toutes les propriétés logiques engendrées par les règles du programme. Ce dernier est donc composé de règles qui énoncent des faits explicites (les règles sans queue et sans variable, du type (3)) et de toutes les autres règles, qu'on peut voir comme des procédés de déduction pour produire les faits implicites.

Considérons par exemple le programme très simple :

p r i x ( f l e u r s , 1 2 0 ) - > ; p r i x ( c h o c o l a t s , 9 0 ) - > ; p r i x ( v i n , 5 0 ) - > ; p r i x ( p o i s s o n _ s e c h e , 4 0 ) - > ; c a d e a u ( c h o c o l a t s ) - > ; c a d e a u ( v i n ) - > ; c a d e a u ( f l e u r s ) - > ; c a d e a u _ p a s _ c h e r ( X ) - > c a d e a u ( X ) p r i x ( X , P ) , { P < = 1 0 0 } ;

Compte tenu des contraintes, la dernière règle donne lieu aux règles sur des arbres :

c a d e a u _ p a s _ c h e r ( p o i s s o n _ s e c h e ) - > c a d e a u ( p o i s s o n _ s e c h e )

c a d e a u _ p a s _ c h e r ( c h o c o l a t s ) - > c a d e a u ( c h o c o l a t s ) p r i x ( c h o c o l a t s , 9 0 ) ; c a d e a u _ p a s _ c h e r ( v i n ) - > c a d e a u ( v i n ) p r i x ( v i n , 5 0 ) ;

et puisque cadeau(chocolats), prix(chocolats, 90), c a d e a u ( v i n )

et p r i x ( v i n , 5 0 ) sont des faits, on en déduira que c a d e a u _ p a s _ c h e r ( c h o c o l a t s ) et c a d e a u _ p a s _ c h e r ( v i n ) sont eux

aussi des faits. Ce programme définit donc l'ensemble de faits : { p r i x ( f l e u r s , 1 2 0 ), prix(chocolats, 90), prix(vin, 50),

p r i x ( p o i s s o n _ s e c h e , 4 0 ), cadeau(chocolats), cadeau(vin),

c a d e a u ( f l e u r s ), cadeau_pas_cher(chocolats) ,

c a d e a u _ p a s _ c h e r ( v i n ) }.

Seuls les deux derniers de ces faits n'étaient pas explicites. Exécution d'un programme

Nous venons de montrer quelle est l'information implicite contenue dans un programme Prolog III. Examinons maintenant en quoi consiste son exécution par la machine. Cette exécution vise à résoudre le problème suivant : « étant donnés une suite t1 t2 … tn de termes et un système S de

contraintes, trouver les valeurs des variables qui transforment les termes ti

en des faits définis par le programme et les contraintes de S en des conditions verifiées »

Ce problème sera soumis à la machine sous la forme d'une requête

t1 t2 … tn , S

- si la suite t1 t2 … tn est vide, alors la requête se résume à demander la

résolution du système S

- si le système S est vide et n = 1 alors la requête se résume à la question « pour quelles valeurs des variables le terme t1 se transforme en un fait défini par le programme ? »

Pour expliquer comment Prolog III calcule la réponse à ces questions nous allons introduire une machine abstraite. Il s'agit d'une machine non déterministe, dont l'unique instruction de base est décrite par les trois formules suivantes :

(1) ( W, t0 t1 … tn , S ) (2) s0  s1 … sm , R

(3) ( W, s1 … sm t1 … tn , S  R  { s0 = t0 } )

La formule (1) représente l'état de la machine à un instant donné. La requête courante est t0 t1 … tn , S. W est l'ensemble des variables auxquelles on

s'intéresse.

La formule (2) représente la règle du programme utilisée pour changer d'état. Au besoin, on a renommé certaines de ses variables, pour qu'elle n'en ait aucune de commune avec (1). Les autres règles du programme auraient pu être employées aussi bien ; utiliser celle-ci plutôt qu'une autre résulte d'un choix.

La formule (3) représente le nouvel état de la machine, après l'application de la règle (2). Le passage dans cet état n'est possible que si le système de contraintes S  R  { s0 = t0 } possède une solution pour laquelle chacun des termes de la suite s1 … sm t1 … tn représente un arbre bien défini.

Pour répondre à la requête t0 … tn , S la machine partira de l'état initial

( W, t0 … tn, S ), où W est l'ensemble des variables qui figurent dans la

requête, et passera dans tous les états qu'elle peut atteindre en répétant l'opération de base ci-dessus. Bien entendu, le choix exprimé par la formule

(2) n'est pas laissé au hasard : Prolog III fait en sorte que toutes les règles

soient successivement essayées1, dans l'ordre où elles ont été écrites dans le

programme. Ainsi, la machine Prolog III est en réalité la machine (déterministe) qui produit toutes les exécutions possibles de la machine non déterministe définie par les expressions (1), (2), (3).

Chaque fois qu'il parviendra à un état de la forme ( W, , S )

c'est-à-dire dont la suite de buts est vide, Prolog III fournira comme réponse la solution du système S sur l'ensemble de variables W.

Par exemple, à partir de la requête très simple

c a d e a u _ p a s _ c h e r ( X ) ;

des états de la machine seront (on ne montre pas les étapes promises à échouer) :

{ X } , c a d e a u _ p a s _ c h e r ( X ) , { } ;

utilisation de la règle cadeau_pas_cher(X) -> etc… :

{ X } , cadeau(X') prix(X',P') ,

{ P100,cadeau_pas_cher(X)=cadeau_pas_cher(X')};

qui se simplifie en :

{ X } , cadeau(X') prix(X',P') , { P100,X=X'};

1 Ou tout au moins toutes les règles raisonnables, c'est-à-dire toutes sauf celles qui de

utilisation de la règle cadeau(chocolats) ->; :

{ X } , prix(X',P') ,

{ P '100,X=X',cadeau(X')=cadeau(chocolats)};

qui se simplifie à son tour en :

{ X } , prix(X',P') ,

{ P '100,X=X',X'=chocolats};

utilisation de la règle prix(chocolats,90) ->; :

{ X } , , { P '100,X=X',X'=chocolats,

p r i x ( X ' , P ' ) = p r i x ( c h o c o l a t s , 9 0 ) } ;

lequel se simplifie en :

{X}, , { P '100,X=X',X'=chocolats,P'=90)};

La suite de buts étant devenue vide, Prolog III affiche alors la solution du système courant S = {P'100,X=X',X'=chocolats,P'=90)}, ou plutôt la

partie intéressante de cette solution, soit

{ X = c h o c o l a t s }

ensuite Prolog III explore les autres exécutions possibles de la machine non déterministe (1), (2), (3) ; c'est ainsi que la solution

{ X = v i n }

est affichée peu après.

Arbres, tuples, chaînes et listes

1. Introduction