EPITA

Introdution à Prolog, cours n° 1

Jean-François Perrot


  1. Histoire de Prolog
    1. Implémentations disponibles aujourd'hui (2009)
    2. La programmation logique comme style de programmation

  2. Première approche : interroger une base de données.
    1. Les données
    2. Les questions directes
    3. Les déductions
    4. Commentaire
      1. Constantes et variables
      2. Réponses multiples
      3. La trace

  3. Seconde approche : avec des fonctions (plus exactement, avec des symboles de fonctions)
    1. Exemple
    2. Termes du 1er ordre
      1. Listes
      2. Symboles arithmétiques
      3. Introduction d'opérateurs supplémentaires
    3. Littéraux
      1. Les littéraux
      2. Prédicats prédéfinis et prédicats évaluables
    4. Clauses de Horn
    5. Exemple

  4. Fonctionnement de base
    1. Paquets de clauses
      1. Le zig-zag
    2. Le séquencement standard avec retour-arrière
      1. Détail technique : le prédicat fail
      2. Interprétation logique du séquencement  de base
    3. Le coupe-choix
      1. Idée
      2. Exemples de coupe-choix 1
      3. Programmation fonctionnelle récursive
      4. Réalisation de boucles (itératives)

  5. Programmes récursifs sur les listes, plus ou moins réversibles
    1. Exemples de définitions récursives sans coupe-choix
      1. La concaténation des listes
    2. Exemples avec coupe-choix
    3. Les chaînes comme listes de codes ASCII
      1. L'exemple historique des mutants



Histoire de Prolog

Prolog : Wikipédia-fr, Wikipedia-en

Implémentations disponibles aujourd'hui (2009)

La programmation logique comme style de programmation

Première approche : interroger une base de données.

Seconde approche : avec des fonctions (plus exactement, avec des symboles de fonctions)

Fonctionnement de base

  1. Paquets de clauses

    L'opération élémentaire du calcul de Prolog est la démonstration d'un énoncé atomique, alias littéral.
    Pour des raisons historiques on parle de résoudre un littéral.
    Il nous faut donc comprendre comment se passe la résolution d'un littéral.

    Cette résolution utilise les règles du système (les clauses) dont la conclusion est compatible (unifiable) avec le littéral-but (voir plus tard),
    donc en particulier qui ont le même prédicat que le but.

    Toutes les clauses relatives au même prédicat sont regroupées en un seul paquet,
    où elles sont rangées dans l'ordre du texte-source.

    L'ordre des paquets de clauses n'a pas d'importance,
    en revanche l'ordre des clauses dans chaque paquet est significatif !

    Le zig-zag
    À chaque étape, Prolog doit démontrer une liste de buts : il procède de gauche à droite dans cette liste
    Pour démontrer chacun de ces buts :
    Exemple : résolution du littéral zig(X),  avec :
        zig(a) :- write('un '), write('deux '), write('trois'), nl.
       zig(b) :- write('quatre '), write('cinq '), write('six'), nl.
       zig(c) :- write('sept'), nl, write(fini_pour_zig), nl.

    zig


    ?- zig(X).
    un deux trois
    X = a 
    ;
    quatre cinq six
    X = b 
    ;
    sept
    fini_pour_zig
    X = c.


  2. Le séquencement standard avec retour-arrière

    Le fonctionnement normal de Prolog lui fait chercher
    toutes les démonstrations possibles du but visé.

    Ceci le conduit à revenir en arrière après un échec,
    pour essayer la clause suivante du paquet.

    Ce mécanisme de retour-arrière (backtrack), superposé au "zig-zag"
    induit un séquencement complexe :

    Exemple : résolution du littéral  zigzag(X, Y), avec
    zigzag(X, Y) :-
       zig(X), write('X = '), write(X), nl,
       zig(Y), write('Y = '), write(Y), nl.


    On observe que le littéral le plus à droite zig(Y) a été résolu 9 fois,
    et zig(X) 3 fois seulement
    [sorte de boucle intérieure sur zig(Y), extérieure sur zig(X) ]


    zag

    Détail technique : le prédicat fail
    Pour observer les phénomènes de séquencement, il est fastidieux de devoir taper un point-virgule ";" à chaque résultat.
    En outre, l'impression automatique des valeurs des variables vient compliquer la lecture (cf. exemple précédent).
    On peut demander à Prolog à épuiser toutes les possibilités en le contraignant à l'échec par le prédicat prédéfini fail
    (sans argument), qui échoue toujours - comme son nom l'indique.
    Exemple :

    ?- zigzag(X,Y), fail.
    un deux trois
    X = a
    un deux trois
    Y = a
    quatre cinq six
    Y = b
    sept
    fini_pour_zig
    Y = c
    quatre cinq six
    X = b
    un deux trois
    Y = a
    quatre cinq six
    Y = b
    sept
    fini_pour_zig
    Y = c
    sept
    fini_pour_zig
    X = c
    un deux trois
    Y = a
    quatre cinq six
    Y = b
    sept
    fini_pour_zig
    Y = c
    false.



    Interprétation logique du séquencement  de base
    Les deux dimensions horizontale et verticale d'un paquet de clauses ont deux interprétations bien différentes.


  3. Le coupe-choix

Programmes récursifs sur les listes, plus ou moins réversibles