• Aucun résultat trouvé

En Prolog III les relations unaires et binaires traduisent des conditions portant sur des arbres, comme « <aa,bb,cc> est différent de aa(bb,cc) » ou « 1 est supérieur à 0 ». Nous disposons de relations tout-à-fait générales, comme l'égalité entre arbres, et de relations spécifiques qui n'ont de sens que pour une catégorie bien particulière d'arbres, comme les relations d'ordre sur les nombres ou l'implication entre booléens.

Les relations ne sont pas des opérations1. Le propre d'une opération, appliquée à un n-uplet d'arbres, est de rendre un arbre à titre de résultat ; le propre d'une relation, appliquée à un n-uplet d'arbres, est d'être ou non vérifiée. Bien que définie sur des arbres ou des couples d'arbres, elle ne leur associe pas des éléments du domaine de Prolog III et, même si dans le langage courant un dit qu'une relation est « vraie » ou « fausse », il ne faut pas voir cela comme des occurrences des valeurs booléennes 1' et 0' du domaine de Prolog III.

Comme les opérations, les relations sont partielles. L'ensemble des arbres ou des couples d'arbres pour lesquels une relation est définie n'est pas nécessairement égal à l'ensemble de tous les arbres ou de tous les couples d'arbres.

Les relations binaires sont au nombre de sept : Egalité et inégalité

La condition a1 = a2

se lit « les arbres a1 et a2 sont égaux ». La condition

a1 # a2

se lit « les arbres a1 et a2 ne sont pas égaux ».

1 Rappelons que d'un point de vue mathématique, définir une relation binaire sur un ensemble D c'est choisir un sous-ensemble B de l'ensemble D ! D des couples d'éléments de D ; les couples appartenant à B sont dits vérifier la relation. De la même manière, définir une relation unaire sur D c'est choisir le sous-ensemble U de D des éléments pour lesquels la relation est vérifiée.

L'égalité des arbres est une relation qui se définit récursivement en affirmant que deux arbres a1 et a2 sont égaux si

- les étiquettes de a1 et a2 sont égales-au-sens-des-étiquettes - a1 et a2 ont le même nombre n de fils

- (si n ! 0) le premier fils de a1 est égal au premier fils de a2, le deuxième fils de a1 est égal au deuxième fils de a2, etc… jusqu'au n-ème fils de a1 qui est égal au n-ème fils de a2.

Bien entendu, ceci suppose que l'on a préalablement défini une égalité-des-

étiquettes. Pour que deux étiquettes soient égales, il faut

- qu'elles soient de même type (deux identificateurs, deux nombres, deux caractères etc…)

- qu'elles soient égales pour les critères d'égalité propres à leur type. Pour l'essentiel, ces critères sont les suivants :

- identificateurs : deux identificateurs sont égaux si leurs formes non abrégées s'épellent exactement de la même manière. On notera bien qu'il n'y a pas d'équivalence entre les lettres majuscules et les minus- cules. La “forme non abrégée” des identificateurs est expliquée au chapitre « Le contrôle et l'environnement des programmes ».

- caractères : deux caractères imprimables internationaux sont égaux si leur forme écrite est la même, ce qui équivaut à dire qu'ils ont la même représentation interne (code ASCII). Pour les caractères nationaux ou les caractères non imprimables il y a lieu de se référer à la documentation particulière du système Prolog III utilisé.

- nombres rationnels. L'égalité entre nombres entiers est une notion primitive, héritée des mathématiques, qui ne pose aucun problème. En ce qui concerne les nombres fractionnaires, si l'on sait que Prolog III les conserve en précision infinie et sous leur forme irréductible, là encore l'égalité. ne pose aucun problème.

- nombres flottants. L'égalité entre deux nombres flottants x et y, ou entre deux nombres x et y dont l'un au moins est flottant, est définie par une relation de la forme |x - y| !!!! ", où " est un seuil qui prend en compte l'ordre de grandeur de x et y, les particularités de la représentation des nombres flottants dans la machine utilisée et éventuellement une estimation de l'erreur commise dans l'expression où x et y apparaissent.

- les cas restants, c'est à dire les deux booléens 0' et 1', et le tuple vide

<> sont sans mystère : chacune de ces valeurs est différente des autres.

Implication La condition

a1 => a2

s'énonce : « les arbres a1 et a2 sont tous les deux des booléens et si a1 vaut 1' alors a2 vaut 1' ». Puisque a1 et a2 sont des booléens, il n'existe que quatre cas possibles et nous pouvons définir cette contrainte par un tableau :

a1 a2 la contrainte a1 => a2 est-elle satisfaite ?

0 ' 0 ' oui 0 ' 1 ' oui 1 ' 0 ' non 1 ' 1 ' oui Comparaisons numériques Les conditions a1 < a2 a1 <= a2 a1 > a2 a1 >= a2

sont vérifiées si les arbres a1 et a2 sont tous les deux des nombres et si a1 est inférieur (resp. inférieur ou égal, supérieur, supérieur ou égal) à a2

Relations unaires

Les relations unaires sont souvent appelées des relations de type, car elles concernent principalement la nature de l'étiquette du nœud initial de l'arbre sur lequel elles portent. Dans certains cas, elles mettent aussi en jeu le

nombre de fils du nœud initial. a !numt

a !chart

a !boolt

a !idt

Ces conditions sont vérifiées si le nœud initial de l'arbre a est étiqueté par, respectivement, un nombre, un caractère, un booléen, un identificateur. Aucune condition n'est imposée pour les autres nœuds.

a !tuple

Cette condition est vérifiée si le nœud initial de l'arbre a est <> , autrement dit si a est un PIII-tuple. Aucune condition ne doit être vérifiée par les autres nœuds.

a ::n

Cette condition se lit « n est un nombre entier non négatif et du nœud initial de a partent n branches ». Souvent mise en conjonction avec la précédente, elles équivalent alors, ensemble, à « a est un tuple de longueur n »

a !num

a !char

a !bool

Ces conditions sont vérifiées si a est une feuille, et si son unique nœud est éti- queté par un nombre (resp. un caractère, un booléen, un identificateur). Par conséquent : a !num équivaut à a ! n u m t et a : : 0 a ! c h a r équivaut à a ! c h a r t et a : : 0 a ! b o o l équivaut à a ! b o o l t et a : : 0 a ! i d équivaut à a ! i d t et a : : 0

7 . Contraintes

De la même manière que nous sommes passés des arbres aux termes, nous allons passer des conditions aux contraintes. Une condition était constituée par l'application d'une relation, entité mathématique, à un arbre ou un couple d'arbres, éléments du domaine de Prolog III. Une contrainte sera un objet syntaxique, formé à partir du symbole qui exprime une relation et un terme ou un couple de termes, sur lesquels on dira encore que la relation porte. Nous allons donc

- nous transporter sur un plan syntaxique1 - introduire les variables

Syntaxe

Dans les programmes Prolog III, les contraintes sont toujours exprimées au sein de systèmes de contraintes. Un système de contraintes est une suite finie de contraintes séparées par des virgules, encadrée par des accolades :

<système de contraintes> ::= { }

::= { <contrainte> {, <contrainte> } }

1 En expliquant les conditions sur des arbres nous n'avons pas pu faire autrement que de définir en même temps les symboles qui expriment les relations ; nous avons donc déjà donné l'essentiel de la syntaxe des contraintes. Bien entendu, une contrainte sur des termes sans variable n'est rien d'autre que l'expression écrite d'une condition sur des arbres.

<contrainte> ::= <terme> = <terme> ::= <terme> # <terme> ::= <terme> => <terme> ::= <contrainte de typage> ::= <contrainte Sup> ::= <contrainte Inf> <contrainte Sup>

::= <terme> <sup> <terme>

::= <contrainte Sup> <sup> <terme> <contrainte Inf>

::= <terme> <inf> <terme>

::= <contrainte Inf> <inf> <terme> <inf>

::= <

|

<=

<sup>

::= >

|

>=

<type d’arbre>

::= !idt

|

!boolt

|

!numt

|

!chart

|

!tuple

::= !id

|

!bool

|

!num

|

!char

<contrainte de typage>

::= <terme> <type d'arbre> ::= <terme> :: <terme>

Relativement à ce que nous savions déjà, cette syntaxe ajoute surtout un détail : il est permis d'agglutiner plusieurs contraintes <, !, > ou " à condition qu'elles soient toutes de type <, ! ou toutes de type >, ". On pourra donc écrire { 1< x< y!!!!3} à la place de { 1< x,x< y,y !!!! 3}

Exemples

Voici des contraintes syntaxiquement correctes :

X !num ( 1 ) F !id ( 2 ) A # B(I, J + 1) ( 3 ) <P, "Durand"> = <"Pierre", N> ( 4 ) A => B & C ( 5 ) 0 < T < 3X/4 + 5Y ( 6 )

et des formules qui ne sont pas des contraintes correctes :

4X + Z ( 1 )

T T ( X ) ( 2 )

A & B ( 3 )

(X = Y) & (Y = Z) ( 4 )

(1), (2) et (3) souffrent du même mal : ce sont des termes corrects, non des