• Aucun résultat trouvé

Prolog III est un langage qui manipule, outre les arbres que l’on supposera bien connus, les tuples, les expressions numériques linéaires, les formules booléennes. Tous ces objets peuvent être solutions de système de contraintes.

Nous allons voir dans ce paragraphe, à travers quelques petits exemples comment manipuler ces différents objets.

ATTENTION. Quand on “joue” avec Prolog III, comme vous allez probable- ment le faire maintenant, on tape un petit programme, qu'on essaye, puis un autre, et encore un autre, etc… Or Prolog III conserve tous ces programmes en mémoire, et on finit immanquablement par obtenir des erreurs qui traduisent des conflits de noms comme « Erreur 46: Regle deja definie ». Pour l'éviter remettez à zéro l'espace des règles, entre deux exemples, en exécutant la commande :

> kill_module(""); {}

>

Les tuples et les chaînes de caractères

Un tuple est une suite d’objets Prolog. Le tuple noté <a1,a2,a3> représente la suite de longueur 3 formée des éléments a1, a2, a3, quelle que soit la nature de ces éléments. Le tuple vide s’écrit naturellement <>. On peut indiquer qu’une variable x est de type tuple en ajoutant la contrainte x !tuple. On peut aussi imposer que x soit un tuple de longueur n donnée par x :: n . L’opération de base sur les tuples est la concaténation, notée par . (point). Observons les exemples suivants :

> {x = <1,2,3>.<4,5>}; {x=<1,2,3,4,5>}

> {x = y.z, y::2, y = <1,2>}; {x=<1,2>.z, y=<1,2>}

>

N.B. Les exemples précédents sont donnés à titre explicatif et la réponse fournie par la machine peut avoir une forme différente, mais équivalente.

Si on souhaite obtenir le premier élément x d’un tuple l, il suffit de l’unifier avec un terme de la forme <x>.r , qui dénote la concaténation d'un tuple <x> à un seul élément et d'un tuple r quelconque. Ceci nous permet d’écrire les deux règles element_de en Prolog III :

> element_de(x,<x>.r) - > ;

> element_de(x,<y>.r) -> element_de(x,r) , {x#y};

>

puis on peut demander :

> element_de(1, <3,5,1>); {} > element_de(x, <3,5,1>); {x=3} {x=5} {x=1} > element_de(9, <3,5,1>); >

Les chaînes de caractères sont des tuples dont les éléments sont des caractères. La chaîne notée "abc" est le tuple de caractères <`a`,`b`,`c`> .

On peut mélanger les chaînes et les tuples, notamment à l'aide de l’opéra- teur de concaténation. On peut imposer à une variable de type chaîne une longueur n connue (le nombre de caractères) en installant la contrainte x :: n .

> {x=y.<`-`>."au-".<`f`,`e`,`u`>, y="pot"}; {x="pot-au-feu", y="pot"}

L’arithmétique et les contraintes numériques

Voyons le problème suivant : on dispose d’un certain nombre de chats, d'oiseaux, les nombres de têtes et de pattes et on demande d’exprimer les relations liant ces nombres. Si on appelle c le nombre de chats, o le nombre d’oiseaux, t le nombre de têtes, p le nombre de pattes, les relations sont les suivantes :

t = c + o et p = 4c + 2o et s’expriment naturellement en Prolog III :

> {t=c+o, p=4c+2o}; {t=o+c, p=2o+4c}

>

Prolog répond par un système d’équations, ce qui signifie que le système est soluble. Allons un peu plus loin en donnant des valeurs à certaines variables. Comme il s’agit d’un système de deux équations à quatre inconnues, nous allons fixer les valeurs de deux des variables pour obtenir les valeurs des deux autres. Fixons le nombre de pattes à 14 et le nombre de têtes à 5 :

> {t=c+o, p=4c+2o, p=14, t=5}; {t=5,c=2,o=3,p=14}

>

Prolog nous dit cette fois-ci que la solution est unique en nous fournissant les valeurs des variables pour lesquelles l’ensemble de contraintes est vérifié. On aurait pu bien évidemment fixer n’importe quel couple de variables pour avoir une solution unique. Avant de continuer avec cet exemple nous allons, afin de ne plus donner explicitement le système d’équations, déclarer dans Prolog une règle liant les quatre variables et les équations. Par la suite, nous n’utiliserons plus que cette relation. Entrons:

> ChatsOiseaux(c,o,p,t) -> , {t=c+o, p=4c+2o};

Nous venons d’introduire dans Prolog une règle dont la sémantique est :

sous réserve que le système de contraintes soit vérifié, la relation ChatsOiseaux(c, o, p, t) est vraie. On peut à présent donner les requêtes suivantes :

> ChatsOiseaux(c,o,14,5); {c=2, o=3} > ChatsOiseaux(1,o,p,5); {o=4, p=12} > ChatsOiseaux(1,1,2,4); > ChatsOiseaux(c,o,6,4); {c=-1, o=5} >

Prolog ne répond rien à la troisième requête car elle n’est pas soluble. A la quatrième, une des variables de la solution est négative. En effet, lors de la formalisation de notre problème, nous n’avons à aucun moment précisé que les solutions devaient être positives ! Nous allons donc réécrire la relation ChatsOiseaux en imposant aux variables figurant dans le système d’équations de ne pas être négatives. Auparavant, nous enlevons la relation ChatsOiseaux en donnant la requête :

> suppress(ChatsOiseaux); {}

>

puis nous écrivons la nouvelle relation : > ChatsOiseaux(c,o,p,t) ->,

{t=c+o, p=4c+2o, c>=0, o>=0, p>=0, t>=0};

>

et nous demandons :

> ChatsOiseaux(c,o,6,4); >

Prolog nous dit qu’il n’y a pas de solution à cette requête, ce que nous voulions. Mais que se passe-t-il si nous fournissons un nombre de pattes et de têtes tels qu’il n’existe pas de solution entière ?

{c=1/2, o=5/2} >

nous nous retrouvons avec 12 chat et 52 d’oiseaux.... Nous n’avions en effet jamais précisé que nous voulions des solutions entières. Prolog résout les équations arithmétiques dans l’ensemble Q des nombres rationnels. Nous arrêterons là cet exemple car il n’existe pas de contraintes imposant à une variable d’être entière; il nous faudra utiliser un prédicat prédéfini pour réaliser cette vérification.

Les booléens et les formules

Prolog manipule aussi les formules et les systèmes de contraintes booléennes. Il en vérifie à tout instant la satisfaisabilité et donne un système « simplifié » comme solution. Nous ne nous étendrons pas ici sur la notion de simplifié ; disons juste que le système solution est équivalent à celui fourni en entrée. Donnons par exemple ces trois relations sur les trois variables a, b,

c :

> {a=>b, b=>c, c=>a}; {b=>c, c=>a, a=>b}

>

Rappelons que ces trois relations implique indiquent que les trois variables a,

b, c sont équivalentes et ont donc même valeur de vérité, sans pour autant que celle-ci soit connue. Prolog répond par un système identique à celui que nous avons fourni au départ, ce système étant en fait déjà "simplifié".

Imposons maintenant que l’une des trois variables a ou b ou c soit vraie. Pour cela on ajoute au système précédent l’équation a|b|c = 1' qui dit que la formule «a ou b ou c » est vraie ( 1' est la constante Prolog vrai, et 0' la constante faux).

> {a=>b, b=>c, c=>a, a|b|c = 1'}; {a=1',b=1',c=1'}

Cette fois-ci, la solution est unique et Prolog nous répond que toutes les variables prennent la valeur "vrai".

Concepts de base

1. Arbres 2. Constantes 3. Opérations 4. Variables 5. Termes 6. Relations 7. Contraintes 8. Résolution des 9. Règles et requêtes

Que trouve-t-on dans ce chapitre ?

Quels sont les concepts fondamentaux de Prolog III ? Quels objets le langage manipule-t-il ? Quelle est la nature des contraintes qui pèseront sur ces objets ? Qu'est-ce qu'un programme Prolog III signifie pour le programmeur ? Comment la machine l'exécute-t-elle ? Selon quelle syntaxe ces objets et contraintes doivent-ils être exprimés ?

Il y a une différence de nature, et non de degré, entre la plupart des autres langages de programmation et Prolog III. On ne peut aborder ce dernier sans examiner auparavant un certain nombre de concepts originaux à la base du langage, indispen- sables pour une utilisation optimale, parfois même une utilisation tout-court, de celui-ci.

Ce chapitre présente l'ensemble des spécifications de Prolog III, d'une manière assez informelle, accessible quel que soit le degré de familiarité que vous entretenez déjà avec la programmation logique.

Nous y définissons les objets manipulés par le langage, puis les opérations et les relations qui permettent d'établir des contraintes sur ces objets. Ensuite, nous présentons ce qu'est un programme Prolog III, ainsi que la manière dont il est exécuté.

1 . Arbres

« Quelle est la nature des objets manipulés ? » C'est une des premières questions auxquelles il nous faut répondre pour expliquer Prolog III. Le langage est tout-à-fait cohérent et uniforme :

TOUS LES OBJETS MANIPULéS PAR PROLOG III SONT DES ARBRES

Certains sont très complexes, voire infinis, tandis que d'autres sont réduits à un unique nœud. Certains ont une dénomination particulière, alors que d'autres ne peuvent être designés qu'au moyen d'une opération qui les construit ou d'un système de contraintes dont ils sont solution.

N'ayant pas à reproduire les démonstrations formelles qui justifient les algorithmes du cœur de Prolog III, nous ne donnerons pas ici de définition rigoureuse des arbres. La notion intuitive habituelle, qui assimile le concept d'arbre à celui d'ensemble organisé hiérarchiquement nous suffira amplement.

Cette hiérarchie est incarnée dans un ensemble de positions, ou nœuds, et un ensemble de flèches reliant ces positions. On dit que les nœuds auxquels aboutit une flèche issue d'un nœud n sont les fils de n. L'ensemble des fils d'un nœud donné est toujours ordonné, ne serait-ce que par l'ordre dans lequel ces nœuds sont pratiquement représentés. Le nœud qui est au sommet de la hiérarchie s'appelle la racine, ou nœud initial de l'arbre.

Chaque nœud d'un arbre est à son tour racine d'un arbre, appelé sous-arbre de l'arbre initial, défini par ce nœud, ses fils, les fils de ses fils, etc… ainsi que les flèches qui émanent de tous ces nœuds.

UN ARBRE COMPORTE UNE éTIQUETTE ET UNE SUITE FINIE DE SOUS-ARBRES.

A chaque nœud d'un arbre Prolog III est associée une étiquette. Les étiquettes possibles sont :

• les identificateurs • les caractères

• les valeurs booléennes 0' et 1'

• les nombres

• le double signe <>

Voici un arbre de Prolog III :

<> 1' 755/10

`D` `u` `p` `o` `n` `t` nom_marie_poids

Le nombre des fils d'un nœud est toujours fini et indépendant de la nature de son étiquette. Bien entendu, la sémantique de cette dernière, ce qu'elle signifie pour le programmeur, peut faire qu'un nœud n'ait de sens qu'assorti d'un nombre déterminé de fils, mais cela n'est pas connu des mécanismes de base de Prolog III.

Le nombre des fils d'un nœud peut être nul : un arbre réduit à un seul nœud est appelé une feuille. Prolog III ne fait pas de distinction entre une feuille et l'étiquette qu'elle porte. Par conséquent, les identificateurs, les caractères, les valeurs booléennes et les nombres sont considérés comme des cas particuliers d'arbres.

Tous ces éléments peuvent servir à étiqueter un nœud, un cas particu- lièrement fréquent étant celui où l'étiquette est un identificateur, comme dans l'exemple dessiné ci-dessus. Fort souvent de tels arbres représentent des relations. Pour l'arbre dont nous parlons, ce pourrait être « s'appelle

Dupont, est marié et pèse 75,5 Kg ».

Un autre cas fréquent est celui où l'étiquette du nœud initial de l'arbre n'a aucune signification pour le programmeur, qui ne s'intéresse donc qu'à la suite des fils. Prolog III permet d'utiliser alors pour étiquette le double signe conventionnel <>. De tels arbres sont appelés PIII-tuples ou, plus simple- ment, tuples, et ils implantent donc la notion de suite finie d'arbres. Dans cet esprit, l'arbre réduit au symbole <> représente la suite vide. Les tuples sont expliqués plus en détail au chapitre « Arbres, tuples, chaînes et listes »

Grâce au puissant opérateur dont ils sont munis, qui traduit l'opération de concaténation des suites finies, les tuples constituent un outil souple et puissant pour la définition de nombreuses structures de données, alliant la généralité des listes et l'efficacité des vecteurs. Ils peuvent donc avantageusement remplacer la notion habituelle de liste, comme elle existe en Lisp ou dans d'autres Prolog.

Cependant ces listes classiques, définies à partir de la notion de paire pointée, peuvent être aussi utilisées en Prolog III, y compris à travers leur syntaxe habituelle, dite d'Edimbourg.

Dans les programmes Prolog III, les arbres sont représentés par des formules appelées termes. La syntaxe des termes apparaîtra progres- sivement tout au long des paragraphes suivants ; elle est résumée au chapitre « Les syntaxes de Prolog III ».

Les arbres et les termes ne sont pas la même chose : les éléments du domaine de Prolog III sont des arbres, les entités syntaxiques qui les représentent sont des termes. Or, dans l'explication de Prolog III il ne sera guère question que de ces derniers, car ils sont la seule expression écrite des arbres en accord avec la syntaxe du langage. Ceci semble encourager une certaine confusion des deux notions. Nous ne saurions trop mettre en garde le lecteur contre une telle confusion, car elle présente de nombreux inconvénients et notamment celui d'empêcher la compréhension de notions parmi les plus importantes.

Cela étant dit, il y a un cas dans lequel on confond un arbre et le terme qui le représente : il s'agit des constantes, qui sont par définition les arbres représentés par des termes simples, dont l'expression ne fait pas intervenir d'opérateur, ainsi que l'explique le paragraphe suivant.

2 . Constantes

Parmi les éléments du domaine de Prolog III, c'est-à-dire les arbres, les

constantes désignent ceux qui ont reçu une dénomination particulière. Comme nous l'avons dit, nous ne ferons pas de distinction entre une constante et le terme qui la représente.

Il ne suffit pas d'être une feuille pour être une constante : un arbre réduit à un unique nombre fractionnaire, comme 755/10, est une feuille, mais il ne possède pas de nom spécifique et il ne peut être exprimé qu'à travers la division dont il est le résultat. Bien entendu, 151/2 est une autre manière de spécifier le même nombre rationnel.

Inversement, toutes les constantes ne représentent pas nécessairement des feuilles. Ainsi une suite de caractères comme

< >

n'est certainement pas atomique ; cependant, Prolog III la considérera com- me une constante, dès lors que l'on utilisera la notation particulière des chaînes, "Dupont". Bien entendu, vous pouvez représenter le même arbre par le terme <`D`,`u`,`p`,`o`,`n`,`t`>.

Les constantes connues sont :

Les identificateurs

Les identificateurs sont les constantes symboliques, comme

p i e r r e

repas_leger c a l c u l 1 2

Un identificateur est une suite de lettres, de chiffres et des deux caractères apostrophe ( ' ) et blanc souligné ( _ ) qui n'a pas la syntaxe d'un nom de variable, c'est-à-dire qui commence par au moins deux lettres. Une description plus précise de la syntaxe des identificateurs est donnée au chapitre « Les syntaxes de Prolog III ».

En réalité la syntaxe des identificateurs est bien plus complexe que celle des exemples montrés ici, puisque la notation complète d'un identificateur comporte un qualifieur (ou préfixe) qui indique le module auquel l'identificateur appartient. L'ensemble des modules intervenant dans un programme Prolog III réalise une partition de l'espace des noms, lui permettant d'être gigantesque tout en restant facile à appréhender par le programmeur. Cependant, l'existence par ailleurs d'un contexte de lecture-

écriture permet le plus souvent de n'utiliser que des notations simplifiées pour les identificateurs.

Les notions de module, de qualifieur et de contexte de lecture-écriture sont expliquées au chapitre « Le contrôle et l'environnement des programmes »

Les caractères

Tous les caractères disponibles sur votre machine peuvent être utilisés dans un programme Prolog III. Les caractères imprimables peuvent être exprimés en les encadrant par des « anti-apostrophes » :

`A`, `a`, `<`

Les caractères non imprimables et ceux ayant un rôle spécial peuvent être indiqués au moyen du caractère d'échappement anti-slash ( \ ), selon une convention proche de celle utilisée dans la communauté UNIX. Par exemple :

` \ ` ` indique le caractère `

` \ n ` indique le caractère “nouvelle ligne”

` \ x 4 1 ` indique le caractère A (de code ASCII 41 en

hexadécimal)

` \ 1 0 1 ` indique le caractère A (de code ASCII 101 en octal) ` \ \ ` indique le caractère \ lui-même

La syntaxe complète des caractères est donnée au chapitre « Les syntaxes de Prolog III ».

Les valeurs booléennes

Les valeurs booléennes sont les deux éléments du domaine de l'algèbre de Boole classique :

0 ' 1 '

Nous ne les interpréterons pas en termes de vrai ou de faux, réservant ces mots pour parler des contraintes (nous dirons qu'une contrainte est vraie ou fausse, pour indiquer qu'elle est ou n'est pas satisfaite). Les contraintes sont expliquées ci-dessous, au § 7.

Les nombres entiers non négatifs

0 1 2 1 9 9 1 815915283247897734345611269596115894272000000000

On notera que les entiers négatifs ne sont pas considérés comme des constantes, puisqu'on peut les exprimer comme résultat d'une opération, le changement de signe, appliquée à un entier positif ou nul. De la même manière, les nombres fractionnaires ne sont pas des constantes non plus, ils sont représentés à l'aide des opérations de division et de changement de signe, appliquées à des entiers.

Les nombres rationnels sont représentés dans la machine en précision parfaite, c'est-à-dire avec autant de chiffres que leur expression exacte le requiert. A la condition, bien entendu, que cela ne dépasse pas la taille de la mémoire de votre machine.

Les nombres flottants non négatifs

Exemples :

1 2 . 3 4 5 0 . 5

314.15926535e-2 1 . 2 E 1 2

La représentation interne, et donc la précision et l'étendue des nombres flottants, sont déterminés par les particularités de votre machine. Leur syntaxe coïncide avec celle utilisée dans la plupart des langages qui connais- sent ce type de données numériques. Elle est donnée en détail au chapitre « Les syntaxes de Prolog III ».

Le tuple vide

< >

Le double signe <> est un symbole conventionnel destiné à servir d'étiquette aux arbres qui, d'un point de vue sémantique, n'en ont pas. Ces arbres se réduisent donc à la suite de leurs fils : ils implantent en Prolog III la notion de suite finie d'arbres, qu'on appelle des tuples.

Comme nous le verrons, les tuples se notent <a1, … an> ; le tuple vide se note donc tout naturellement <>. Ceci justifie le nom donné à ce signe.

Les chaînes de caractères

La notation courante des chaînes de caractères, à l'aide de guillemets :

"Et oui"

est en réalité une deuxième notation pour l'arbre

`E` `t` ` ` `o` `u` `i` < >

En Prolog III, une chaîne de caractères est toujours structurée, puisque c'est un tuple de caractères. Les chaînes ne sont des entités atomiques qu'en tant qu'objets syntaxiques, et encore à la condition d'utiliser la notation des constantes-chaînes, "Et oui".

Cas particulier, le tuple vide et la chaîne vide sont la même chose ; les deux notations "" et <> sont donc équivalentes.